Skip to content

Commit daa624d

Browse files
nbd168Paolo Abeni
authored andcommitted
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: bee88cd ("net: add support for segmenting TCP fraglist GSO packets") Signed-off-by: Felix Fietkau <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent 2fc8a34 commit daa624d

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

net/ipv6/tcpv6_offload.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,23 @@ INDIRECT_CALLABLE_SCOPE int tcp6_gro_complete(struct sk_buff *skb, int thoff)
9494
}
9595

9696
static void __tcpv6_gso_segment_csum(struct sk_buff *seg,
97+
struct in6_addr *oldip,
98+
const struct in6_addr *newip,
9799
__be16 *oldport, __be16 newport)
98100
{
99-
struct tcphdr *th;
101+
struct tcphdr *th = tcp_hdr(seg);
102+
103+
if (!ipv6_addr_equal(oldip, newip)) {
104+
inet_proto_csum_replace16(&th->check, seg,
105+
oldip->s6_addr32,
106+
newip->s6_addr32,
107+
true);
108+
*oldip = *newip;
109+
}
100110

101111
if (*oldport == newport)
102112
return;
103113

104-
th = tcp_hdr(seg);
105114
inet_proto_csum_replace2(&th->check, seg, *oldport, newport, false);
106115
*oldport = newport;
107116
}
@@ -129,10 +138,10 @@ static struct sk_buff *__tcpv6_gso_segment_list_csum(struct sk_buff *segs)
129138
th2 = tcp_hdr(seg);
130139
iph2 = ipv6_hdr(seg);
131140

132-
iph2->saddr = iph->saddr;
133-
iph2->daddr = iph->daddr;
134-
__tcpv6_gso_segment_csum(seg, &th2->source, th->source);
135-
__tcpv6_gso_segment_csum(seg, &th2->dest, th->dest);
141+
__tcpv6_gso_segment_csum(seg, &iph2->saddr, &iph->saddr,
142+
&th2->source, th->source);
143+
__tcpv6_gso_segment_csum(seg, &iph2->daddr, &iph->daddr,
144+
&th2->dest, th->dest);
136145
}
137146

138147
return segs;

0 commit comments

Comments
 (0)