diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -2680,7 +2680,6 @@ if (tcp_is_sack_recovery(tp, &to)) { TCPSTAT_INC( tcps_sack_recovery_episode); - tp->snd_recover = tp->snd_nxt; tp->snd_cwnd = maxseg; (void) tcp_output(tp); if (SEQ_GT(th->th_ack, tp->snd_una)) diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -878,6 +878,8 @@ * for RFC6675 rescue retransmission. */ sack_changed = SACK_NOCHANGE; + if (SEQ_LT(tp->snd_nxt, tp->snd_fack)) + tp->snd_nxt = tp->snd_fack; 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; @@ -983,12 +985,15 @@ if (tp->t_flags & TF_SENTFIN) highdata--; highdata = SEQ_MIN(highdata, tp->snd_recover); - if (th->th_ack != highdata) { + if (SEQ_LT(th->th_ack, highdata)) { tp->snd_fack = th->th_ack; if ((temp = tcp_sackhole_insert(tp, SEQ_MAX(th->th_ack, - highdata - maxseg), highdata, NULL)) != NULL) - tp->sackhint.hole_bytes += temp->end - - temp->start; + highdata - maxseg), highdata, NULL)) != NULL) { + tp->sackhint.hole_bytes += + temp->end - temp->start; + if (SEQ_LT(tp->snd_nxt, highdata)) + tp->snd_nxt = highdata; + } } } (void) tcp_output(tp); diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -790,7 +790,7 @@ in_losing(inp); } tp->snd_nxt = tp->snd_una; - tp->snd_recover = tp->snd_max; + tp->snd_recover = tp->snd_fack; /* * Force a segment to be sent. */