[PATCH net v3 1/4] net/mlx5e: psp: tso: replace only the length in checksum seed

From: Todd Freed

Date: Fri Oct 23 2026 - 19:48:10 EST


for psp tcp with tso,

- __tcp_transmit_skb() -> tcp_v6_send_check() or tcp_v4_send_check()
computes the checksum seed using the addresses on the socket and the
total length, then

- mlx5e_psp_handle_tx_skb() recomputes the checksum seed using
addresses from the packet's l3 header, and the length of one segment

the length difference is expected by the device. however, the
difference in addresses is incorrect in cases where the l3 header daddr
is an intermediate hop (e.g. IPV6_RTHDR). this causes every segment of
the tso packet to go out with a bad tcp checksum, in this case.

the fix is to replace only the length in the seed which tcp had already
computed. this is also what tcp_gso_segment() does.

tested on connectx-7 with the rest of this series applied, with a psp
tcp socket whose segment routing header's first hop isn't the final
destination, and the peer checking tcp checksums in software.

Fixes: e5a1861a298e ("net/mlx5e: Implement PSP Tx data path")
Signed-off-by: Todd Freed <toddfreed@xxxxxxxx>
---
.../mellanox/mlx5/core/en_accel/psp_rxtx.c | 21 ++++++++-----------
1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c
index 348fd7a96261..d9c2742b3c24 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/psp_rxtx.c
@@ -177,18 +177,15 @@ bool mlx5e_psp_handle_tx_skb(struct net_device *netdev,
return false;
}
if (skb_is_gso(skb)) {
- int len = skb_shinfo(skb)->gso_size + inner_tcp_hdrlen(skb);
- struct tcphdr *th = inner_tcp_hdr(skb);
-
- if (skb->protocol == htons(ETH_P_IP)) {
- const struct iphdr *ip = ip_hdr(skb);
-
- th->check = ~tcp_v4_check(len, ip->saddr, ip->daddr, 0);
- } else {
- const struct ipv6hdr *ip6 = ipv6_hdr(skb);
-
- th->check = ~tcp_v6_check(len, &ip6->saddr, &ip6->daddr, 0);
- }
+ u32 seg_len = skb_shinfo(skb)->gso_size + inner_tcp_hdrlen(skb);
+ u32 len = skb->len - skb_inner_transport_offset(skb);
+
+ /* update just the length component of the checksum seed
+ * tcp computed the seed with the total length, but mlx5
+ * devices are expecting the segment length
+ */
+ inet_proto_csum_replace4(&inner_tcp_hdr(skb)->check, skb,
+ htonl(len), htonl(seg_len), true);
}

return true;
--
2.53.0-Meta