summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_bridge.c76
-rw-r--r--sys/net/if_ethersubr.c7
-rw-r--r--sys/net/if_vlan.c30
3 files changed, 89 insertions, 24 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 96ee7a54158..b28f4746e77 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.172 2008/09/10 14:01:23 blambert Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.173 2008/10/16 19:12:51 naddy Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -35,6 +35,7 @@
#include "gif.h"
#include "pf.h"
#include "carp.h"
+#include "vlan.h"
#include <sys/param.h>
#include <sys/proc.h>
@@ -95,6 +96,10 @@
#include <netinet/ip_carp.h>
#endif
+#if NVLAN > 0
+#include <net/if_vlan_var.h>
+#endif
+
#include <net/if_bridge.h>
/*
@@ -1354,6 +1359,11 @@ bridgeintr_frame(struct bridge_softc *sc, struct mbuf *m)
#endif
len = m->m_pkthdr.len;
+#if NVLAN > 0
+ if ((m->m_flags & M_VLANTAG) &&
+ (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
+ len += ETHER_VLAN_ENCAP_LEN;
+#endif
if ((len - ETHER_HDR_LEN) > dst_if->if_mtu)
bridge_fragment(sc, dst_if, &eh, m);
else {
@@ -1527,7 +1537,7 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
struct bridge_iflist *p;
struct mbuf *mc;
struct ifnet *dst_if;
- int len = m->m_pkthdr.len, used = 0;
+ int len, used = 0;
splassert(IPL_NET);
@@ -1609,6 +1619,12 @@ bridge_broadcast(struct bridge_softc *sc, struct ifnet *ifp,
continue;
#endif
+ len = mc->m_pkthdr.len;
+#if NVLAN > 0
+ if ((mc->m_flags & M_VLANTAG) &&
+ (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
+ len += ETHER_VLAN_ENCAP_LEN;
+#endif
if ((len - ETHER_HDR_LEN) > dst_if->if_mtu)
bridge_fragment(sc, dst_if, eh, mc);
else {
@@ -2076,6 +2092,11 @@ bridge_blocknonip(struct ether_header *eh, struct mbuf *m)
if (m->m_pkthdr.len < ETHER_HDR_LEN)
return (1);
+#if NVLAN > 0
+ if (m->m_flags & M_VLANTAG)
+ return (1);
+#endif
+
etype = ntohs(eh->ether_type);
switch (etype) {
case ETHERTYPE_ARP:
@@ -2412,6 +2433,11 @@ bridge_filter(struct bridge_softc *sc, int dir, struct ifnet *ifp,
int hlen;
u_int16_t etype;
+#if NVLAN > 0
+ if (m->m_flags & M_VLANTAG)
+ return (m);
+#endif
+
etype = ntohs(eh->ether_type);
if (etype != ETHERTYPE_IP && etype != ETHERTYPE_IPV6) {
@@ -2600,15 +2626,22 @@ bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,
goto dropit;
#else
etype = ntohs(eh->ether_type);
- if (etype == ETHERTYPE_VLAN &&
- (ifp->if_capabilities & IFCAP_VLAN_MTU) &&
- ((m->m_pkthdr.len - sizeof(struct ether_vlan_header)) <=
- ifp->if_mtu)) {
- s = splnet();
- bridge_ifenqueue(sc, ifp, m);
- splx(s);
- return;
+#if NVLAN > 0
+ if ((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN) {
+ int len = m->m_pkthdr.len;
+
+ if (m->m_flags & M_VLANTAG)
+ len += ETHER_VLAN_ENCAP_LEN;
+ if ((ifp->if_capabilities & IFCAP_VLAN_MTU) &&
+ (len - sizeof(struct ether_vlan_header) <= ifp->if_mtu)) {
+ s = splnet();
+ bridge_ifenqueue(sc, ifp, m);
+ splx(s);
+ return;
+ }
+ goto dropit;
}
+#endif
if (etype != ETHERTYPE_IP) {
if (etype > ETHERMTU ||
m->m_pkthdr.len < (LLC_SNAPFRAMELEN +
@@ -2703,6 +2736,29 @@ bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
if (ifp->if_type == IFT_GIF)
m->m_flags |= M_PROTO1;
#endif
+#if NVLAN > 0
+ /*
+ * If the underlying interface cannot do VLAN tag insertion itself,
+ * create an encapsulation header.
+ */
+ if ((m->m_flags & M_VLANTAG) &&
+ (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0) {
+ struct ether_vlan_header evh;
+
+ m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&evh);
+ evh.evl_proto = evh.evl_encap_proto;
+ evh.evl_encap_proto = htons(ETHERTYPE_VLAN);
+ evh.evl_tag = htons(m->m_pkthdr.ether_vtag);
+ m_adj(m, ETHER_HDR_LEN);
+ M_PREPEND(m, sizeof(evh), M_DONTWAIT);
+ if (m == NULL) {
+ sc->sc_if.if_oerrors++;
+ return (ENOBUFS);
+ }
+ m_copyback(m, 0, sizeof(evh), &evh);
+ m->m_flags &= ~M_VLANTAG;
+ }
+#endif
len = m->m_pkthdr.len;
mflags = m->m_flags;
IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 45456994caa..dcbaab93b0c 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.126 2008/10/09 03:31:07 brad Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.127 2008/10/16 19:12:51 naddy Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -587,7 +587,8 @@ ether_input(ifp0, eh, m)
}
#if NVLAN > 0
- if (etype == ETHERTYPE_VLAN && (vlan_input(eh, m) == 0))
+ if (((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN)
+ && (vlan_input(eh, m) == 0))
return;
#endif
@@ -612,7 +613,7 @@ ether_input(ifp0, eh, m)
#endif
#if NVLAN > 0
- if (etype == ETHERTYPE_VLAN) {
+ if ((m->m_flags & M_VLANTAG) || etype == ETHERTYPE_VLAN) {
/* The bridge did not want the vlan frame either, drop it. */
ifp->if_noproto++;
m_freem(m);
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index c2f48b5b5e3..191de2e49d7 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vlan.c,v 1.75 2008/10/16 14:23:35 naddy Exp $ */
+/* $OpenBSD: if_vlan.c,v 1.76 2008/10/16 19:12:51 naddy Exp $ */
/*
* Copyright 1998 Massachusetts Institute of Technology
@@ -276,13 +276,17 @@ vlan_input(eh, m)
u_int tag;
struct ifnet *ifp = m->m_pkthdr.rcvif;
- if (m->m_len < EVL_ENCAPLEN &&
- (m = m_pullup(m, EVL_ENCAPLEN)) == NULL) {
- ifp->if_ierrors++;
- return (0);
- }
+ if (m->m_flags & M_VLANTAG) {
+ tag = EVL_VLANOFTAG(m->m_pkthdr.ether_vtag);
+ } else {
+ if (m->m_len < EVL_ENCAPLEN &&
+ (m = m_pullup(m, EVL_ENCAPLEN)) == NULL) {
+ ifp->if_ierrors++;
+ return (0);
+ }
- tag = EVL_VLANOFTAG(ntohs(*mtod(m, u_int16_t *)));
+ tag = EVL_VLANOFTAG(ntohs(*mtod(m, u_int16_t *)));
+ }
LIST_FOREACH(ifv, &vlan_tagh[TAG_HASH(tag)], ifv_list) {
if (m->m_pkthdr.rcvif == ifv->ifv_p && tag == ifv->ifv_tag)
@@ -305,10 +309,14 @@ vlan_input(eh, m)
* reentrant!).
*/
m->m_pkthdr.rcvif = &ifv->ifv_if;
- eh->ether_type = mtod(m, u_int16_t *)[1];
- m->m_len -= EVL_ENCAPLEN;
- m->m_data += EVL_ENCAPLEN;
- m->m_pkthdr.len -= EVL_ENCAPLEN;
+ if (m->m_flags & M_VLANTAG) {
+ m->m_flags &= ~M_VLANTAG;
+ } else {
+ eh->ether_type = mtod(m, u_int16_t *)[1];
+ m->m_len -= EVL_ENCAPLEN;
+ m->m_data += EVL_ENCAPLEN;
+ m->m_pkthdr.len -= EVL_ENCAPLEN;
+ }
#if NBPFILTER > 0
if (ifv->ifv_if.if_bpf)