summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormikeb <mikeb@openbsd.org>2014-12-04 16:16:20 +0000
committermikeb <mikeb@openbsd.org>2014-12-04 16:16:20 +0000
commit65486ef6afb7084963c48e03fa7d14769d5f0f5f (patch)
tree9e0d726e7d81bd969d469e68d6e5f827cddbbf00
parentasm version from libkern, but mempcy() remains tied to the (diff)
downloadwireguard-openbsd-65486ef6afb7084963c48e03fa7d14769d5f0f5f.tar.xz
wireguard-openbsd-65486ef6afb7084963c48e03fa7d14769d5f0f5f.zip
Repair VLAN tagging in the bridge output path
Since bridge_output/bridge_ifenqueue replace ether_output that does VLAN tagging and call into if_start directly we need to make sure that tag has been set by the bridge. XXX This abuses "if_output == vlan_output" check, but hopefully XXX vlan(4) will use a distinct if_type someday and this code XXX will be improved. Discussed with henning and Rafael Zalamena, ok henning
-rw-r--r--sys/net/if_bridge.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 5717a811b18..f2b4fd6a6f9 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.228 2014/11/18 02:37:31 tedu Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.229 2014/12/04 16:16:20 mikeb Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -2705,6 +2705,11 @@ bridge_fragment(struct bridge_softc *sc, struct ifnet *ifp,
m_freem(m);
}
+#if NVLAN > 0
+extern int vlan_output(struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct rtentry *);
+#endif
+
int
bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
{
@@ -2726,22 +2731,33 @@ bridge_ifenqueue(struct bridge_softc *sc, struct ifnet *ifp, struct mbuf *m)
* 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);
+ if (ifp->if_output == vlan_output) {
+ struct ifvlan *ifv = ifp->if_softc;
+ struct ifnet *p = ifv->ifv_p;
+
+ /* should we use the tx tagging hw offload at all? */
+ if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) &&
+ (ifv->ifv_type == ETHERTYPE_VLAN)) {
+ m->m_pkthdr.ether_vtag = ifv->ifv_tag +
+ (m->m_pkthdr.pf.prio << EVL_PRIO_BITS);
+ m->m_flags |= M_VLANTAG;
+ } else {
+ 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(ifv->ifv_type);
+ evh.evl_tag = htons(ifv->ifv_tag +
+ (m->m_pkthdr.pf.prio << EVL_PRIO_BITS));
+ 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_NOWAIT);
+ m->m_flags &= ~M_VLANTAG;
}
- m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
- m->m_flags &= ~M_VLANTAG;
}
#endif
len = m->m_pkthdr.len;