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