git: d6c4cea7740d - main - loopback: improve checksum offloading

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Sun, 28 Jun 2026 10:57:58 UTC
The branch main has been updated by tuexen:

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

commit d6c4cea7740d5c5c673a06ba37e4f1bdcddb2ece
Author:     Timo Völker <timo.voelker@fh-muenster.de>
AuthorDate: 2026-06-28 10:50:15 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2026-06-28 10:50:15 +0000

    loopback: improve checksum offloading
    
    * Allow disabling IFCAP_RXCSUM_IPV6 or IFCAP_TXCSUM_IPV6.
    * Do not pretend the checksum is correct by setting the LO_CSUM_SET
      flags if IFCAP_RXCSUM_IPV6 or IFCAP_RXCSUM is enabled. Instead,
      remove the LO_CSUM_SET flags (in case they have been set somehow)
      if IFCAP_RXCSUM_IPV6 or IFCAP_RXCSUM is disabled.
    * Do not unset the transmit checksum offload flags LO_CSUM_FEATURES or
      LO_CSUM_FEATURES6 since they now have a meaning for the receive path.
    
    Reviewed by:            glebius, pouria, tuexen
    Okayed by:              bz
    MFC after:              1 week
    Differential Revision:  https://reviews.freebsd.org/D57518
---
 share/man/man4/lo.4 | 23 ++++++++++-------------
 sys/net/if_loop.c   | 42 ++++++------------------------------------
 2 files changed, 16 insertions(+), 49 deletions(-)

diff --git a/share/man/man4/lo.4 b/share/man/man4/lo.4
index 7bad739eec41..c0c39093473e 100644
--- a/share/man/man4/lo.4
+++ b/share/man/man4/lo.4
@@ -27,7 +27,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 23, 2024
+.Dd June 28, 2026
 .Dt LO 4
 .Os
 .Sh NAME
@@ -54,19 +54,16 @@ The loopback should
 be configured first unless no hardware
 interfaces exist.
 .Pp
-If the transmit checksum offload capability flag is enabled on a loopback
-interface, checksums will not be generated by IP, UDP, TCP, or SCTP for packets
-sent on the interface.
+If the transmit checksum offload capability is enabled on a loopback interface,
+checksums will not be generated by IP, UDP, TCP, or SCTP for packets sent on the
+interface.
+By default, this capability is enabled to avoid the overhead of checksumming for
+local communication where data corruption is unlikely.
 .Pp
-If the receive checksum offload capability flag is enabled on a loopback
-interface, checksums will not be validated by IP, UDP, TCP, or SCTP for packets
-received on the interface.
-.Pp
-By default, both receive and transmit checksum flags will be enabled, in
-order to avoid the overhead of checksumming for local communication where
-data corruption is unlikely.
-If transmit checksum generation is disabled, then validation should also be
-disabled in order to avoid packets being dropped due to invalid checksums.
+If the receive checksum offload capability is disabled on a loopback interface,
+the flags that indicate a valid checksum will be unset if set previously.
+By default, this capability is enabled to avoid another checksum validation if
+it has already been validated.
 .Sh DIAGNOSTICS
 .Bl -diag
 .It lo%d: can't handle af%d.
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index fc5ce9548bcc..69108e9f332a 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -229,38 +229,22 @@ looutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
 	else
 		af = RO_GET_FAMILY(ro, dst);
 
-#if 1	/* XXX */
 	switch (af) {
 	case AF_INET:
-		if (ifp->if_capenable & IFCAP_RXCSUM) {
-			m->m_pkthdr.csum_data = 0xffff;
-			m->m_pkthdr.csum_flags = LO_CSUM_SET;
+		if ((ifp->if_capenable & IFCAP_RXCSUM) == 0) {
+			m->m_pkthdr.csum_flags &= ~LO_CSUM_SET;
 		}
-		m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES;
 		break;
 	case AF_INET6:
-#if 0
-		/*
-		 * XXX-BZ for now always claim the checksum is good despite
-		 * any interface flags.   This is a workaround for 9.1-R and
-		 * a proper solution ought to be sought later.
-		 */
-		if (ifp->if_capenable & IFCAP_RXCSUM_IPV6) {
-			m->m_pkthdr.csum_data = 0xffff;
-			m->m_pkthdr.csum_flags = LO_CSUM_SET;
+		if ((ifp->if_capenable & IFCAP_RXCSUM_IPV6) == 0) {
+			m->m_pkthdr.csum_flags &= ~LO_CSUM_SET;
 		}
-#else
-		m->m_pkthdr.csum_data = 0xffff;
-		m->m_pkthdr.csum_flags = LO_CSUM_SET;
-#endif
-		m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES6;
 		break;
 	default:
 		printf("looutput: af=%d unexpected\n", af);
 		m_freem(m);
 		return (EAFNOSUPPORT);
 	}
-#endif
 	return (if_simloop(ifp, m, af, 0));
 }
 
@@ -420,29 +404,15 @@ loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
 			ifp->if_capenable ^= IFCAP_RXCSUM;
 		if ((mask & IFCAP_TXCSUM) != 0)
 			ifp->if_capenable ^= IFCAP_TXCSUM;
-		if ((mask & IFCAP_RXCSUM_IPV6) != 0) {
-#if 0
+		if ((mask & IFCAP_RXCSUM_IPV6) != 0)
 			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
-#else
-			error = EOPNOTSUPP;
-			break;
-#endif
-		}
-		if ((mask & IFCAP_TXCSUM_IPV6) != 0) {
-#if 0
+		if ((mask & IFCAP_TXCSUM_IPV6) != 0)
 			ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
-#else
-			error = EOPNOTSUPP;
-			break;
-#endif
-		}
 		ifp->if_hwassist = 0;
 		if (ifp->if_capenable & IFCAP_TXCSUM)
 			ifp->if_hwassist = LO_CSUM_FEATURES;
-#if 0
 		if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
 			ifp->if_hwassist |= LO_CSUM_FEATURES6;
-#endif
 		break;
 
 	default: