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 @@ -510,6 +510,7 @@ } /* XXXLAS: EXIT_RECOVERY ? */ tp->t_bytes_acked = 0; + tp->sackhint.recover_fs = 0; } /* @@ -2590,6 +2591,9 @@ tp->sackhint.sack_bytes_rexmit; tp->sackhint.prr_delivered += del_data; if (pipe > tp->snd_ssthresh) { + if (tp->sackhint.recover_fs == 0) + tp->sackhint.recover_fs = + max(1, tp->snd_nxt - tp->snd_una); snd_cnt = (tp->sackhint.prr_delivered * tp->snd_ssthresh / tp->sackhint.recover_fs) + @@ -2677,14 +2681,14 @@ tcp_timer_activate(tp, TT_REXMT, 0); tp->t_rtttime = 0; if (V_tcp_do_prr) { - /* - * snd_ssthresh is already updated by - * cc_cong_signal. - */ - tp->sackhint.prr_delivered = 0; - tp->sackhint.sack_bytes_rexmit = 0; - if (!(tp->sackhint.recover_fs = tp->snd_nxt - tp->snd_una)) - tp->sackhint.recover_fs = 1; + /* + * snd_ssthresh is already updated by + * cc_cong_signal. + */ + tp->sackhint.prr_delivered = 0; + tp->sackhint.sack_bytes_rexmit = 0; + tp->sackhint.recover_fs = max(1, + tp->snd_nxt - tp->snd_una); } if (tp->t_flags & TF_SACK_PERMIT) { TCPSTAT_INC( diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -742,6 +742,16 @@ TCPS_HAVEESTABLISHED(tp->t_state) ? TP_KEEPIDLE(tp) : TP_KEEPINIT(tp)); + /* + * Make sure critical variables are initialized + * if transitioning while in Recovery. + */ + if IN_FASTRECOVERY(tp->t_flags) { + if (tp->sackhint.recover_fs == 0) + tp->sackhint.recover_fs = max(1, + tp->snd_nxt - tp->snd_una); + } + return (0); }