aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Völker <timo.voelker@fh-muenster.de>2026-06-28 10:50:15 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2026-08-06 05:45:51 +0000
commitfd3582e683d6cf97c59dcd898ece47a5497d5995 (patch)
tree85a07301b8e2be7e03d402e94f9294bf223916e1
parent976f400a7e5284e36a62c253647d519728b1241f (diff)
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 Differential Revision: https://reviews.freebsd.org/D57518 (cherry picked from commit d6c4cea7740d5c5c673a06ba37e4f1bdcddb2ece)
-rw-r--r--share/man/man4/lo.423
-rw-r--r--sys/net/if_loop.c42
2 files changed, 16 insertions, 49 deletions
diff --git a/share/man/man4/lo.4 b/share/man/man4/lo.4
index f1ac67c7d7db..5b808153559a 100644
--- a/share/man/man4/lo.4
+++ b/share/man/man4/lo.4
@@ -29,7 +29,7 @@
.\"
.\" @(#)lo.4 8.1 (Berkeley) 6/5/93
.\"
-.Dd June 23, 2024
+.Dd June 28, 2026
.Dt LO 4
.Os
.Sh NAME
@@ -56,19 +56,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 27c9281957e2..90252ae06b05 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -231,38 +231,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));
}
@@ -416,29 +400,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: