On 11/10/17(Wed) 17:01, Martin Pieuchot wrote:
> OpenBSD 6.2 includes nice performance and latency improvements due to
> the work done in the Network Stack in the previous years. However as
> soon as IPsec is enabled, all network related processing are affected.
> In other words you cannot profit from the last MP work in the Network
> stack if you use IPsec.
>
> During the last 6 months I hoped that somebody else would look at the
> IPsec stack and tell us what needs to be done. This didn't happen.
>
> Now that 6.2 is released, we cannot afford to continue to parallelize
> the Network Stack if some of our users and testers still run it under
> KERNEL_LOCK().
>
> So I did an audit of the IPsec stack and came with the small diff below.
> This diff doesn't remove the KERNEL_LOCK() (yet), but add some asserts
> to make sure that the global data structure are all accessed while
> holding the NET_LOCK().
Here's the diff to stop grabbing the KERNEL_LOCK(), please test and
report back.
Index: net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.517
diff -u -p -r1.517 if.c
--- net/if.c 16 Oct 2017 08:19:15 -0000 1.517
+++ net/if.c 16 Oct 2017 10:37:37 -0000
@@ -871,9 +871,6 @@ if_input_process(void *xifidx)
struct ifih *ifih;
struct srp_ref sr;
int s;
-#ifdef IPSEC
- int locked = 0;
-#endif /* IPSEC */
ifp = if_get(ifidx);
if (ifp == NULL)
@@ -900,22 +897,6 @@ if_input_process(void *xifidx)
*/
NET_LOCK();
s = splnet();
-
-#ifdef IPSEC
- /*
- * IPsec is not ready to run without KERNEL_LOCK(). So all
- * the traffic on your machine is punished if you have IPsec
- * enabled.
- */
- extern int ipsec_in_use;
- if (ipsec_in_use) {
- NET_UNLOCK();
- KERNEL_LOCK();
- NET_LOCK();
- locked = 1;
- }
-#endif /* IPSEC */
-
while ((m = ml_dequeue(&ml)) != NULL) {
/*
* Pass this mbuf to all input handlers of its
@@ -932,11 +913,6 @@ if_input_process(void *xifidx)
}
splx(s);
NET_UNLOCK();
-
-#ifdef IPSEC
- if (locked)
- KERNEL_UNLOCK();
-#endif /* IPSEC */
out:
if_put(ifp);
}
Index: netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.323
diff -u -p -r1.323 ip_input.c
--- netinet/ip_input.c 9 Oct 2017 08:35:38 -0000 1.323
+++ netinet/ip_input.c 16 Oct 2017 10:41:09 -0000
@@ -482,8 +482,6 @@ ip_input_if(struct mbuf **mp, int *offp,
if (ipsec_in_use) {
int rv;
- KERNEL_ASSERT_LOCKED();
-
rv = ipsec_forward_check(m, hlen, AF_INET);
if (rv != 0) {
ipstat_inc(ips_cantforward);
@@ -1825,40 +1823,16 @@ ip_send_dispatch(void *xmq)
struct mbuf_queue *mq = xmq;
struct mbuf *m;
struct mbuf_list ml;
-#ifdef IPSEC
- int locked = 0;
-#endif /* IPSEC */
mq_delist(mq, &ml);
if (ml_empty(&ml))
return;
NET_LOCK();
-
-#ifdef IPSEC
- /*
- * IPsec is not ready to run without KERNEL_LOCK(). So all
- * the traffic on your machine is punished if you have IPsec
- * enabled.
- */
- extern int ipsec_in_use;
- if (ipsec_in_use) {
- NET_UNLOCK();
- KERNEL_LOCK();
- NET_LOCK();
- locked = 1;
- }
-#endif /* IPSEC */
-
while ((m = ml_dequeue(&ml)) != NULL) {
ip_output(m, NULL, NULL, 0, NULL, NULL, 0);
}
NET_UNLOCK();
-
-#ifdef IPSEC
- if (locked)
- KERNEL_UNLOCK();
-#endif /* IPSEC */
}
void
Index: netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.342
diff -u -p -r1.342 ip_output.c
--- netinet/ip_output.c 20 Sep 2017 16:22:02 -0000 1.342
+++ netinet/ip_output.c 16 Oct 2017 10:41:22 -0000
@@ -233,7 +233,6 @@ reroute:
#ifdef IPSEC
if (ipsec_in_use || inp != NULL) {
- KERNEL_ASSERT_LOCKED();
/* Do we have any pending SAs to apply ? */
tdb = ip_output_ipsec_lookup(m, hlen, &error, inp,
ipsecflowinfo);
@@ -404,7 +403,6 @@ sendit:
* Check if the packet needs encapsulation.
*/
if (tdb != NULL) {
- KERNEL_ASSERT_LOCKED();
/* Callee frees mbuf */
error = ip_output_ipsec_send(tdb, m, ifp, ro);
goto done;
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.203
diff -u -p -r1.203 ip6_input.c
--- netinet6/ip6_input.c 9 Oct 2017 08:35:38 -0000 1.203
+++ netinet6/ip6_input.c 16 Oct 2017 10:41:26 -0000
@@ -521,7 +521,6 @@ ip6_input_if(struct mbuf **mp, int *offp
if (ipsec_in_use) {
int rv;
- KERNEL_ASSERT_LOCKED();
rv = ipsec_forward_check(m, *offp, AF_INET6);
if (rv != 0) {
ip6stat_inc(ip6s_cantforward);
@@ -1455,40 +1454,16 @@ ip6_send_dispatch(void *xmq)
struct mbuf_queue *mq = xmq;
struct mbuf *m;
struct mbuf_list ml;
-#ifdef IPSEC
- int locked = 0;
-#endif /* IPSEC */
mq_delist(mq, &ml);
if (ml_empty(&ml))
return;
NET_LOCK();
-
-#ifdef IPSEC
- /*
- * IPsec is not ready to run without KERNEL_LOCK(). So all
- * the traffic on your machine is punished if you have IPsec
- * enabled.
- */
- extern int ipsec_in_use;
- if (ipsec_in_use) {
- NET_UNLOCK();
- KERNEL_LOCK();
- NET_LOCK();
- locked = 1;
- }
-#endif /* IPSEC */
-
while ((m = ml_dequeue(&ml)) != NULL) {
ip6_output(m, NULL, NULL, IPV6_MINMTU, NULL, NULL);
}
NET_UNLOCK();
-
-#ifdef IPSEC
- if (locked)
- KERNEL_UNLOCK();
-#endif /* IPSEC */
}
void