Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.612 diff -u -p -r1.612 if.c --- net/if.c 10 Jul 2020 13:23:34 -0000 1.612 +++ net/if.c 16 Jul 2020 00:07:34 -0000 @@ -631,8 +631,6 @@ if_attach_common(struct ifnet *ifp) if (ifp->if_enqueue == NULL) ifp->if_enqueue = if_enqueue_ifq; ifp->if_llprio = IFQ_DEFPRIO; - - SRPL_INIT(&ifp->if_inputs); } void @@ -805,109 +803,6 @@ if_output_local(struct ifnet *ifp, struc return (ifiq_enqueue(ifiq, m) == 0 ? 0 : ENOBUFS); } -struct ifih { - SRPL_ENTRY(ifih) ifih_next; - int (*ifih_input)(struct ifnet *, struct mbuf *, - void *); - void *ifih_cookie; - int ifih_refcnt; - struct refcnt ifih_srpcnt; -}; - -void if_ih_ref(void *, void *); -void if_ih_unref(void *, void *); - -struct srpl_rc ifih_rc = SRPL_RC_INITIALIZER(if_ih_ref, if_ih_unref, NULL); - -void -if_ih_insert(struct ifnet *ifp, int (*input)(struct ifnet *, struct mbuf *, - void *), void *cookie) -{ - struct ifih *ifih; - - /* the kernel lock guarantees serialised modifications to if_inputs */ - KERNEL_ASSERT_LOCKED(); - - SRPL_FOREACH_LOCKED(ifih, &ifp->if_inputs, ifih_next) { - if (ifih->ifih_input == input && ifih->ifih_cookie == cookie) { - ifih->ifih_refcnt++; - break; - } - } - - if (ifih == NULL) { - ifih = malloc(sizeof(*ifih), M_DEVBUF, M_WAITOK); - - ifih->ifih_input = input; - ifih->ifih_cookie = cookie; - ifih->ifih_refcnt = 1; - refcnt_init(&ifih->ifih_srpcnt); - SRPL_INSERT_HEAD_LOCKED(&ifih_rc, &ifp->if_inputs, - ifih, ifih_next); - } -} - -void -if_ih_ref(void *null, void *i) -{ - struct ifih *ifih = i; - - refcnt_take(&ifih->ifih_srpcnt); -} - -void -if_ih_unref(void *null, void *i) -{ - struct ifih *ifih = i; - - refcnt_rele_wake(&ifih->ifih_srpcnt); -} - -void -if_ih_remove(struct ifnet *ifp, int (*input)(struct ifnet *, struct mbuf *, - void *), void *cookie) -{ - struct ifih *ifih; - - /* the kernel lock guarantees serialised modifications to if_inputs */ - KERNEL_ASSERT_LOCKED(); - - SRPL_FOREACH_LOCKED(ifih, &ifp->if_inputs, ifih_next) { - if (ifih->ifih_input == input && ifih->ifih_cookie == cookie) - break; - } - - KASSERT(ifih != NULL); - - if (--ifih->ifih_refcnt == 0) { - SRPL_REMOVE_LOCKED(&ifih_rc, &ifp->if_inputs, ifih, - ifih, ifih_next); - - refcnt_finalize(&ifih->ifih_srpcnt, "ifihrm"); - free(ifih, M_DEVBUF, sizeof(*ifih)); - } -} - -static void -if_ih_input(struct ifnet *ifp, struct mbuf *m) -{ - struct ifih *ifih; - struct srp_ref sr; - - /* - * Pass this mbuf to all input handlers of its - * interface until it is consumed. - */ - SRPL_FOREACH(ifih, &sr, &ifp->if_inputs, ifih_next) { - if ((*ifih->ifih_input)(ifp, m, ifih->ifih_cookie)) - break; - } - SRPL_LEAVE(&sr); - - if (ifih == NULL) - m_freem(m); -} - void if_input_process(struct ifnet *ifp, struct mbuf_list *ml) { @@ -933,7 +828,7 @@ if_input_process(struct ifnet *ifp, stru */ NET_LOCK(); while ((m = ml_dequeue(ml)) != NULL) - if_ih_input(ifp, m); + (*ifp->if_input)(ifp, m); NET_UNLOCK(); } @@ -960,7 +855,7 @@ if_vinput(struct ifnet *ifp, struct mbuf } #endif - if_ih_input(ifp, m); + (*ifp->if_input)(ifp, m); } void Index: net/if_aggr.c =================================================================== RCS file: /cvs/src/sys/net/if_aggr.c,v retrieving revision 1.32 diff -u -p -r1.32 if_aggr.c --- net/if_aggr.c 10 Jul 2020 13:26:41 -0000 1.32 +++ net/if_aggr.c 16 Jul 2020 00:07:34 -0000 @@ -332,6 +332,7 @@ struct aggr_port { uint32_t p_mtu; int (*p_ioctl)(struct ifnet *, u_long, caddr_t); + void (*p_input)(struct ifnet *, struct mbuf *); int (*p_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -723,13 +724,14 @@ aggr_eh_is_slow(const struct ether_heade eh->ether_type == htons(ETHERTYPE_SLOW)); } -static int -aggr_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +static void +aggr_input(struct ifnet *ifp0, struct mbuf *m) { - struct ether_header *eh; - struct aggr_port *p = cookie; + struct arpcom *ac0 = (struct arpcom *)ifp0; + struct aggr_port *p = ac0->ac_trunkport; struct aggr_softc *sc = p->p_aggr; struct ifnet *ifp = &sc->sc_if; + struct ether_header *eh; int hlen = sizeof(*eh); if (!ISSET(ifp->if_flags, IFF_RUNNING)) @@ -745,7 +747,7 @@ aggr_input(struct ifnet *ifp0, struct mb m = m_pullup(m, hlen); if (m == NULL) { /* short++ */ - return (1); + return; } eh = mtod(m, struct ether_header *); } @@ -756,7 +758,7 @@ aggr_input(struct ifnet *ifp0, struct mb case SLOWPROTOCOLS_SUBTYPE_LACP_MARKER: if (mq_enqueue(&p->p_rxm_mq, m) == 0) task_add(systq, &p->p_rxm_task); - return (1); + return; default: break; } @@ -770,11 +772,10 @@ aggr_input(struct ifnet *ifp0, struct mb if_vinput(ifp, m); - return (1); + return; drop: m_freem(m); - return (1); } static int @@ -1072,6 +1073,10 @@ aggr_add_port(struct aggr_softc *sc, con if (ifp0->if_type != IFT_ETHER) return (EPROTONOSUPPORT); + error = ether_is_brport(ifp0); + if (error != 0) + return (error); + if (ifp0->if_hardmtu < ifp->if_mtu) return (ENOBUFS); @@ -1103,6 +1108,7 @@ aggr_add_port(struct aggr_softc *sc, con CTASSERT(sizeof(p->p_lladdr) == sizeof(ac0->ac_enaddr)); memcpy(p->p_lladdr, ac0->ac_enaddr, sizeof(p->p_lladdr)); p->p_ioctl = ifp0->if_ioctl; + p->p_input = ifp0->if_input; p->p_output = ifp0->if_output; error = aggr_group(sc, p, SIOCADDMULTI); @@ -1161,12 +1167,18 @@ aggr_add_port(struct aggr_softc *sc, con aggr_update_capabilities(sc); + /* + * use (and modification) of ifp->if_input and ac->ac_trunkport + * is protected by NET_LOCK. + */ + ac0->ac_trunkport = p; + /* make sure p is visible before handlers can run */ membar_producer(); ifp0->if_ioctl = aggr_p_ioctl; + ifp0->if_input = aggr_input; ifp0->if_output = aggr_p_output; - if_ih_insert(ifp0, aggr_input, p); aggr_mux(sc, p, LACP_MUX_E_BEGIN); aggr_rxm(sc, p, LACP_RXM_E_BEGIN); @@ -1385,10 +1397,13 @@ aggr_p_dtor(struct aggr_softc *sc, struc timeout_del(&p->p_current_while_timer); timeout_del(&p->p_wait_while_timer); - if_ih_remove(ifp0, aggr_input, p); + /* + * use (and modification) of ifp->if_input and ac->ac_trunkport + * is protected by NET_LOCK. + */ ac0->ac_trunkport = NULL; - + ifp0->if_input = p->p_input; ifp0->if_ioctl = p->p_ioctl; ifp0->if_output = p->p_output; Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.341 diff -u -p -r1.341 if_bridge.c --- net/if_bridge.c 13 Jul 2020 03:21:33 -0000 1.341 +++ net/if_bridge.c 16 Jul 2020 00:07:34 -0000 @@ -109,7 +109,8 @@ void bridge_ifdetach(void *); void bridge_spandetach(void *); int bridge_ifremove(struct bridge_iflist *); void bridge_spanremove(struct bridge_iflist *); -int bridge_input(struct ifnet *, struct mbuf *, void *); +struct mbuf * + bridge_input(struct ifnet *, struct mbuf *, void *); void bridge_process(struct ifnet *, struct mbuf *); void bridgeintr_frame(struct ifnet *, struct ifnet *, struct mbuf *); void bridge_bifgetstp(struct bridge_softc *, struct bridge_iflist *, @@ -149,6 +150,11 @@ struct niqueue bridgeintrq = NIQUEUE_INI struct if_clone bridge_cloner = IF_CLONE_INITIALIZER("bridge", bridge_clone_create, bridge_clone_destroy); +const struct ether_brport bridge_brport = { + bridge_input, + NULL, +}; + void bridgeattach(int n) { @@ -198,8 +204,6 @@ bridge_clone_create(struct if_clone *ifc DLT_EN10MB, ETHER_HDR_LEN); #endif - if_ih_insert(ifp, ether_input, NULL); - return (0); } @@ -236,10 +240,6 @@ bridge_clone_destroy(struct ifnet *ifp) /* Undo pseudo-driver changes. */ if_deactivate(ifp); - if_ih_remove(ifp, ether_input, NULL); - - KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs)); - if_detach(ifp); free(sc, M_DEVBUF, sizeof *sc); @@ -289,6 +289,10 @@ bridge_ioctl(struct ifnet *ifp, u_long c break; } + error = ether_is_brport(ifs); + if (error != 0) + break; + /* If it's in the span list, it can't be a member. */ SMR_SLIST_FOREACH_LOCKED(bif, &sc->sc_spanlist, bif_next) { if (bif->ifp == ifs) @@ -313,6 +317,14 @@ bridge_ioctl(struct ifnet *ifp, u_long c break; } + /* + * XXX If the NET_LOCK() or ifpromisc() calls above + * had to sleep, then something else could have come + * along and taken over ifs while the kernel lock was + * released. Or worse, ifs could have been destroyed + * cos ifunit() is... optimistic. + */ + bif->bridge_sc = sc; bif->ifp = ifs; bif->bif_flags = IFBIF_LEARNING | IFBIF_DISCOVER; @@ -321,7 +333,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c ifs->if_bridgeidx = ifp->if_index; task_set(&bif->bif_dtask, bridge_ifdetach, bif); if_detachhook_add(ifs, &bif->bif_dtask); - if_ih_insert(bif->ifp, bridge_input, NULL); + ether_set_brport(bif->ifp, &bridge_brport); SMR_SLIST_INSERT_HEAD_LOCKED(&sc->sc_iflist, bif, bif_next); break; case SIOCBRDGDEL: @@ -542,7 +554,7 @@ bridge_ifremove(struct bridge_iflist *bi SMR_SLIST_REMOVE_LOCKED(&sc->sc_iflist, bif, bridge_iflist, bif_next); if_detachhook_del(bif->ifp, &bif->bif_dtask); - if_ih_remove(bif->ifp, bridge_input, NULL); + ether_clr_brport(bif->ifp); smr_barrier(); @@ -1087,19 +1099,19 @@ bridge_ourether(struct ifnet *ifp, uint8 * Receive input from an interface. Queue the packet for bridging if its * not for us, and schedule an interrupt. */ -int -bridge_input(struct ifnet *ifp, struct mbuf *m, void *cookie) +struct mbuf * +bridge_input(struct ifnet *ifp, struct mbuf *m, void *null) { KASSERT(m->m_flags & M_PKTHDR); if (m->m_flags & M_PROTO1) { m->m_flags &= ~M_PROTO1; - return (0); + return (m); } niq_enqueue(&bridgeintrq, m); - return (1); + return (NULL); } void Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.261 diff -u -p -r1.261 if_ethersubr.c --- net/if_ethersubr.c 24 Nov 2019 07:50:55 -0000 1.261 +++ net/if_ethersubr.c 16 Jul 2020 00:07:34 -0000 @@ -86,6 +86,7 @@ didn't get a copy, you may request one f #include #include #include +#include #include #include @@ -103,6 +104,16 @@ didn't get a copy, you may request one f #include #endif +#include "vlan.h" +#if NVLAN > 0 +#include +#endif + +#include "carp.h" +#if NCARP > 0 +#include +#endif + #include "pppoe.h" #if NPPPOE > 0 #include @@ -343,30 +354,167 @@ ether_output(struct ifnet *ifp, struct m return (if_enqueue(ifp, m)); } +int +ether_is_brport(struct ifnet *ifp) +{ + struct arpcom *ac = (struct arpcom *)ifp; + + KERNEL_ASSERT_LOCKED(); + if (SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL) + return (EBUSY); + + return (0); +} + +void +ether_set_brport(struct ifnet *ifp, const struct ether_brport *eb) +{ + struct arpcom *ac = (struct arpcom *)ifp; + + KERNEL_ASSERT_LOCKED(); + KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) == NULL, + "%s setting an already set brport", ifp->if_xname); + + SMR_PTR_SET_LOCKED(&ac->ac_brport, eb); +} + +void +ether_clr_brport(struct ifnet *ifp) +{ + struct arpcom *ac = (struct arpcom *)ifp; + + KERNEL_ASSERT_LOCKED(); + KASSERTMSG(SMR_PTR_GET_LOCKED(&ac->ac_brport) != NULL, + "%s clearing an already clear brport", ifp->if_xname); + + SMR_PTR_SET_LOCKED(&ac->ac_brport, NULL); +} + +const struct ether_brport * +ether_get_brport(struct ifnet *ifp) +{ + struct arpcom *ac = (struct arpcom *)ifp; + SMR_ASSERT_CRITICAL(); + return (SMR_PTR_GET(&ac->ac_brport)); +} + +const struct ether_brport * +ether_get_brport_locked(struct ifnet *ifp) +{ + struct arpcom *ac = (struct arpcom *)ifp; + KERNEL_ASSERT_LOCKED(); + return (SMR_PTR_GET_LOCKED(&ac->ac_brport)); +} + /* - * Process a received Ethernet packet; - * the packet is in the mbuf chain m without - * the ether header, which is provided separately. + * Process a received Ethernet packet. + * + * Ethernet input has several "phases" of filtering packets to + * support virtual/pseudo interfaces before actual layer 3 protocol + * handling. + * + * First phase: + * + * The first phase supports drivers that aggregate multiple Ethernet + * ports into a single logical interface, ie, aggr(4) and trunk(4). + * These drivers intercept packets by swapping out the if_input handler + * on the "port" interfaces to steal the packets before they get here + * to ether_input(). */ -int -ether_input(struct ifnet *ifp, struct mbuf *m, void *cookie) + +void +ether_input(struct ifnet *ifp, struct mbuf *m) { - struct ether_header *eh; void (*input)(struct ifnet *, struct mbuf *); + struct ether_header *eh; u_int16_t etype; struct arpcom *ac; + const struct ether_brport *eb; + unsigned int sdelim = 0; /* Drop short frames */ - if (m->m_len < ETHER_HDR_LEN) + if (m->m_len < sizeof(*eh)) goto dropanyway; - ac = (struct arpcom *)ifp; + /* + * Second phase: service delimited packet filtering. + * + * Let vlan(4) and svlan(4) look at "service delimited" + * packets. If a virtual interface does not exist to take + * those packets, they're returned to ether_input() so a + * bridge can have a go at forwarding them. + */ + eh = mtod(m, struct ether_header *); + etype = ntohs(eh->ether_type); + + if (ISSET(m->m_flags, M_VLANTAG) || + etype == ETHERTYPE_VLAN || etype == ETHERTYPE_QINQ) { +#if NVLAN > 0 + m = vlan_input(ifp, m); + if (m == NULL) + return; +#endif /* NVLAN > 0 */ + + sdelim = 1; + } + + /* + * Third phase: bridge processing. + * + * Give the packet to a bridge interface, ie, bridge(4), + * switch(4), or tpmr(4), if it is configured. A bridge + * may take the packet and forward it to another port, or it + * may return it here to ether_input() to support local + * delivery to this port. + */ + + ac = (struct arpcom *)ifp; + + smr_read_enter(); + eb = SMR_PTR_GET(&ac->ac_brport); + if (eb != NULL) { + m = (*eb->eb_input)(ifp, m, eb->eb_port); + if (m == NULL) { + smr_read_leave(); + return; + } + } + smr_read_leave(); - /* Is the packet for us? */ + /* + * Fourth phase: drop service delimited packets. + * + * If the packet has a tag, and a bridge didn't want it, + * it's not for this port. + */ + + if (sdelim) + goto dropanyway; + + /* + * Fifth phase: destination address check. + * + * Is the packet specifically addressed to this port? + */ + + eh = mtod(m, struct ether_header *); if (memcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) != 0) { +#if NCARP > 0 + /* + * If it's not for this port, it could be for carp(4). + */ + if (ifp->if_type != IFT_CARP && + !SRPL_EMPTY_LOCKED(&ifp->if_carp)) { + m = carp_input(ifp, m); + if (m == NULL) + return; + } +#endif - /* If not, it must be multicast or broadcast to go further */ + /* + * If not, it must be multicast or broadcast to go further. + */ if (!ETHER_IS_MULTICAST(eh->ether_dhost)) goto dropanyway; @@ -384,17 +532,14 @@ ether_input(struct ifnet *ifp, struct mb m->m_flags |= M_BCAST; else m->m_flags |= M_MCAST; - ifp->if_imcasts++; } /* - * HW vlan tagged packets that were not collected by vlan(4) must - * be dropped now. + * Sixth phase: protocol demux. + * + * At this point it is known that the packet is destined + * for layer 3 protocol handling on the local port. */ - if (m->m_flags & M_VLANTAG) - goto dropanyway; - - etype = ntohs(eh->ether_type); switch (etype) { case ETHERTYPE_IP: @@ -432,7 +577,7 @@ ether_input(struct ifnet *ifp, struct mb if ((session = pipex_pppoe_lookup_session(m)) != NULL) { pipex_pppoe_input(m, session); - return (1); + return; } } #endif @@ -440,7 +585,7 @@ ether_input(struct ifnet *ifp, struct mb niq_enqueue(&pppoediscinq, m); else niq_enqueue(&pppoeinq, m); - return (1); + return; #endif #ifdef MPLS case ETHERTYPE_MPLS: @@ -451,7 +596,7 @@ ether_input(struct ifnet *ifp, struct mb #if NBPE > 0 case ETHERTYPE_PBB: bpe_input(ifp, m); - return (1); + return; #endif default: goto dropanyway; @@ -459,10 +604,9 @@ ether_input(struct ifnet *ifp, struct mb m_adj(m, sizeof(*eh)); (*input)(ifp, m); - return (1); + return; dropanyway: m_freem(m); - return (1); } /* @@ -522,12 +666,11 @@ ether_ifattach(struct ifnet *ifp) ifp->if_addrlen = ETHER_ADDR_LEN; ifp->if_hdrlen = ETHER_HDR_LEN; ifp->if_mtu = ETHERMTU; + ifp->if_input = ether_input; if (ifp->if_output == NULL) ifp->if_output = ether_output; ifp->if_rtrequest = ether_rtrequest; - if_ih_insert(ifp, ether_input, NULL); - if (ifp->if_hardmtu == 0) ifp->if_hardmtu = ETHERMTU; @@ -547,10 +690,6 @@ ether_ifdetach(struct ifnet *ifp) /* Undo pseudo-driver changes. */ if_deactivate(ifp); - - if_ih_remove(ifp, ether_input, NULL); - - KASSERT(SRPL_EMPTY_LOCKED(&ifp->if_inputs)); for (enm = LIST_FIRST(&ac->ac_multiaddrs); enm != NULL; Index: net/if_loop.c =================================================================== RCS file: /cvs/src/sys/net/if_loop.c,v retrieving revision 1.90 diff -u -p -r1.90 if_loop.c --- net/if_loop.c 8 Jan 2020 09:09:10 -0000 1.90 +++ net/if_loop.c 16 Jul 2020 00:07:34 -0000 @@ -143,7 +143,7 @@ int loioctl(struct ifnet *, u_long, caddr_t); void loopattach(int); void lortrequest(struct ifnet *, int, struct rtentry *); -int loinput(struct ifnet *, struct mbuf *, void *); +void loinput(struct ifnet *, struct mbuf *); int looutput(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); @@ -175,6 +175,7 @@ loop_clone_create(struct if_clone *ifc, ifp->if_xflags = IFXF_CLONED; ifp->if_rtrequest = lortrequest; ifp->if_ioctl = loioctl; + ifp->if_input = loinput; ifp->if_output = looutput; ifp->if_type = IFT_LOOP; ifp->if_hdrlen = sizeof(u_int32_t); @@ -188,7 +189,6 @@ loop_clone_create(struct if_clone *ifc, #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); #endif - if_ih_insert(ifp, loinput, NULL); return (0); } @@ -218,7 +218,6 @@ loop_clone_destroy(struct ifnet *ifp) rdomain = ifp->if_rdomain; } - if_ih_remove(ifp, loinput, NULL); if_detach(ifp); free(ifp, M_DEVBUF, sizeof(*ifp)); @@ -228,8 +227,8 @@ loop_clone_destroy(struct ifnet *ifp) return (0); } -int -loinput(struct ifnet *ifp, struct mbuf *m, void *cookie) +void +loinput(struct ifnet *ifp, struct mbuf *m) { int error; @@ -239,8 +238,6 @@ loinput(struct ifnet *ifp, struct mbuf * error = if_input_local(ifp, m, m->m_pkthdr.ph_family); if (error) ifp->if_ierrors++; - - return (1); } int Index: net/if_switch.c =================================================================== RCS file: /cvs/src/sys/net/if_switch.c,v retrieving revision 1.32 diff -u -p -r1.32 if_switch.c --- net/if_switch.c 13 Jul 2020 03:28:20 -0000 1.32 +++ net/if_switch.c 16 Jul 2020 00:07:34 -0000 @@ -68,7 +68,8 @@ int switch_port_add(struct switch_softc void switch_port_detach(void *); int switch_port_del(struct switch_softc *, struct ifbreq *); int switch_port_list(struct switch_softc *, struct ifbifconf *); -int switch_input(struct ifnet *, struct mbuf *, void *); +struct mbuf * + switch_input(struct ifnet *, struct mbuf *, void *); struct mbuf *switch_port_ingress(struct switch_softc *, struct ifnet *, struct mbuf *); @@ -119,6 +120,11 @@ struct rwlock switch_ifs_lk = RWLOCK_INI struct pool swfcl_pool; +const struct ether_brport switch_brport = { + switch_input, + NULL, +}; + void switchattach(int n) { @@ -509,9 +515,6 @@ switch_port_add(struct switch_softc *sc, if (ifs->if_type != IFT_ETHER) return (EPROTONOSUPPORT); - if (ifs->if_bridgeidx != 0) - return (EBUSY); - if (ifs->if_switchport != NULL) { swpo = (struct switch_port *)ifs->if_switchport; if (swpo->swpo_switch == sc) @@ -523,15 +526,22 @@ switch_port_add(struct switch_softc *sc, if ((error = ifpromisc(ifs, 1)) != 0) return (error); + error = ether_is_brport(ifs); + if (error != 0) { + ifpromisc(ifs, 0); + return (error); + } + swpo = malloc(sizeof(*swpo), M_DEVBUF, M_NOWAIT|M_ZERO); if (swpo == NULL) { ifpromisc(ifs, 0); return (ENOMEM); } + swpo->swpo_switch = sc; swpo->swpo_ifindex = ifs->if_index; ifs->if_switchport = (caddr_t)swpo; - if_ih_insert(ifs, switch_input, NULL); + ether_set_brport(ifs, &switch_brport); swpo->swpo_port_no = swofp_assign_portno(sc, ifs->if_index); task_set(&swpo->swpo_dtask, switch_port_detach, ifs); if_detachhook_add(ifs, &swpo->swpo_dtask); @@ -603,7 +613,7 @@ switch_port_detach(void *arg) ifp->if_switchport = NULL; if_detachhook_del(ifp, &swpo->swpo_dtask); ifpromisc(ifp, 0); - if_ih_remove(ifp, switch_input, NULL); + ether_clr_brport(ifp); TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next); free(swpo, M_DEVBUF, sizeof(*swpo)); } @@ -633,19 +643,19 @@ switch_port_del(struct switch_softc *sc, return (error); } -int -switch_input(struct ifnet *ifp, struct mbuf *m, void *cookie) +struct mbuf * +switch_input(struct ifnet *ifp, struct mbuf *m, void *null) { KASSERT(m->m_flags & M_PKTHDR); if (m->m_flags & M_PROTO1) { m->m_flags &= ~M_PROTO1; - return (0); + return (m); } niq_enqueue(&switchintrq, m); - return (1); + return (NULL); } Index: net/if_tpmr.c =================================================================== RCS file: /cvs/src/sys/net/if_tpmr.c,v retrieving revision 1.11 diff -u -p -r1.11 if_tpmr.c --- net/if_tpmr.c 10 Jul 2020 13:26:42 -0000 1.11 +++ net/if_tpmr.c 16 Jul 2020 00:07:34 -0000 @@ -91,6 +91,8 @@ struct tpmr_port { struct tpmr_softc *p_tpmr; unsigned int p_slot; + + struct ether_brport p_brport; }; struct tpmr_softc { @@ -281,10 +283,10 @@ tpmr_pf(struct ifnet *ifp0, int dir, str } #endif /* NPF > 0 */ -static int -tpmr_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +static struct mbuf * +tpmr_input(struct ifnet *ifp0, struct mbuf *m, void *brport) { - struct tpmr_port *p = cookie; + struct tpmr_port *p = brport; struct tpmr_softc *sc = p->p_tpmr; struct ifnet *ifp = &sc->sc_if; struct tpmr_port *pn; @@ -317,7 +319,7 @@ tpmr_input(struct ifnet *ifp0, struct mb #if NPF > 0 if (!ISSET(ifp->if_flags, IFF_LINK1) && (m = tpmr_pf(ifp0, PF_IN, m)) == NULL) - return (1); + return (NULL); #endif len = m->m_pkthdr.len; @@ -353,11 +355,11 @@ tpmr_input(struct ifnet *ifp0, struct mb } smr_read_leave(); - return (1); + return (NULL); drop: m_freem(m); - return (1); + return (NULL); } static int @@ -520,7 +522,6 @@ tpmr_add_port(struct tpmr_softc *sc, con { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0; - struct arpcom *ac0; struct tpmr_port **pp; struct tpmr_port *p; int i; @@ -537,9 +538,9 @@ tpmr_add_port(struct tpmr_softc *sc, con if (ifp0->if_type != IFT_ETHER) return (EPROTONOSUPPORT); - ac0 = (struct arpcom *)ifp0; - if (ac0->ac_trunkport != NULL) - return (EBUSY); + error = ether_is_brport(ifp0); + if (error != 0) + return (error); /* let's try */ @@ -565,12 +566,20 @@ tpmr_add_port(struct tpmr_softc *sc, con if (error != 0) goto free; + /* this might have changed if we slept for malloc or ifpromisc */ + error = ether_is_brport(ifp0); + if (error != 0) + goto unpromisc; + task_set(&p->p_ltask, tpmr_p_linkch, p); if_linkstatehook_add(ifp0, &p->p_ltask); task_set(&p->p_dtask, tpmr_p_detach, p); if_detachhook_add(ifp0, &p->p_dtask); + p->p_brport.eb_input = tpmr_input; + p->p_brport.eb_port = p; + /* commit */ DPRINTF(sc, "%s %s trunkport: creating port\n", ifp->if_xname, ifp0->if_xname); @@ -584,12 +593,9 @@ tpmr_add_port(struct tpmr_softc *sc, con p->p_slot = i; - ac0->ac_trunkport = p; - /* make sure p is visible before handlers can run */ - membar_producer(); + ether_set_brport(ifp0, &p->p_brport); ifp0->if_ioctl = tpmr_p_ioctl; ifp0->if_output = tpmr_p_output; - if_ih_insert(ifp0, tpmr_input, p); SMR_PTR_SET_LOCKED(pp, p); @@ -597,6 +603,8 @@ tpmr_add_port(struct tpmr_softc *sc, con return (0); +unpromisc: + ifpromisc(ifp0, 0); free: free(p, M_DEVBUF, sizeof(*p)); put: @@ -654,10 +662,19 @@ tpmr_del_port(struct tpmr_softc *sc, con static int tpmr_p_ioctl(struct ifnet *ifp0, u_long cmd, caddr_t data) { - struct arpcom *ac0 = (struct arpcom *)ifp0; - struct tpmr_port *p = ac0->ac_trunkport; + const struct ether_brport *eb = ether_get_brport_locked(ifp0); + struct tpmr_port *p; int error = 0; + KASSERTMSG(eb != NULL, + "%s: %s called without an ether_brport set", + ifp0->if_xname, __func__); + KASSERTMSG(eb->eb_input == tpmr_input, + "%s: %s called, but eb_input seems wrong (%p != tpmr_input())", + ifp0->if_xname, __func__, eb->eb_input); + + p = eb->eb_port; + switch (cmd) { case SIOCSIFADDR: error = EBUSY; @@ -674,6 +691,7 @@ tpmr_p_ioctl(struct ifnet *ifp0, u_long CTASSERT(sizeof(rp->rp_ifname) == sizeof(ifp->if_xname)); memcpy(rp->rp_ifname, ifp->if_xname, sizeof(rp->rp_ifname)); + break; } @@ -689,8 +707,9 @@ static int tpmr_p_output(struct ifnet *ifp0, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { - struct arpcom *ac0 = (struct arpcom *)ifp0; - struct tpmr_port *p = ac0->ac_trunkport; + int (*p_output)(struct ifnet *, struct mbuf *, struct sockaddr *, + struct rtentry *) = NULL; + const struct ether_brport *eb; /* restrict transmission to bpf only */ if ((m_tag_find(m, PACKET_TAG_DLT, NULL) == NULL)) { @@ -698,7 +717,20 @@ tpmr_p_output(struct ifnet *ifp0, struct return (EBUSY); } - return ((*p->p_output)(ifp0, m, dst, rt)); + smr_read_enter(); + eb = ether_get_brport(ifp0); + if (eb != NULL && eb->eb_input == tpmr_input) { + struct tpmr_port *p = eb->eb_port; + p_output = p->p_output; /* code doesn't go away */ + } + smr_read_leave(); + + if (p_output == NULL) { + m_freem(m); + return (ENXIO); + } + + return ((*p_output)(ifp0, m, dst, rt)); } static void @@ -706,18 +738,14 @@ tpmr_p_dtor(struct tpmr_softc *sc, struc { struct ifnet *ifp = &sc->sc_if; struct ifnet *ifp0 = p->p_ifp0; - struct arpcom *ac0 = (struct arpcom *)ifp0; DPRINTF(sc, "%s %s: destroying port\n", ifp->if_xname, ifp0->if_xname); - if_ih_remove(ifp0, tpmr_input, p); - ifp0->if_ioctl = p->p_ioctl; ifp0->if_output = p->p_output; - membar_producer(); - ac0->ac_trunkport = NULL; + ether_clr_brport(ifp0); sc->sc_nports--; SMR_PTR_SET_LOCKED(&sc->sc_ports[p->p_slot], NULL); Index: net/if_trunk.c =================================================================== RCS file: /cvs/src/sys/net/if_trunk.c,v retrieving revision 1.147 diff -u -p -r1.147 if_trunk.c --- net/if_trunk.c 10 Jul 2020 13:22:22 -0000 1.147 +++ net/if_trunk.c 16 Jul 2020 00:07:34 -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); -int trunk_input(struct ifnet *, struct mbuf *, void *); +void trunk_input(struct ifnet *, struct mbuf *); void trunk_start(struct ifnet *); void trunk_init(struct ifnet *); void trunk_stop(struct ifnet *); @@ -380,9 +380,11 @@ trunk_port_create(struct trunk_softc *tr if (tr->tr_port_create != NULL) error = (*tr->tr_port_create)(tp); - ac0->ac_trunkport = tp; /* Change input handler of the physical interface. */ - if_ih_insert(ifp, trunk_input, tp); + tp->tp_input = ifp->if_input; + NET_ASSERT_LOCKED(); + ac0->ac_trunkport = tp; + ifp->if_input = trunk_input; return (error); } @@ -413,7 +415,8 @@ trunk_port_destroy(struct trunk_port *tp struct arpcom *ac0 = (struct arpcom *)ifp; /* Restore previous input handler. */ - if_ih_remove(ifp, trunk_input, tp); + NET_ASSERT_LOCKED(); + ifp->if_input = tp->tp_input; ac0->ac_trunkport = NULL; /* Remove multicast addresses from this port */ @@ -649,15 +652,24 @@ trunk_ioctl(struct ifnet *ifp, u_long cm error = EPROTONOSUPPORT; break; } + /* + * Use of ifp->if_input and ac->ac_trunkport is + * protected by NET_LOCK, but that may not be true + * in the future. The below comment and code flow is + * maintained to help in that future. + * * Serialize modifications to the trunk and trunk * ports via the ifih SRP: detaching trunk_input * from the trunk port will require all currently * running trunk_input's on this port to finish * granting us an exclusive access to it. */ - SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) - if_ih_remove(tp->tp_if, trunk_input, tp); + NET_ASSERT_LOCKED(); + SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) { + /* if_ih_remove(tp->tp_if, trunk_input, tp); */ + tp->tp_if->if_input = tp->tp_input; + } if (tr->tr_proto != TRUNK_PROTO_NONE) error = tr->tr_detach(tr); if (error != 0) @@ -671,9 +683,11 @@ trunk_ioctl(struct ifnet *ifp, u_long cm tr->tr_proto = trunk_protos[i].ti_proto; if (tr->tr_proto != TRUNK_PROTO_NONE) error = trunk_protos[i].ti_attach(tr); - SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) - if_ih_insert(tp->tp_if, - trunk_input, tp); + SLIST_FOREACH(tp, &tr->tr_ports, tp_entries) { + /* if_ih_insert(tp->tp_if, + trunk_input, tp); */ + tp->tp_if->if_input = trunk_input; + } /* Update trunk capabilities */ tr->tr_capabilities = trunk_capabilities(tr); goto out; @@ -1118,14 +1132,18 @@ trunk_stop(struct ifnet *ifp) (*tr->tr_stop)(tr); } -int -trunk_input(struct ifnet *ifp, struct mbuf *m, void *cookie) +void +trunk_input(struct ifnet *ifp, struct mbuf *m) { - struct trunk_softc *tr; + struct arpcom *ac0 = (struct arpcom *)ifp; struct trunk_port *tp; + struct trunk_softc *tr; struct ifnet *trifp = NULL; struct ether_header *eh; + if (m->m_len < sizeof(*eh)) + goto bad; + eh = mtod(m, struct ether_header *); if (ETHER_IS_MULTICAST(eh->ether_dhost)) ifp->if_imcasts++; @@ -1134,7 +1152,7 @@ trunk_input(struct ifnet *ifp, struct mb if (ifp->if_type != IFT_IEEE8023ADLAG) goto bad; - tp = (struct trunk_port *)cookie; + tp = (struct trunk_port *)ac0->ac_trunkport; if ((tr = (struct trunk_softc *)tp->tp_trunk) == NULL) goto bad; @@ -1147,7 +1165,7 @@ trunk_input(struct ifnet *ifp, struct mb * We stop here if the packet has been consumed * by the protocol routine. */ - return (1); + return; } if ((trifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) @@ -1163,19 +1181,18 @@ trunk_input(struct ifnet *ifp, struct mb if (bcmp(&tr->tr_ac.ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN)) { m_freem(m); - return (1); + return; } } if_vinput(trifp, m); - return (1); + return; bad: if (trifp != NULL) trifp->if_ierrors++; m_freem(m); - return (1); } int Index: net/if_trunk.h =================================================================== RCS file: /cvs/src/sys/net/if_trunk.h,v retrieving revision 1.29 diff -u -p -r1.29 if_trunk.h --- net/if_trunk.h 7 Nov 2019 07:36:32 -0000 1.29 +++ net/if_trunk.h 16 Jul 2020 00:07:34 -0000 @@ -172,6 +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 *); SLIST_ENTRY(trunk_port) tp_entries; }; Index: net/if_tun.c =================================================================== RCS file: /cvs/src/sys/net/if_tun.c,v retrieving revision 1.224 diff -u -p -r1.224 if_tun.c --- net/if_tun.c 10 Jul 2020 13:26:42 -0000 1.224 +++ net/if_tun.c 16 Jul 2020 00:07:34 -0000 @@ -115,7 +115,7 @@ int tun_dev_poll(dev_t, int, struct proc int tun_dev_kqfilter(dev_t, struct knote *); int tun_ioctl(struct ifnet *, u_long, caddr_t); -int tun_input(struct ifnet *, struct mbuf *, void *); +void tun_input(struct ifnet *, struct mbuf *); int tun_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); int tun_enqueue(struct ifnet *, struct mbuf *); @@ -240,6 +240,7 @@ tun_create(struct if_clone *ifc, int uni if_counters_alloc(ifp); if ((flags & TUN_LAYER2) == 0) { + ifp->if_input = tun_input; ifp->if_output = tun_output; ifp->if_mtu = ETHERMTU; ifp->if_flags = (IFF_POINTOPOINT|IFF_MULTICAST); @@ -253,8 +254,6 @@ tun_create(struct if_clone *ifc, int uni #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t)); #endif - - if_ih_insert(ifp, tun_input, NULL); } else { sc->sc_flags |= TUN_LAYER2; ether_fakeaddr(ifp); @@ -320,9 +319,7 @@ tun_clone_destroy(struct ifnet *ifp) klist_invalidate(&sc->sc_wsel.si_note); splx(s); - if (!ISSET(sc->sc_flags, TUN_LAYER2)) - if_ih_remove(ifp, tun_input, NULL); - else + if (ISSET(sc->sc_flags, TUN_LAYER2)) ether_ifdetach(ifp); if_detach(ifp); @@ -880,8 +877,8 @@ put: return (error); } -int -tun_input(struct ifnet *ifp, struct mbuf *m0, void *cookie) +void +tun_input(struct ifnet *ifp, struct mbuf *m0) { uint32_t af; @@ -909,8 +906,6 @@ tun_input(struct ifnet *ifp, struct mbuf m_freem(m0); break; } - - return (1); } /* Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.109 diff -u -p -r1.109 if_var.h --- net/if_var.h 10 Jul 2020 13:26:42 -0000 1.109 +++ net/if_var.h 16 Jul 2020 00:07:34 -0000 @@ -159,7 +159,7 @@ struct ifnet { /* and the entries */ struct task if_linkstatetask; /* [I] task to do route updates */ /* procedure handles */ - SRPL_HEAD(, ifih) if_inputs; /* [K] input routines (dequeue) */ + void (*if_input)(struct ifnet *, struct mbuf *); int (*if_output)(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); /* output routine (enqueue) */ /* link level output function */ @@ -345,11 +345,6 @@ void ifa_add(struct ifnet *, struct ifad void ifa_del(struct ifnet *, struct ifaddr *); void ifa_update_broadaddr(struct ifnet *, struct ifaddr *, struct sockaddr *); - -void if_ih_insert(struct ifnet *, int (*)(struct ifnet *, struct mbuf *, - void *), void *); -void if_ih_remove(struct ifnet *, int (*)(struct ifnet *, struct mbuf *, - void *), void *); void if_addrhook_add(struct ifnet *, struct task *); void if_addrhook_del(struct ifnet *, struct task *); Index: net/if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.203 diff -u -p -r1.203 if_vlan.c --- net/if_vlan.c 1 Feb 2020 10:27:40 -0000 1.203 +++ net/if_vlan.c 16 Jul 2020 00:07:34 -0000 @@ -119,7 +119,6 @@ void vlanattach(int count); int vlan_clone_create(struct if_clone *, int); int vlan_clone_destroy(struct ifnet *); -int vlan_input(struct ifnet *, struct mbuf *, void *); int vlan_enqueue(struct ifnet *, struct mbuf *); void vlan_start(struct ifqueue *ifq); int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr); @@ -358,44 +357,45 @@ vlan_inject(struct mbuf *m, uint16_t typ return (m); } -/* - * vlan_input() returns 1 if it has consumed the packet, 0 otherwise. - */ -int -vlan_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +struct mbuf * +vlan_input(struct ifnet *ifp0, struct mbuf *m) { struct vlan_softc *sc; + struct ifnet *ifp; struct ether_vlan_header *evl; - struct ether_header *eh; struct vlan_list *tagh, *list; - uint16_t tag; + uint16_t vtag, tag; uint16_t etype; int rxprio; - eh = mtod(m, struct ether_header *); - etype = ntohs(eh->ether_type); - if (m->m_flags & M_VLANTAG) { + vtag = m->m_pkthdr.ether_vtag; etype = ETHERTYPE_VLAN; tagh = vlan_tagh; - } else if ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ)) { - if (m->m_len < sizeof(*evl) && - (m = m_pullup(m, sizeof(*evl))) == NULL) { - ifp0->if_ierrors++; - return (1); + } else { + if (m->m_len < sizeof(*evl)) { + m = m_pullup(m, sizeof(*evl)); + if (m == NULL) + return (NULL); } evl = mtod(m, struct ether_vlan_header *); - m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag); - tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh; - } else { - /* Skip non-VLAN packets. */ - return (0); + vtag = bemtoh16(&evl->evl_tag); + etype = bemtoh16(&evl->evl_encap_proto); + switch (etype) { + case ETHERTYPE_VLAN: + tagh = vlan_tagh; + break; + case ETHERTYPE_QINQ: + tagh = svlan_tagh; + break; + default: + panic("%s: unexpected etype 0x%04x", __func__, etype); + /* NOTREACHED */ + } } - /* From now on ether_vtag is fine */ - tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag); - + tag = EVL_VLANOFTAG(vtag); list = &tagh[TAG_HASH(tag)]; smr_read_enter(); SMR_SLIST_FOREACH(sc, list, sc_list) { @@ -407,7 +407,11 @@ vlan_input(struct ifnet *ifp0, struct mb } smr_read_leave(); - if (sc == NULL || !ISSET(sc->sc_if.if_flags, IFF_RUNNING)) { + if (sc == NULL) + return (m); /* decline, let bridge have a go */ + + ifp = &sc->sc_if; + if (!ISSET(ifp->if_flags, IFF_RUNNING)) { m_freem(m); goto leave; } @@ -417,11 +421,11 @@ vlan_input(struct ifnet *ifp0, struct mb * the given source interface and vlan tag, remove the * encapsulation. */ - if (m->m_flags & M_VLANTAG) { - m->m_flags &= ~M_VLANTAG; + if (ISSET(m->m_flags, M_VLANTAG)) { + CLR(m->m_flags, M_VLANTAG); } else { - eh->ether_type = evl->evl_proto; - memmove((char *)eh + EVL_ENCAPLEN, eh, sizeof(*eh)); + memmove((caddr_t)evl + EVL_ENCAPLEN, evl, + offsetof(struct ether_vlan_header, evl_encap_proto)); m_adj(m, EVL_ENCAPLEN); } @@ -440,11 +444,10 @@ vlan_input(struct ifnet *ifp0, struct mb break; } - if_vinput(&sc->sc_if, m); + if_vinput(ifp, m); leave: - if (sc != NULL) - refcnt_rele_wake(&sc->sc_refcnt); - return (1); + refcnt_rele_wake(&sc->sc_refcnt); + return (NULL); } int @@ -530,8 +533,6 @@ vlan_up(struct vlan_softc *sc) /* configure the parent to handle packets for this vlan */ vlan_multi_apply(sc, ifp0, SIOCADDMULTI); - if_ih_insert(ifp0, vlan_input, NULL); - /* we're running now */ SET(ifp->if_flags, IFF_RUNNING); vlan_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate); @@ -574,7 +575,6 @@ vlan_down(struct vlan_softc *sc) ifp0 = if_get(sc->sc_ifidx0); if (ifp0 != NULL) { - if_ih_remove(ifp0, vlan_input, NULL); if (ISSET(sc->sc_flags, IFVF_PROMISC)) ifpromisc(ifp0, 0); vlan_multi_apply(sc, ifp0, SIOCDELMULTI); Index: net/if_vlan_var.h =================================================================== RCS file: /cvs/src/sys/net/if_vlan_var.h,v retrieving revision 1.41 diff -u -p -r1.41 if_vlan_var.h --- net/if_vlan_var.h 27 Apr 2019 04:46:03 -0000 1.41 +++ net/if_vlan_var.h 16 Jul 2020 00:07:34 -0000 @@ -47,6 +47,7 @@ struct vlanreq { }; #ifdef _KERNEL +struct mbuf *vlan_input(struct ifnet *, struct mbuf *); struct mbuf *vlan_inject(struct mbuf *, uint16_t, uint16_t); #endif /* _KERNEL */ Index: netinet/if_ether.h =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.h,v retrieving revision 1.76 diff -u -p -r1.76 if_ether.h --- netinet/if_ether.h 17 Jul 2019 16:46:18 -0000 1.76 +++ netinet/if_ether.h 16 Jul 2020 00:07:34 -0000 @@ -199,6 +199,11 @@ do { \ #include /* for "struct ifnet" */ +struct ether_brport { + struct mbuf *(*eb_input)(struct ifnet *, struct mbuf *, void *); + void *eb_port; +}; + /* * Structure shared between the ethernet driver modules and * the address resolution code. For example, each ec_softc or il_softc @@ -213,6 +218,7 @@ struct arpcom { int ac_multirangecnt; /* number of mcast ranges */ void *ac_trunkport; + const struct ether_brport *ac_brport; }; extern int arpt_keep; /* arp resolved cache expire */ @@ -247,7 +253,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); -int ether_input(struct ifnet *, struct mbuf *, void *); +void ether_input(struct ifnet *, struct mbuf *); int ether_resolve(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *, struct ether_header *); struct mbuf * @@ -258,6 +264,13 @@ int ether_output(struct ifnet *, struct void ether_rtrequest(struct ifnet *, int, struct rtentry *); char *ether_sprintf(u_char *); +int ether_is_brport(struct ifnet *); +void ether_set_brport(struct ifnet *, const struct ether_brport *); +void ether_clr_brport(struct ifnet *); +const struct ether_brport * + ether_get_brport(struct ifnet *); +const struct ether_brport * + ether_get_brport_locked(struct ifnet *); /* * Ethernet multicast address structure. There is one of these for each Index: netinet/ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.345 diff -u -p -r1.345 ip_carp.c --- netinet/ip_carp.c 21 May 2020 05:24:59 -0000 1.345 +++ netinet/ip_carp.c 16 Jul 2020 00:07:34 -0000 @@ -208,7 +208,6 @@ void carp_hmac_generate(struct carp_vhos unsigned char *, u_int8_t); int carp_hmac_verify(struct carp_vhost_entry *, u_int32_t *, unsigned char *); -int carp_input(struct ifnet *, struct mbuf *, void *); void carp_proto_input_c(struct ifnet *, struct mbuf *, struct carp_header *, int, sa_family_t); int carp_proto_input_if(struct ifnet *, struct mbuf **, int *, int); @@ -949,9 +948,6 @@ carpdetach(void *arg) cif = &ifp0->if_carp; - /* Restore previous input handler. */ - if_ih_remove(ifp0, carp_input, NULL); - SRPL_REMOVE_LOCKED(&carp_sc_rc, cif, sc, carp_softc, sc_list); sc->sc_carpdev = NULL; @@ -1376,23 +1372,14 @@ carp_vhe_match(struct carp_softc *sc, ui return (match); } -int -carp_input(struct ifnet *ifp0, struct mbuf *m, void *cookie) +struct mbuf * +carp_input(struct ifnet *ifp0, struct mbuf *m) { struct ether_header *eh; struct srpl *cif; struct carp_softc *sc; struct srp_ref sr; -#if NVLAN > 0 - /* - * If the underlying interface removed the VLAN header itself, - * it's not for us. - */ - if (ISSET(m->m_flags, M_VLANTAG)) - return (0); -#endif - eh = mtod(m, struct ether_header *); cif = &ifp0->if_carp; @@ -1426,7 +1413,7 @@ carp_input(struct ifnet *ifp0, struct mb SRPL_LEAVE(&sr); if (!ETHER_IS_MULTICAST(eh->ether_dhost)) - return (0); + return (m); /* * XXX Should really check the list of multicast addresses @@ -1446,14 +1433,14 @@ carp_input(struct ifnet *ifp0, struct mb } SRPL_LEAVE(&sr); - return (0); + return (m); } if_vinput(&sc->sc_if, m); out: SRPL_LEAVE(&sr); - return (1); + return (NULL); } int @@ -1731,9 +1718,6 @@ carp_set_ifp(struct carp_softc *sc, stru if (sc->sc_naddrs || sc->sc_naddrs6) sc->sc_if.if_flags |= IFF_UP; carp_set_enaddr(sc); - - /* Change input handler of the physical interface. */ - if_ih_insert(ifp0, carp_input, NULL); carp_carpdev_state(sc); Index: netinet/ip_carp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.h,v retrieving revision 1.48 diff -u -p -r1.48 ip_carp.h --- netinet/ip_carp.h 8 Dec 2019 11:08:22 -0000 1.48 +++ netinet/ip_carp.h 16 Jul 2020 00:07:34 -0000 @@ -207,6 +207,8 @@ carp_strict_addr_chk(struct ifnet *ifp_a ifp_a->if_carpdev == ifp_b->if_carpdev)); } +struct mbuf *carp_input(struct ifnet *, struct mbuf *); + int carp_proto_input(struct mbuf **, int *, int, int); void carp_carpdev_state(void *); void carp_group_demote_adj(struct ifnet *, int, char *); Index: dev/usb/if_umb.c =================================================================== RCS file: /cvs/src/sys/dev/usb/if_umb.c,v retrieving revision 1.35 diff -u -p -r1.35 if_umb.c --- dev/usb/if_umb.c 10 Jul 2020 13:26:41 -0000 1.35 +++ dev/usb/if_umb.c 16 Jul 2020 00:07:34 -0000 @@ -137,7 +137,7 @@ void umb_close_bulkpipes(struct umb_so int umb_ioctl(struct ifnet *, u_long, caddr_t); int umb_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); -int umb_input(struct ifnet *, struct mbuf *, void *); +void umb_input(struct ifnet *, struct mbuf *); void umb_start(struct ifnet *); void umb_rtrequest(struct ifnet *, int, struct rtentry *); void umb_watchdog(struct ifnet *); @@ -522,9 +522,9 @@ umb_attach(struct device *parent, struct sizeof (struct ncm_pointer16); ifp->if_mtu = 1500; /* use a common default */ ifp->if_hardmtu = sc->sc_maxpktlen; + ifp->if_input = umb_input; ifp->if_output = umb_output; if_attach(ifp); - if_ih_insert(ifp, umb_input, NULL); if_alloc_sadl(ifp); ifp->if_softc = sc; #if NBPFILTER > 0 @@ -575,7 +575,6 @@ umb_detach(struct device *self, int flag sc->sc_resp_buf = NULL; } if (ifp->if_softc != NULL) { - if_ih_remove(ifp, umb_input, NULL); if_detach(ifp); } @@ -775,21 +774,21 @@ umb_output(struct ifnet *ifp, struct mbu return if_enqueue(ifp, m); } -int -umb_input(struct ifnet *ifp, struct mbuf *m, void *cookie) +void +umb_input(struct ifnet *ifp, struct mbuf *m) { uint32_t af; if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); - return 1; + return; } if (m->m_pkthdr.len < sizeof (struct ip) + sizeof(af)) { ifp->if_ierrors++; DPRINTFN(4, "%s: dropping short packet (len %d)\n", __func__, m->m_pkthdr.len); m_freem(m); - return 1; + return; } m->m_pkthdr.ph_rtableid = ifp->if_rdomain; @@ -802,20 +801,19 @@ umb_input(struct ifnet *ifp, struct mbuf switch (af) { case AF_INET: ipv4_input(ifp, m); - return 1; + return; #ifdef INET6 case AF_INET6: ipv6_input(ifp, m); - return 1; + return; #endif /* INET6 */ default: ifp->if_ierrors++; DPRINTFN(4, "%s: dropping packet with bad IP version (af %d)\n", __func__, af); m_freem(m); - return 1; + return; } - return 1; } static inline int