git: fbcf3b74e8f2 - main - tcp: fix detection of bad RTOs

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Thu, 20 Mar 2025 19:35:34 UTC
The branch main has been updated by tuexen:

URL: https://cgit.FreeBSD.org/src/commit/?id=fbcf3b74e8f2c0c5ba37f1839bfe9395eb2fd0b1

commit fbcf3b74e8f2c0c5ba37f1839bfe9395eb2fd0b1
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2025-03-20 15:17:40 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2025-03-20 15:17:40 +0000

    tcp: fix detection of bad RTOs
    
    If timestamps are enabled, the actions performed by a retransmission
    timeout were rolled back, when they should not.
    It is needed to make sure the incoming segment advances SND.UNA.
    To do this, remove the incorrect upfront check and extend the check in
    the fast path to handle also the case of timestamps.
    
    PR:                     282605
    Reviewed by:            cc, rscheff, Peter Lei
    MFC after:              3 days
    Sponsored by:           Netflix, Inc.
    Differential Revision:  https://reviews.freebsd.org/D49414
---
 sys/netinet/tcp_input.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index cf480ccf9772..8f50843d940d 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1635,11 +1635,6 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
 		to.to_tsecr -= tp->ts_offset;
 		if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks())) {
 			to.to_tsecr = 0;
-		} else if (tp->t_rxtshift == 1 &&
-			 tp->t_flags & TF_PREVVALID &&
-			 tp->t_badrxtwin != 0 &&
-			 TSTMP_LT(to.to_tsecr, tp->t_badrxtwin)) {
-			cc_cong_signal(tp, th, CC_RTO_ERR);
 		}
 	}
 	/*
@@ -1792,15 +1787,17 @@ tcp_do_segment(struct tcpcb *tp, struct mbuf *m, struct tcphdr *th,
 				TCPSTAT_INC(tcps_predack);
 
 				/*
-				 * "bad retransmit" recovery without timestamps.
+				 * "bad retransmit" recovery.
 				 */
-				if ((to.to_flags & TOF_TS) == 0 &&
-				    tp->t_rxtshift == 1 &&
+				if (tp->t_rxtshift == 1 &&
 				    tp->t_flags & TF_PREVVALID &&
 				    tp->t_badrxtwin != 0 &&
-				    TSTMP_LT(ticks, tp->t_badrxtwin)) {
+				    (((to.to_flags & TOF_TS) != 0 &&
+				      to.to_tsecr != 0 &&
+				      TSTMP_LT(to.to_tsecr, tp->t_badrxtwin)) ||
+				     ((to.to_flags & TOF_TS) == 0 &&
+				      TSTMP_LT(ticks, tp->t_badrxtwin))))
 					cc_cong_signal(tp, th, CC_RTO_ERR);
-				}
 
 				/*
 				 * Recalculate the transmit timer / rtt.