On Mon, Apr 21, 2014 at 09:01:52PM +0200, Henning Brauer wrote:
> so while so many here were so busy bikeshedding, wasting everyone's
> time and hindering progress, reyk and I found that several people,
> including me, had flaws in their testing. unfortunately have to go the
> vlan_output route. root cause "undo undo damage", don't make me explain
> please... 
> 
> new diff.
> testing also improved :)
> 

ok reyk@

> Index: if_ethersubr.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_ethersubr.c,v
> retrieving revision 1.170
> diff -u -p -r1.170 if_ethersubr.c
> --- if_ethersubr.c    21 Apr 2014 18:52:25 -0000      1.170
> +++ if_ethersubr.c    21 Apr 2014 18:53:16 -0000
> @@ -155,8 +155,8 @@ u_char etherbroadcastaddr[ETHER_ADDR_LEN
>      { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
>  #define senderr(e) { error = (e); goto bad;}
>  
> -static inline int    ether_addheader(struct mbuf **, u_int16_t, u_char *,
> -                        u_char *);
> +static inline int    ether_addheader(struct mbuf **, struct ifnet *,
> +                        u_int16_t, u_char *, u_char *);
>  
>  int
>  ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data)
> @@ -193,10 +193,40 @@ ether_ioctl(struct ifnet *ifp, struct ar
>  }
>  
>  static inline int
> -ether_addheader(struct mbuf **m, u_int16_t etype, u_char *esrc, u_char *edst)
> +ether_addheader(struct mbuf **m, struct ifnet *ifp, u_int16_t etype,
> +    u_char *esrc, u_char *edst)
>  {
>       struct ether_header *eh;
>  
> +#if NVLAN > 0
> +     if ((*m)->m_flags & M_VLANTAG) {
> +             struct ifvlan   *ifv = ifp->if_softc;
> +             struct ifnet    *p = ifv->ifv_p;
> +
> +             /* should we use the tx tagging hw offload at all? */
> +             if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
> +                 (ifv->ifv_type == ETHERTYPE_VLAN)) {
> +                     (*m)->m_pkthdr.ether_vtag = ifv->ifv_tag +
> +                         ((*m)->m_pkthdr.pf.prio << EVL_PRIO_BITS);
> +                     /* don't return, need to add regular ethernet header */
> +             } else {
> +                     struct ether_vlan_header        *evh;
> +
> +                     M_PREPEND(*m, sizeof(*evh), M_DONTWAIT);
> +                     if (*m == 0)
> +                             return (-1);
> +                     evh = mtod(*m, struct ether_vlan_header *);
> +                     memcpy(evh->evl_dhost, edst, sizeof(evh->evl_dhost));
> +                     memcpy(evh->evl_shost, esrc, sizeof(evh->evl_shost));
> +                     evh->evl_proto = etype;
> +                     evh->evl_encap_proto = htons(ifv->ifv_type);
> +                     evh->evl_tag = htons(ifv->ifv_tag +
> +                         ((*m)->m_pkthdr.pf.prio << EVL_PRIO_BITS));
> +                     (*m)->m_flags &= ~M_VLANTAG;
> +                     return (0);
> +             }
> +     }
> +#endif /* NVLAN > 0 */
>       M_PREPEND(*m, ETHER_HDR_LEN, M_DONTWAIT);
>       if (*m == 0)
>               return (-1);
> @@ -364,7 +394,7 @@ ether_output(struct ifnet *ifp0, struct 
>               esrc = carp_get_srclladdr(ifp0, esrc);
>  #endif
>  
> -     if (ether_addheader(&m, etype, esrc, edst) == -1)
> +     if (ether_addheader(&m, ifp, etype, esrc, edst) == -1)
>               senderr(ENOBUFS);
>  
>  #if NBRIDGE > 0
> Index: if_vlan.c
> ===================================================================
> RCS file: /cvs/src/sys/net/if_vlan.c,v
> retrieving revision 1.102
> diff -u -p -r1.102 if_vlan.c
> --- if_vlan.c 10 Mar 2014 12:21:35 -0000      1.102
> +++ if_vlan.c 21 Apr 2014 18:53:16 -0000
> @@ -80,6 +80,8 @@ u_long vlan_tagmask, svlan_tagmask;
>  #define TAG_HASH(tag)                (tag & vlan_tagmask)
>  LIST_HEAD(vlan_taghash, ifvlan)      *vlan_tagh, *svlan_tagh;
>  
> +int  vlan_output(struct ifnet *, struct mbuf *, struct sockaddr *,
> +         struct rtentry *);
>  void vlan_start(struct ifnet *ifp);
>  int  vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
>  int  vlan_unconfig(struct ifnet *ifp, struct ifnet *newp);
> @@ -152,6 +154,7 @@ vlan_clone_create(struct if_clone *ifc, 
>       /* Now undo some of the damage... */
>       ifp->if_type = IFT_L2VLAN;
>       ifp->if_hdrlen = EVL_ENCAPLEN;
> +     ifp->if_output = vlan_output;
>  
>       return (0);
>  }
> @@ -177,6 +180,18 @@ vlan_ifdetach(void *ptr)
>       vlan_clone_destroy(&ifv->ifv_if);
>  }
>  
> +int
> +vlan_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
> +    struct rtentry *rt)
> +{
> +     /*
> +      * we have to use a custom output function because ether_output
> +      * can't figure out ifp is a vlan in a reasonable way
> +      */
> +     m->m_flags |= M_VLANTAG;
> +     return (ether_output(ifp, m, dst, rt));
> +}
> +
>  void
>  vlan_start(struct ifnet *ifp)
>  {
> @@ -206,36 +221,6 @@ vlan_start(struct ifnet *ifp)
>               if (ifp->if_bpf)
>                       bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
>  #endif
> -
> -             /*
> -              * If the IFCAP_VLAN_HWTAGGING capability is set on the parent,
> -              * it can do VLAN tag insertion itself and doesn't require us
> -              * to create a special header for it. In this case, we just pass
> -              * the packet along.
> -              */
> -             if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
> -                 (ifv->ifv_type == ETHERTYPE_VLAN)) {
> -                     m->m_pkthdr.ether_vtag = ifv->ifv_tag +
> -                         (m->m_pkthdr.pf.prio << EVL_PRIO_BITS);
> -                     m->m_flags |= M_VLANTAG;
> -             } else {
> -                     struct ether_vlan_header evh;
> -
> -                     m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
> -                     evh.evl_proto = evh.evl_encap_proto;
> -                     evh.evl_encap_proto = htons(ifv->ifv_type);
> -                     evh.evl_tag = htons(ifv->ifv_tag +
> -                         (m->m_pkthdr.pf.prio << EVL_PRIO_BITS));
> -
> -                     m_adj(m, ETHER_HDR_LEN);
> -                     M_PREPEND(m, sizeof(evh), M_DONTWAIT);
> -                     if (m == NULL) {
> -                             ifp->if_oerrors++;
> -                             continue;
> -                     }
> -
> -                     m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
> -             }
>  
>               /*
>                * Send it, precisely as ether_output() would have.
> 
> 
> 
> -- 
> Henning Brauer, h...@bsws.de, henn...@openbsd.org
> BS Web Services GmbH, http://bsws.de, Full-Service ISP
> Secure Hosting, Mail and DNS Services. Dedicated Servers, Root to Fully 
> Managed
> Henning Brauer Consulting, http://henningbrauer.com/
> 

Reply via email to