diff options
-rw-r--r-- | sys/net/if_bridge.c | 76 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 7 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 30 |
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) |