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. 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_ */