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