mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
tcp: always set retrans_stamp on recovery
Previously TCP socket's retrans_stamp is not set if the retransmission has failed to send. As a result if a socket is experiencing local issues to retransmit packets, determining when to abort a socket is complicated w/o knowning the starting time of the recovery since retrans_stamp may remain zero. This complication causes sub-optimal behavior that TCP may use the latest, instead of the first, retransmission time to compute the elapsed time of a stalling connection due to local issues. Then TCP may disrecard TCP retries settings and keep retrying until it finally succeed: not a good idea when the local host is already strained. The simple fix is to always timestamp the start of a recovery. It's worth noting that retrans_stamp is also used to compare echo timestamp values to detect spurious recovery. This patch does not break that because retrans_stamp is still later than when the original packet was sent. Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Neal Cardwell <ncardwell@google.com> Reviewed-by: Soheil Hassas Yeganeh <soheil@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
7f12422c48
commit
7ae189759c
2 changed files with 7 additions and 25 deletions
|
@ -2963,13 +2963,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
|
||||||
#endif
|
#endif
|
||||||
TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
|
TCP_SKB_CB(skb)->sacked |= TCPCB_RETRANS;
|
||||||
tp->retrans_out += tcp_skb_pcount(skb);
|
tp->retrans_out += tcp_skb_pcount(skb);
|
||||||
|
|
||||||
/* Save stamp of the first retransmit. */
|
|
||||||
if (!tp->retrans_stamp)
|
|
||||||
tp->retrans_stamp = tcp_skb_timestamp(skb);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save stamp of the first (attempted) retransmit. */
|
||||||
|
if (!tp->retrans_stamp)
|
||||||
|
tp->retrans_stamp = tcp_skb_timestamp(skb);
|
||||||
|
|
||||||
if (tp->undo_retrans < 0)
|
if (tp->undo_retrans < 0)
|
||||||
tp->undo_retrans = 0;
|
tp->undo_retrans = 0;
|
||||||
tp->undo_retrans += tcp_skb_pcount(skb);
|
tp->undo_retrans += tcp_skb_pcount(skb);
|
||||||
|
|
|
@ -22,28 +22,14 @@
|
||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
#include <net/tcp.h>
|
#include <net/tcp.h>
|
||||||
|
|
||||||
static u32 tcp_retransmit_stamp(const struct sock *sk)
|
|
||||||
{
|
|
||||||
u32 start_ts = tcp_sk(sk)->retrans_stamp;
|
|
||||||
|
|
||||||
if (unlikely(!start_ts)) {
|
|
||||||
struct sk_buff *head = tcp_rtx_queue_head(sk);
|
|
||||||
|
|
||||||
if (!head)
|
|
||||||
return 0;
|
|
||||||
start_ts = tcp_skb_timestamp(head);
|
|
||||||
}
|
|
||||||
return start_ts;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
|
static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
|
||||||
{
|
{
|
||||||
struct inet_connection_sock *icsk = inet_csk(sk);
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
||||||
u32 elapsed, start_ts;
|
u32 elapsed, start_ts;
|
||||||
s32 remaining;
|
s32 remaining;
|
||||||
|
|
||||||
start_ts = tcp_retransmit_stamp(sk);
|
start_ts = tcp_sk(sk)->retrans_stamp;
|
||||||
if (!icsk->icsk_user_timeout || !start_ts)
|
if (!icsk->icsk_user_timeout)
|
||||||
return icsk->icsk_rto;
|
return icsk->icsk_rto;
|
||||||
elapsed = tcp_time_stamp(tcp_sk(sk)) - start_ts;
|
elapsed = tcp_time_stamp(tcp_sk(sk)) - start_ts;
|
||||||
remaining = icsk->icsk_user_timeout - elapsed;
|
remaining = icsk->icsk_user_timeout - elapsed;
|
||||||
|
@ -197,10 +183,7 @@ static bool retransmits_timed_out(struct sock *sk,
|
||||||
if (!inet_csk(sk)->icsk_retransmits)
|
if (!inet_csk(sk)->icsk_retransmits)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
start_ts = tcp_retransmit_stamp(sk);
|
start_ts = tcp_sk(sk)->retrans_stamp;
|
||||||
if (!start_ts)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (likely(timeout == 0)) {
|
if (likely(timeout == 0)) {
|
||||||
linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base);
|
linear_backoff_thresh = ilog2(TCP_RTO_MAX/rto_base);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue