Our original plan was to unlock the forwarding path without taking any
lock. That's why I added some KERNEL_LOCK()/KERNEL_UNLOCK() around non
MP-safe data structures.
Now we're going to rely on the NET_LOCK() for the interface address and
multicast list. So replace the KERNEL_LOCK()/KERNEL_UNLOCK() their.
IPsec will still need the KERNEL_LOCK(). But taking and releasing it
doesn't make sense. It's also wrong since tdb are not refcounted. So
assert that the KERNEL_LOCK() is held. The idea is to run the softnet
task under KERNEL_LOCK() if ipsec_in_use is true.
ok?
Index: netinet/in.c
===================================================================
RCS file: /cvs/src/sys/netinet/in.c,v
retrieving revision 1.138
diff -u -p -u -4 -r1.138 in.c
--- netinet/in.c 16 May 2017 12:24:01 -0000 1.138
+++ netinet/in.c 28 May 2017 14:00:12 -0000
@@ -797,10 +797,8 @@ in_addmulti(struct in_addr *ap, struct i
{
struct in_multi *inm;
struct ifreq ifr;
- NET_ASSERT_LOCKED();
-
/*
* See if address already in list.
*/
IN_LOOKUP_MULTI(*ap, ifp, inm);
@@ -900,12 +898,10 @@ in_hasmulti(struct in_addr *ap, struct i
{
struct in_multi *inm;
int joined;
- KERNEL_LOCK();
IN_LOOKUP_MULTI(*ap, ifp, inm);
joined = (inm != NULL);
- KERNEL_UNLOCK();
return (joined);
}
Index: netinet/in_var.h
===================================================================
RCS file: /cvs/src/sys/netinet/in_var.h,v
retrieving revision 1.39
diff -u -p -u -4 -r1.39 in_var.h
--- netinet/in_var.h 15 Jun 2016 19:39:34 -0000 1.39
+++ netinet/in_var.h 28 May 2017 14:01:33 -0000
@@ -85,8 +85,9 @@ struct in_aliasreq {
/* struct ifnet *ifp; */ \
/* struct in_ifaddr *ia; */ \
do { \
struct ifaddr *ifa; \
+ NET_ASSERT_LOCKED(); \
TAILQ_FOREACH(ifa, &(ifp)->if_addrlist, ifa_list) { \
if (ifa->ifa_addr->sa_family == AF_INET) \
break; \
} \
@@ -141,8 +142,9 @@ ifmatoinm(struct ifmaddr *ifma)
do { \
struct ifmaddr *ifma; \
\
(inm) = NULL; \
+ NET_ASSERT_LOCKED(); \
TAILQ_FOREACH(ifma, &(ifp)->if_maddrlist, ifma_list) \
if (ifma->ifma_addr->sa_family == AF_INET && \
ifmatoinm(ifma)->inm_addr.s_addr == (addr).s_addr) {\
(inm) = ifmatoinm(ifma); \
Index: netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.306
diff -u -p -u -4 -r1.306 ip_input.c
--- netinet/ip_input.c 28 May 2017 12:22:54 -0000 1.306
+++ netinet/ip_input.c 28 May 2017 13:56:09 -0000
@@ -440,11 +440,11 @@ ipv4_input(struct mbuf *m)
#ifdef IPSEC
if (ipsec_in_use) {
int rv;
- KERNEL_LOCK();
+ KERNEL_ASSERT_LOCKED();
+
rv = ipsec_forward_check(m, hlen, AF_INET);
- KERNEL_UNLOCK();
if (rv != 0) {
ipstat_inc(ips_cantforward);
goto bad;
}
@@ -666,9 +666,9 @@ in_ouraddr(struct mbuf *m, struct ifnet
* The check in the loop assumes you only rx a packet on an UP
* interface, and that M_BCAST will only be set on a BROADCAST
* interface.
*/
- KERNEL_LOCK();
+ NET_ASSERT_LOCKED();
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
@@ -677,9 +677,8 @@ in_ouraddr(struct mbuf *m, struct ifnet
match = 1;
break;
}
}
- KERNEL_UNLOCK();
}
return (match);
}
Index: netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.339
diff -u -p -u -4 -r1.339 ip_output.c
--- netinet/ip_output.c 19 Apr 2017 15:21:54 -0000 1.339
+++ netinet/ip_output.c 28 May 2017 13:58:03 -0000
@@ -191,13 +191,11 @@ reroute:
mtu = ifp->if_mtu;
if (ip->ip_src.s_addr == INADDR_ANY) {
struct in_ifaddr *ia;
- KERNEL_LOCK();
IFP_TO_IA(ifp, ia);
if (ia != NULL)
ip->ip_src = ia->ia_addr.sin_addr;
- KERNEL_UNLOCK();
}
} else {
struct in_ifaddr *ia;
@@ -232,13 +230,12 @@ reroute:
}
#ifdef IPSEC
if (ipsec_in_use || inp != NULL) {
- KERNEL_LOCK();
+ KERNEL_ASSERT_LOCKED();
/* Do we have any pending SAs to apply ? */
tdb = ip_output_ipsec_lookup(m, hlen, &error, inp,
ipsecflowinfo);
- KERNEL_UNLOCK();
if (error != 0) {
/* Should silently drop packet */
if (error == -EINVAL)
error = 0;
@@ -306,13 +303,11 @@ reroute:
*/
if (ip->ip_src.s_addr == INADDR_ANY) {
struct in_ifaddr *ia;
- KERNEL_LOCK();
IFP_TO_IA(ifp, ia);
if (ia != NULL)
ip->ip_src = ia->ia_addr.sin_addr;
- KERNEL_UNLOCK();
}
if ((imo == NULL || imo->imo_loop) &&
in_hasmulti(&ip->ip_dst, ifp)) {
@@ -406,12 +401,11 @@ sendit:
/*
* Check if the packet needs encapsulation.
*/
if (tdb != NULL) {
- KERNEL_LOCK();
+ KERNEL_ASSERT_LOCKED();
/* Callee frees mbuf */
error = ip_output_ipsec_send(tdb, m, ifp, ro);
- KERNEL_UNLOCK();
goto done;
}
#endif /* IPSEC */
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.190
diff -u -p -u -4 -r1.190 ip6_input.c
--- netinet6/ip6_input.c 28 May 2017 09:25:51 -0000 1.190
+++ netinet6/ip6_input.c 28 May 2017 13:59:21 -0000
@@ -473,11 +473,10 @@ ip6_input(struct mbuf *m)
#ifdef IPSEC
if (ipsec_in_use) {
int rv;
- KERNEL_LOCK();
+ KERNEL_ASSERT_LOCKED();
rv = ipsec_forward_check(m, off, AF_INET6);
- KERNEL_UNLOCK();
if (rv != 0) {
ip6stat_inc(ip6s_cantforward);
goto bad;
}