The branch main has been updated by rscheff: URL: https://cgit.FreeBSD.org/src/commit/?id=65d4a83399843cb4c6dd44061599390843c162db
commit 65d4a83399843cb4c6dd44061599390843c162db Author: Richard Scheffenegger <rsch...@freebsd.org> AuthorDate: 2025-08-06 20:25:30 +0000 Commit: Richard Scheffenegger <rsch...@freebsd.org> CommitDate: 2025-08-06 21:47:05 +0000 tcp: ensure SACK rxmit never ends up left of its hole When a RTO happens during SACK loss recovery, snd_recover can possibly pulled left. With Lost Retransmission Detection (LRD) this can lead to rxmit of a hole to end up pointing to the left of the hole, which is unexpected and leads to complications. Reviewed By: tuexen, #transport Sponsored by: NetApp, Inc. MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D51725 --- sys/netinet/tcp_output.c | 2 +- sys/netinet/tcp_sack.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index bc5b42ee6f2c..2dfb7faf56e3 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1250,7 +1250,7 @@ send: * fack acks recoverypoint. */ if ((tp->t_flags & TF_LRD) && SEQ_GEQ(p->rxmit, p->end)) - p->rxmit = tp->snd_recover; + p->rxmit = SEQ_MAX(p->rxmit, tp->snd_recover); tp->sackhint.sack_bytes_rexmit += len; } if (IN_RECOVERY(tp->t_flags)) { diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index 66275cb04bdd..b6c55fac50b3 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -816,7 +816,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) cur->end = sblkp->start; cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); if ((tp->t_flags & TF_LRD) && SEQ_GEQ(cur->rxmit, cur->end)) - cur->rxmit = tp->snd_recover; + cur->rxmit = SEQ_MAX(cur->rxmit, tp->snd_recover); } else { /* * ACKs some data in middle of a hole; need @@ -843,7 +843,7 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) cur->rxmit = SEQ_MIN(cur->rxmit, cur->end); if ((tp->t_flags & TF_LRD) && SEQ_GEQ(cur->rxmit, cur->end)) - cur->rxmit = tp->snd_recover; + cur->rxmit = SEQ_MAX(cur->rxmit, tp->snd_recover); delivered_data += (sblkp->end - sblkp->start); } }