aboutsummaryrefslogtreecommitdiff
path: root/sys/netipsec
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2020-06-25 23:57:30 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2020-06-25 23:57:30 +0000
commitf82eb2a6f04c2a4193378f932fe8ab9b84fbb67d (patch)
treeb39807c00b315d3052be7b95f7912f9556a7c69b /sys/netipsec
parent9b934d43602f5538bac58b32853359f9a178765e (diff)
downloadsrc-f82eb2a6f04c2a4193378f932fe8ab9b84fbb67d.tar.gz
src-f82eb2a6f04c2a4193378f932fe8ab9b84fbb67d.zip
Enter and exit the network epoch for async IPsec callbacks.
When an IPsec packet has been encrypted or decrypted, the next step in the packet's traversal through the network stack is invoked from a crypto worker thread, not from the original calling thread. These threads need to enter the network epoch before passing packets down to IP output routines or up to transport protocols. Reviewed by: ae Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D25444
Notes
Notes: svn path=/head/; revision=362635
Diffstat (limited to 'sys/netipsec')
-rw-r--r--sys/netipsec/ipsec_input.c16
-rw-r--r--sys/netipsec/ipsec_output.c13
2 files changed, 23 insertions, 6 deletions
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index 9814495f7d6f..7f9317bee8b6 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -278,6 +278,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
int protoff)
{
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
+ struct epoch_tracker et;
struct ipsec_ctx_data ctx;
struct xform_history *xh;
struct secasindex *saidx;
@@ -424,7 +425,9 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
if (saidx->mode == IPSEC_MODE_TUNNEL)
error = ipsec_if_input(m, sav, af);
if (error == 0) {
+ NET_EPOCH_ENTER(et);
error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
+ NET_EPOCH_EXIT(et);
if (error) {
IPSEC_ISTAT(sproto, qfull);
DPRINTF(("%s: queue full; proto %u packet dropped\n",
@@ -489,6 +492,7 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
int protoff)
{
IPSEC_DEBUG_DECLARE(char buf[IPSEC_ADDRSTRLEN]);
+ struct epoch_tracker et;
struct ipsec_ctx_data ctx;
struct xform_history *xh;
struct secasindex *saidx;
@@ -621,8 +625,10 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
if (saidx->mode == IPSEC_MODE_TUNNEL)
error = ipsec_if_input(m, sav, af);
if (error == 0) {
+ NET_EPOCH_ENTER(et);
error = netisr_queue_src(isr_prot,
(uintptr_t)sav->spi, m);
+ NET_EPOCH_EXIT(et);
if (error) {
IPSEC_ISTAT(sproto, qfull);
DPRINTF(("%s: queue full; proto %u packet"
@@ -638,11 +644,12 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
*/
nest = 0;
nxt = nxt8;
+ NET_EPOCH_ENTER(et);
while (nxt != IPPROTO_DONE) {
if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) {
IP6STAT_INC(ip6s_toomanyhdr);
error = EINVAL;
- goto bad;
+ goto bad_epoch;
}
/*
@@ -653,7 +660,7 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
IP6STAT_INC(ip6s_tooshort);
in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
error = EINVAL;
- goto bad;
+ goto bad_epoch;
}
/*
* Enforce IPsec policy checking if we are seeing last header.
@@ -663,12 +670,15 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 &&
ipsec6_in_reject(m, NULL)) {
error = EINVAL;
- goto bad;
+ goto bad_epoch;
}
nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &skip, nxt);
}
+ NET_EPOCH_EXIT(et);
key_freesav(&sav);
return (0);
+bad_epoch:
+ NET_EPOCH_EXIT(et);
bad:
key_freesav(&sav);
if (m)
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index 0bfc709e80b9..557c0d1d4a4e 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -688,6 +688,7 @@ int
ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
u_int idx)
{
+ struct epoch_tracker et;
struct xform_history *xh;
struct secasindex *saidx;
struct m_tag *mtag;
@@ -789,19 +790,25 @@ ipsec_process_done(struct mbuf *m, struct secpolicy *sp, struct secasvar *sav,
* We're done with IPsec processing, transmit the packet using the
* appropriate network protocol (IP or IPv6).
*/
+ NET_EPOCH_ENTER(et);
switch (saidx->dst.sa.sa_family) {
#ifdef INET
case AF_INET:
key_freesav(&sav);
- return ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
+ error = ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL);
+ break;
#endif /* INET */
#ifdef INET6
case AF_INET6:
key_freesav(&sav);
- return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ break;
#endif /* INET6 */
+ default:
+ panic("ipsec_process_done");
}
- panic("ipsec_process_done");
+ NET_EPOCH_EXIT(et);
+ return (error);
bad:
m_freem(m);
key_freesav(&sav);