diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2025-01-13 18:13:45 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2025-01-13 18:13:45 +0000 |
commit | b84f41b4e82df373f8e682d45791b6ab636cd94e (patch) | |
tree | 29966397e968a3c4bac8d6a21f7df78e3f28c3b2 | |
parent | 72c11c40ab5b091a30cddbd4b8d007ac7c29fcf9 (diff) |
tcp: properly reset sackhint values when SACK recovery is done
When the SACK scoreboard collapses, properly clear all the counters.
The counters are used in tcp_compute_pipe(), which can be called
anytime later after the SACK recovery. The returned result can be
totally bogus, including both too large and too small values.
PR: 283649
Reviewed by: rscheff
Differential Revision: https://reviews.freebsd.org/D48236
-rw-r--r-- | sys/netinet/tcp_sack.c | 27 |
1 files changed, 17 insertions, 10 deletions
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index f642acd4c46a..90d789f0e224 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -653,8 +653,6 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) * scoreboard). */ tp->snd_fack = SEQ_MAX(tp->snd_una, th_ack); - tp->sackhint.sacked_bytes = 0; /* reset */ - tp->sackhint.hole_bytes = 0; } /* * In the while-loop below, incoming SACK blocks (sack_blocks[]) and @@ -870,12 +868,26 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) } } - KASSERT(!(TAILQ_EMPTY(&tp->snd_holes) && (tp->sackhint.hole_bytes != 0)), - ("SACK scoreboard empty, but accounting non-zero\n")); - + KASSERT(delivered_data >= 0, ("delivered_data < 0")); KASSERT(notlost_bytes <= tp->sackhint.hole_bytes, ("SACK: more bytes marked notlost than in scoreboard holes")); + if (TAILQ_EMPTY(&tp->snd_holes)) { + KASSERT(tp->sackhint.hole_bytes == 0, + ("SACK scoreboard empty, but accounting non-zero\n")); + tp->sackhint.sack_bytes_rexmit = 0; + tp->sackhint.sacked_bytes = 0; + tp->sackhint.lost_bytes = 0; + } else { + KASSERT(tp->sackhint.hole_bytes > 0, + ("SACK scoreboard not empty, but has no bytes\n")); + tp->sackhint.delivered_data = delivered_data; + tp->sackhint.sacked_bytes += delivered_data - left_edge_delta; + KASSERT((tp->sackhint.sacked_bytes >= 0), ("sacked_bytes < 0")); + tp->sackhint.lost_bytes = tp->sackhint.hole_bytes - + notlost_bytes; + } + if (!(to->to_flags & TOF_SACK)) /* * If this ACK did not contain any @@ -886,11 +898,6 @@ tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack) * for RFC6675 rescue retransmission. */ sack_changed = SACK_NOCHANGE; - tp->sackhint.delivered_data = delivered_data; - tp->sackhint.sacked_bytes += delivered_data - left_edge_delta; - tp->sackhint.lost_bytes = tp->sackhint.hole_bytes - notlost_bytes; - KASSERT((delivered_data >= 0), ("delivered_data < 0")); - KASSERT((tp->sackhint.sacked_bytes >= 0), ("sacked_bytes < 0")); return (sack_changed); } |