Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/net Supports hardware 802.1q VLAN tagging, per discussio...
details: https://anonhg.NetBSD.org/src/rev/6285fccbcc51
branches: trunk
changeset: 499344:6285fccbcc51
user: bouyer <bouyer%NetBSD.org@localhost>
date: Fri Nov 17 19:21:53 2000 +0000
description:
Supports hardware 802.1q VLAN tagging, per discussion on tech-net. The tag is
stored in a m_aux mbuf defined by AF_LINK, ETHERTYPE_VLAN.
Thanks to Jason & Itojun for the feedback.
diffstat:
sys/net/if_ether.h | 4 +-
sys/net/if_ethersubr.c | 19 ++++-
sys/net/if_vlan.c | 180 ++++++++++++++++++++++++++++--------------------
3 files changed, 125 insertions(+), 78 deletions(-)
diffs (292 lines):
diff -r eb3582a8e9cf -r 6285fccbcc51 sys/net/if_ether.h
--- a/sys/net/if_ether.h Fri Nov 17 19:14:41 2000 +0000
+++ b/sys/net/if_ether.h Fri Nov 17 19:21:53 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ether.h,v 1.20 2000/10/11 16:53:41 thorpej Exp $ */
+/* $NetBSD: if_ether.h,v 1.21 2000/11/17 19:21:53 bouyer Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -154,7 +154,7 @@
};
#define ETHERCAP_VLAN_MTU 0x00000001 /* VLAN-compatible MTU */
-#define ETHERCAP_VLAN_TAGGING 0x00000002 /* VLAN tag support */
+#define ETHERCAP_VLAN_HWTAGGING 0x00000002 /* hardware VLAN tag support */
#ifdef _KERNEL
extern u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN];
diff -r eb3582a8e9cf -r 6285fccbcc51 sys/net/if_ethersubr.c
--- a/sys/net/if_ethersubr.c Fri Nov 17 19:14:41 2000 +0000
+++ b/sys/net/if_ethersubr.c Fri Nov 17 19:21:53 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ethersubr.c,v 1.69 2000/11/15 01:02:15 thorpej Exp $ */
+/* $NetBSD: if_ethersubr.c,v 1.70 2000/11/17 19:21:53 bouyer Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -505,6 +505,7 @@
u_int16_t etype;
int s;
struct ether_header *eh;
+ struct mbuf *n;
#if defined (ISO) || defined (LLC) || defined(NETATALK)
struct llc *l;
#endif
@@ -543,6 +544,22 @@
return;
}
+ /* Check if the mbuf has a VLAN tag */
+ n = m_aux_find(m, AF_LINK, ETHERTYPE_VLAN);
+ if (n) {
+#if NVLAN > 0
+ /*
+ * vlan_input() will either recursively call ether_input()
+ * or drop the packet.
+ */
+ if (((struct ethercom *)ifp)->ec_nvlans != 0)
+ vlan_input(ifp, m);
+ else
+#endif
+ m_freem(m);
+ return;
+ }
+
/*
* Handle protocols that expect to have the Ethernet header
* (and possibly FCS) intact.
diff -r eb3582a8e9cf -r 6285fccbcc51 sys/net/if_vlan.c
--- a/sys/net/if_vlan.c Fri Nov 17 19:14:41 2000 +0000
+++ b/sys/net/if_vlan.c Fri Nov 17 19:21:53 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_vlan.c,v 1.23 2000/11/15 18:15:11 bouyer Exp $ */
+/* $NetBSD: if_vlan.c,v 1.24 2000/11/17 19:21:53 bouyer Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -665,6 +665,7 @@
{
struct ifvlan *ifv = ifp->if_softc;
struct ifnet *p = ifv->ifv_p;
+ struct ethercom *ec = (void *) ifv->ifv_p;
struct mbuf *m;
ifp->if_flags |= IFF_OACTIVE;
@@ -678,51 +679,66 @@
if (ifp->if_bpf)
bpf_mtap(ifp->if_bpf, m);
#endif
-
/*
- * XXX Should handle the case where the underlying hardware
- * interface can do VLAN tag insertion itself.
+ * If the parent can insert the tag itself, just mark
+ * the tag in the mbuf header.
*/
- M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT);
- if (m == NULL) {
- printf("%s: unable to prepend encap header",
- ifv->ifv_p->if_xname);
- ifp->if_oerrors++;
- continue;
- }
-
- switch (p->if_type) {
- case IFT_ETHER:
- {
- struct ether_vlan_header *evl;
-
- if (m->m_len < sizeof(struct ether_vlan_header) &&
- (m = m_pullup(m,
- sizeof(struct ether_vlan_header))) == NULL) {
- printf("%s: unable to pullup encap header",
+ if (ec->ec_capabilities & ETHERCAP_VLAN_HWTAGGING) {
+ struct mbuf *n;
+ n = m_aux_add(m, AF_LINK, ETHERTYPE_VLAN);
+ if (n == NULL) {
+ ifp->if_oerrors++;
+ m_freem(m);
+ continue;
+ }
+ *mtod(n, int *) = ifv->ifv_tag;
+ n->m_len = sizeof(int);
+ } else {
+ /*
+ * insert the tag ourselve
+ */
+ M_PREPEND(m, ifv->ifv_encaplen, M_DONTWAIT);
+ if (m == NULL) {
+ printf("%s: unable to prepend encap header",
ifv->ifv_p->if_xname);
ifp->if_oerrors++;
continue;
}
- /*
- * Transform the Ethernet header into an Ethernet
- * header with 802.1Q encapsulation.
- */
- memmove(mtod(m, caddr_t),
- mtod(m, caddr_t) + ifv->ifv_encaplen,
- sizeof(struct ether_header));
- evl = mtod(m, struct ether_vlan_header *);
- evl->evl_proto = evl->evl_encap_proto;
- evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
- evl->evl_tag = htons(ifv->ifv_tag);
- break;
- }
+ switch (p->if_type) {
+ case IFT_ETHER:
+ {
+ struct ether_vlan_header *evl;
+
+ if (m->m_len < sizeof(struct ether_vlan_header))
+ m = m_pullup(m,
+ sizeof(struct ether_vlan_header));
+ if (m == NULL) {
+ printf("%s: unable to pullup encap "
+ "header", ifv->ifv_p->if_xname);
+ ifp->if_oerrors++;
+ continue;
+ }
+
+ /*
+ * Transform the Ethernet header into an
+ * Ethernet header with 802.1Q encapsulation.
+ */
+ memmove(mtod(m, caddr_t),
+ mtod(m, caddr_t) + ifv->ifv_encaplen,
+ sizeof(struct ether_header));
+ evl = mtod(m, struct ether_vlan_header *);
+ evl->evl_proto = evl->evl_encap_proto;
+ evl->evl_encap_proto = htons(ETHERTYPE_VLAN);
+ evl->evl_tag = htons(ifv->ifv_tag);
+ break;
+ }
#ifdef DIAGNOSTIC
- default:
- panic("vlan_start: impossible");
+ default:
+ panic("vlan_start: impossible");
#endif
+ }
}
/*
@@ -757,45 +773,68 @@
{
struct ifvlan *ifv;
u_int tag;
+ struct mbuf *n;
- switch (ifp->if_type) {
- case IFT_ETHER:
- {
- struct ether_vlan_header *evl;
+ n = m_aux_find(m, AF_LINK, ETHERTYPE_VLAN);
+ if (n) {
+ /* m contains a normal ethernet frame, the tag is in m_aux */
+ tag = *mtod(n, int *);
+ m_aux_delete(m, n);
+ for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
+ ifv = LIST_NEXT(ifv, ifv_list))
+ if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
+ break;
+ } else {
+ switch (ifp->if_type) {
+ case IFT_ETHER:
+ {
+ struct ether_vlan_header *evl;
- if (m->m_len < sizeof(struct ether_vlan_header) &&
- (m = m_pullup(m,
- sizeof(struct ether_vlan_header))) == NULL) {
- printf("%s: no memory for VLAN header, "
- "dropping packet.\n", ifp->if_xname);
- return;
+ if (m->m_len < sizeof(struct ether_vlan_header) &&
+ (m = m_pullup(m,
+ sizeof(struct ether_vlan_header))) == NULL) {
+ printf("%s: no memory for VLAN header, "
+ "dropping packet.\n", ifp->if_xname);
+ return;
+ }
+ evl = mtod(m, struct ether_vlan_header *);
+ KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN);
+
+ tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
+
+ /*
+ * Restore the original ethertype. We'll remove
+ * the encapsulation after we've found the vlan
+ * interface corresponding to the tag.
+ */
+ evl->evl_encap_proto = evl->evl_proto;
+ break;
+ }
+
+ default:
+ tag = (u_int) -1; /* XXX GCC */
+#ifdef DIAGNOSTIC
+ panic("vlan_input: impossible");
+#endif
}
- evl = mtod(m, struct ether_vlan_header *);
- KASSERT(ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN);
- tag = EVL_VLANOFTAG(ntohs(evl->evl_tag));
+ for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
+ ifv = LIST_NEXT(ifv, ifv_list))
+ if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
+ break;
+
/*
- * Restore the original ethertype. We'll remove
- * the encapsulation after we've found the vlan
- * interface corresponding to the tag.
+ * Now, remove the encapsulation header. The original
+ * header has already been fixed up above.
*/
- evl->evl_encap_proto = evl->evl_proto;
- break;
- }
-
- default:
- tag = (u_int) -1; /* XXX GCC */
-#ifdef DIAGNOSTIC
- panic("vlan_input: impossible");
-#endif
+ if (ifv) {
+ memmove(mtod(m, caddr_t) + ifv->ifv_encaplen,
+ mtod(m, caddr_t), sizeof(struct ether_header));
+ m_adj(m, ifv->ifv_encaplen);
+ }
}
- for (ifv = LIST_FIRST(&ifv_list); ifv != NULL;
- ifv = LIST_NEXT(ifv, ifv_list))
- if (ifp == ifv->ifv_p && tag == ifv->ifv_tag)
- break;
-
if (ifv == NULL ||
(ifv->ifv_if.if_flags & (IFF_UP|IFF_RUNNING)) !=
(IFF_UP|IFF_RUNNING)) {
@@ -803,15 +842,6 @@
ifp->if_noproto++;
return;
}
-
- /*
- * Now, remove the encapsulation header. The original
- * header has already been fixed up above.
- */
- memmove(mtod(m, caddr_t) + ifv->ifv_encaplen, mtod(m, caddr_t),
- sizeof(struct ether_header));
- m_adj(m, ifv->ifv_encaplen);
-
m->m_pkthdr.rcvif = &ifv->ifv_if;
ifv->ifv_if.if_ipackets++;
Home |
Main Index |
Thread Index |
Old Index