Index | Thread | Search

From:
Jan Klemkow <jan@openbsd.org>
Subject:
bridge(4): use vlan hardware tagging
To:
tech@openbsd.org
Date:
Mon, 4 Aug 2025 12:02:30 +0200

Download raw body.

Thread
Hi,

This diff adds the use of VLAN hardware tagging in bridge(4) and
vether(4) similar to veb(4).

ok?

bye,
Jan

Index: net/if_bridge.c
===================================================================
RCS file: /cvs/src/sys/net/if_bridge.c,v
diff -u -p -r1.376 if_bridge.c
--- net/if_bridge.c	7 Jul 2025 02:28:50 -0000	1.376
+++ net/if_bridge.c	4 Aug 2025 08:13:23 -0000
@@ -798,6 +798,24 @@ bridge_stop(struct bridge_softc *sc)
 	bridge_rtflush(sc, IFBF_FLUSHDYN);
 }
 
+struct mbuf *
+bridge_offload(struct ifnet *ifp, struct mbuf *m)
+{
+#if NVLAN > 0
+	/*
+	 * If the underlying interface has no VLAN hardware tagging support,
+	 * inject one in software.
+	 */
+	if (ISSET(m->m_flags, M_VLANTAG) &&
+	    !ISSET(ifp->if_capabilities, IFCAP_VLAN_HWTAGGING)) {
+		m = vlan_inject(m, ETHERTYPE_VLAN, m->m_pkthdr.ether_vtag);
+		if (m == NULL)
+			return NULL;
+	}
+#endif
+	return m;
+}
+
 /*
  * Send output from the bridge.  The mbuf has the ethernet header
  * already attached.  We must enqueue or free the mbuf before exiting.
@@ -897,6 +915,9 @@ bridge_enqueue(struct ifnet *ifp, struct
 				continue;
 			}
 
+			if ((mc = bridge_offload(dst_if, mc)) == NULL)
+				goto out;
+
 			error = bridge_ifenqueue(brifp, dst_if, mc);
 			if (error)
 				continue;
@@ -914,6 +935,9 @@ bridge_enqueue(struct ifnet *ifp, struct
 		goto out;
 	}
 
+	if ((m = bridge_offload(dst_if, m)) == NULL)
+		goto out;
+
 	bridge_ifenqueue(brifp, dst_if, m);
 	if_put(dst_if);
 out:
@@ -1093,6 +1117,9 @@ bridgeintr_frame(struct ifnet *brifp, st
 	if (m == NULL)
 		goto bad;
 
+	if ((m = bridge_offload(dst_if, m)) == NULL)
+		goto bad;
+
 	len = m->m_pkthdr.len;
 #if NVLAN > 0
 	if ((m->m_flags & M_VLANTAG) &&
@@ -1170,18 +1197,6 @@ bridge_process(struct ifnet *ifp, struct
 	if (m->m_pkthdr.len < sizeof(*eh))
 		goto bad;
 
-#if NVLAN > 0
-	/*
-	 * If the underlying interface removed the VLAN header itself,
-	 * add it back.
-	 */
-	if (ISSET(m->m_flags, M_VLANTAG)) {
-		m = vlan_inject(m, ETHERTYPE_VLAN, m->m_pkthdr.ether_vtag);
-		if (m == NULL)
-			goto bad;
-	}
-#endif
-
 #if NBPFILTER > 0
 	if_bpf = brifp->if_bpf;
 	if (if_bpf)
@@ -1358,6 +1373,9 @@ bridge_broadcast(struct bridge_softc *sc
 		if (mc == NULL)
 			continue;
 
+		if ((mc = bridge_offload(dst_if, mc)) == NULL)
+			goto bad;
+
 		len = mc->m_pkthdr.len;
 #if NVLAN > 0
 		if ((mc->m_flags & M_VLANTAG) &&
@@ -1371,6 +1389,7 @@ bridge_broadcast(struct bridge_softc *sc
 		}
 	}
 
+ bad:
 	if (!used)
 		m_freem(m);
 }
@@ -1425,6 +1444,11 @@ bridge_span(struct ifnet *brifp, struct 
 
 		if ((ifp->if_flags & IFF_RUNNING) == 0)
 			continue;
+
+		if ((m = bridge_offload(ifp, m)) == NULL) {
+			brifp->if_oerrors++;
+			continue;
+		}
 
 		mc = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
 		if (mc == NULL) {
Index: net/if_vether.c
===================================================================
RCS file: /cvs/src/sys/net/if_vether.c,v
diff -u -p -r1.37 if_vether.c
--- net/if_vether.c	7 Jul 2025 02:28:50 -0000	1.37
+++ net/if_vether.c	3 Aug 2025 16:12:48 -0000
@@ -27,6 +27,7 @@
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 
+#include "vlan.h"
 #include "bpfilter.h"
 #if NBPFILTER > 0
 #include <net/bpf.h>
@@ -85,6 +86,9 @@ vether_clone_create(struct if_clone *ifc
 
 	ifp->if_hardmtu = ETHER_MAX_HARDMTU_LEN;
 	ifp->if_capabilities = IFCAP_VLAN_MTU;
+#if NVLAN > 0
+	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+#endif
 	ifp->if_xflags = IFXF_CLONED | IFXF_MPSAFE;
 
 	ifmedia_init(&sc->sc_media, 0, vether_media_change,