Commit 0d08c42c authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

tcp: gso: fix truesize tracking

commit 6ff50cd5 ("tcp: gso: do not generate out of order packets")
had an heuristic that can trigger a warning in skb_try_coalesce(),
because skb->truesize of the gso segments were exactly set to mss.

This breaks the requirement that

skb->truesize >= skb->len + truesizeof(struct sk_buff);

It can trivially be reproduced by :

ifconfig lo mtu 1500
ethtool -K lo tso off
netperf

As the skbs are looped into the TCP networking stack, skb_try_coalesce()
warns us of these skb under-estimating their truesize.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fc59d5bd
...@@ -18,6 +18,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, ...@@ -18,6 +18,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
netdev_features_t features) netdev_features_t features)
{ {
struct sk_buff *segs = ERR_PTR(-EINVAL); struct sk_buff *segs = ERR_PTR(-EINVAL);
unsigned int sum_truesize = 0;
struct tcphdr *th; struct tcphdr *th;
unsigned int thlen; unsigned int thlen;
unsigned int seq; unsigned int seq;
...@@ -102,13 +103,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, ...@@ -102,13 +103,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
if (copy_destructor) { if (copy_destructor) {
skb->destructor = gso_skb->destructor; skb->destructor = gso_skb->destructor;
skb->sk = gso_skb->sk; skb->sk = gso_skb->sk;
/* {tcp|sock}_wfree() use exact truesize accounting : sum_truesize += skb->truesize;
* sum(skb->truesize) MUST be exactly be gso_skb->truesize
* So we account mss bytes of 'true size' for each segment.
* The last segment will contain the remaining.
*/
skb->truesize = mss;
gso_skb->truesize -= mss;
} }
skb = skb->next; skb = skb->next;
th = tcp_hdr(skb); th = tcp_hdr(skb);
...@@ -125,7 +120,9 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, ...@@ -125,7 +120,9 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
if (copy_destructor) { if (copy_destructor) {
swap(gso_skb->sk, skb->sk); swap(gso_skb->sk, skb->sk);
swap(gso_skb->destructor, skb->destructor); swap(gso_skb->destructor, skb->destructor);
swap(gso_skb->truesize, skb->truesize); sum_truesize += skb->truesize;
atomic_add(sum_truesize - gso_skb->truesize,
&skb->sk->sk_wmem_alloc);
} }
delta = htonl(oldlen + (skb_tail_pointer(skb) - delta = htonl(oldlen + (skb_tail_pointer(skb) -
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment