svn commit: r362635 - head/sys/netipsec

John Baldwin jhb at FreeBSD.org
Thu Jun 25 23:57:31 UTC 2020


Author: jhb
Date: Thu Jun 25 23:57:30 2020
New Revision: 362635
URL: https://svnweb.freebsd.org/changeset/base/362635

Log:
  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

Modified:
  head/sys/netipsec/ipsec_input.c
  head/sys/netipsec/ipsec_output.c

Modified: head/sys/netipsec/ipsec_input.c
==============================================================================
--- head/sys/netipsec/ipsec_input.c	Thu Jun 25 21:34:43 2020	(r362634)
+++ head/sys/netipsec/ipsec_input.c	Thu Jun 25 23:57:30 2020	(r362635)
@@ -278,6 +278,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar
     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
 	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
     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
 		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
 	 */
 	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
 			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
 		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)

Modified: head/sys/netipsec/ipsec_output.c
==============================================================================
--- head/sys/netipsec/ipsec_output.c	Thu Jun 25 21:34:43 2020	(r362634)
+++ head/sys/netipsec/ipsec_output.c	Thu Jun 25 23:57:30 2020	(r362635)
@@ -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 *s
 	 * 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);


More information about the svn-src-head mailing list