mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 00:04:15 +08:00
tcp: fix to allow timestamp undo if no retransmits were sent
[ Upstream commite37ab73736
] Fix the TCP loss recovery undo logic in tcp_packet_delayed() so that it can trigger undo even if TSQ prevents a fast recovery episode from reaching tcp_retransmit_skb(). Geumhwan Yu <geumhwan.yu@samsung.com> recently reported that after this commit from 2019: commitbc9f38c832
("tcp: avoid unconditional congestion window undo on SYN retransmit") ...and before this fix we could have buggy scenarios like the following: + Due to reordering, a TCP connection receives some SACKs and enters a spurious fast recovery. + TSQ prevents all invocations of tcp_retransmit_skb(), because many skbs are queued in lower layers of the sending machine's network stack; thus tp->retrans_stamp remains 0. + The connection receives a TCP timestamp ECR value echoing a timestamp before the fast recovery, indicating that the fast recovery was spurious. + The connection fails to undo the spurious fast recovery because tp->retrans_stamp is 0, and thus tcp_packet_delayed() returns false, due to the new logic in the 2019 commit: commitbc9f38c832
("tcp: avoid unconditional congestion window undo on SYN retransmit") This fix tweaks the logic to be more similar to the tcp_packet_delayed() logic beforebc9f38c832
, except that we take care not to be fooled by the FLAG_SYN_ACKED code path zeroing out tp->retrans_stamp (the bug noted and fixed by Yuchung inbc9f38c832
). Note that this returns the high-level behavior of tcp_packet_delayed() to again match the comment for the function, which says: "Nothing was retransmitted or returned timestamp is less than timestamp of the first retransmission." Note that this comment is in the original 2005-04-16 Linux git commit, so this is evidently long-standing behavior. Fixes:bc9f38c832
("tcp: avoid unconditional congestion window undo on SYN retransmit") Reported-by: Geumhwan Yu <geumhwan.yu@samsung.com> Diagnosed-by: Geumhwan Yu <geumhwan.yu@samsung.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20241001200517.2756803-2-ncardwell.sw@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
ad0d76b8ee
commit
ffdcd3bd2b
@ -2433,8 +2433,22 @@ static bool tcp_skb_spurious_retrans(const struct tcp_sock *tp,
|
||||
*/
|
||||
static inline bool tcp_packet_delayed(const struct tcp_sock *tp)
|
||||
{
|
||||
return tp->retrans_stamp &&
|
||||
tcp_tsopt_ecr_before(tp, tp->retrans_stamp);
|
||||
const struct sock *sk = (const struct sock *)tp;
|
||||
|
||||
if (tp->retrans_stamp &&
|
||||
tcp_tsopt_ecr_before(tp, tp->retrans_stamp))
|
||||
return true; /* got echoed TS before first retransmission */
|
||||
|
||||
/* Check if nothing was retransmitted (retrans_stamp==0), which may
|
||||
* happen in fast recovery due to TSQ. But we ignore zero retrans_stamp
|
||||
* in TCP_SYN_SENT, since when we set FLAG_SYN_ACKED we also clear
|
||||
* retrans_stamp even if we had retransmitted the SYN.
|
||||
*/
|
||||
if (!tp->retrans_stamp && /* no record of a retransmit/SYN? */
|
||||
sk->sk_state != TCP_SYN_SENT) /* not the FLAG_SYN_ACKED case? */
|
||||
return true; /* nothing was retransmitted */
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Undo procedures. */
|
||||
|
Loading…
Reference in New Issue
Block a user