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

tcp: plug skb_still_in_host_queue() to TSQ

Jakub and Neil reported an increase of RTO timers whenever
TX completions are delayed a bit more (by increasing
NIC TX coalescing parameters)

Main issue is that TCP stack has a logic preventing a packet
being retransmit if the prior clone has not yet been
orphaned or freed.

This logic came with commit 1f3279ae ("tcp: avoid
retransmits of TCP packets hanging in host queues")

Thankfully, in the case skb_still_in_host_queue() detects
the initial clone is still in flight, it can use TSQ logic
that will eventually retry later, at the moment the clone
is freed or orphaned.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarNeil Spring <ntspring@fb.com>
Reported-by: default avatarJakub Kicinski <kuba@kernel.org>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: Yuchung Cheng <ycheng@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8176f8c0
...@@ -1140,7 +1140,7 @@ static inline bool skb_fclone_busy(const struct sock *sk, ...@@ -1140,7 +1140,7 @@ static inline bool skb_fclone_busy(const struct sock *sk,
return skb->fclone == SKB_FCLONE_ORIG && return skb->fclone == SKB_FCLONE_ORIG &&
refcount_read(&fclones->fclone_ref) > 1 && refcount_read(&fclones->fclone_ref) > 1 &&
fclones->skb2.sk == sk; READ_ONCE(fclones->skb2.sk) == sk;
} }
/** /**
......
...@@ -2775,14 +2775,18 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto) ...@@ -2775,14 +2775,18 @@ bool tcp_schedule_loss_probe(struct sock *sk, bool advancing_rto)
* a packet is still in a qdisc or driver queue. * a packet is still in a qdisc or driver queue.
* In this case, there is very little point doing a retransmit ! * In this case, there is very little point doing a retransmit !
*/ */
static bool skb_still_in_host_queue(const struct sock *sk, static bool skb_still_in_host_queue(struct sock *sk,
const struct sk_buff *skb) const struct sk_buff *skb)
{ {
if (unlikely(skb_fclone_busy(sk, skb))) { if (unlikely(skb_fclone_busy(sk, skb))) {
set_bit(TSQ_THROTTLED, &sk->sk_tsq_flags);
smp_mb__after_atomic();
if (skb_fclone_busy(sk, skb)) {
NET_INC_STATS(sock_net(sk), NET_INC_STATS(sock_net(sk),
LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES); LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES);
return true; return true;
} }
}
return false; return false;
} }
......
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