tag lookups consider the type of interface as well as its tag, so
it isnt necessary to have separate hashes for vlans and svlans.

following on from this, i would like to widen the tag hash and maybe
xor some more bits in to get the key. vlan tags are 12 bits, so the
following appeals to me:

#define TAG_HASH_SIZE   64
#define TAG_HASH(tag)   ((tag & vlan_tagmask) ^ ((tag >> 6) & vlan_tagmask))

it would also be nice to have vlan interfaces refer to their parents
by interface indexes instead of actual pointers. that would allow
the hash lookup to be done without necessarily calling if_get in
vlan_input, but that would also require not accounting errors on
the parent interface.

anyway.

tests?

Index: if_vlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vlan.c,v
retrieving revision 1.132
diff -u -p -r1.132 if_vlan.c
--- if_vlan.c   29 Jun 2015 10:32:29 -0000      1.132
+++ if_vlan.c   1 Jul 2015 07:26:18 -0000
@@ -74,7 +74,7 @@ u_long vlan_tagmask, svlan_tagmask;
 
 #define TAG_HASH_SIZE          32
 #define TAG_HASH(tag)          (tag & vlan_tagmask)
-LIST_HEAD(vlan_taghash, ifvlan)        *vlan_tagh, *svlan_tagh;
+LIST_HEAD(vlan_taghash, ifvlan)        *vlan_tagh;
 
 
 int    vlan_input(struct mbuf *);
@@ -102,18 +102,15 @@ struct if_clone svlan_cloner =
 void
 vlanattach(int count)
 {
-       /* Normal VLAN */
        vlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT,
            &vlan_tagmask);
        if (vlan_tagh == NULL)
                panic("vlanattach: hashinit");
+
+       /* Normal VLAN */
        if_clone_attach(&vlan_cloner);
 
        /* Service-VLAN for QinQ/802.1ad provider bridges */
-       svlan_tagh = hashinit(TAG_HASH_SIZE, M_DEVBUF, M_NOWAIT,
-           &svlan_tagmask);
-       if (svlan_tagh == NULL)
-               panic("vlanattach: hashinit");
        if_clone_attach(&svlan_cloner);
 }
 
@@ -249,7 +246,6 @@ vlan_input(struct mbuf *m)
        struct ifnet                    *ifp;
        struct ether_vlan_header        *evl;
        struct ether_header             *eh;
-       struct vlan_taghash             *tagh;
        u_int                            tag;
        struct mbuf_list                 ml = MBUF_LIST_INITIALIZER();
        u_int16_t                        etype;
@@ -266,7 +262,6 @@ vlan_input(struct mbuf *m)
 
        if (m->m_flags & M_VLANTAG) {
                etype = ETHERTYPE_VLAN;
-               tagh = vlan_tagh;
        } else if ((etype == ETHERTYPE_VLAN) || (etype == ETHERTYPE_QINQ)) {
                if (m->m_len < EVL_ENCAPLEN &&
                    (m = m_pullup(m, EVL_ENCAPLEN)) == NULL) {
@@ -276,7 +271,6 @@ vlan_input(struct mbuf *m)
 
                evl = mtod(m, struct ether_vlan_header *);
                m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag);
-               tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
        } else {
                /* Skip non-VLAN packets. */
                return (0);
@@ -290,7 +284,7 @@ vlan_input(struct mbuf *m)
        if (m->m_pkthdr.pf.prio <= 1)
                m->m_pkthdr.pf.prio = !m->m_pkthdr.pf.prio;
 
-       LIST_FOREACH(ifv, &tagh[TAG_HASH(tag)], ifv_list) {
+       LIST_FOREACH(ifv, &vlan_tagh[TAG_HASH(tag)], ifv_list) {
                if (ifp == ifv->ifv_p && tag == ifv->ifv_tag &&
                    etype == ifv->ifv_type)
                        break;
@@ -344,7 +338,6 @@ int
 vlan_config(struct ifvlan *ifv, struct ifnet *p, u_int16_t tag)
 {
        struct sockaddr_dl      *sdl1, *sdl2;
-       struct vlan_taghash     *tagh;
        u_int                    flags;
        int                      s;
 
@@ -429,14 +422,12 @@ vlan_config(struct ifvlan *ifv, struct i
 
        vlan_vlandev_state(ifv);
 
-       tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
-
        s = splnet();
        /* Change input handler of the physical interface. */
        if (++ifv->ifv_ifih->ifih_refcnt == 1)
                SLIST_INSERT_HEAD(&p->if_inputs, ifv->ifv_ifih, ifih_next);
 
-       LIST_INSERT_HEAD(&tagh[TAG_HASH(tag)], ifv, ifv_list);
+       LIST_INSERT_HEAD(&vlan_tagh[TAG_HASH(tag)], ifv, ifv_list);
        splx(s);
 
        return (0);

Reply via email to