On 12/11/14(Wed) 00:22, Rafael Zalamena wrote: > The diff attached to this mail fixes the bridge output for VLANs noted in > this link: > http://marc.info/?l=openbsd-misc&m=141508025731320&w=2 > > Now when we are doing VLAN input we check whether the VLAN is a bridge port > or not, if it does then we have to do nothing and just pass the packet and > the bridge will handle it. This way we save some time by not doing VLAN > popping in the packets.
In this case, would it makes more sense to move the vlan_input() chunk after the bridge_input() one in ether_input()? > Bridge was not ready or consistent in some places to handle this, so some > checks were altered to consider tagged packets without the M_VLANTAG flag. > (this means we continue to ignore tagged packets in 'bridge_ip' and > 'bridge_blocknonip') > Also, when copying packets, remember to copy the packet M_VLANTAG as well. > > Altered the function vlan_input to update the ether_input ifp pointer, so > now ether_input doesn't need to be re-entered when we didn't pop the VLAN > tag. > > Lightly tested with in my VPLS setup. > > Index: net/if_bridge.c > =================================================================== > RCS file: /cvs/src/sys/net/if_bridge.c,v > retrieving revision 1.227 > diff -u -p -r1.227 if_bridge.c > --- net/if_bridge.c 8 Sep 2014 06:24:13 -0000 1.227 > +++ net/if_bridge.c 12 Nov 2014 01:40:03 -0000 > @@ -1373,6 +1373,9 @@ bridge_input(struct ifnet *ifp, struct e > if (mc == NULL) > return (m); > bcopy(eh, mtod(mc, caddr_t), ETHER_HDR_LEN); > + if (m->m_flags & M_VLANTAG) > + mc->m_flags |= M_VLANTAG; > + > s = splnet(); > if (IF_QFULL(&sc->sc_if.if_snd)) { > m_freem(mc); > @@ -2064,12 +2067,13 @@ bridge_blocknonip(struct ether_header *e > if (m->m_pkthdr.len < ETHER_HDR_LEN) > return (1); > > + etype = ntohs(eh->ether_type); > #if NVLAN > 0 > - if (m->m_flags & M_VLANTAG) > + if ((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN || > + etype == ETHERTYPE_QINQ) > return (1); > #endif > > - etype = ntohs(eh->ether_type); > switch (etype) { > case ETHERTYPE_ARP: > case ETHERTYPE_REVARP: > @@ -2399,12 +2403,12 @@ bridge_ip(struct bridge_softc *sc, int d > int hlen; > u_int16_t etype; > > + etype = ntohs(eh->ether_type); > #if NVLAN > 0 > - if (m->m_flags & M_VLANTAG) > + if ((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN || > + etype == ETHERTYPE_QINQ) > return (m); > #endif > - > - etype = ntohs(eh->ether_type); > > if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) { > if (etype > ETHERMTU || > Index: net/if_ethersubr.c > =================================================================== > RCS file: /cvs/src/sys/net/if_ethersubr.c,v > retrieving revision 1.177 > diff -u -p -r1.177 if_ethersubr.c > --- net/if_ethersubr.c 6 Nov 2014 14:28:47 -0000 1.177 > +++ net/if_ethersubr.c 12 Nov 2014 01:40:03 -0000 > @@ -552,7 +552,7 @@ ether_input(struct ifnet *ifp0, struct e > > #if NVLAN > 0 > if (((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN || > - etype == ETHERTYPE_QINQ) && (vlan_input(eh, m) == 0)) > + etype == ETHERTYPE_QINQ) && (vlan_input(eh, m, &ifp) == 0)) > return; > #endif > > Index: net/if_vlan.c > =================================================================== > RCS file: /cvs/src/sys/net/if_vlan.c,v > retrieving revision 1.109 > diff -u -p -r1.109 if_vlan.c > --- net/if_vlan.c 7 Oct 2014 11:16:23 -0000 1.109 > +++ net/if_vlan.c 12 Nov 2014 01:40:03 -0000 > @@ -47,6 +47,7 @@ > * will not modify the ethernet header. > */ > > +#include "bridge.h" > #include "vlan.h" > > #include <sys/param.h> > @@ -272,7 +273,7 @@ vlan_start(struct ifnet *ifp) > * vlan_input() returns 0 if it has consumed the packet, 1 otherwise. > */ > int > -vlan_input(struct ether_header *eh, struct mbuf *m) > +vlan_input(struct ether_header *eh, struct mbuf *m, struct ifnet **ifp0) > { > struct ifvlan *ifv; > struct ifnet *ifp = m->m_pkthdr.rcvif; > @@ -320,6 +321,21 @@ vlan_input(struct ether_header *eh, stru > * reentrant!). > */ > m->m_pkthdr.rcvif = &ifv->ifv_if; > + > +#if NBRIDGE > 0 > + /* If we are in a bridge, let it handle it */ > + if (ifv->ifv_if.if_bridgeport != NULL) { > + *ifp0 = &ifv->ifv_if; > +#if NBPFILTER > 0 > + if (ifv->ifv_if.if_bpf) > + bpf_mtap_hdr(ifv->ifv_if.if_bpf, (char *)eh, > + ETHER_HDR_LEN, m, BPF_DIRECTION_IN, NULL); > +#endif > + ifv->ifv_if.if_ipackets++; > + return (1); > + } > +#endif > + > if (m->m_flags & M_VLANTAG) { > m->m_flags &= ~M_VLANTAG; > } else { > Index: net/if_vlan_var.h > =================================================================== > RCS file: /cvs/src/sys/net/if_vlan_var.h,v > retrieving revision 1.24 > diff -u -p -r1.24 if_vlan_var.h > --- net/if_vlan_var.h 24 Oct 2013 11:14:33 -0000 1.24 > +++ net/if_vlan_var.h 12 Nov 2014 01:40:03 -0000 > @@ -95,7 +95,7 @@ struct ifvlan { > #define ifv_type ifv_mib.ifvm_type > #define IFVF_PROMISC 0x01 > > -extern int vlan_input(struct ether_header *eh, struct mbuf *m); > +int vlan_input(struct ether_header *, struct mbuf *, struct ifnet **); > #endif /* _KERNEL */ > > #endif /* _NET_IF_VLAN_VAR_H_ */ >