Hi,

This diff allows to run udp_input() in parallel.  It consists of
three major parts.

- Use PR_MPSAFE flag to protocol deliver loop with shared
  netlock.  Queue packet and switch to deliver loop with exclusive
  netlock, of a protocol is not MP safe.

- Use a rwlock to protect the inp_notify field.  As ip_output()
  may be called in in_pcbnotifyall() and may sleep in pflock, we
  need a sleeping lock.

- Use a mutex at the inpcb to protect the recv socket buffer.

Before commiting I will split the diff in parts.  Just showing what
I have now.

bluhm

Index: net/if_bridge.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.364
diff -u -p -r1.364 if_bridge.c
--- net/if_bridge.c     7 Aug 2022 00:57:43 -0000       1.364
+++ net/if_bridge.c     15 Aug 2022 21:14:52 -0000
@@ -1590,7 +1590,7 @@ bridge_ipsec(struct ifnet *ifp, struct e
                            off);
                        tdb_unref(tdb);
                        if (prot != IPPROTO_DONE)
-                               ip_deliver(&m, &hlen, prot, af);
+                               ip_deliver(&m, &hlen, prot, af, 0);
                        return (1);
                } else {
                        tdb_unref(tdb);
Index: netinet/in_pcb.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.270
diff -u -p -r1.270 in_pcb.c
--- netinet/in_pcb.c    8 Aug 2022 12:06:30 -0000       1.270
+++ netinet/in_pcb.c    15 Aug 2022 16:29:49 -0000
@@ -236,6 +236,7 @@ in_pcballoc(struct socket *so, struct in
        inp->inp_table = table;
        inp->inp_socket = so;
        refcnt_init_trace(&inp->inp_refcnt, DT_REFCNT_IDX_INPCB);
+       mtx_init(&inp->inp_mtx, IPL_SOFTNET);
        inp->inp_seclevel[SL_AUTH] = IPSEC_AUTH_LEVEL_DEFAULT;
        inp->inp_seclevel[SL_ESP_TRANS] = IPSEC_ESP_TRANS_LEVEL_DEFAULT;
        inp->inp_seclevel[SL_ESP_NETWORK] = IPSEC_ESP_NETWORK_LEVEL_DEFAULT;
@@ -695,8 +696,6 @@ in_pcbnotifyall(struct inpcbtable *table
        struct in_addr faddr;
        u_int rdomain;
 
-       NET_ASSERT_LOCKED_EXCLUSIVE();
-
        if (dst->sa_family != AF_INET)
                return;
        faddr = satosin(dst)->sin_addr;
@@ -707,6 +706,7 @@ in_pcbnotifyall(struct inpcbtable *table
 
        SIMPLEQ_INIT(&inpcblist);
        rdomain = rtable_l2(rtable);
+       rw_enter_write(&table->inpt_notify);
        mtx_enter(&table->inpt_mtx);
        TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
 #ifdef INET6
@@ -728,6 +728,7 @@ in_pcbnotifyall(struct inpcbtable *table
                (*notify)(inp, errno);
                in_pcbunref(inp);
        }
+       rw_exit_write(&table->inpt_notify);
 }
 
 /*
Index: netinet/in_pcb.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_pcb.h,v
retrieving revision 1.129
diff -u -p -r1.129 in_pcb.h
--- netinet/in_pcb.h    15 May 2022 09:12:20 -0000      1.129
+++ netinet/in_pcb.h    15 Aug 2022 16:29:49 -0000
@@ -66,6 +66,7 @@
 
 #include <sys/queue.h>
 #include <sys/mutex.h>
+#include <sys/rwlock.h>
 #include <sys/refcnt.h>
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
@@ -79,6 +80,8 @@
  *     I       immutable after creation
  *     N       net lock
  *     t       inpt_mtx                pcb table mutex
+ *     y       inpt_notify             pcb table rwlock for notify
+ *     p       inpcb_mtx               pcb mutex
  */
 
 struct pf_state_key;
@@ -102,7 +105,7 @@ struct inpcb {
        LIST_ENTRY(inpcb) inp_hash;             /* [t] local and foreign hash */
        LIST_ENTRY(inpcb) inp_lhash;            /* [t] local port hash */
        TAILQ_ENTRY(inpcb) inp_queue;           /* [t] inet PCB queue */
-       SIMPLEQ_ENTRY(inpcb) inp_notify;        /* [N] notify or udp append */
+       SIMPLEQ_ENTRY(inpcb) inp_notify;        /* [y] notify or udp append */
        struct    inpcbtable *inp_table;        /* [I] inet queue/hash table */
        union     inpaddru inp_faddru;          /* Foreign address. */
        union     inpaddru inp_laddru;          /* Local address. */
@@ -121,6 +124,7 @@ struct inpcb {
 #define        inp_route       inp_ru.ru_route
 #define        inp_route6      inp_ru.ru_route6
        struct    refcnt inp_refcnt;    /* refcount PCB, delay memory free */
+       struct    mutex inp_mtx;        /* protect PCB and socket members */
        int       inp_flags;            /* generic IP/datagram flags */
        union {                         /* Header prototype. */
                struct ip hu_ip;
@@ -164,6 +168,7 @@ LIST_HEAD(inpcbhead, inpcb);
 
 struct inpcbtable {
        struct mutex inpt_mtx;                  /* protect queue and hash */
+       struct rwlock inpt_notify;              /* protect inp_notify list */
        TAILQ_HEAD(inpthead, inpcb) inpt_queue; /* [t] inet PCB queue */
        struct  inpcbhead *inpt_hashtbl;        /* [t] local and foreign hash */
        struct  inpcbhead *inpt_lhashtbl;       /* [t] local port hash */
Index: netinet/in_proto.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in_proto.c,v
retrieving revision 1.99
diff -u -p -r1.99 in_proto.c
--- netinet/in_proto.c  15 Aug 2022 09:11:38 -0000      1.99
+++ netinet/in_proto.c  15 Aug 2022 21:15:24 -0000
@@ -185,7 +185,7 @@ const struct protosw inetsw[] = {
   .pr_type     = SOCK_DGRAM,
   .pr_domain   = &inetdomain,
   .pr_protocol = IPPROTO_UDP,
-  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_SPLICE,
+  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPSAFE,
   .pr_input    = udp_input,
   .pr_ctlinput = udp_ctlinput,
   .pr_ctloutput        = ip_ctloutput,
Index: netinet/ip_divert.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_divert.c,v
retrieving revision 1.69
diff -u -p -r1.69 ip_divert.c
--- netinet/ip_divert.c 15 Aug 2022 09:11:39 -0000      1.69
+++ netinet/ip_divert.c 15 Aug 2022 16:29:49 -0000
@@ -227,22 +227,15 @@ divert_packet(struct mbuf *m, int dir, u
                if_put(ifp);
        }
 
+       mtx_enter(&inp->inp_mtx);
        so = inp->inp_socket;
-       /*
-        * XXXSMP sbappendaddr() is not MP safe and this function is called
-        * from pf with shared netlock.  To call only one sbappendaddr() from
-        * divert_packet(), protect it with kernel lock.  All other places
-        * call sbappendaddr() with exclusive net lock.  This blocks
-        * divert_packet() as we have the shared lock.
-        */
-       KERNEL_LOCK();
        if (sbappendaddr(so, &so->so_rcv, sintosa(&sin), m, NULL) == 0) {
-               KERNEL_UNLOCK();
+               mtx_leave(&inp->inp_mtx);
                divstat_inc(divs_fullsock);
                goto bad;
        }
-       sorwakeup(inp->inp_socket);
-       KERNEL_UNLOCK();
+       mtx_leave(&inp->inp_mtx);
+       sorwakeup(so);
 
        in_pcbunref(inp);
        return;
Index: netinet/ip_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.379
diff -u -p -r1.379 ip_input.c
--- netinet/ip_input.c  15 Aug 2022 16:15:36 -0000      1.379
+++ netinet/ip_input.c  16 Aug 2022 11:55:58 -0000
@@ -138,7 +138,7 @@ static struct mbuf_queue    ipsendraw_mq;
 extern struct niqueue          arpinq;
 
 int    ip_ours(struct mbuf **, int *, int, int);
-int    ip_local(struct mbuf **, int *, int, int);
+int    ip_local(struct mbuf **, int *, int);
 int    ip_dooptions(struct mbuf *, struct ifnet *);
 int    in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **);
 
@@ -231,6 +231,11 @@ ip_init(void)
 #endif
 }
 
+struct ip_offnxt {
+       int     ion_off;
+       int     ion_nxt;
+};
+
 /*
  * Enqueue packet for local delivery.  Queuing is used as a boundary
  * between the network layer (input/forward path) running with
@@ -245,7 +250,31 @@ ip_ours(struct mbuf **mp, int *offp, int
 
        /* We are already in a IPv4/IPv6 local deliver loop. */
        if (af != AF_UNSPEC)
-               return ip_local(mp, offp, nxt, af);
+               return nxt;
+
+       nxt = ip_deliver(mp, offp, nxt, AF_INET, 1);
+       if (nxt == IPPROTO_DONE)
+               return IPPROTO_DONE;
+
+        /* save values for later, use after dequeue */
+       if (*offp != sizeof(struct ip)) {
+               struct m_tag *mtag;
+               struct ip_offnxt *ion;
+
+               /* mbuf tags are expensive, but only used for header options */
+               mtag = m_tag_get(PACKET_TAG_IP_OFFNXT, sizeof(*ion),
+                   M_NOWAIT);
+               if (mtag == NULL) {
+                       ipstat_inc(ips_idropped);
+                       m_freemp(mp);
+                       return IPPROTO_DONE;
+               }
+               ion = (struct ip_offnxt *)(mtag + 1);
+               ion->ion_off = *offp;
+               ion->ion_nxt = nxt;
+
+               m_tag_prepend(*mp, mtag);
+       }
 
        niq_enqueue(&ipintrq, *mp);
        *mp = NULL;
@@ -268,7 +297,7 @@ ipintr(void)
                        panic("ipintr no HDR");
 #endif
                off = 0;
-               nxt = ip_local(&m, &off, IPPROTO_IPV4, AF_UNSPEC);
+               nxt = ip_local(&m, &off, IPPROTO_IPV4);
                KASSERT(nxt == IPPROTO_DONE);
        }
 }
@@ -558,20 +587,30 @@ ip_input_if(struct mbuf **mp, int *offp,
  * If fragmented try to reassemble.  Pass to next level.
  */
 int
-ip_local(struct mbuf **mp, int *offp, int nxt, int af)
+ip_local(struct mbuf **mp, int *offp, int nxt)
 {
        if (*offp == 0) {
-               struct ip *ip;
+               struct m_tag *mtag;
+
+               mtag = m_tag_find(*mp, PACKET_TAG_IP_OFFNXT, NULL);
+               if (mtag != NULL) {
+                       struct ip_offnxt *ion;
 
-               ip = mtod(*mp, struct ip *);
-               *offp = ip->ip_hl << 2;
-               nxt = ip->ip_p;
+                       ion = (struct ip_offnxt *)(mtag + 1);
+                       *offp = ion->ion_off;
+                       nxt = ion->ion_nxt;
+
+                       m_tag_delete(*mp, mtag);
+               } else {
+                       struct ip *ip;
+
+                       ip = mtod(*mp, struct ip *);
+                       *offp = ip->ip_hl << 2;
+                       nxt = ip->ip_p;
+               }
        }
 
-       /* Check whether we are already in a IPv4/IPv6 local deliver loop. */
-       if (af == AF_UNSPEC)
-               nxt = ip_deliver(mp, offp, nxt, AF_INET);
-       return nxt;
+       return ip_deliver(mp, offp, nxt, AF_INET, 0);
 }
 
 int
@@ -691,7 +730,7 @@ ip_fragcheck(struct mbuf **mp, int *offp
 #endif
 
 int
-ip_deliver(struct mbuf **mp, int *offp, int nxt, int af)
+ip_deliver(struct mbuf **mp, int *offp, int nxt, int af, int shared)
 {
        const struct protosw *psw;
        int naf = af;
@@ -699,26 +738,24 @@ ip_deliver(struct mbuf **mp, int *offp, 
        int nest = 0;
 #endif /* INET6 */
 
-       NET_ASSERT_LOCKED_EXCLUSIVE();
-
-       /* pf might have modified stuff, might have to chksum */
-       switch (af) {
-       case AF_INET:
-               in_proto_cksum_out(*mp, NULL);
-               break;
-#ifdef INET6
-       case AF_INET6:
-               in6_proto_cksum_out(*mp, NULL);
-               break;
-#endif /* INET6 */
-       }
-
        /*
         * Tell launch routine the next header
         */
        IPSTAT_INC(delivered);
 
        while (nxt != IPPROTO_DONE) {
+               switch (af) {
+               case AF_INET:
+                       psw = &inetsw[ip_protox[nxt]];
+                       break;
+#ifdef INET6
+               case AF_INET6:
+                       psw = &inet6sw[ip6_protox[nxt]];
+                       break;
+#endif /* INET6 */
+               }
+               if (shared && !ISSET(psw->pr_flags, PR_MPSAFE))
+                       break;
 #ifdef INET6
                if (af == AF_INET6 &&
                    ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
@@ -755,16 +792,6 @@ ip_deliver(struct mbuf **mp, int *offp, 
                case IPPROTO_IPV6:
                        naf = AF_INET6;
                        ip6stat_inc(ip6s_delivered);
-                       break;
-#endif /* INET6 */
-               }
-               switch (af) {
-               case AF_INET:
-                       psw = &inetsw[ip_protox[nxt]];
-                       break;
-#ifdef INET6
-               case AF_INET6:
-                       psw = &inet6sw[ip6_protox[nxt]];
                        break;
 #endif /* INET6 */
                }
Index: netinet/ip_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_var.h,v
retrieving revision 1.97
diff -u -p -r1.97 ip_var.h
--- netinet/ip_var.h    15 Aug 2022 09:11:39 -0000      1.97
+++ netinet/ip_var.h    15 Aug 2022 21:11:33 -0000
@@ -249,7 +249,7 @@ int  ip_sysctl(int *, u_int, void *, siz
 void    ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
            struct mbuf *);
 int     ip_input_if(struct mbuf **, int *, int, int, struct ifnet *);
-int     ip_deliver(struct mbuf **, int *, int, int);
+int     ip_deliver(struct mbuf **, int *, int, int, int);
 void    ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int);
 int     rip_ctloutput(int, struct socket *, int, int, struct mbuf *);
 void    rip_init(void);
Index: netinet/raw_ip.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.130
diff -u -p -r1.130 raw_ip.c
--- netinet/raw_ip.c    15 Aug 2022 09:11:39 -0000      1.130
+++ netinet/raw_ip.c    15 Aug 2022 16:29:49 -0000
@@ -158,8 +158,8 @@ rip_input(struct mbuf **mp, int *offp, i
                }
        }
 #endif
-       NET_ASSERT_LOCKED_EXCLUSIVE();
        SIMPLEQ_INIT(&inpcblist);
+       rw_enter_write(&rawcbtable.inpt_notify);
        mtx_enter(&rawcbtable.inpt_mtx);
        TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
                if (inp->inp_socket->so_state & SS_CANTRCVMORE)
@@ -187,6 +187,8 @@ rip_input(struct mbuf **mp, int *offp, i
        mtx_leave(&rawcbtable.inpt_mtx);
 
        if (SIMPLEQ_EMPTY(&inpcblist)) {
+               rw_exit_write(&rawcbtable.inpt_notify);
+
                if (ip->ip_p != IPPROTO_ICMP)
                        icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
                            0, 0);
@@ -197,6 +199,8 @@ rip_input(struct mbuf **mp, int *offp, i
                counters[ips_noproto]++;
                counters[ips_delivered]--;
                counters_leave(&ref, ipcounters);
+
+               return IPPROTO_DONE;
        }
 
        while ((inp = SIMPLEQ_FIRST(&inpcblist)) != NULL) {
@@ -222,6 +226,8 @@ rip_input(struct mbuf **mp, int *offp, i
                }
                in_pcbunref(inp);
        }
+       rw_exit_write(&rawcbtable.inpt_notify);
+
        return IPPROTO_DONE;
 }
 
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.282
diff -u -p -r1.282 udp_usrreq.c
--- netinet/udp_usrreq.c        15 Aug 2022 09:11:39 -0000      1.282
+++ netinet/udp_usrreq.c        15 Aug 2022 16:29:49 -0000
@@ -370,8 +370,8 @@ udp_input(struct mbuf **mp, int *offp, i
                 * Locate pcb(s) for datagram.
                 * (Algorithm copied from raw_intr().)
                 */
-               NET_ASSERT_LOCKED_EXCLUSIVE();
                SIMPLEQ_INIT(&inpcblist);
+               rw_enter_write(&udbtable.inpt_notify);
                mtx_enter(&udbtable.inpt_mtx);
                TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {
                        if (inp->inp_socket->so_state & SS_CANTRCVMORE)
@@ -444,6 +444,7 @@ udp_input(struct mbuf **mp, int *offp, i
                mtx_leave(&udbtable.inpt_mtx);
 
                if (SIMPLEQ_EMPTY(&inpcblist)) {
+                       rw_exit_write(&udbtable.inpt_notify);
                        /*
                         * No matching pcb found; discard datagram.
                         * (No need to send an ICMP Port Unreachable
@@ -467,6 +468,8 @@ udp_input(struct mbuf **mp, int *offp, i
                        }
                        in_pcbunref(inp);
                }
+               rw_exit_write(&udbtable.inpt_notify);
+
                return IPPROTO_DONE;
        }
        /*
@@ -647,12 +650,17 @@ udp_sbappend(struct inpcb *inp, struct m
        }
 #endif
        m_adj(m, hlen);
+
+       mtx_enter(&inp->inp_mtx);
        if (sbappendaddr(so, &so->so_rcv, srcaddr, m, opts) == 0) {
+               mtx_leave(&inp->inp_mtx);
                udpstat_inc(udps_fullsock);
                m_freem(m);
                m_freem(opts);
                return;
        }
+       mtx_leave(&inp->inp_mtx);
+
        sorwakeup(so);
 }
 
Index: netinet6/in6_pcb.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.119
diff -u -p -r1.119 in6_pcb.c
--- netinet6/in6_pcb.c  8 Aug 2022 12:06:31 -0000       1.119
+++ netinet6/in6_pcb.c  15 Aug 2022 16:29:49 -0000
@@ -387,8 +387,6 @@ in6_pcbnotify(struct inpcbtable *table, 
        u_int32_t flowinfo;
        u_int rdomain;
 
-       NET_ASSERT_LOCKED_EXCLUSIVE();
-
        if ((unsigned)cmd >= PRC_NCMDS)
                return;
 
@@ -430,6 +428,7 @@ in6_pcbnotify(struct inpcbtable *table, 
 
        SIMPLEQ_INIT(&inpcblist);
        rdomain = rtable_l2(rtable);
+       rw_enter_write(&table->inpt_notify);
        mtx_enter(&table->inpt_mtx);
        TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
                if ((inp->inp_flags & INP_IPV6) == 0)
@@ -513,6 +512,7 @@ in6_pcbnotify(struct inpcbtable *table, 
                (*notify)(inp, errno);
                in_pcbunref(inp);
        }
+       rw_exit_write(&table->inpt_notify);
 }
 
 struct inpcb *
Index: netinet6/in6_proto.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.110
diff -u -p -r1.110 in6_proto.c
--- netinet6/in6_proto.c        15 Aug 2022 09:11:39 -0000      1.110
+++ netinet6/in6_proto.c        15 Aug 2022 21:15:44 -0000
@@ -136,7 +136,7 @@ const struct protosw inet6sw[] = {
   .pr_type     = SOCK_DGRAM,
   .pr_domain   = &inet6domain,
   .pr_protocol = IPPROTO_UDP,
-  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_SPLICE,
+  .pr_flags    = PR_ATOMIC|PR_ADDR|PR_SPLICE|PR_MPSAFE,
   .pr_input    = udp_input,
   .pr_ctlinput = udp6_ctlinput,
   .pr_ctloutput        = ip6_ctloutput,
Index: netinet6/ip6_input.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.253
diff -u -p -r1.253 ip6_input.c
--- netinet6/ip6_input.c        15 Aug 2022 16:15:37 -0000      1.253
+++ netinet6/ip6_input.c        15 Aug 2022 21:11:17 -0000
@@ -120,7 +120,7 @@ struct cpumem *ip6counters;
 uint8_t ip6_soiikey[IP6_SOIIKEY_LEN];
 
 int ip6_ours(struct mbuf **, int *, int, int);
-int ip6_local(struct mbuf **, int *, int, int);
+int ip6_local(struct mbuf **, int *, int);
 int ip6_check_rh0hdr(struct mbuf *, int *);
 int ip6_hbhchcheck(struct mbuf **, int *, int *);
 int ip6_hopopts_input(struct mbuf **, int *, u_int32_t *, u_int32_t *);
@@ -189,7 +189,11 @@ ip6_ours(struct mbuf **mp, int *offp, in
 
        /* We are already in a IPv4/IPv6 local deliver loop. */
        if (af != AF_UNSPEC)
-               return ip6_local(mp, offp, nxt, af);
+               return nxt;
+
+       nxt = ip_deliver(mp, offp, nxt, AF_INET6, 1);
+       if (nxt == IPPROTO_DONE)
+               return IPPROTO_DONE;
 
        /* save values for later, use after dequeue */
        if (*offp != sizeof(struct ip6_hdr)) {
@@ -232,7 +236,7 @@ ip6intr(void)
                        panic("ip6intr no HDR");
 #endif
                off = 0;
-               nxt = ip6_local(&m, &off, IPPROTO_IPV6, AF_UNSPEC);
+               nxt = ip6_local(&m, &off, IPPROTO_IPV6);
                KASSERT(nxt == IPPROTO_DONE);
        }
 }
@@ -614,7 +618,7 @@ ip6_input_if(struct mbuf **mp, int *offp
 }
 
 int
-ip6_local(struct mbuf **mp, int *offp, int nxt, int af)
+ip6_local(struct mbuf **mp, int *offp, int nxt)
 {
        if (*offp == 0) {
                struct m_tag *mtag;
@@ -638,10 +642,7 @@ ip6_local(struct mbuf **mp, int *offp, i
                }
        }
 
-       /* Check whether we are already in a IPv4/IPv6 local deliver loop. */
-       if (af == AF_UNSPEC)
-               nxt = ip_deliver(mp, offp, nxt, AF_INET6);
-       return nxt;
+       return ip_deliver(mp, offp, nxt, AF_INET6, 0);
 }
 
 /* On error free mbuf and return IPPROTO_DONE. */
Index: netinet6/raw_ip6.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.150
diff -u -p -r1.150 raw_ip6.c
--- netinet6/raw_ip6.c  15 Aug 2022 09:11:39 -0000      1.150
+++ netinet6/raw_ip6.c  15 Aug 2022 16:29:49 -0000
@@ -170,8 +170,8 @@ rip6_input(struct mbuf **mp, int *offp, 
                }
        }
 #endif
-       NET_ASSERT_LOCKED_EXCLUSIVE();
        SIMPLEQ_INIT(&inpcblist);
+       rw_enter_write(&rawin6pcbtable.inpt_notify);
        mtx_enter(&rawin6pcbtable.inpt_mtx);
        TAILQ_FOREACH(in6p, &rawin6pcbtable.inpt_queue, inp_queue) {
                if (in6p->inp_socket->so_state & SS_CANTRCVMORE)
@@ -222,6 +222,8 @@ rip6_input(struct mbuf **mp, int *offp, 
                struct counters_ref ref;
                uint64_t *counters;
 
+               rw_exit_write(&rawin6pcbtable.inpt_notify);
+
                if (proto != IPPROTO_ICMPV6) {
                        rip6stat_inc(rip6s_nosock);
                        if (m->m_flags & M_MCAST)
@@ -238,6 +240,8 @@ rip6_input(struct mbuf **mp, int *offp, 
                counters = counters_enter(&ref, ip6counters);
                counters[ip6s_delivered]--;
                counters_leave(&ref, ip6counters);
+
+               return IPPROTO_DONE;
        }
 
        while ((in6p = SIMPLEQ_FIRST(&inpcblist)) != NULL) {
@@ -265,6 +269,8 @@ rip6_input(struct mbuf **mp, int *offp, 
                }
                in_pcbunref(in6p);
        }
+       rw_exit_write(&rawin6pcbtable.inpt_notify);
+
        return IPPROTO_DONE;
 }
 
Index: sys/mbuf.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.255
diff -u -p -r1.255 mbuf.h
--- sys/mbuf.h  15 Aug 2022 16:15:37 -0000      1.255
+++ sys/mbuf.h  15 Aug 2022 21:19:01 -0000
@@ -471,6 +471,8 @@ struct m_tag *m_tag_next(struct mbuf *, 
 #define PACKET_TAG_IPSEC_IN_DONE       0x0001  /* IPsec applied, in */
 #define PACKET_TAG_IPSEC_OUT_DONE      0x0002  /* IPsec applied, out */
 #define PACKET_TAG_IPSEC_FLOWINFO      0x0004  /* IPsec flowinfo */
+#define PACKET_TAG_IP_OFFNXT           0x0010  /* IPv4 offset and next proto */
+#define PACKET_TAG_IP6_OFFNXT          0x0020  /* IPv6 offset and next proto */
 #define PACKET_TAG_WIREGUARD           0x0040  /* WireGuard data */
 #define PACKET_TAG_GRE                 0x0080  /* GRE processing done */
 #define PACKET_TAG_DLT                 0x0100 /* data link layer type */
@@ -479,7 +481,6 @@ struct m_tag *m_tag_next(struct mbuf *, 
 #define PACKET_TAG_SRCROUTE            0x1000 /* IPv4 source routing options */
 #define PACKET_TAG_TUNNEL              0x2000  /* Tunnel endpoint address */
 #define PACKET_TAG_CARP_BAL_IP         0x4000  /* carp(4) ip balanced marker */
-#define PACKET_TAG_IP6_OFFNXT          0x8000  /* IPv6 offset and next proto */
 
 #define MTAG_BITS \
     ("\20\1IPSEC_IN_DONE\2IPSEC_OUT_DONE\3IPSEC_FLOWINFO" \
Index: sys/protosw.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/protosw.h,v
retrieving revision 1.37
diff -u -p -r1.37 protosw.h
--- sys/protosw.h       15 Aug 2022 09:11:39 -0000      1.37
+++ sys/protosw.h       15 Aug 2022 21:16:51 -0000
@@ -112,6 +112,7 @@ struct protosw {
 #define        PR_ABRTACPTDIS  0x20            /* abort on accept(2) to 
disconnected
                                           socket */
 #define        PR_SPLICE       0x40            /* socket splicing is possible 
*/
+#define        PR_MPSAFE       0x80            /* input runs with shared 
netlock */
 
 /*
  * The arguments to usrreq are:

Reply via email to