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: