[openwrt/openwrt] kernel: fix IPv6 TCP GSO segmentation with NAT

LEDE Commits lede-commits at lists.infradead.org
Mon Feb 24 03:27:07 PST 2025


nbd pushed a commit to openwrt/openwrt.git, branch openwrt-24.10:
https://git.openwrt.org/8c1296f157e46f6f594cf4cef1b17d7151893b8d

commit 8c1296f157e46f6f594cf4cef1b17d7151893b8d
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Mon Feb 24 12:26:01 2025 +0100

    kernel: fix IPv6 TCP GSO segmentation with NAT
    
    Add missing checksum update
    
    Fixes: https://github.com/openwrt/openwrt/issues/15857
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
    (cherry picked from commit 00e4b23e27bd4ed3e0370b9b474ec53f72bd1282)
---
 ...et-ipv6-fix-TCP-GSO-segmentation-with-NAT.patch | 54 ++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/target/linux/generic/pending-6.6/686-net-ipv6-fix-TCP-GSO-segmentation-with-NAT.patch b/target/linux/generic/pending-6.6/686-net-ipv6-fix-TCP-GSO-segmentation-with-NAT.patch
new file mode 100644
index 0000000000..9591e16ec9
--- /dev/null
+++ b/target/linux/generic/pending-6.6/686-net-ipv6-fix-TCP-GSO-segmentation-with-NAT.patch
@@ -0,0 +1,54 @@
+From: Felix Fietkau <nbd at nbd.name>
+Date: Mon, 24 Feb 2025 12:18:23 +0100
+Subject: [PATCH] net: ipv6: fix TCP GSO segmentation with NAT
+
+When updating the source/destination address, the TCP/UDP checksum needs to
+be updated as well.
+
+Fixes: bee88cd5bd83 ("net: add support for segmenting TCP fraglist GSO packets")
+Signed-off-by: Felix Fietkau <nbd at nbd.name>
+---
+
+--- a/net/ipv6/tcpv6_offload.c
++++ b/net/ipv6/tcpv6_offload.c
+@@ -112,24 +112,36 @@ static struct sk_buff *__tcpv6_gso_segme
+ 	struct sk_buff *seg;
+ 	struct tcphdr *th2;
+ 	struct ipv6hdr *iph2;
++	bool addr_equal;
+ 
+ 	seg = segs;
+ 	th = tcp_hdr(seg);
+ 	iph = ipv6_hdr(seg);
+ 	th2 = tcp_hdr(seg->next);
+ 	iph2 = ipv6_hdr(seg->next);
++	addr_equal = ipv6_addr_equal(&iph->saddr, &iph2->saddr) &&
++		     ipv6_addr_equal(&iph->daddr, &iph2->daddr);
+ 
+ 	if (!(*(const u32 *)&th->source ^ *(const u32 *)&th2->source) &&
+-	    ipv6_addr_equal(&iph->saddr, &iph2->saddr) &&
+-	    ipv6_addr_equal(&iph->daddr, &iph2->daddr))
++	    addr_equal)
+ 		return segs;
+ 
+ 	while ((seg = seg->next)) {
+ 		th2 = tcp_hdr(seg);
+ 		iph2 = ipv6_hdr(seg);
+ 
+-		iph2->saddr = iph->saddr;
+-		iph2->daddr = iph->daddr;
++		if (!addr_equal) {
++			inet_proto_csum_replace16(&th2->check, seg,
++						  iph2->saddr.s6_addr32,
++						  iph->saddr.s6_addr32,
++						  true);
++			inet_proto_csum_replace16(&th2->check, seg,
++						  iph2->daddr.s6_addr32,
++						  iph->daddr.s6_addr32,
++						  true);
++			iph2->saddr = iph->saddr;
++			iph2->daddr = iph->daddr;
++		}
+ 		__tcpv6_gso_segment_csum(seg, &th2->source, th->source);
+ 		__tcpv6_gso_segment_csum(seg, &th2->dest, th->dest);
+ 	}




More information about the lede-commits mailing list