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

Reply via email to