When svlan(4) was introduced, it got its own taghash in if_vlan.c.
This wasn't necessary as "etype" was already checked in the old hash
lookup.
So simplify the code again, and use the savings for some extra hash
buckets. :-)
Survives this stacked test between i386 and sparc64 (use .1 on one system,
and .2 on the other and ping all ip's):
#!/bin/sh
VLANDEV="fxp0"
IP4="1"
ifconfig svlan100 vlan 100 vlanprio 1 vlandev $VLANDEV \
10.10.101.$IP4 netmask 255.255.255.0
ifconfig svlan200 vlan 200 vlanprio 2 vlandev svlan100 \
10.10.102.$IP4 netmask 255.255.255.0
ifconfig vlan300 vlan 300 vlanprio 3 vlandev svlan200 \
10.10.103.$IP4 netmask 255.255.255.0
ifconfig svlan300 vlan 300 vlanprio 4 vlandev vlan300 \
10.10.104.$IP4 netmask 255.255.255.0
ifconfig vlan200 vlan 200 vlanprio 5 vlandev svlan300 \
10.10.105.$IP4 netmask 255.255.255.0
ifconfig vlan100 vlan 100 vlanprio 6 vlandev vlan200 \
10.10.106.$IP4 netmask 255.255.255.0
tcpdump:
19:53:17.566551 QinQ svid 100 pri 1 QinQ svid 200 pri 2 802.1Q vid 300 pri
3 QinQ svid 300 pri 4 802.1Q vid 200 pri 5 802.1Q vid 100 pri 6
10.10.106.1 > 10.10.106.2: icmp: echo request
19:53:17.566636 QinQ svid 100 pri 1 QinQ svid 200 pri 2 802.1Q vid 300 pri
3 QinQ svid 300 pri 4 802.1Q vid 200 pri 5 802.1Q vid 100 pri 6
10.10.106.2 > 10.10.106.1: icmp: echo reply
--
Cam
Index: if_vlan.c
===================================================================
RCS file: /cvs/src/sys/net/if_vlan.c,v
retrieving revision 1.87
diff -u -r1.87 if_vlan.c
--- if_vlan.c 18 Feb 2011 17:06:45 -0000 1.87
+++ if_vlan.c 4 Jul 2011 18:33:47 -0000
@@ -77,11 +77,11 @@
#include <net/if_vlan_var.h>
extern struct ifaddr **ifnet_addrs;
-u_long vlan_tagmask, svlan_tagmask;
+u_long vlan_tagmask;
-#define TAG_HASH_SIZE 32
+#define TAG_HASH_SIZE 64
#define TAG_HASH(tag) (tag & vlan_tagmask)
-LIST_HEAD(vlan_taghash, ifvlan) *vlan_tagh, *svlan_tagh;
+LIST_HEAD(vlan_taghash, ifvlan) *vlan_tagh;
void vlan_start(struct ifnet *ifp);
int vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr);
@@ -107,18 +107,12 @@
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");
- 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(&vlan_cloner);
if_clone_attach(&svlan_cloner);
}
@@ -277,13 +271,11 @@
{
struct ifvlan *ifv;
struct ifnet *ifp = m->m_pkthdr.rcvif;
- struct vlan_taghash *tagh;
u_int tag;
u_int16_t etype;
if (m->m_flags & M_VLANTAG) {
etype = ETHERTYPE_VLAN;
- tagh = vlan_tagh;
tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
} else {
if (m->m_len < EVL_ENCAPLEN &&
@@ -293,11 +285,10 @@
}
etype = ntohs(eh->ether_type);
- tagh = etype == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
tag = EVL_VLANOFTAG(ntohs(*mtod(m, u_int16_t *)));
}
- LIST_FOREACH(ifv, &tagh[TAG_HASH(tag)], ifv_list) {
+ LIST_FOREACH(ifv, &vlan_tagh[TAG_HASH(tag)], ifv_list) {
if (m->m_pkthdr.rcvif == ifv->ifv_p && tag == ifv->ifv_tag &&
etype == ifv->ifv_type)
break;
@@ -359,7 +350,6 @@
{
struct ifaddr *ifa1, *ifa2;
struct sockaddr_dl *sdl1, *sdl2;
- struct vlan_taghash *tagh;
u_int flags;
int s;
@@ -449,8 +439,7 @@
ifv->ifv_tag = tag;
s = splnet();
- tagh = ifv->ifv_type == ETHERTYPE_QINQ ? svlan_tagh : vlan_tagh;
- LIST_INSERT_HEAD(&tagh[TAG_HASH(tag)], ifv, ifv_list);
+ LIST_INSERT_HEAD(&vlan_tagh[TAG_HASH(tag)], ifv, ifv_list);
/* Register callback for physical link state changes */
ifv->lh_cookie = hook_establish(p->if_linkstatehooks, 1,