On 21/04/15(Tue) 12:35, Martin Pieuchot wrote:
> This diff adds the necessary glue to bridge(4) to be able to convert
> other pseudo-drivers to if_input(). This will also help bridge(4)'s
> own conversion.
>
> Since bridge_input() already returns a mbuf, I believe this change is
> less error prone than the carp(4) one. But I appreciate reviews,
> tests and oks.
Anybody?
>
> 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 20 Apr 2015 11:35:56 -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_bridge.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_bridge.c,v
> retrieving revision 1.235
> diff -u -p -r1.235 if_bridge.c
> --- net/if_bridge.c 17 Apr 2015 11:04:01 -0000 1.235
> +++ net/if_bridge.c 20 Apr 2015 11:55:38 -0000
> @@ -115,10 +115,9 @@ 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 *);
> struct mbuf *bridge_dispatch(struct bridge_iflist *, struct ifnet *,
> - struct ether_header *, struct mbuf *);
> + struct mbuf *);
> void bridge_stop(struct bridge_softc *);
> void bridge_init(struct bridge_softc *);
> int bridge_bifconf(struct bridge_softc *, struct ifbifconf *);
> @@ -180,6 +179,7 @@ int
> bridge_clone_create(struct if_clone *ifc, int unit)
> {
> struct bridge_softc *sc;
> + struct ifih *bridge_ifih;
> struct ifnet *ifp;
> int i, s;
>
> @@ -187,8 +187,15 @@ bridge_clone_create(struct if_clone *ifc
> if (!sc)
> return (ENOMEM);
>
> + bridge_ifih = malloc(sizeof(*bridge_ifih), M_DEVBUF, M_NOWAIT);
> + if (bridge_ifih == NULL) {
> + free(sc, M_DEVBUF, 0);
> + return (ENOMEM);
> + }
> +
> sc->sc_stp = bstp_create(&sc->sc_if);
> if (!sc->sc_stp) {
> + free(bridge_ifih, M_DEVBUF, sizeof(*bridge_ifih));
> free(sc, M_DEVBUF, 0);
> return (ENOMEM);
> }
> @@ -222,6 +229,9 @@ bridge_clone_create(struct if_clone *ifc
> DLT_EN10MB, ETHER_HDR_LEN);
> #endif
>
> + bridge_ifih->ifih_input = ether_input;
> + SLIST_INSERT_HEAD(&ifp->if_inputs, bridge_ifih, ifih_next);
> +
> s = splnet();
> LIST_INSERT_HEAD(&bridge_list, sc, sc_list);
> splx(s);
> @@ -234,6 +244,7 @@ bridge_clone_destroy(struct ifnet *ifp)
> {
> struct bridge_softc *sc = ifp->if_softc;
> struct bridge_iflist *bif;
> + struct ifih *bridge_ifih;
> int s;
>
> bridge_stop(sc);
> @@ -250,6 +261,17 @@ bridge_clone_destroy(struct ifnet *ifp)
> splx(s);
>
> bstp_destroy(sc->sc_stp);
> +
> + /* Undo pseudo-driver changes. */
> + if_deactivate(ifp);
> +
> + bridge_ifih = SLIST_FIRST(&ifp->if_inputs);
> + SLIST_REMOVE_HEAD(&ifp->if_inputs, ifih_next);
> +
> + KASSERT(SLIST_EMPTY(&ifp->if_inputs));
> +
> + free(bridge_ifih, M_DEVBUF, sizeof(*bridge_ifih));
> +
> if_detach(ifp);
>
> free(sc, M_DEVBUF, 0);
> @@ -990,7 +1012,7 @@ bridge_output(struct ifnet *ifp, struct
> struct mbuf *mc;
> int used = 0;
>
> - bridge_span(sc, NULL, m);
> + bridge_span(sc, m);
>
> TAILQ_FOREACH(p, &sc->sc_iflist, next) {
> dst_if = p->ifp;
> @@ -1066,7 +1088,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);
> @@ -1282,12 +1304,13 @@ 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 bridge_iflist *ifl;
> + struct ether_header *eh;
> #if NVLAN > 0
> - uint16_t etype = ntohs(eh->ether_type);
> + uint16_t etype = ntohs(eh0->ether_type);
> #endif /* NVLAN > 0 */
>
> /*
> @@ -1306,15 +1329,20 @@ 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);
>
> - m = bridge_dispatch(ifl, ifp, eh, m);
> + m = bridge_dispatch(ifl, ifp, m);
>
> #if NVLAN > 0
> if ((m != NULL) && ((m->m_flags & M_VLANTAG) ||
> @@ -1330,15 +1358,17 @@ bridge_input(struct ifnet *ifp, struct e
> }
>
> struct mbuf *
> -bridge_dispatch(struct bridge_iflist *ifl, struct ifnet *ifp,
> - struct ether_header *eh, struct mbuf *m)
> +bridge_dispatch(struct bridge_iflist *ifl, struct ifnet *ifp, struct mbuf *m)
> {
> struct bridge_softc *sc = ifl->bridge_sc;
> struct bridge_iflist *srcifl;
> + struct ether_header *eh;
> struct arpcom *ac;
> struct mbuf *mc;
> int s;
>
> + eh = mtod(m, struct ether_header *);
> +
> if (m->m_flags & (M_BCAST | M_MCAST)) {
> /*
> * Reserved destination MAC addresses (01:80:C2:00:00:0x)
> @@ -1367,18 +1397,9 @@ bridge_dispatch(struct bridge_iflist *if
> (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);
> @@ -1398,11 +1419,11 @@ bridge_dispatch(struct bridge_iflist *if
> 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;
> }
> @@ -1445,21 +1466,21 @@ bridge_dispatch(struct bridge_iflist *if
> * 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);
> @@ -1474,10 +1495,6 @@ bridge_dispatch(struct bridge_iflist *if
> 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);
> @@ -1635,13 +1652,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;
> @@ -1654,12 +1670,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/if_ethersubr.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_ethersubr.c,v
> retrieving revision 1.194
> diff -u -p -r1.194 if_ethersubr.c
> --- net/if_ethersubr.c 13 Apr 2015 08:52:51 -0000 1.194
> +++ net/if_ethersubr.c 20 Apr 2015 11:35:56 -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
>