summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2024-04-16 12:40:41 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2024-04-16 12:40:41 +0000
commit989891d6ea337764b983eb195f21039b0e3ae440 (patch)
tree13a2ddcabfae2308696e93ee5b17ccb18bd01524
parentbf10c52847ea519e51b68a84d67f6070bfec05ac (diff)
Run raw IPv6 input in parallel.
Get rip6_input() in the same shape as rip_input(). Call soisdisconnected() from rip6_disconnect(). This means that the raw IP socket cannot be reconnected later. Now raw IPv6 behaves like IPv4 in this regard, KAME code is quite inconsistent here. Also make sure that there is no race between disconnect, input and wakeup. The inpcb fileds inp_icmp6filt and inp_cksum6 are protected by exclusive net lock in icmp6_ctloutput(). With all that, mark raw IPv6 sockets to handle input in parallel. OK mvs@
-rw-r--r--sys/netinet6/in6_proto.c6
-rw-r--r--sys/netinet6/raw_ip6.c26
2 files changed, 20 insertions, 12 deletions
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index db218af06c4..f73e00b4d2c 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_proto.c,v 1.113 2024/01/11 14:15:12 bluhm Exp $ */
+/* $OpenBSD: in6_proto.c,v 1.114 2024/04/16 12:40:40 bluhm Exp $ */
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
/*
@@ -158,7 +158,7 @@ const struct protosw inet6sw[] = {
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_RAW,
- .pr_flags = PR_ATOMIC|PR_ADDR,
+ .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPINPUT,
.pr_input = rip6_input,
.pr_ctlinput = rip6_ctlinput,
.pr_ctloutput = rip6_ctloutput,
@@ -322,7 +322,7 @@ const struct protosw inet6sw[] = {
/* raw wildcard */
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
- .pr_flags = PR_ATOMIC|PR_ADDR,
+ .pr_flags = PR_ATOMIC|PR_ADDR|PR_MPINPUT,
.pr_input = rip6_input,
.pr_ctloutput = rip6_ctloutput,
.pr_usrreqs = &rip6_usrreqs,
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index 177eeb8e88b..5804af2624f 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip6.c,v 1.182 2024/02/13 12:22:09 bluhm Exp $ */
+/* $OpenBSD: raw_ip6.c,v 1.183 2024/04/16 12:40:40 bluhm Exp $ */
/* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */
/*
@@ -155,9 +155,9 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
} else
rip6stat_inc(rip6s_ipackets);
- bzero(&rip6src, sizeof(rip6src));
- rip6src.sin6_len = sizeof(struct sockaddr_in6);
+ memset(&rip6src, 0, sizeof(rip6src));
rip6src.sin6_family = AF_INET6;
+ rip6src.sin6_len = sizeof(rip6src);
/* KAME hack: recover scopeid */
in6_recoverscope(&rip6src, &ip6->ip6_src);
@@ -186,7 +186,13 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
TAILQ_FOREACH(inp, &rawin6pcbtable.inpt_queue, inp_queue) {
KASSERT(ISSET(inp->inp_flags, INP_IPV6));
- if (inp->inp_socket->so_rcv.sb_state & SS_CANTRCVMORE)
+ /*
+ * Packet must not be inserted after disconnected wakeup
+ * call. To avoid race, check again when holding receive
+ * buffer mutex.
+ */
+ if (ISSET(READ_ONCE(inp->inp_socket->so_rcv.sb_state),
+ SS_CANTRCVMORE))
continue;
if (rtable_l2(inp->inp_rtableid) !=
rtable_l2(m->m_pkthdr.ph_rtableid))
@@ -264,7 +270,7 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
if (n != NULL) {
struct socket *so = inp->inp_socket;
- int ret;
+ int ret = 0;
if (inp->inp_flags & IN6P_CONTROLOPTS)
ip6_savecontrol(inp, n, &opts);
@@ -272,12 +278,14 @@ rip6_input(struct mbuf **mp, int *offp, int proto, int af)
m_adj(n, *offp);
mtx_enter(&so->so_rcv.sb_mtx);
- ret = sbappendaddr(so, &so->so_rcv,
- sin6tosa(&rip6src), n, opts);
+ if (!ISSET(inp->inp_socket->so_rcv.sb_state,
+ SS_CANTRCVMORE)) {
+ ret = sbappendaddr(so, &so->so_rcv,
+ sin6tosa(&rip6src), n, opts);
+ }
mtx_leave(&so->so_rcv.sb_mtx);
if (ret == 0) {
- /* should notify about lost packet */
m_freem(n);
m_freem(opts);
rip6stat_inc(rip6s_fullsock);
@@ -727,7 +735,7 @@ rip6_disconnect(struct socket *so)
if ((so->so_state & SS_ISCONNECTED) == 0)
return (ENOTCONN);
- so->so_state &= ~SS_ISCONNECTED; /* XXX */
+ soisdisconnected(so);
mtx_enter(&rawin6pcbtable.inpt_mtx);
inp->inp_faddr6 = in6addr_any;
mtx_leave(&rawin6pcbtable.inpt_mtx);