From: Ilpo Järvinen Date: Wed, 1 Apr 2009 23:18:20 +0000 (+0000) Subject: tcp: miscounts due to tcp_fragment pcount reset X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=9eb9362e569062e2f841b7a023e5fcde10ed63b4;p=linux-2.6-omap-h63xx.git tcp: miscounts due to tcp_fragment pcount reset It seems that trivial reset of pcount to one was not sufficient in tcp_retransmit_skb. Multiple counters experience a positive miscount when skb's pcount gets lowered without the necessary adjustments (depending on skb's sacked bits which exactly), at worst a packets_out miscount can crash at RTO if the write queue is empty! Triggering this requires mss change, so bidir tcp or mtu probe or like. Signed-off-by: Ilpo Järvinen Reported-by: Markus Trippelsdorf Tested-by: Uwe Bugla Signed-off-by: David S. Miller --- diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f1db89bb3aa..53300fa2359 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1893,7 +1893,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) if (tcp_fragment(sk, skb, cur_mss, cur_mss)) return -ENOMEM; /* We'll try again later. */ } else { - tcp_init_tso_segs(sk, skb, cur_mss); + int oldpcount = tcp_skb_pcount(skb); + + if (unlikely(oldpcount > 1)) { + tcp_init_tso_segs(sk, skb, cur_mss); + tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); + } } tcp_retrans_try_collapse(sk, skb, cur_mss);