Like vlan(4) and carp(4), bridge(4) also need to be tweaked to still work during the if_input() transition. Removing the ether_input() calls in this driver was a bit tricky *because* bridge_input() is called after ether_input().
See how 3 M_PREPEND() are converted to 1? And soon none will be required. Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.233 diff -u -p -r1.233 if_bridge.c --- net/if_bridge.c 7 Apr 2015 10:46:20 -0000 1.233 +++ net/if_bridge.c 9 Apr 2015 13:56:07 -0000 @@ -115,8 +115,7 @@ void bridge_broadcast(struct bridge_soft struct ether_header *, struct mbuf *); void bridge_localbroadcast(struct bridge_softc *, struct ifnet *, struct ether_header *, struct mbuf *); -void bridge_span(struct bridge_softc *, struct ether_header *, - struct mbuf *); +void bridge_span(struct bridge_softc *, struct mbuf *); void bridge_stop(struct bridge_softc *); void bridge_init(struct bridge_softc *); int bridge_bifconf(struct bridge_softc *, struct ifbifconf *); @@ -1004,7 +1003,7 @@ bridge_output(struct ifnet *ifp, struct return (0); } #endif /* IPSEC */ - bridge_span(sc, NULL, m); + bridge_span(sc, m); TAILQ_FOREACH(p, &sc->sc_iflist, next) { dst_if = p->ifp; @@ -1080,7 +1079,7 @@ sendunicast: (sa = bridge_tunneltag(m, dst_p->brt_tunnel.sa.sa_family)) != NULL) memcpy(sa, &dst_p->brt_tunnel.sa, dst_p->brt_tunnel.sa.sa_len); - bridge_span(sc, NULL, m); + bridge_span(sc, m); if ((dst_if->if_flags & IFF_RUNNING) == 0) { m_freem(m); return (ENETDOWN); @@ -1296,9 +1295,10 @@ bridgeintr_frame(struct bridge_softc *sc * not for us, and schedule an interrupt. */ struct mbuf * -bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) +bridge_input(struct ifnet *ifp, struct ether_header *eh0, struct mbuf *m) { struct bridge_softc *sc; + struct ether_header *eh; int s; struct bridge_iflist *ifl, *srcifl; struct arpcom *ac; @@ -1320,13 +1320,18 @@ bridge_input(struct ifnet *ifp, struct e if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) return (m); + M_PREPEND(m, sizeof(*eh), M_DONTWAIT); + if (m == NULL) + return (NULL); + eh = mtod(m, struct ether_header *); + memmove(eh, eh0, sizeof(*eh)); + #if NBPFILTER > 0 if (sc->sc_if.if_bpf) - bpf_mtap_hdr(sc->sc_if.if_bpf, (caddr_t)eh, - ETHER_HDR_LEN, m, BPF_DIRECTION_IN, NULL); + bpf_mtap_ether(sc->sc_if.if_bpf, m, BPF_DIRECTION_IN); #endif - bridge_span(sc, eh, m); + bridge_span(sc, m); if (m->m_flags & (M_BCAST | M_MCAST)) { /* @@ -1356,18 +1361,9 @@ bridge_input(struct ifnet *ifp, struct e (ifl->bif_state == BSTP_IFSTATE_DISCARDING)) return (m); - /* - * make a copy of 'm' with 'eh' tacked on to the - * beginning. Return 'm' for local processing - * and enqueue the copy. Schedule netisr. - */ mc = m_copym2(m, 0, M_COPYALL, M_NOWAIT); if (mc == NULL) return (m); - M_PREPEND(mc, ETHER_HDR_LEN, M_DONTWAIT); - if (mc == NULL) - return (m); - bcopy(eh, mtod(mc, caddr_t), ETHER_HDR_LEN); s = splnet(); if (IF_QFULL(&sc->sc_if.if_snd)) { m_freem(mc); @@ -1387,11 +1383,11 @@ bridge_input(struct ifnet *ifp, struct e m->m_pkthdr.ph_rtableid = ifl->ifp->if_rdomain; #if NBPFILTER > 0 if (ifl->ifp->if_bpf) - bpf_mtap(ifl->ifp->if_bpf, m, + bpf_mtap_ether(ifl->ifp->if_bpf, m, BPF_DIRECTION_IN); #endif m->m_flags |= M_PROTO1; - ether_input(m, eh); + ether_input_mbuf(ifl->ifp, m); ifl->ifp->if_ipackets++; m = NULL; } @@ -1434,21 +1430,21 @@ bridge_input(struct ifnet *ifp, struct e * is aware */ #if NBPFILTER > 0 if (ifl->ifp->if_bpf) - bpf_mtap_hdr(ifl->ifp->if_bpf, (caddr_t)eh, - ETHER_HDR_LEN, m, BPF_DIRECTION_IN, NULL); + bpf_mtap_ether(ifl->ifp->if_bpf, m, + BPF_DIRECTION_IN); #endif /* Count for the interface we are going to */ ifl->ifp->if_ipackets++; /* Count for the bridge */ sc->sc_if.if_ipackets++; - sc->sc_if.if_ibytes += ETHER_HDR_LEN + m->m_pkthdr.len; + sc->sc_if.if_ibytes += m->m_pkthdr.len; m->m_pkthdr.rcvif = ifl->ifp; m->m_pkthdr.ph_rtableid = ifl->ifp->if_rdomain; if (ifp->if_type == IFT_GIF) { m->m_flags |= M_PROTO1; - ether_input(m, eh); + ether_input_mbuf(ifl->ifp, m); m = NULL; } return (m); @@ -1463,10 +1459,6 @@ bridge_input(struct ifnet *ifp, struct e return (NULL); } } - M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT); - if (m == NULL) - return (NULL); - bcopy(eh, mtod(m, caddr_t), ETHER_HDR_LEN); s = splnet(); if (IF_QFULL(&sc->sc_if.if_snd)) { m_freem(m); @@ -1624,13 +1616,12 @@ bridge_localbroadcast(struct bridge_soft BPF_DIRECTION_IN); #endif - ether_input(m1, NULL); + ether_input_mbuf(ifp, m1); ifp->if_ipackets++; } void -bridge_span(struct bridge_softc *sc, struct ether_header *eh, - struct mbuf *morig) +bridge_span(struct bridge_softc *sc, struct mbuf *morig) { struct bridge_iflist *p; struct ifnet *ifp; @@ -1643,12 +1634,6 @@ bridge_span(struct bridge_softc *sc, str m = m_copym2(morig, 0, M_COPYALL, M_NOWAIT); if (m == NULL) return; - if (eh != NULL) { - M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT); - if (m == NULL) - return; - bcopy(eh, mtod(m, caddr_t), ETHER_HDR_LEN); - } TAILQ_FOREACH(p, &sc->sc_spanlist, next) { ifp = p->ifp; Index: net/bridgestp.c =================================================================== RCS file: /cvs/src/sys/net/bridgestp.c,v retrieving revision 1.52 diff -u -p -r1.52 bridgestp.c --- net/bridgestp.c 14 Mar 2015 03:38:51 -0000 1.52 +++ net/bridgestp.c 9 Apr 2015 13:17:52 -0000 @@ -596,6 +596,9 @@ bstp_input(struct bstp_state *bs, struct len = ntohs(eh->ether_type); if (len < sizeof(tpdu)) goto out; + + m_adj(m, ETHER_HDR_LEN); + if (m->m_pkthdr.len > len) m_adj(m, len - m->m_pkthdr.len); if ((m = m_pullup(m, sizeof(tpdu))) == NULL) Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.191 diff -u -p -r1.191 if_ethersubr.c --- net/if_ethersubr.c 7 Apr 2015 10:46:20 -0000 1.191 +++ net/if_ethersubr.c 9 Apr 2015 13:56:52 -0000 @@ -559,6 +559,7 @@ ether_input(struct mbuf *m, void *hdr) return (1); /* The bridge has determined it's for us. */ ifp = m->m_pkthdr.rcvif; + m_adj(m, ETHER_HDR_LEN); } } #endif