With the diff below the IPv6 forwarding path is ready to be executed w/o
KERNEL_LOCK().

I'm renaming the current ip6_ours() into ip6_local().  This function
still need to be executed with the KERNEL_LOCK() held and most of the
time it will be from the netisr loop.

The new ip6_ours() will be use to enqueue mbuf that will be delivered
locally. 

This reduce differences with IPv4 even further.

Comments, oks?

Index: netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.144
diff -u -p -r1.144 ipsec_input.c
--- netinet/ipsec_input.c       8 Feb 2017 12:37:43 -0000       1.144
+++ netinet/ipsec_input.c       22 Feb 2017 15:37:15 -0000
@@ -592,7 +592,7 @@ ipsec_common_input_cb(struct mbuf *m, st
                return;
 #ifdef INET6
        case AF_INET6:
-               ip6_ours(m, skip, prot);
+               ip6_local(m, skip, prot);
                return;
 #endif /* INET6 */
        default:
Index: netinet6/ip6_forward.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v
retrieving revision 1.94
diff -u -p -r1.94 ip6_forward.c
--- netinet6/ip6_forward.c      5 Feb 2017 16:04:14 -0000       1.94
+++ netinet6/ip6_forward.c      22 Feb 2017 15:54:26 -0000
@@ -89,10 +89,21 @@ ip6_forward(struct mbuf *m, struct rtent
        struct ifnet *ifp = NULL;
        int error = 0, type = 0, code = 0;
        struct mbuf *mcopy = NULL;
+       int off, nxt, ours = 0;
 #ifdef IPSEC
        struct tdb *tdb = NULL;
 #endif /* IPSEC */
        char src6[INET6_ADDRSTRLEN], dst6[INET6_ADDRSTRLEN];
+
+       if (ip6_hbhchcheck(m, &off, &nxt, &ours))
+               return;
+
+       if (ours) {
+               KERNEL_LOCK();
+               ip6_local(m, off, nxt);
+               KERNEL_UNLOCK();
+               return;
+       }
 
        /*
         * Do not forward packets to multicast destination (should be handled
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.179
diff -u -p -r1.179 ip6_input.c
--- netinet6/ip6_input.c        8 Feb 2017 12:37:43 -0000       1.179
+++ netinet6/ip6_input.c        22 Feb 2017 15:55:40 -0000
@@ -119,8 +119,8 @@ struct niqueue ip6intrq = NIQUEUE_INITIA
 
 struct cpumem *ip6counters;
 
+void ip6_ours(struct mbuf *);
 int ip6_check_rh0hdr(struct mbuf *, int *);
-int ip6_hbhchcheck(struct mbuf *, int *, int *, int *);
 int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
 struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
 
@@ -180,12 +180,11 @@ ip6_input(struct mbuf *m)
        struct ip6_hdr *ip6;
        struct sockaddr_in6 sin6;
        struct rtentry *rt = NULL;
-       int off, nxt, ours = 0;
        u_int16_t src_scope, dst_scope;
 #if NPF > 0
        struct in6_addr odst;
 #endif
-       int srcrt = 0;
+       int off, srcrt = 0;
 
        ifp = if_get(m->m_pkthdr.ph_ifidx);
        if (ifp == NULL)
@@ -339,14 +338,14 @@ ip6_input(struct mbuf *m)
 
        if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
            IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
-               ours = 1;
-               goto hbhcheck;
+               ip6_ours(m);
+               goto out;
        }
 
 #if NPF > 0
        if (pf_ouraddr(m) == 1) {
-               ours = 1;
-               goto hbhcheck;
+               ip6_ours(m);
+               goto out;
        }
 #endif
 
@@ -354,6 +353,8 @@ ip6_input(struct mbuf *m)
         * Multicast check
         */
        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
+               int nxt, ours = 0;
+
                /*
                 * Make sure M_MCAST is set.  It should theoretically
                 * already be there, but let's play safe because upper
@@ -370,6 +371,8 @@ ip6_input(struct mbuf *m)
 
 #ifdef MROUTING
                if (ip6_mforwarding && ip6_mrouter) {
+                       int rv;
+
                        if (ip6_hbhchcheck(m, &off, &nxt, &ours))
                                goto out;
 
@@ -383,14 +386,17 @@ ip6_input(struct mbuf *m)
                         * ip6_mforward() returns a non-zero value, the packet
                         * must be discarded, else it may be accepted below.
                         */
-                       if (ip6_mforward(ip6, ifp, m)) {
+                       KERNEL_LOCK();
+                       rv = ip6_mforward(ip6, ifp, m);
+                       if (rv != 0) {
                                ip6stat_inc(ip6s_cantforward);
-                               goto bad;
+                               m_freem(m);
+                       } else if (ours) {
+                               ip6_local(m, off, nxt);
+                       } else {
+                               m_freem(m);
                        }
-
-                       if (!ours)
-                               goto bad;
-                       ip6_ours(m, off, nxt);
+                       KERNEL_UNLOCK();
                        goto out;
                }
 #endif
@@ -400,7 +406,8 @@ ip6_input(struct mbuf *m)
                                ip6stat_inc(ip6s_cantforward);
                        goto bad;
                }
-               goto hbhcheck;
+               ip6_ours(m);
+               goto out;
        }
 
 
@@ -438,9 +445,8 @@ ip6_input(struct mbuf *m)
 
                        goto bad;
                } else {
-                       /* this address is ready */
-                       ours = 1;
-                       goto hbhcheck;
+                       ip6_ours(m);
+                       goto out;
                }
        }
 
@@ -459,19 +465,6 @@ ip6_input(struct mbuf *m)
                goto bad;
        }
 
-  hbhcheck:
-
-       if (ip6_hbhchcheck(m, &off, &nxt, &ours))
-               goto out;
-
-       if (ours) {
-               ip6_ours(m, off, nxt);
-               goto out;
-       }
-
-       /*
-        * Forward if desirable.
-        */
        ip6_forward(m, rt, srcrt);
        if_put(ifp);
        return;
@@ -483,7 +476,20 @@ ip6_input(struct mbuf *m)
 }
 
 void
-ip6_ours(struct mbuf *m, int off, int nxt)
+ip6_ours(struct mbuf *m)
+{
+       int off, nxt;
+
+       KERNEL_ASSERT_LOCKED();
+
+       if (ip6_hbhchcheck(m, &off, &nxt, NULL))
+               return;
+
+       ip6_local(m, off, nxt);
+}
+
+void
+ip6_local(struct mbuf *m, int off, int nxt)
 {
        int nest = 0;
 
@@ -582,7 +588,7 @@ ip6_hbhchcheck(struct mbuf *m, int *offp
                 * accept the packet if a router alert option is included
                 * and we act as an IPv6 router.
                 */
-               if (rtalert != ~0 && ip6_forwarding)
+               if (rtalert != ~0 && ip6_forwarding && oursp != NULL)
                        *oursp = 1;
        } else
                *nxtp = ip6->ip6_nxt;
Index: netinet6/ip6_var.h
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.68
diff -u -p -r1.68 ip6_var.h
--- netinet6/ip6_var.h  8 Feb 2017 12:37:43 -0000       1.68
+++ netinet6/ip6_var.h  22 Feb 2017 15:54:54 -0000
@@ -304,7 +304,8 @@ int icmp6_ctloutput(int, struct socket *
 void   ip6_init(void);
 void   ip6intr(void);
 void   ip6_input(struct mbuf *);
-void   ip6_ours(struct mbuf *, int, int);
+void   ip6_local(struct mbuf *, int, int);
+int    ip6_hbhchcheck(struct mbuf *, int *, int *, int *);
 void   ip6_freepcbopts(struct ip6_pktopts *);
 void   ip6_freemoptions(struct ip6_moptions *);
 int    ip6_unknown_opt(u_int8_t *, struct mbuf *, int);

Reply via email to