git: 574d46b25ab6 - main - epair: add VLAN_HWTAGGING
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 30 Jan 2026 10:59:49 UTC
The branch main has been updated by tuexen:
URL: https://cgit.FreeBSD.org/src/commit/?id=574d46b25ab6f42ad97017bb8b72520e9539e36f
commit 574d46b25ab6f42ad97017bb8b72520e9539e36f
Author: Timo Völker <timo.voelker@fh-muenster.de>
AuthorDate: 2026-01-30 10:54:33 +0000
Commit: Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2026-01-30 10:54:33 +0000
epair: add VLAN_HWTAGGING
Add capability VLAN_HWTAGGING to the epair interface and enable it by
default.
When sending a packet over a VLAN interface that uses an epair
interface, the flag M_VLANTAG and the ether_vtag (which contains the
VLAN ID and/or PCP) are set in the mbuf to inform the hardware that
the VLAN header has to be added. The sending epair end does not need
to actually add a VLAN header. It can just pass the mbuf with this
setting to the other epair end, which receives the packet. The
receiving epair end can just pass the mbuf with this setting to the
upper layer. Due to this setting, the upper layer believes that there
was a VLAN header that has been removed by the interface.
If the packet later leaves the host, the outgoing physical interface
can add the VLAN header in hardware if it supports VLAN_HWTAGGING.
If not, the implementation of Ethernet or bridge adds the VLAN header
in software.
Reviewed by: zlei, tuexen
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D52465
---
share/man/man4/epair.4 | 20 +++++++++++++++++++-
sys/net/if_epair.c | 28 ++++++++++++++++------------
2 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/share/man/man4/epair.4 b/share/man/man4/epair.4
index b406c423361b..ba42106d45f8 100644
--- a/share/man/man4/epair.4
+++ b/share/man/man4/epair.4
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 4, 2025
+.Dd January 30, 2026
.Dt EPAIR 4
.Os
.Sh NAME
@@ -113,6 +113,7 @@ The
.Nm
has RXCSUM and RXCSUM6 enabled because it may receive a packet where the
checksum has already been validated by a physical interface.
+.Pp
The
.Nm
supports TXCSUM and TXCSUM6 for TCP and UDP, but only by forwarding the order
@@ -131,6 +132,23 @@ enables/disables it on the other end).
In case one end is in a bridge and the bridge disabled TXCSUM or TXCSUM6,
this avoids a sender to send packets with checksum offloading into the
bridge by using the other end.
+.Pp
+The
+.Nm
+supports VLAN_HWTAGGING without actually adding a VLAN tag.
+The sending
+.Nm
+end just forwards the offloading information to the other end.
+The receiving
+.Nm
+end leaves the offloading information set to pretend that there was a VLAN tag
+in the Ethernet header, which has been removed already.
+To avoid a situation where the receiving
+.Nm
+end has VLAN_HWTAGGING disabled, this capability is synchronized between the
+.Nm
+interface pair (i.e., enabling/disabling the capability on one end
+enables/disables it on the other end).
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr altq 4 ,
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index fbffa8f359a0..60849ca1d4f2 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -150,10 +150,6 @@ epair_clear_mbuf(struct mbuf *m)
m->m_pkthdr.csum_flags &= ~CSUM_SND_TAG;
}
- /* Clear vlan information. */
- m->m_flags &= ~M_VLANTAG;
- m->m_pkthdr.ether_vtag = 0;
-
m_tag_delete_nonpersistent(m);
}
@@ -493,6 +489,7 @@ epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifp->if_capenable = ifr->ifr_reqcap | IFCAP_RXCSUM |
IFCAP_RXCSUM_IPV6;
epair_caps_changed(ifp);
+ VLAN_CAPABILITIES(ifp);
/*
* If IFCAP_TXCSUM(_IPV6) has been changed, change it on the
* other epair interface as well.
@@ -501,17 +498,23 @@ epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* In that case this capability needs to be disabled on the
* other epair interface to avoid sending packets in the bridge
* that rely on this capability.
+ * Do the same for IFCAP_VLAN_HWTAGGING. If the sending epair
+ * end has this capability enabled, the other end has to have
+ * it enabled too. Otherwise, epair would have to add the VLAN
+ * tag in the Ethernet header.
*/
sc = ifp->if_softc;
if ((ifp->if_capenable ^ sc->oifp->if_capenable) &
- (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) {
+ (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 | IFCAP_VLAN_HWTAGGING)) {
sc->oifp->if_capenable &=
- ~(IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+ ~(IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 |
+ IFCAP_VLAN_HWTAGGING);
sc->oifp->if_capenable |= ifp->if_capenable &
- (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+ (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6 |
+ IFCAP_VLAN_HWTAGGING);
epair_caps_changed(sc->oifp);
+ VLAN_CAPABILITIES(sc->oifp);
}
- VLAN_CAPABILITIES(ifp);
error = 0;
break;
@@ -626,10 +629,11 @@ epair_setup_ifp(struct epair_softc *sc, char *name, int unit)
ifp->if_dname = epairname;
ifp->if_dunit = unit;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_TXCSUM |
- IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6;
- ifp->if_capenable = IFCAP_VLAN_MTU | IFCAP_TXCSUM |
- IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6;
+ ifp->if_capabilities =
+ IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
+ IFCAP_TXCSUM | IFCAP_RXCSUM |
+ IFCAP_TXCSUM_IPV6 | IFCAP_RXCSUM_IPV6;
+ ifp->if_capenable = ifp->if_capabilities;
epair_caps_changed(ifp);
ifp->if_transmit = epair_transmit;
ifp->if_qflush = epair_qflush;