Index: conf/GENERIC =================================================================== RCS file: /cvs/src/sys/conf/GENERIC,v retrieving revision 1.289 diff -u -p -r1.289 GENERIC --- conf/GENERIC 11 Aug 2023 02:35:38 -0000 1.289 +++ conf/GENERIC 29 Aug 2023 12:04:35 -0000 @@ -97,6 +97,7 @@ pseudo-device mpe # MPLS PE interface pseudo-device mpw # MPLS pseudowire support pseudo-device mpip # MPLS IP Layer2 pseudowire support pseudo-device bpe # Provider Backbone Bridge edge interface +pseudo-device rport # rdomain port interface pseudo-device pair # Virtual Ethernet interface pair pseudo-device ppp # PPP pseudo-device pppoe # PPP over Ethernet (RFC 2516) Index: conf/files =================================================================== RCS file: /cvs/src/sys/conf/files,v retrieving revision 1.725 diff -u -p -r1.725 files --- conf/files 7 Aug 2023 01:59:38 -0000 1.725 +++ conf/files 29 Aug 2023 12:04:35 -0000 @@ -560,6 +560,7 @@ pseudo-device msts: tty pseudo-device endrun: tty pseudo-device loop: ifnet +pseudo-device rport: ifnet pseudo-device pair: ifnet, ether pseudo-device ppp: ifnet pseudo-device tun: ifnet @@ -847,6 +848,7 @@ file net/if_mpw.c mpw file net/if_mpip.c mpip file net/if_bpe.c bpe needs-count file net/if_vether.c vether +file net/if_rport.c rport file net/if_pair.c pair file net/if_pppx.c pppx needs-count file net/if_vxlan.c vxlan needs-count Index: dev/usb/if_umb.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_umb.c,v retrieving revision 1.52 diff -u -p -r1.52 if_umb.c --- dev/usb/if_umb.c 26 Aug 2023 11:33:46 -0000 1.52 +++ dev/usb/if_umb.c 29 Aug 2023 12:04:37 -0000 @@ -23,13 +23,16 @@ * Compliance testing guide * https://www.usb.org/sites/default/files/MBIM-Compliance-1.0.pdf */ + #include "bpfilter.h" +#include "kstat.h" #include #include #include #include #include +#include #if NBPFILTER > 0 #include @@ -203,6 +206,17 @@ void umb_decode_qmi(struct umb_softc * void umb_intr(struct usbd_xfer *, void *, usbd_status); +#if NKSTAT > 0 +void umb_kstat_attach(struct umb_softc *); +void umb_kstat_detach(struct umb_softc *); + +struct umb_kstat_signal { + struct kstat_kv rssi; + struct kstat_kv error_rate; + struct kstat_kv reports; +}; +#endif + int umb_xfer_tout = USBD_DEFAULT_TIMEOUT; uint8_t umb_uuid_basic_connect[] = MBIM_UUID_BASIC_CONNECT; @@ -618,6 +632,11 @@ umb_attach(struct device *parent, struct #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif + +#if NKSTAT > 0 + umb_kstat_attach(sc); +#endif + /* * Open the device now so that we are able to query device information. * XXX maybe close when done? @@ -645,6 +664,10 @@ umb_detach(struct device *self, int flag umb_down(sc, 1); umb_close(sc); +#if NKSTAT > 0 + umb_kstat_detach(sc); +#endif + usb_rem_wait_task(sc->sc_udev, &sc->sc_get_response_task); if (timeout_initialized(&sc->sc_statechg_timer)) timeout_del(&sc->sc_statechg_timer); @@ -1670,6 +1693,9 @@ umb_decode_signal_state(struct umb_softc struct mbim_cid_signal_state *ss = data; struct ifnet *ifp = GET_IFP(sc); int rssi; +#if NKSTAT > 0 + struct kstat *ks; +#endif if (len < sizeof (*ss)) return 0; @@ -1686,6 +1712,35 @@ umb_decode_signal_state(struct umb_softc sc->sc_info.ber = letoh32(ss->err_rate); if (sc->sc_info.ber == -99) sc->sc_info.ber = UMB_VALUE_UNKNOWN; + +#if NKSTAT > 0 + ks = sc->sc_kstat_signal; + if (ks != NULL) { + struct umb_kstat_signal *uks = ks->ks_data; + + rw_enter_write(&sc->sc_kstat_lock); + kstat_kv_u64(&uks->reports)++; + + if (sc->sc_info.rssi == UMB_VALUE_UNKNOWN) + uks->rssi.kv_type = KSTAT_KV_T_NULL; + else { + uks->rssi.kv_type = KSTAT_KV_T_INT32; + kstat_kv_s32(&uks->rssi) = sc->sc_info.rssi; + } + + if (sc->sc_info.ber == UMB_VALUE_UNKNOWN) + uks->error_rate.kv_type = KSTAT_KV_T_NULL; + else { + uks->error_rate.kv_type = KSTAT_KV_T_INT32; + kstat_kv_s32(&uks->error_rate) = sc->sc_info.ber; + } + + ks->ks_interval.tv_sec = letoh32(ss->ss_intvl); + getnanouptime(&ks->ks_updated); + rw_exit_write(&sc->sc_kstat_lock); + } +#endif + return 1; } @@ -3146,3 +3201,51 @@ umb_dump(void *buf, int len) addlog("\n"); } #endif /* UMB_DEBUG */ + +#if NKSTAT > 0 + +void +umb_kstat_attach(struct umb_softc *sc) +{ + struct kstat *ks; + struct umb_kstat_signal *uks; + + rw_init(&sc->sc_kstat_lock, "umbkstat"); + + ks = kstat_create(DEVNAM(sc), 0, "mbim-signal", 0, KSTAT_T_KV, 0); + if (ks == NULL) + return; + + uks = malloc(sizeof(*uks), M_DEVBUF, M_WAITOK|M_ZERO); + kstat_kv_init(&uks->rssi, "rssi", KSTAT_KV_T_NULL); + kstat_kv_init(&uks->error_rate, "error rate", KSTAT_KV_T_NULL); + kstat_kv_init(&uks->reports, "reports", KSTAT_KV_T_COUNTER64); + + kstat_set_rlock(ks, &sc->sc_kstat_lock); + ks->ks_data = uks; + ks->ks_datalen = sizeof(*uks); + ks->ks_read = kstat_read_nop; + + ks->ks_softc = sc; + sc->sc_kstat_signal = ks; + kstat_install(ks); +} + +void +umb_kstat_detach(struct umb_softc *sc) +{ + struct kstat *ks = sc->sc_kstat_signal; + struct umb_kstat_signal *uks; + + if (ks == NULL) + return; + + kstat_remove(ks); + sc->sc_kstat_signal = NULL; + + uks = ks->ks_data; + free(uks, M_DEVBUF, sizeof(*uks)); + + kstat_destroy(ks); +} +#endif /* NKSTAT > 0 */ Index: dev/usb/if_umb.h =================================================================== RCS file: /cvs/src/sys/dev/usb/if_umb.h,v retrieving revision 1.10 diff -u -p -r1.10 if_umb.h --- dev/usb/if_umb.h 4 Jul 2021 19:22:32 -0000 1.10 +++ dev/usb/if_umb.h 29 Aug 2023 12:04:37 -0000 @@ -388,5 +388,8 @@ struct umb_softc { #define sc_state sc_info.state #define sc_roaming sc_info.enable_roaming struct umb_info sc_info; + + struct rwlock sc_kstat_lock; + struct kstat *sc_kstat_signal; }; #endif /* _KERNEL */ Index: kern/uipc_mbuf.c =================================================================== RCS file: /cvs/src/sys/kern/uipc_mbuf.c,v retrieving revision 1.287 diff -u -p -r1.287 uipc_mbuf.c --- kern/uipc_mbuf.c 23 Jun 2023 04:36:49 -0000 1.287 +++ kern/uipc_mbuf.c 29 Aug 2023 12:04:37 -0000 @@ -1573,6 +1573,18 @@ ml_enqueue(struct mbuf_list *ml, struct } void +ml_requeue(struct mbuf_list *ml, struct mbuf *m) +{ + m->m_nextpkt = ml->ml_head; + ml->ml_head = m; + + if (ml->ml_tail == NULL) + ml->ml_tail = m; + + ml->ml_len++; +} + +void ml_enlist(struct mbuf_list *mla, struct mbuf_list *mlb) { if (!ml_empty(mlb)) { Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.707 diff -u -p -r1.707 if.c --- net/if.c 18 Aug 2023 08:10:16 -0000 1.707 +++ net/if.c 29 Aug 2023 12:04:38 -0000 @@ -92,6 +92,7 @@ #include #include #include +#include #include #include @@ -247,13 +248,18 @@ int ifq_congestion; int netisr; struct softnet { - char sn_name[16]; - struct taskq *sn_taskq; + char sn_name[16]; + struct taskq *sn_taskq; + + struct mbuf_queue sn_proto_queue; + struct task sn_proto_input; }; #define NET_TASKQ 4 struct softnet softnets[NET_TASKQ]; +static void net_tq_proto_process(void *); + struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL); /* @@ -283,6 +289,9 @@ ifinit(void) TASKQ_MPSAFE); if (sn->sn_taskq == NULL) panic("unable to create network taskq %d", i); + + mq_init(&sn->sn_proto_queue, 1024, IPL_SOFTNET); + task_set(&sn->sn_proto_input, net_tq_proto_process, sn); } } @@ -845,28 +854,10 @@ if_input_local(struct ifnet *ifp, struct ifp->if_ipackets++; ifp->if_ibytes += m->m_pkthdr.len; - switch (af) { - case AF_INET: - if (ISSET(keepcksum, M_IPV4_CSUM_OUT)) - m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; - ipv4_input(ifp, m); - break; -#ifdef INET6 - case AF_INET6: - ipv6_input(ifp, m); - break; -#endif /* INET6 */ -#ifdef MPLS - case AF_MPLS: - mpls_input(ifp, m); - break; -#endif /* MPLS */ - default: - printf("%s: can't handle af%d\n", ifp->if_xname, af); - m_freem(m); - return (EAFNOSUPPORT); - } + if (af == AF_INET && ISSET(keepcksum, M_IPV4_CSUM_OUT)) + m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK; + net_proto_requeue(m, af); return (0); } @@ -961,34 +952,102 @@ if_output_mq(struct ifnet *ifp, struct m return error; } -int -if_output_local(struct ifnet *ifp, struct mbuf *m, sa_family_t af) +struct netstack { + struct mbuf_list *ns_ifinput; + struct mbuf_list ns_proto; + struct mbuf_list ns_junk; +}; + +void +netstack_vinput(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) { - struct ifiqueue *ifiq; - unsigned int flow = 0; +#if NBPFILTER > 0 + caddr_t if_bpf; +#endif - m->m_pkthdr.ph_family = af; m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; - if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) - flow = m->m_pkthdr.ph_flowid; + counters_pkt(ifp->if_counters, + ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); + +#if NPF > 0 + pf_pkt_addr_changed(m); +#endif - ifiq = ifp->if_iqs[flow % ifp->if_niqs]; +#if NBPFILTER > 0 + if_bpf = ifp->if_bpf; + if (if_bpf) { + if ((*ifp->if_bpf_mtap)(if_bpf, m, BPF_DIRECTION_IN)) { + m_freem(m); + return; + } + } +#endif - return (ifiq_enqueue(ifiq, m) == 0 ? 0 : ENOBUFS); + ml_requeue(ns->ns_ifinput, m); } void -if_input_process(struct ifnet *ifp, struct mbuf_list *ml) +netstack_proto_input(struct netstack *ns, struct ifnet *ifp, int af, + struct mbuf *m) { - struct mbuf *m; + switch (af) { + case AF_INET: + m = ipv4_check(ifp, m); + break; +#if INET6 + case AF_INET6: + m = ipv6_check(ifp, m); + break; +#endif /* INET6 */ + } - if (ml_empty(ml)) + if (m == NULL) return; - if (!ISSET(ifp->if_xflags, IFXF_CLONED)) - enqueue_randomness(ml_len(ml) ^ (uintptr_t)MBUF_LIST_FIRST(ml)); + m->m_pkthdr.ph_family = af; + ml_enqueue(&ns->ns_proto, m); +} + +static void +netstack_proto_process(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) +{ + void (*input)(struct ifnet *, struct mbuf *); + + switch (m->m_pkthdr.ph_family) { + case AF_INET: + input = ipv4_input; + break; +#ifdef INET6 + case AF_INET6: + input = ipv6_input; + break; +#endif +#ifdef MPLS + case AF_MPLS: + input = mpls_input; + break; +#endif + default: + ml_enqueue(&ns->ns_junk, m); + return; + } + + (*input)(ifp, m); +} + +void +netstack_mfreem(struct netstack *ns, struct mbuf *m) +{ + ml_enqueue(&ns->ns_junk, m); +} + +static void +netstack_process(struct netstack *ns) +{ + struct ifnet *ifp; + struct mbuf *m; /* * We grab the shared netlock for packet processing in the softnet @@ -997,43 +1056,77 @@ if_input_process(struct ifnet *ifp, stru * read only or MP safe. Usually they hold the exclusive net lock. */ - NET_LOCK_SHARED(); - while ((m = ml_dequeue(ml)) != NULL) - (*ifp->if_input)(ifp, m); - NET_UNLOCK_SHARED(); + do { + while ((m = ml_dequeue(ns->ns_ifinput)) != NULL) { + ifp = if_get(m->m_pkthdr.ph_ifidx); + if (ifp != NULL) + (*ifp->if_input)(ns, ifp, m); + else + ml_enqueue(&ns->ns_junk, m); + if_put(ifp); + } + + m = ml_dequeue(&ns->ns_proto); + if (m == NULL) + break; + + NET_LOCK_SHARED(); + do { + ifp = if_get(m->m_pkthdr.ph_ifidx); + if (ifp != NULL) + netstack_proto_process(ns, ifp, m); + else + ml_enqueue(&ns->ns_junk, m); + if_put(ifp); + + m = ml_dequeue(&ns->ns_proto); + } while (m != NULL); + NET_UNLOCK_SHARED(); + } while (!ml_empty(ns->ns_ifinput)); + + ml_purge(&ns->ns_junk); } void if_vinput(struct ifnet *ifp, struct mbuf *m) { -#if NBPFILTER > 0 - caddr_t if_bpf; -#endif + ifiq_enqueue(&ifp->if_rcv, m); +} - m->m_pkthdr.ph_ifidx = ifp->if_index; - m->m_pkthdr.ph_rtableid = ifp->if_rdomain; +void +net_tq_proto_process(void *arg) +{ + struct softnet *sn = arg; + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + struct netstack ns = { + .ns_ifinput = &ml, + .ns_proto = MBUF_LIST_INITIALIZER(), + .ns_junk = MBUF_LIST_INITIALIZER(), + }; - counters_pkt(ifp->if_counters, - ifc_ipackets, ifc_ibytes, m->m_pkthdr.len); + mq_delist(&sn->sn_proto_queue, &ns.ns_proto); + if (ml_empty(&ns.ns_proto)) + return; -#if NPF > 0 - pf_pkt_addr_changed(m); -#endif + netstack_process(&ns); +} -#if NBPFILTER > 0 - if_bpf = ifp->if_bpf; - if (if_bpf) { - if ((*ifp->if_bpf_mtap)(if_bpf, m, BPF_DIRECTION_IN)) { - m_freem(m); - return; - } - } -#endif +void +if_input_process(struct ifnet *ifp, struct mbuf_list *ml) +{ + struct netstack ns = { + .ns_ifinput = ml, + .ns_proto = MBUF_LIST_INITIALIZER(), + .ns_junk = MBUF_LIST_INITIALIZER(), + }; - if (__predict_true(!ISSET(ifp->if_xflags, IFXF_MONITOR))) - (*ifp->if_input)(ifp, m); - else - m_freem(m); + if (ml_empty(ml)) + return; + + if (!ISSET(ifp->if_xflags, IFXF_CLONED)) + enqueue_randomness(ml_len(ml) ^ (uintptr_t)MBUF_LIST_FIRST(ml)); + + netstack_process(&ns); } void @@ -1678,30 +1771,9 @@ p2p_bpf_mtap(caddr_t if_bpf, const struc } void -p2p_input(struct ifnet *ifp, struct mbuf *m) +p2p_input(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) { - void (*input)(struct ifnet *, struct mbuf *); - - switch (m->m_pkthdr.ph_family) { - case AF_INET: - input = ipv4_input; - break; -#ifdef INET6 - case AF_INET6: - input = ipv6_input; - break; -#endif -#ifdef MPLS - case AF_MPLS: - input = mpls_input; - break; -#endif - default: - m_freem(m); - return; - } - - (*input)(ifp, m); + netstack_proto_input(ns, ifp, m->m_pkthdr.ph_family, m); } /* @@ -3546,15 +3618,15 @@ unhandled_af(int af) panic("unhandled af %d", af); } +static int nettaskqs; + struct taskq * net_tq(unsigned int ifindex) { struct softnet *sn; - static int nettaskqs; if (nettaskqs == 0) nettaskqs = min(NET_TASKQ, ncpus); - sn = &softnets[ifindex % nettaskqs]; return (sn->sn_taskq); @@ -3574,4 +3646,23 @@ net_tq_barriers(const char *wmesg) } refcnt_finalize(&r, wmesg); +} + +void +net_proto_requeue(struct mbuf *m, int af) +{ + unsigned int flow = 0; + struct softnet *sn; + + if (nettaskqs == 0) + nettaskqs = min(NET_TASKQ, ncpus); + + m->m_pkthdr.ph_family = af; + + if (ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) + flow = m->m_pkthdr.ph_flowid; + + sn = &softnets[flow % nettaskqs]; + if (mq_enqueue(&sn->sn_proto_queue, m)) + task_add(sn->sn_taskq, &sn->sn_proto_input); } Index: net/if_aggr.c =================================================================== RCS file: /cvs/src/sys/net/if_aggr.c,v retrieving revision 1.40 diff -u -p -r1.40 if_aggr.c --- net/if_aggr.c 16 May 2023 14:32:54 -0000 1.40 +++ net/if_aggr.c 29 Aug 2023 12:04:38 -0000 @@ -333,7 +333,7 @@ struct aggr_port { uint32_t p_mtu; int (*p_ioctl)(struct ifnet *, u_long, caddr_t); - void (*p_input)(struct ifnet *, struct mbuf *); + void (*p_input)(struct netstack *, struct ifnet *, struct mbuf *); int (*p_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -728,7 +728,7 @@ aggr_eh_is_slow(const struct ether_heade } static void -aggr_input(struct ifnet *ifp0, struct mbuf *m) +aggr_input(struct netstack *ns, struct ifnet *ifp0, struct mbuf *m) { struct arpcom *ac0 = (struct arpcom *)ifp0; struct aggr_port *p = ac0->ac_trunkport; @@ -773,12 +773,11 @@ aggr_input(struct ifnet *ifp0, struct mb if (!ISSET(m->m_pkthdr.csum_flags, M_FLOWID)) m->m_pkthdr.ph_flowid = ifp0->if_index ^ sc->sc_mix; - if_vinput(ifp, m); - + netstack_vinput(ns, ifp, m); return; drop: - m_freem(m); + netstack_mfreem(ns, m); } static int Index: net/if_bpe.c =================================================================== RCS file: /cvs/src/sys/net/if_bpe.c,v retrieving revision 1.19 diff -u -p -r1.19 if_bpe.c --- net/if_bpe.c 8 Nov 2021 04:54:44 -0000 1.19 +++ net/if_bpe.c 29 Aug 2023 12:04:38 -0000 @@ -727,7 +727,7 @@ bpe_find(struct ifnet *ifp0, uint32_t is } void -bpe_input(struct ifnet *ifp0, struct mbuf *m) +bpe_input(struct netstack *ns, struct ifnet *ifp0, struct mbuf *m) { struct bpe_softc *sc; struct ifnet *ifp; @@ -807,11 +807,11 @@ bpe_input(struct ifnet *ifp0, struct mbu pf_pkt_addr_changed(m); #endif - if_vinput(ifp, m); + netstack_vinput(ns, ifp, m); return; drop: - m_freem(m); + netstack_mfreem(ns, m); } void Index: net/if_bpe.h =================================================================== RCS file: /cvs/src/sys/net/if_bpe.h,v retrieving revision 1.1 diff -u -p -r1.1 if_bpe.h --- net/if_bpe.h 20 Dec 2018 23:00:55 -0000 1.1 +++ net/if_bpe.h 29 Aug 2023 12:04:38 -0000 @@ -20,7 +20,7 @@ #define _NET_IF_BPE_H #ifdef _KERNEL -void bpe_input(struct ifnet *, struct mbuf *); +void bpe_input(struct netstack *, struct ifnet *, struct mbuf *); #endif #endif /* _NET_IF_GRE_H_ */ Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.291 diff -u -p -r1.291 if_ethersubr.c --- net/if_ethersubr.c 27 Jul 2023 20:21:25 -0000 1.291 +++ net/if_ethersubr.c 29 Aug 2023 12:04:38 -0000 @@ -377,15 +377,15 @@ ether_output(struct ifnet *ifp, struct m * to ether_input(). */ void -ether_input(struct ifnet *ifp, struct mbuf *m) +ether_input(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) { struct ether_header *eh; - void (*input)(struct ifnet *, struct mbuf *); u_int16_t etype; struct arpcom *ac; const struct ether_brport *eb; unsigned int sdelim = 0; uint64_t dst, self; + int af; /* Drop short frames */ if (m->m_len < ETHER_HDR_LEN) @@ -407,7 +407,7 @@ ether_input(struct ifnet *ifp, struct mb if (ISSET(m->m_flags, M_VLANTAG) || etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ) { #if NVLAN > 0 - m = vlan_input(ifp, m, &sdelim); + m = vlan_input(ns, ifp, m, &sdelim); if (m == NULL) return; #else @@ -504,27 +504,29 @@ ether_input(struct ifnet *ifp, struct mb switch (etype) { case ETHERTYPE_IP: - input = ipv4_input; + af = AF_INET; break; case ETHERTYPE_ARP: if (ifp->if_flags & IFF_NOARP) goto dropanyway; - input = arpinput; - break; + m_adj(m, sizeof(*eh)); + arpinput(ifp, m); + return; case ETHERTYPE_REVARP: if (ifp->if_flags & IFF_NOARP) goto dropanyway; - input = revarpinput; - break; + m_adj(m, sizeof(*eh)); + revarpinput(ifp, m); + return; #ifdef INET6 /* * Schedule IPv6 software interrupt for incoming IPv6 packet. */ case ETHERTYPE_IPV6: - input = ipv6_input; + af = AF_INET6; break; #endif /* INET6 */ #if NPPPOE > 0 || defined(PIPEX) @@ -555,12 +557,12 @@ ether_input(struct ifnet *ifp, struct mb #ifdef MPLS case ETHERTYPE_MPLS: case ETHERTYPE_MPLS_MCAST: - input = mpls_input; + af = AF_MPLS; break; #endif #if NBPE > 0 case ETHERTYPE_PBB: - bpe_input(ifp, m); + bpe_input(ns, ifp, m); return; #endif default: @@ -568,10 +570,10 @@ ether_input(struct ifnet *ifp, struct mb } m_adj(m, sizeof(*eh)); - (*input)(ifp, m); + netstack_proto_input(ns, ifp, af, m); return; dropanyway: - m_freem(m); + netstack_mfreem(ns, m); return; } Index: net/if_loop.c =================================================================== RCS file: /cvs/src/sys/net/if_loop.c,v retrieving revision 1.97 diff -u -p -r1.97 if_loop.c --- net/if_loop.c 21 Jul 2023 22:24:41 -0000 1.97 +++ net/if_loop.c 29 Aug 2023 12:04:38 -0000 @@ -143,7 +143,7 @@ int loioctl(struct ifnet *, u_long, caddr_t); void loopattach(int); void lortrequest(struct ifnet *, int, struct rtentry *); -void loinput(struct ifnet *, struct mbuf *); +void loinput(struct netstack *, struct ifnet *, struct mbuf *); int looutput(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int lo_bpf_mtap(caddr_t, const struct mbuf *, u_int); @@ -241,7 +241,7 @@ lo_bpf_mtap(caddr_t if_bpf, const struct } void -loinput(struct ifnet *ifp, struct mbuf *m) +loinput(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) { int error; @@ -270,7 +270,9 @@ looutput(struct ifnet *ifp, struct mbuf * Do not call if_input_local() directly. Queue the packet to avoid * stack overflow and make TCP handshake over loopback work. */ - return (if_output_local(ifp, m, dst->sa_family)); + + m->m_pkthdr.ph_family = dst->sa_family; + return (ifiq_enqueue(&ifp->if_rcv, m)); } void Index: net/if_rport.c =================================================================== RCS file: net/if_rport.c diff -N net/if_rport.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ net/if_rport.c 29 Aug 2023 12:04:38 -0000 @@ -0,0 +1,438 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2023 David Gwynne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef INET6 +#include +#include +#include +#endif /* INET6 */ + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include +#endif + +#ifdef MPLS +#include +#endif + +#include "pf.h" +#if NPF > 0 +#include +#endif + +#define RPORT_MTU_MIN 1280 +#define RPORT_MTU_MAX 32768 /* LOMTU, but could be higher */ +#define RPORT_MTU_DEFAULT RPORT_MTU_MAX + +struct rport_softc { + struct ifnet sc_if; + + unsigned int sc_peer_idx; +}; + +static int rport_clone_create(struct if_clone *, int); +static int rport_clone_destroy(struct ifnet *); + +static int rport_ioctl(struct ifnet *, u_long, caddr_t); +static int rport_output(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *); +static int rport_enqueue(struct ifnet *, struct mbuf *); +static void rport_start(struct ifqueue *); +static void rport_input(struct netstack *, struct ifnet *, struct mbuf *); + +static int rport_up(struct rport_softc *); +static int rport_down(struct rport_softc *); + +static int rport_set_parent(struct rport_softc *, + const struct if_parent *); +static int rport_get_parent(struct rport_softc *, struct if_parent *); +static int rport_del_parent(struct rport_softc *); + +static struct if_clone rport_cloner = + IF_CLONE_INITIALIZER("rport", rport_clone_create, rport_clone_destroy); + +static struct rwlock rport_interfaces_lock = + RWLOCK_INITIALIZER("rports"); + +void +rportattach(int count) +{ + if_clone_attach(&rport_cloner); +} + +static int +rport_clone_create(struct if_clone *ifc, int unit) +{ + struct rport_softc *sc; + struct ifnet *ifp; + + sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); + ifp = &sc->sc_if; + + snprintf(ifp->if_xname, sizeof(ifp->if_xname), + "%s%d", ifc->ifc_name, unit); + + ifp->if_mtu = RPORT_MTU_DEFAULT; + ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST; + ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE; + ifp->if_ioctl = rport_ioctl; + ifp->if_bpf_mtap = p2p_bpf_mtap; + ifp->if_output = rport_output; + ifp->if_enqueue = rport_enqueue; + ifp->if_qstart = rport_start; + ifp->if_input = rport_input; + ifp->if_rtrequest = p2p_rtrequest; + ifp->if_type = IFT_TUNNEL; + ifp->if_softc = sc; + + if_attach(ifp); + if_alloc_sadl(ifp); + if_counters_alloc(ifp); + +#if NBPFILTER > 0 + bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); +#endif + + return (0); +} + +int +rport_clone_destroy(struct ifnet *ifp) +{ + struct rport_softc *sc = ifp->if_softc; + + NET_LOCK(); + if (ISSET(ifp->if_flags, IFF_RUNNING)) + rport_down(sc); + rport_del_parent(sc); + NET_UNLOCK(); + + if_detach(ifp); + + free(sc, M_DEVBUF, sizeof(*sc)); + + return (0); +} + +static int +rport_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rt) +{ + struct m_tag *mtag; + int error = 0; + + if (!ISSET(ifp->if_flags, IFF_RUNNING)) { + error = ENETDOWN; + goto drop; + } + + switch (dst->sa_family) { + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif +#ifdef MPLS + case AF_MPLS: +#endif + break; + default: + error = EAFNOSUPPORT; + goto drop; + } + + /* Try to limit infinite recursion through misconfiguration. */ + mtag = NULL; + while ((mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) != NULL) { + if (*(int *)(mtag + 1) == ifp->if_index) { + error = EIO; + goto drop; + } + } + + mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT); + if (mtag == NULL) { + error = ENOBUFS; + goto drop; + } + *(int *)(mtag + 1) = ifp->if_index; + m_tag_prepend(m, mtag); + + m->m_flags &= ~(M_BCAST|M_MCAST); + m->m_pkthdr.ph_family = dst->sa_family; +#if NPF > 0 + pf_pkt_addr_changed(m); +#endif + + error = if_enqueue(ifp, m); + if (error) + counters_inc(ifp->if_counters, ifc_oerrors); + + return (error); + +drop: + m_freem(m); + return (error); +} + +static int +rport_enqueue(struct ifnet *ifp, struct mbuf *m) +{ + struct ifqueue *ifq = &ifp->if_snd; + int error; + + error = ifq_enqueue(ifq, m); + if (error) + return (error); + + /* + * always defer handover of packets to the peer to the ifq + * bundle task to provide control over the NET_LOCK scope. + */ + task_add(ifq->ifq_softnet, &ifq->ifq_bundle); + + return (0); +} + +static void +rport_start(struct ifqueue *ifq) +{ + struct ifnet *ifp = ifq->ifq_if; + struct rport_softc *sc = ifp->if_softc; + struct ifnet *ifp0; + struct mbuf *m; + + ifp0 = if_get(sc->sc_peer_idx); + if (ifp0 == NULL || !ISSET(ifp0->if_flags, IFF_RUNNING)) { + ifq_purge(ifq); + if_put(ifp0); + return; + } + + NET_LOCK_SHARED(); + while ((m = ifq_dequeue(ifq)) != NULL) { +#if NBPFILTER > 0 + caddr_t if_bpf = READ_ONCE(ifp->if_bpf); + if (if_bpf && bpf_mtap_af(if_bpf, m->m_pkthdr.ph_family, + m, BPF_DIRECTION_OUT)) { + m_freem(m); + continue; + } +#endif + + if_vinput(ifp0, m); + } + NET_UNLOCK_SHARED(); + + if_put(ifp0); +} + +static void +rport_input(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) +{ + netstack_proto_input(ns, ifp, m->m_pkthdr.ph_family, m); +} + +static int +rport_up(struct rport_softc *sc) +{ + NET_ASSERT_LOCKED(); + + SET(sc->sc_if.if_flags, IFF_RUNNING); + + return (0); +} + +static int +rport_down(struct rport_softc *sc) +{ + NET_ASSERT_LOCKED(); + + CLR(sc->sc_if.if_flags, IFF_RUNNING); + + return (0); +} + +static int +rport_set_parent(struct rport_softc *sc, const struct if_parent *p) +{ + struct ifnet *ifp = &sc->sc_if; + struct ifnet *ifp0; + struct rport_softc *sc0; + int error; + + error = rw_enter(&rport_interfaces_lock, RW_WRITE | RW_INTR); + if (error != 0) + return (error); + + ifp0 = if_unit(p->ifp_parent); + if (ifp0 == NULL) { + error = EINVAL; + goto leave; + } + + if (ifp0 == ifp) { + error = EINVAL; + goto leave; + } + + if (ifp0->if_input != rport_input) { + error = EPROTONOSUPPORT; + goto put; + } + + sc0 = ifp0->if_softc; + + if (sc->sc_peer_idx == ifp0->if_index) { + /* nop */ + KASSERT(sc0->sc_peer_idx == ifp->if_index); + goto put; + } + + if (sc->sc_peer_idx != 0 || sc0->sc_peer_idx != 0) { + error = EBUSY; + goto put; + } + + /* commit */ + sc->sc_peer_idx = ifp0->if_index; + sc0->sc_peer_idx = ifp->if_index; + +put: + if_put(ifp0); +leave: + rw_exit(&rport_interfaces_lock); + + return (error); +} + +static int +rport_get_parent(struct rport_softc *sc, struct if_parent *p) +{ + struct ifnet *ifp0; + int error = 0; + + ifp0 = if_get(sc->sc_peer_idx); + if (ifp0 == NULL) + error = EADDRNOTAVAIL; + else { + if (strlcpy(p->ifp_parent, ifp0->if_xname, + sizeof(p->ifp_parent)) >= sizeof(p->ifp_parent)) + panic("%s strlcpy", __func__); + } + if_put(ifp0); + + return (error); +} + +static int +rport_del_parent(struct rport_softc *sc) +{ + struct rport_softc *sc0; + struct ifnet *ifp0; + int error; + + error = rw_enter(&rport_interfaces_lock, RW_WRITE | RW_INTR); + if (error != 0) + return (error); + + ifp0 = if_get(sc->sc_peer_idx); + sc->sc_peer_idx = 0; + + if (ifp0 != NULL) { + sc0 = ifp0->if_softc; + sc0->sc_peer_idx = 0; + } + if_put(ifp0); + + rw_exit(&rport_interfaces_lock); + + return (0); +} + +static int +rport_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct rport_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + int error = 0; + + switch (cmd) { + case SIOCSIFADDR: + break; + case SIOCSIFFLAGS: + if (ISSET(ifp->if_flags, IFF_UP)) { + if (!ISSET(ifp->if_flags, IFF_RUNNING)) + error = rport_up(sc); + } else { + if (ISSET(ifp->if_flags, IFF_RUNNING)) + error = rport_down(sc); + } + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + break; + + case SIOCSIFMTU: + if (ifr->ifr_mtu < RPORT_MTU_MIN || + ifr->ifr_mtu > RPORT_MTU_MAX) { + error = EINVAL; + break; + } + + ifp->if_mtu = ifr->ifr_mtu; + break; + + case SIOCSIFPARENT: + error = rport_set_parent(sc, (struct if_parent *)data); + break; + case SIOCGIFPARENT: + error = rport_get_parent(sc, (struct if_parent *)data); + break; + case SIOCDIFPARENT: + error = rport_del_parent(sc); + break; + + default: + error = ENOTTY; + break; + } + + return (error); +} Index: net/if_tpmr.c =================================================================== RCS file: /cvs/src/sys/net/if_tpmr.c,v retrieving revision 1.33 diff -u -p -r1.33 if_tpmr.c --- net/if_tpmr.c 16 May 2023 14:32:54 -0000 1.33 +++ net/if_tpmr.c 29 Aug 2023 12:04:38 -0000 @@ -271,6 +271,7 @@ tpmr_pf(struct ifnet *ifp0, int dir, str { struct ether_header *eh, copy; const struct tpmr_pf_ip_family *fam; + int pfact; eh = mtod(m, struct ether_header *); switch (ntohs(eh->ether_type)) { @@ -295,7 +296,10 @@ tpmr_pf(struct ifnet *ifp0, int dir, str return (NULL); } - if (pf_test(fam->af, dir, ifp0, &m) != PF_PASS) { + NET_LOCK_SHARED(); + pfact = pf_test(fam->af, dir, ifp0, &m); + NET_UNLOCK_SHARED(); + if (pfact != PF_PASS) { m_freem(m); return (NULL); } @@ -305,7 +309,9 @@ tpmr_pf(struct ifnet *ifp0, int dir, str if (dir == PF_IN && ISSET(m->m_pkthdr.pf.flags, PF_TAG_DIVERTED)) { pf_mbuf_unlink_state_key(m); pf_mbuf_unlink_inpcb(m); + NET_LOCK_SHARED(); (*fam->ip_input)(ifp0, m); + NET_UNLOCK_SHARED(); return (NULL); } Index: net/if_trunk.c =================================================================== RCS file: /cvs/src/sys/net/if_trunk.c,v retrieving revision 1.152 diff -u -p -r1.152 if_trunk.c --- net/if_trunk.c 2 Aug 2021 21:10:55 -0000 1.152 +++ net/if_trunk.c 29 Aug 2023 12:04:38 -0000 @@ -76,7 +76,7 @@ int trunk_ether_delmulti(struct trunk_s void trunk_ether_purgemulti(struct trunk_softc *); int trunk_ether_cmdmulti(struct trunk_port *, u_long); int trunk_ioctl_allports(struct trunk_softc *, u_long, caddr_t); -void trunk_input(struct ifnet *, struct mbuf *); +void trunk_input(struct netstack *, struct ifnet *, struct mbuf *); void trunk_start(struct ifnet *); void trunk_init(struct ifnet *); void trunk_stop(struct ifnet *); @@ -1142,13 +1142,14 @@ trunk_stop(struct ifnet *ifp) } void -trunk_input(struct ifnet *ifp, struct mbuf *m) +trunk_input(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) { struct arpcom *ac0 = (struct arpcom *)ifp; struct trunk_port *tp; struct trunk_softc *tr; struct ifnet *trifp = NULL; struct ether_header *eh; + int rv; if (m->m_len < sizeof(*eh)) goto bad; @@ -1169,7 +1170,10 @@ trunk_input(struct ifnet *ifp, struct mb if (tr->tr_proto == TRUNK_PROTO_NONE) goto bad; - if ((*tr->tr_input)(tr, tp, m)) { + NET_LOCK_SHARED(); + rv = (*tr->tr_input)(tr, tp, m); + NET_UNLOCK_SHARED(); + if (rv != 0) { /* * We stop here if the packet has been consumed * by the protocol routine. @@ -1193,7 +1197,6 @@ trunk_input(struct ifnet *ifp, struct mb return; } } - if_vinput(trifp, m); return; Index: net/if_trunk.h =================================================================== RCS file: /cvs/src/sys/net/if_trunk.h,v retrieving revision 1.30 diff -u -p -r1.30 if_trunk.h --- net/if_trunk.h 22 Jul 2020 02:16:02 -0000 1.30 +++ net/if_trunk.h 29 Aug 2023 12:04:38 -0000 @@ -172,7 +172,7 @@ struct trunk_port { int (*tp_ioctl)(struct ifnet *, u_long, caddr_t); int (*tp_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); - void (*tp_input)(struct ifnet *, struct mbuf *); + void (*tp_input)(struct netstack *, struct ifnet *, struct mbuf *); SLIST_ENTRY(trunk_port) tp_entries; }; Index: net/if_tun.c =================================================================== RCS file: /cvs/src/sys/net/if_tun.c,v retrieving revision 1.238 diff -u -p -r1.238 if_tun.c --- net/if_tun.c 10 Feb 2023 14:39:18 -0000 1.238 +++ net/if_tun.c 29 Aug 2023 12:04:38 -0000 @@ -114,7 +114,7 @@ int tun_dev_write(dev_t, struct uio *, i int tun_dev_kqfilter(dev_t, struct knote *); int tun_ioctl(struct ifnet *, u_long, caddr_t); -void tun_input(struct ifnet *, struct mbuf *); +void tun_input(struct netstack *, struct ifnet *, struct mbuf *); int tun_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int tun_enqueue(struct ifnet *, struct mbuf *); @@ -924,7 +924,7 @@ put: } void -tun_input(struct ifnet *ifp, struct mbuf *m0) +tun_input(struct netstack *ns, struct ifnet *ifp, struct mbuf *m0) { uint32_t af; @@ -934,24 +934,7 @@ tun_input(struct ifnet *ifp, struct mbuf /* strip the tunnel header */ m_adj(m0, sizeof(af)); - switch (ntohl(af)) { - case AF_INET: - ipv4_input(ifp, m0); - break; -#ifdef INET6 - case AF_INET6: - ipv6_input(ifp, m0); - break; -#endif -#ifdef MPLS - case AF_MPLS: - mpls_input(ifp, m0); - break; -#endif - default: - m_freem(m0); - break; - } + netstack_proto_input(ns, ifp, af, m0); } int Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.129 diff -u -p -r1.129 if_var.h --- net/if_var.h 7 Jul 2023 08:05:02 -0000 1.129 +++ net/if_var.h 29 Aug 2023 12:04:38 -0000 @@ -89,6 +89,7 @@ struct rtentry; struct ifnet; struct task; struct cpumem; +struct netstack; /* * Structure describing a `cloning' interface. @@ -160,7 +161,7 @@ struct ifnet { /* and the entries */ struct task if_linkstatetask; /* [I] task to do route updates */ /* procedure handles */ - void (*if_input)(struct ifnet *, struct mbuf *); + void (*if_input)(struct netstack *, struct ifnet *, struct mbuf *); int (*if_bpf_mtap)(caddr_t, const struct mbuf *, u_int); int (*if_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); /* output routine (enqueue) */ @@ -323,7 +324,7 @@ int if_enqueue(struct ifnet *, struct mb int if_enqueue_ifq(struct ifnet *, struct mbuf *); void if_input(struct ifnet *, struct mbuf_list *); void if_vinput(struct ifnet *, struct mbuf *); -void if_input_process(struct ifnet *, struct mbuf_list *); +void if_input_process(struct ifnet *ifp, struct mbuf_list *); int if_input_local(struct ifnet *, struct mbuf *, sa_family_t); int if_output_ml(struct ifnet *, struct mbuf_list *, struct sockaddr *, struct rtentry *); @@ -331,10 +332,9 @@ int if_output_mq(struct ifnet *, struct struct sockaddr *, struct rtentry *); int if_output_tso(struct ifnet *, struct mbuf **, struct sockaddr *, struct rtentry *, u_int); -int if_output_local(struct ifnet *, struct mbuf *, sa_family_t); void if_rtrequest_dummy(struct ifnet *, int, struct rtentry *); void p2p_rtrequest(struct ifnet *, int, struct rtentry *); -void p2p_input(struct ifnet *, struct mbuf *); +void p2p_input(struct netstack *, struct ifnet *, struct mbuf *); int p2p_bpf_mtap(caddr_t, const struct mbuf *, u_int); struct ifaddr *ifa_ifwithaddr(struct sockaddr *, u_int); @@ -386,6 +386,13 @@ int if_txhprio_l2_check(int); int if_txhprio_l3_check(int); int if_rxhprio_l2_check(int); int if_rxhprio_l3_check(int); + +void netstack_vinput(struct netstack *, struct ifnet *, struct mbuf *); +void netstack_proto_input(struct netstack *, struct ifnet *, int, + struct mbuf *); +void netstack_mfreem(struct netstack *, struct mbuf *); + +void net_proto_requeue(struct mbuf *, int); #endif /* _KERNEL */ Index: net/if_veb.c =================================================================== RCS file: /cvs/src/sys/net/if_veb.c,v retrieving revision 1.31 diff -u -p -r1.31 if_veb.c --- net/if_veb.c 16 May 2023 14:32:54 -0000 1.31 +++ net/if_veb.c 29 Aug 2023 12:04:38 -0000 @@ -168,7 +168,7 @@ static int veb_clone_create(struct if_cl static int veb_clone_destroy(struct ifnet *); static int veb_ioctl(struct ifnet *, u_long, caddr_t); -static void veb_input(struct ifnet *, struct mbuf *); +static void veb_input(struct netstack *, struct ifnet *, struct mbuf *); static int veb_enqueue(struct ifnet *, struct mbuf *); static int veb_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -612,6 +612,7 @@ veb_pf(struct ifnet *ifp0, int dir, stru { struct ether_header *eh, copy; const struct veb_pf_ip_family *fam; + int pfact; /* * pf runs on vport interfaces when they enter or leave the @@ -646,7 +647,11 @@ veb_pf(struct ifnet *ifp0, int dir, stru return (NULL); } - if (pf_test(fam->af, dir, ifp0, &m) != PF_PASS) { + NET_LOCK_SHARED(); + pfact = pf_test(fam->af, dir, ifp0, &m); + NET_UNLOCK_SHARED(); + + if (pfact != PF_PASS) { m_freem(m); return (NULL); } @@ -656,7 +661,9 @@ veb_pf(struct ifnet *ifp0, int dir, stru if (dir == PF_IN && ISSET(m->m_pkthdr.pf.flags, PF_TAG_DIVERTED)) { pf_mbuf_unlink_state_key(m); pf_mbuf_unlink_inpcb(m); + NET_LOCK_SHARED(); (*fam->ip_input)(ifp0, m); + NET_UNLOCK_SHARED(); return (NULL); } @@ -1191,7 +1198,7 @@ drop: } static void -veb_input(struct ifnet *ifp, struct mbuf *m) +veb_input(struct netstack *ns, struct ifnet *ifp, struct mbuf *m) { m_freem(m); } Index: net/if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.215 diff -u -p -r1.215 if_vlan.c --- net/if_vlan.c 16 May 2023 14:32:54 -0000 1.215 +++ net/if_vlan.c 29 Aug 2023 12:04:38 -0000 @@ -374,7 +374,8 @@ vlan_inject(struct mbuf *m, uint16_t typ } struct mbuf * -vlan_input(struct ifnet *ifp0, struct mbuf *m, unsigned int *sdelim) +vlan_input(struct netstack *ns, struct ifnet *ifp0, struct mbuf *m, + unsigned int *sdelim) { struct vlan_softc *sc; struct ifnet *ifp; @@ -413,15 +414,13 @@ vlan_input(struct ifnet *ifp0, struct mb tag = EVL_VLANOFTAG(vtag); list = &tagh[TAG_HASH(tag)]; - smr_read_enter(); SMR_SLIST_FOREACH(sc, list, sc_list) { - if (ifp0->if_index == sc->sc_ifidx0 && tag == sc->sc_tag && - etype == sc->sc_type) { - refcnt_take(&sc->sc_refcnt); + if (ifp0->if_index == sc->sc_ifidx0 && + tag == sc->sc_tag && + etype == sc->sc_type) break; - } + } - smr_read_leave(); if (sc == NULL) { /* VLAN 0 Priority Tagging */ @@ -433,10 +432,8 @@ vlan_input(struct ifnet *ifp0, struct mb eh = mtod(m, struct ether_header *); if (eh->ether_type == htons(ETHERTYPE_VLAN) || - eh->ether_type == htons(ETHERTYPE_QINQ)) { - m_freem(m); - return (NULL); - } + eh->ether_type == htons(ETHERTYPE_QINQ)) + goto drop; } else *sdelim = 1; @@ -445,8 +442,8 @@ vlan_input(struct ifnet *ifp0, struct mb ifp = &sc->sc_if; if (!ISSET(ifp->if_flags, IFF_RUNNING)) { - m_freem(m); - goto leave; + /* XXX decline? */ + goto drop; } /* @@ -471,9 +468,10 @@ vlan_input(struct ifnet *ifp0, struct mb break; } - if_vinput(ifp, m); -leave: - refcnt_rele_wake(&sc->sc_refcnt); + netstack_vinput(ns, ifp, m); + return (NULL); +drop: + netstack_mfreem(ns, m); return (NULL); } Index: net/if_vlan_var.h =================================================================== RCS file: /cvs/src/sys/net/if_vlan_var.h,v retrieving revision 1.46 diff -u -p -r1.46 if_vlan_var.h --- net/if_vlan_var.h 26 Apr 2023 00:14:21 -0000 1.46 +++ net/if_vlan_var.h 29 Aug 2023 12:04:38 -0000 @@ -47,7 +47,8 @@ struct vlanreq { }; #ifdef _KERNEL -struct mbuf *vlan_input(struct ifnet *, struct mbuf *, unsigned int *); +struct mbuf *vlan_input(struct netstack *, struct ifnet *, + struct mbuf *, unsigned int *); struct mbuf *vlan_inject(struct mbuf *, uint16_t, uint16_t); void vlan_flags_from_parent(struct ifnet *, int); #endif /* _KERNEL */ Index: netinet/if_ether.h =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.h,v retrieving revision 1.90 diff -u -p -r1.90 if_ether.h --- netinet/if_ether.h 27 Jul 2023 20:21:25 -0000 1.90 +++ netinet/if_ether.h 29 Aug 2023 12:04:38 -0000 @@ -278,7 +278,7 @@ int ether_multiaddr(struct sockaddr *, u void ether_ifattach(struct ifnet *); void ether_ifdetach(struct ifnet *); int ether_ioctl(struct ifnet *, struct arpcom *, u_long, caddr_t); -void ether_input(struct ifnet *, struct mbuf *); +void ether_input(struct netstack *, struct ifnet *, struct mbuf *); int ether_resolve(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *, struct ether_header *); struct mbuf * Index: sys/mbuf.h =================================================================== RCS file: /cvs/src/sys/sys/mbuf.h,v retrieving revision 1.261 diff -u -p -r1.261 mbuf.h --- sys/mbuf.h 16 Jul 2023 03:01:31 -0000 1.261 +++ sys/mbuf.h 29 Aug 2023 12:04:38 -0000 @@ -505,6 +505,7 @@ struct m_tag *m_tag_next(struct mbuf *, void ml_init(struct mbuf_list *); void ml_enqueue(struct mbuf_list *, struct mbuf *); +void ml_requeue(struct mbuf_list *, struct mbuf *); struct mbuf * ml_dequeue(struct mbuf_list *); void ml_enlist(struct mbuf_list *, struct mbuf_list *); struct mbuf * ml_dechain(struct mbuf_list *);