Gary, and anyone else who can test VLAN support, please try this
patch and tell me if it works.
-Matt
Index: net/vlan/if_vlan.c
===================================================================
RCS file: /cvs/src/sys/net/vlan/if_vlan.c,v
retrieving revision 1.18
diff -u -r1.18 if_vlan.c
--- net/vlan/if_vlan.c 28 Nov 2005 17:13:46 -0000 1.18
+++ net/vlan/if_vlan.c 27 Dec 2005 22:42:05 -0000
@@ -379,10 +379,8 @@
{
struct bpf_if *bif;
struct ifvlan *ifv;
- struct ether_header *eh = mtod(m, struct ether_header *);
struct ifnet *rcvif;
- m_adj(m, ETHER_HDR_LEN);
rcvif = m->m_pkthdr.rcvif;
ASSERT_SERIALIZED(rcvif->if_serializer);
@@ -392,14 +390,18 @@
* bpf tap if active.
*/
if ((bif = rcvif->if_bpf) != NULL) {
+ struct ether_header *eh;
struct ether_vlan_header evh;
+ eh = mtod(m, struct ether_header *);
+ m_adj(m, ETHER_HDR_LEN);
bcopy(eh, &evh, 2*ETHER_ADDR_LEN);
evh.evl_encap_proto = htons(ETHERTYPE_VLAN);
evh.evl_tag = htons(t);
evh.evl_proto = eh->ether_type;
-
bpf_ptap(bif, m, &evh, ETHER_HDR_LEN + EVL_ENCAPLEN);
+ /* XXX assumes data was left intact */
+ M_PREPEND(m, ETHER_HDR_LEN, MB_WAIT);
}
for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
@@ -423,7 +425,7 @@
ifv->ifv_if.if_ipackets++;
lwkt_serialize_exit(rcvif->if_serializer);
lwkt_serialize_enter(ifv->ifv_if.if_serializer);
- ether_input(&ifv->ifv_if, eh, m);
+ ether_input(&ifv->ifv_if, NULL, m);
lwkt_serialize_exit(ifv->ifv_if.if_serializer);
lwkt_serialize_enter(rcvif->if_serializer);
return 0;
@@ -434,6 +436,7 @@
{
struct ifvlan *ifv;
struct ifnet *rcvif;
+ struct ether_header eh_copy;
rcvif = m->m_pkthdr.rcvif;
ASSERT_SERIALIZED(rcvif->if_serializer);
@@ -455,20 +458,22 @@
/*
* Having found a valid vlan interface corresponding to
* the given source interface and vlan tag, remove the
- * encapsulation, and run the real packet through
- * ether_input() a second time (it had better be
+ * remaining encapsulation (ether_vlan_header minus the ether_header
+ * that had already been removed) and run the real packet
+ * through ether_input() a second time (it had better be
* reentrant!).
*/
+ eh_copy = *eh;
+ eh_copy.ether_type = mtod(m, u_int16_t *)[1]; /* evl_proto */
m->m_pkthdr.rcvif = &ifv->ifv_if;
- eh->ether_type = mtod(m, u_int16_t *)[1];
- m->m_data += EVL_ENCAPLEN;
- m->m_len -= EVL_ENCAPLEN;
- m->m_pkthdr.len -= EVL_ENCAPLEN;
+ m_adj(m, EVL_ENCAPLEN);
+ M_PREPEND(m, ETHER_HDR_LEN, MB_WAIT);
+ *(struct ether_header *)mtod(m, void *) = eh_copy;
ifv->ifv_if.if_ipackets++;
lwkt_serialize_exit(rcvif->if_serializer);
lwkt_serialize_enter(ifv->ifv_if.if_serializer);
- ether_input(&ifv->ifv_if, eh, m);
+ ether_input(&ifv->ifv_if, NULL, m);
lwkt_serialize_exit(ifv->ifv_if.if_serializer);
lwkt_serialize_enter(rcvif->if_serializer);
return 0;