The branch main has been updated by tuexen:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=39d4094173f9a49ff52f5f4408e4dbd5d6ef0409

commit 39d4094173f9a49ff52f5f4408e4dbd5d6ef0409
Author:     Timo Völker <timo.voel...@fh-muenster.de>
AuthorDate: 2025-09-04 12:06:20 +0000
Commit:     Michael Tuexen <tue...@freebsd.org>
CommitDate: 2025-09-04 12:06:20 +0000

    epair: add support for checksum offloading
    
    Add capabilities RXCSUM and RXCSUM6 as well as TXCSUM and TXCSUM6 for
    for receive and transmit checksum offloading for TCP and UDP to the
    epair interface and enable them by default.
    RXCSUM and RXCSUM6 are enabled because an epair interface may receive
    a packet with the csum_flag CSUM_DATA_VALID set, which is expected
    only if these capabilities are enabled. Since it seems not helpful to
    remove this flag, it is not possible to disable these capabilities.
    TXCSUM and TXCSUM6 are synchronized between the two epair interface
    ends. If enabled/disabled on one end, it will be enabled/disabled on
    the other end. If the sending epair interface end has TXCSUM or TXCSUM6
    enabled and the receiving end is in a bridge, it is assumed that all
    interfaces in the bridge have that capability enabled. Otherwise the
    bridge would have disabled that capability on the receiving epair
    interface end in the bridge which would have disabled that capability
    on the sending epair interface end as well due to the synchronization.
    
    This change was committed and reverted earlier, since several pf
    tests were failing. This has been addressed.
    
    Reviewed by:            bcr, Seyed Pouria Mousavizadeh Tehrani, tuexen
    MFC after:              4 weeks
    Differential Revision:  https://reviews.freebsd.org/D51639
---
 share/man/man4/epair.4 | 25 ++++++++++++++++++++-
 sys/net/if_epair.c     | 61 ++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/share/man/man4/epair.4 b/share/man/man4/epair.4
index 342b15b5612a..b406c423361b 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 August 12, 2025
+.Dd September 4, 2025
 .Dt EPAIR 4
 .Os
 .Sh NAME
@@ -108,6 +108,29 @@ As with any other Ethernet interface,
 can have a
 .Xr vlan 4
 configured on top of it.
+.Pp
+The
+.Nm
+has RXCSUM and RXCSUM6 enabled because it may receive a packet where the
+checksum has already been validated by a physical interface.
+The
+.Nm
+supports TXCSUM and TXCSUM6 for TCP and UDP, but only by forwarding the order
+to compute the checksum.
+Thus, when using an
+.Nm
+interface, a TCP or UDP sender can offload checksum computation
+to a physical interface.
+Note that, in case the packet does not leave the host, the checksum is
+unnecessary and will be ignored if offloaded.
+Such packets contain an incorrect checksum, since it is not computed yet.
+TXCSUM and TXCSUM6 are synchronized between the
+.Nm
+interface pair (i.e., enabling/disabling the capability on one end
+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.
 .Sh SEE ALSO
 .Xr ioctl 2 ,
 .Xr altq 4 ,
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index 581c2434b8fb..fbffa8f359a0 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -69,6 +69,7 @@
 #include <net/if_media.h>
 #include <net/if_private.h>
 #include <net/if_types.h>
+#include <net/if_vlan_var.h>
 #include <net/netisr.h>
 #ifdef RSS
 #include <net/rss_config.h>
@@ -434,6 +435,21 @@ epair_media_status(struct ifnet *ifp __unused, struct 
ifmediareq *imr)
        imr->ifm_active = IFM_ETHER | IFM_10G_T | IFM_FDX;
 }
 
+/*
+ * Update ifp->if_hwassist according to the current value of ifp->if_capenable.
+ */
+static void
+epair_caps_changed(struct ifnet *ifp)
+{
+       uint64_t hwassist = 0;
+
+       if (ifp->if_capenable & IFCAP_TXCSUM)
+               hwassist |= CSUM_IP_TCP | CSUM_IP_UDP;
+       if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
+               hwassist |= CSUM_IP6_TCP | CSUM_IP6_UDP;
+       ifp->if_hwassist = hwassist;
+}
+
 static int
 epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 {
@@ -461,6 +477,44 @@ epair_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                error = 0;
                break;
 
+       case SIOCGIFCAP:
+               ifr->ifr_reqcap = ifp->if_capabilities;
+               ifr->ifr_curcap = ifp->if_capenable;
+               error = 0;
+               break;
+       case SIOCSIFCAP:
+               /*
+                * Enable/disable capabilities as requested, besides
+                * IFCAP_RXCSUM(_IPV6), which always remain enabled.
+                * Incoming packets may have the mbuf flag CSUM_DATA_VALID set.
+                * Without IFCAP_RXCSUM(_IPV6), this flag would have to be
+                * removed, which does not seem helpful.
+                */
+               ifp->if_capenable = ifr->ifr_reqcap | IFCAP_RXCSUM |
+                   IFCAP_RXCSUM_IPV6;
+               epair_caps_changed(ifp);
+               /*
+                * If IFCAP_TXCSUM(_IPV6) has been changed, change it on the
+                * other epair interface as well.
+                * A bridge disables IFCAP_TXCSUM(_IPV6) when adding one epair
+                * interface if another interface in the bridge has it disabled.
+                * 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.
+                */
+               sc = ifp->if_softc;
+               if ((ifp->if_capenable ^ sc->oifp->if_capenable) &
+                   (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) {
+                       sc->oifp->if_capenable &=
+                           ~(IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+                       sc->oifp->if_capenable |= ifp->if_capenable &
+                           (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6);
+                       epair_caps_changed(sc->oifp);
+               }
+               VLAN_CAPABILITIES(ifp);
+               error = 0;
+               break;
+
        default:
                /* Let the common ethernet handler process this. */
                error = ether_ioctl(ifp, cmd, data);
@@ -572,8 +626,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;
-       ifp->if_capenable = IFCAP_VLAN_MTU;
+       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;
+       epair_caps_changed(ifp);
        ifp->if_transmit = epair_transmit;
        ifp->if_qflush = epair_qflush;
        ifp->if_start = epair_start;

Reply via email to