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