mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 05:26:07 +00:00
tcp: do not send too big packets at retransmit time
Arjun reported a bug in TCP stack and bisected it to a recent commit. In case where we process SACK, we can coalesce multiple skbs into fat ones (tcp_shift_skb_data()), to lower write queue overhead, because we do not expect to retransmit these packets. However, SACK reneging can happen, forcing the sender to retransmit all these packets. If skb->len is above 64KB, we then send buggy IP packets that could hang TSO engine on cxgb4. Neal suggested to use tcp_tso_autosize() instead of tp->gso_segs so that we cook packets of optimal size vs TCP/pacing. Thanks to Arjun for reporting the bug and running the tests ! Fixes: 10d3be569243 ("tcp-tso: do not split TSO packets at retransmit time") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Arjun V <arjun@chelsio.com> Tested-by: Arjun V <arjun@chelsio.com> Acked-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
96183182ad
commit
a3d2e9f8eb
@ -2751,7 +2751,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *hole = NULL;
|
||||
u32 last_lost;
|
||||
u32 max_segs, last_lost;
|
||||
int mib_idx;
|
||||
int fwd_rexmitting = 0;
|
||||
|
||||
@ -2771,6 +2771,7 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
|
||||
last_lost = tp->snd_una;
|
||||
}
|
||||
|
||||
max_segs = tcp_tso_autosize(sk, tcp_current_mss(sk));
|
||||
tcp_for_write_queue_from(skb, sk) {
|
||||
__u8 sacked = TCP_SKB_CB(skb)->sacked;
|
||||
int segs;
|
||||
@ -2784,6 +2785,10 @@ void tcp_xmit_retransmit_queue(struct sock *sk)
|
||||
segs = tp->snd_cwnd - tcp_packets_in_flight(tp);
|
||||
if (segs <= 0)
|
||||
return;
|
||||
/* In case tcp_shift_skb_data() have aggregated large skbs,
|
||||
* we need to make sure not sending too bigs TSO packets
|
||||
*/
|
||||
segs = min_t(int, segs, max_segs);
|
||||
|
||||
if (fwd_rexmitting) {
|
||||
begin_fwd:
|
||||
|
Loading…
x
Reference in New Issue
Block a user