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);