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);
                                }
                        }

Reply via email to