summaryrefslogtreecommitdiffstats
path: root/sys/net/if_ethersubr.c
diff options
context:
space:
mode:
authorcsjp <csjp@FreeBSD.org>2006-11-18 23:17:22 +0000
committercsjp <csjp@FreeBSD.org>2006-11-18 23:17:22 +0000
commit5aa5d3eb87ef22b838901d976a898e7826d9032f (patch)
tree8daa14e003cb59b6b1fab70f6be511048b5bb81d /sys/net/if_ethersubr.c
parentaee58e2da0c688785939850d85b12b57fbb12396 (diff)
downloadFreeBSD-src-5aa5d3eb87ef22b838901d976a898e7826d9032f.zip
FreeBSD-src-5aa5d3eb87ef22b838901d976a898e7826d9032f.tar.gz
Currently, drivers that support hardware offload of VLAN tag
processing are forced to toggle this functionality when the card is put in and out of promiscuous mode. The main reason for this is because the hardware strips the VLAN tag, making it impossible for the tag information to show up in network diagnostic tools like tcpdump(1). This change introduces ether_vlan_mtap(), which is called if the mbuf has M_VLANTAG set. VLAN information is extracted from the mbuf and inserted into a stack allocated ether vlan header which is then inserted through the bpf machinery via bpf_mtap2(). The original mbuf's data pointer and lengths are temporarily adjusted to eliminate the original Ethernet header for the duration of the tap operation. This should have no long term effects on the mbuf. Also, define a new macro, ETHER_BPF_MTAP which should be used by drivers which support hardware offload of VLAN tag processing. The fixes for the relevant drivers will follow shortly. Discussed with: rwatson, andre, jhb (and others) Much feedback from: sam, ru MFC after: 1 month [1] [1] The version that is eventually MFCed will be somewhat different then this, as there has been significant work done to the VLAN code in HEAD.
Diffstat (limited to 'sys/net/if_ethersubr.c')
-rw-r--r--sys/net/if_ethersubr.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 61fa58b..5a507e3 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1185,5 +1185,45 @@ static moduledata_t ether_mod = {
0
};
+void
+ether_vlan_mtap(struct bpf_if *bp, struct mbuf *m, void *data, u_int dlen)
+{
+ struct ether_vlan_header vlan;
+ struct mbuf mv, mb;
+
+ KASSERT((m->m_flags & M_VLANTAG) != 0,
+ ("%s: vlan information not present", __func__));
+ KASSERT(m->m_len >= sizeof(struct ether_header),
+ ("%s: mbuf not large enough for header", __func__));
+ bcopy(mtod(m, char *), &vlan, sizeof(struct ether_header));
+ vlan.evl_proto = vlan.evl_encap_proto;
+ vlan.evl_encap_proto = htons(ETHERTYPE_VLAN);
+ vlan.evl_tag = htons(m->m_pkthdr.ether_vtag);
+ m->m_len -= sizeof(struct ether_header);
+ m->m_data += sizeof(struct ether_header);
+ /*
+ * If a data link has been supplied by the caller, then we will need to
+ * re-create a stack allocated mbuf chain with the following structure:
+ *
+ * (1) mbuf #1 will contain the supplied data link
+ * (2) mbuf #2 will contain the vlan header
+ * (3) mbuf #3 will contain the original mbuf's packet data
+ *
+ * Otherwise, submit the packet and vlan header via bpf_mtap2().
+ */
+ if (data != NULL) {
+ mv.m_next = m;
+ mv.m_data = (caddr_t)&vlan;
+ mv.m_len = sizeof(vlan);
+ mb.m_next = &mv;
+ mb.m_data = data;
+ mb.m_len = dlen;
+ bpf_mtap(bp, &mb);
+ } else
+ bpf_mtap2(bp, &vlan, sizeof(vlan), m);
+ m->m_len += sizeof(struct ether_header);
+ m->m_data -= sizeof(struct ether_header);
+}
+
DECLARE_MODULE(ether, ether_mod, SI_SUB_INIT_IF, SI_ORDER_ANY);
MODULE_VERSION(ether, 1);
OpenPOWER on IntegriCloud