I'd like to add a lock/unlock the remaining parts of the IPv4 forwarding
path that still require some work:

 1/ IP source options
 2/ per-ifp lookups related to multicast traffic
 3/ IPsec lookups

This should not matter for the moment since the whole path already run
under the big lock.  However this document which part of the code needs
to be fixed and will allow us to test the routing lookup with PF
disabled, then the big fat PF_LOCK.

Comments?  Oks?

Index: netinet/in.c
===================================================================
RCS file: /cvs/src/sys/netinet/in.c,v
retrieving revision 1.126
diff -u -p -r1.126 in.c
--- netinet/in.c        21 Jan 2016 11:23:48 -0000      1.126
+++ netinet/in.c        7 Apr 2016 14:48:01 -0000
@@ -890,8 +890,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/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.269
diff -u -p -r1.269 ip_input.c
--- netinet/ip_input.c  29 Mar 2016 10:34:42 -0000      1.269
+++ netinet/ip_input.c  7 Apr 2016 14:48:01 -0000
@@ -227,7 +227,7 @@ ipv4_input(struct mbuf *m)
 {
        struct ifnet *ifp;
        struct ip *ip;
-       int hlen, len;
+       int rv, hlen, len;
        in_addr_t pfrdr = 0;
 
        ifp = if_get(m->m_pkthdr.ph_ifidx);
@@ -355,8 +355,6 @@ ipv4_input(struct mbuf *m)
 
 #ifdef MROUTING
                if (ipmforwarding && ip_mrouter) {
-                       int rv;
-
                        if (m->m_flags & M_EXT) {
                                if ((m = m_pullup(m, hlen)) == NULL) {
                                        ipstat.ips_toosmall++;
@@ -430,7 +428,10 @@ ipv4_input(struct mbuf *m)
        }
 #ifdef IPSEC
        if (ipsec_in_use) {
-               if (ip_input_ipsec_fwd_check(m, hlen) != 0) {
+               KERNEL_LOCK();
+               rv = ip_input_ipsec_fwd_check(m, hlen);
+               KERNEL_UNLOCK();
+               if (rv != 0) {
                        ipstat.ips_cantforward++;
                        goto bad;
                }
@@ -1025,6 +1026,7 @@ ip_dooptions(struct mbuf *m, struct ifne
        cp = (u_char *)(ip + 1);
        cnt = (ip->ip_hl << 2) - sizeof (struct ip);
 
+       KERNEL_LOCK();
        for (; cnt > 0; cnt -= optlen, cp += optlen) {
                opt = cp[IPOPT_OPTVAL];
                if (opt == IPOPT_EOL)
@@ -1225,12 +1227,14 @@ ip_dooptions(struct mbuf *m, struct ifne
                        ipt.ipt_ptr += sizeof(u_int32_t);
                }
        }
+       KERNEL_UNLOCK();
        if (forward && ipforwarding) {
                ip_forward(m, ifp, 1);
                return (1);
        }
        return (0);
 bad:
+       KERNEL_UNLOCK();
        icmp_error(m, type, code, 0, 0);
        ipstat.ips_badoptions++;
        return (1);
Index: netinet/ip_output.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.318
diff -u -p -r1.318 ip_output.c
--- netinet/ip_output.c 11 Feb 2016 12:56:08 -0000      1.318
+++ netinet/ip_output.c 7 Apr 2016 14:48:01 -0000
@@ -100,10 +100,9 @@ ip_output(struct mbuf *m0, struct mbuf *
        struct ifnet *ifp = NULL;
        struct mbuf *m = m0;
        int hlen = sizeof (struct ip);
-       int len, error = 0;
+       int rv, len, error = 0;
        struct route iproute;
        struct sockaddr_in *dst;
-       struct in_ifaddr *ia;
        struct tdb *tdb = NULL;
        u_long mtu;
 
@@ -183,9 +182,17 @@ reroute:
        if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
            (ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
            imo != NULL && (ifp = if_get(imo->imo_ifidx)) != NULL) {
+               struct in_ifaddr *ia;
+
                mtu = ifp->if_mtu;
+               KERNEL_LOCK();
                IFP_TO_IA(ifp, ia);
+               if (ip->ip_src.s_addr == INADDR_ANY && ia)
+                       ip->ip_src = ia->ia_addr.sin_addr;
+               KERNEL_UNLOCK();
        } else {
+               struct in_ifaddr *ia;
+
                if (ro->ro_rt == NULL)
                        ro->ro_rt = rtalloc_mpath(&ro->ro_dst,
                            &ip->ip_src.s_addr, ro->ro_tableid);
@@ -206,17 +213,19 @@ reroute:
 
                if (ro->ro_rt->rt_flags & RTF_GATEWAY)
                        dst = satosin(ro->ro_rt->rt_gateway);
-       }
 
-       /* Set the source IP address */
-       if (ip->ip_src.s_addr == INADDR_ANY && ia)
-               ip->ip_src = ia->ia_addr.sin_addr;
+               /* Set the source IP address */
+               if (ip->ip_src.s_addr == INADDR_ANY && ia)
+                       ip->ip_src = ia->ia_addr.sin_addr;
+       }
 
 #ifdef IPSEC
        if (ipsec_in_use || inp != NULL) {
+               KERNEL_LOCK();
                /* 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)
@@ -289,9 +298,13 @@ reroute:
                 * of outgoing interface.
                 */
                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) &&
@@ -322,8 +335,6 @@ reroute:
                         */
                        if (ipmforwarding && ip_mrouter &&
                            (flags & IP_FORWARDING) == 0) {
-                               int rv;
-
                                KERNEL_LOCK();
                                rv = ip_mforward(m, ifp);
                                KERNEL_UNLOCK();
@@ -389,8 +400,10 @@ sendit:
         * Check if the packet needs encapsulation.
         */
        if (tdb != NULL) {
+               KERNEL_LOCK();
                /* Callee frees mbuf */
                error = ip_output_ipsec_send(tdb, m, ifp, ro);
+               KERNEL_UNLOCK();
                goto done;
        }
 #endif /* IPSEC */

Reply via email to