Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit ee575eb

Browse files
nealcardwellgregkh
authored andcommitted
tcp: fix to allow timestamp undo if no retransmits were sent
[ Upstream commit e37ab73 ] 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: commit bc9f38c ("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: commit bc9f38c ("tcp: avoid unconditional congestion window undo on SYN retransmit") This fix tweaks the logic to be more similar to the tcp_packet_delayed() logic before bc9f38c, 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 in bc9f38c). 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: bc9f38c ("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>
1 parent c87d299 commit ee575eb

File tree

1 file changed

+16
-2
lines changed

1 file changed

+16
-2
lines changed

net/ipv4/tcp_input.c

+16-2
Original file line numberDiff line numberDiff line change
@@ -2473,8 +2473,22 @@ static bool tcp_skb_spurious_retrans(const struct tcp_sock *tp,
24732473
*/
24742474
static inline bool tcp_packet_delayed(const struct tcp_sock *tp)
24752475
{
2476-
return tp->retrans_stamp &&
2477-
tcp_tsopt_ecr_before(tp, tp->retrans_stamp);
2476+
const struct sock *sk = (const struct sock *)tp;
2477+
2478+
if (tp->retrans_stamp &&
2479+
tcp_tsopt_ecr_before(tp, tp->retrans_stamp))
2480+
return true; /* got echoed TS before first retransmission */
2481+
2482+
/* Check if nothing was retransmitted (retrans_stamp==0), which may
2483+
* happen in fast recovery due to TSQ. But we ignore zero retrans_stamp
2484+
* in TCP_SYN_SENT, since when we set FLAG_SYN_ACKED we also clear
2485+
* retrans_stamp even if we had retransmitted the SYN.
2486+
*/
2487+
if (!tp->retrans_stamp && /* no record of a retransmit/SYN? */
2488+
sk->sk_state != TCP_SYN_SENT) /* not the FLAG_SYN_ACKED case? */
2489+
return true; /* nothing was retransmitted */
2490+
2491+
return false;
24782492
}
24792493

24802494
/* Undo procedures. */

0 commit comments

Comments
 (0)