Diff below requires the "No NCARP" diff I just sent to apply cleanly but
should be independent.

The idea is to move back the VLAN encapsulation into the vlan(4) driver.
As with carp(4) vlan_start() is used.  This simplifies the bpf(4) dance
and make all our pseudo-driver call bpf_mtap() in the *_start() routine
like the ``real'' Ethernet drivers.

Ok?

diff --git sys/net/if_bridge.c sys/net/if_bridge.c
index 7963795..f989aee 100644
--- sys/net/if_bridge.c
+++ sys/net/if_bridge.c
@@ -2641,11 +2641,6 @@ bridge_fragment(struct bridge_softc *sc, struct ifnet 
*ifp,
                m_freem(m);
 }
 
-#if NVLAN > 0
-extern int vlan_output(struct ifnet *, struct mbuf *, struct sockaddr *,
-    struct rtentry *);
-#endif
-
 int
 bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
 {
@@ -2661,45 +2656,6 @@ bridge_ifenqueue(struct bridge_softc *sc, struct ifnet 
*ifp, struct mbuf *m)
                ifp->if_ibytes += m->m_pkthdr.len;
        }
 #endif
-#if NVLAN > 0
-       /*
-        * If the underlying interface cannot do VLAN tag insertion itself,
-        * create an encapsulation header.
-        */
-       if (ifp->if_output == vlan_output) {
-               struct ifvlan   *ifv = ifp->if_softc;
-               struct ifnet    *p = ifv->ifv_p;
-               u_int8_t        prio = m->m_pkthdr.pf.prio;
-
-               /* IEEE 802.1p has prio 0 and 1 swapped */
-               if (prio <= 1)
-                       prio = !prio;
-
-               /* 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 +
-                           (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 +
-                           (prio << EVL_PRIO_BITS));
-                       m_adj(m, ETHER_HDR_LEN);
-                       M_PREPEND(m, sizeof(evh), M_DONTWAIT);
-                       if (m == NULL) {
-                               sc->sc_if.if_oerrors++;
-                               return (ENOBUFS);
-                       }
-                       m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
-                       m->m_flags &= ~M_VLANTAG;
-               }
-       }
-#endif
        len = m->m_pkthdr.len;
 
        error = if_output(ifp, m);
diff --git sys/net/if_ethersubr.c sys/net/if_ethersubr.c
index e9c4055..0373701 100644
--- sys/net/if_ethersubr.c
+++ sys/net/if_ethersubr.c
@@ -108,11 +108,6 @@ didn't get a copy, you may request one from 
<lice...@ipv6.nrl.navy.mil>.
 #include <net/if_bridge.h>
 #endif
 
-#include "vlan.h"
-#if NVLAN > 0
-#include <net/if_vlan_var.h>
-#endif /* NVLAN > 0 */
-
 #include "pppoe.h"
 #if NPPPOE > 0
 #include <net/if_pppoe.h>
@@ -135,9 +130,6 @@ 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 **, struct ifnet *,
-                          u_int16_t, u_char *, u_char *);
-
 int
 ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long cmd, caddr_t data)
 {
@@ -172,79 +164,18 @@ ether_ioctl(struct ifnet *ifp, struct arpcom *arp, u_long 
cmd, caddr_t data)
        return (error);
 }
 
-static inline int
-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;
-               u_int8_t        prio = (*m)->m_pkthdr.pf.prio;
-
-               /* IEEE 802.1p has prio 0 and 1 swapped */
-               if (prio <= 1)
-                       prio = !prio;
-
-#if NBRIDGE > 0
-               /*
-                * The bridge might send on non-vlan interfaces -- which
-                * do not need this header -- or add the vlan-header itself
-                * in bridge_ifenqueue -- which would add a second header.
-                */
-               if (ifp->if_bridgeport)
-                       (*m)->m_flags &= ~M_VLANTAG;
-               else
-#endif
-               /* 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 +
-                           (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 == NULL)
-                               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 +
-                           (prio << EVL_PRIO_BITS));
-                       (*m)->m_flags &= ~M_VLANTAG;
-                       return (0);
-               }
-       }
-#endif /* NVLAN > 0 */
-       M_PREPEND(*m, ETHER_HDR_LEN, M_DONTWAIT);
-       if (*m == NULL)
-               return (-1);
-       eh = mtod(*m, struct ether_header *);
-       eh->ether_type = etype;
-       memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost));
-       memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
-       return (0);
-}
-
 /*
  * Ethernet output routine.
  * Encapsulate a packet of type family for the local net.
  * Assumes that ifp is actually pointer to arpcom structure.
  */
 int
-ether_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
+ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
     struct rtentry *rt)
 {
        u_int16_t etype;
        u_char edst[ETHER_ADDR_LEN];
        u_char *esrc;
-       struct mbuf *m = m0;
        struct mbuf *mcopy = NULL;
        struct ether_header *eh;
        struct arpcom *ac = (struct arpcom *)ifp;
@@ -338,8 +269,13 @@ ether_output(struct ifnet *ifp, struct mbuf *m0, struct 
sockaddr *dst,
        if (mcopy)
                (void) looutput(ifp, mcopy, dst, rt);
 
-       if (ether_addheader(&m, ifp, etype, esrc, edst) == -1)
-               senderr(ENOBUFS);
+       M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
+       if (m == NULL)
+               return (ENOBUFS);
+       eh = mtod(m, struct ether_header *);
+       eh->ether_type = etype;
+       memcpy(eh->ether_dhost, edst, sizeof(eh->ether_dhost));
+       memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost));
 
 #if NBRIDGE > 0
        /*
diff --git sys/net/if_vlan.c sys/net/if_vlan.c
index e3dd261..fe89b73 100644
--- sys/net/if_vlan.c
+++ sys/net/if_vlan.c
@@ -47,9 +47,6 @@
  * will not modify the ethernet header.
  */
 
-#include "bridge.h"
-#include "vlan.h"
-
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
@@ -59,11 +56,6 @@
 #include <sys/sockio.h>
 #include <sys/systm.h>
 
-#include "bpfilter.h"
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
@@ -73,6 +65,16 @@
 
 #include <net/if_vlan_var.h>
 
+#include "bpfilter.h"
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#include "bridge.h"
+#if NBRIDGE > 0
+#include <net/if_bridge.h>
+#endif
+
 u_long vlan_tagmask, svlan_tagmask;
 
 #define TAG_HASH_SIZE          32
@@ -81,8 +83,6 @@ LIST_HEAD(vlan_taghash, ifvlan)       *vlan_tagh, *svlan_tagh;
 
 
 int    vlan_input(struct mbuf *);
-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,7 +152,6 @@ vlan_clone_create(struct if_clone *ifc, int unit)
        if_attach(ifp);
        ether_ifattach(ifp);
        ifp->if_hdrlen = EVL_ENCAPLEN;
-       ifp->if_output = vlan_output;
 
        return (0);
 }
@@ -176,24 +175,13 @@ 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)
 {
-       struct ifvlan   *ifv;
+       struct ifvlan   *ifv;
        struct ifnet    *p;
        struct mbuf     *m;
+       uint8_t          prio;
 
        ifv = ifp->if_softc;
        p = ifv->ifv_p;
@@ -203,6 +191,11 @@ vlan_start(struct ifnet *ifp)
                if (m == NULL)
                        break;
 
+#if NBPFILTER > 0
+               if (ifp->if_bpf)
+                       bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif /* NBPFILTER > 0 */
+
                if ((p->if_flags & (IFF_UP|IFF_RUNNING)) !=
                    (IFF_UP|IFF_RUNNING)) {
                        IF_DROP(&p->if_snd);
@@ -211,43 +204,37 @@ vlan_start(struct ifnet *ifp)
                        continue;
                }
 
-#if NBPFILTER > 0
-               if (ifp->if_bpf) {
-                       if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
-                           (ifv->ifv_type == ETHERTYPE_VLAN))
-                               bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
-                       else {
-                               struct mbuf *m0;
-                               u_int off;
-                               struct m_hdr mh;
-                               struct {
-                                       uint8_t dst[ETHER_ADDR_LEN];
-                                       uint8_t src[ETHER_ADDR_LEN];
-                               } hdr;
-
-                               /* copy the ether addresses off the front */
-                               m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
-
-                               /* find the ethertype after the vlan subhdr*/
-                               m0 = m_getptr(m,
-                                   offsetof(struct ether_vlan_header,
-                                   evl_proto), &off);
-                               KASSERT(m0 != NULL);
-
-                               /* pretend the vlan subhdr isnt there */
-                               mh.mh_flags = 0;
-                               mh.mh_data = mtod(m0, caddr_t) + off;
-                               mh.mh_len = m0->m_len - off;
-                               mh.mh_next = m0->m_next;
-
-                               /* dst+src + ethertype == ethernet header */
-                               bpf_mtap_hdr(ifp->if_bpf,
-                                   (caddr_t)&hdr, sizeof(hdr),
-                                   (struct mbuf *)&mh, BPF_DIRECTION_OUT,
-                                   NULL);
+               /* IEEE 802.1p has prio 0 and 1 swapped */
+               prio = m->m_pkthdr.pf.prio;
+               if (prio <= 1)
+                       prio = !prio;
+
+               /*
+                * If the underlying interface cannot do VLAN tag insertion
+                * itself, create an encapsulation header.
+                */
+               if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
+                   (ifv->ifv_type == ETHERTYPE_VLAN)) {
+                       m->m_pkthdr.ether_vtag = ifv->ifv_tag +
+                           (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 +
+                           (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);
+                       m->m_flags &= ~M_VLANTAG;
                }
-#endif /* NBPFILTER > 0 */
 
                if (if_output(p, m)) {
                        ifp->if_oerrors++;

Reply via email to