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 @@ -2612,8 +2612,7 @@ cc_ack_received(tp, th, nsegs, CC_DUPACK); if (V_tcp_do_prr && - IN_FASTRECOVERY(tp->t_flags) && - (tp->t_flags & TF_SACK_PERMIT)) { + IN_FASTRECOVERY(tp->t_flags)) { tcp_do_prr_ack(tp, th, &to); } else if ((tp->t_flags & TF_SACK_PERMIT) && (to.to_flags & TOF_SACK) && @@ -2689,8 +2688,16 @@ * snd_ssthresh is already updated by * cc_cong_signal. */ - tp->sackhint.prr_delivered = - tp->sackhint.sacked_bytes; + if ((tp->t_flags & TF_SACK_PERMIT) && + (to.to_flags & TOF_SACK)) { + tp->sackhint.prr_delivered = + tp->sackhint.sacked_bytes; + } else { + tp->sackhint.prr_delivered = + imin(tp->snd_max - tp->snd_una, + imin(INT_MAX / 65536, + tp->t_dupacks) * maxseg); + } tp->sackhint.recover_fs = max(1, tp->snd_nxt - tp->snd_una); } @@ -3968,11 +3975,23 @@ * (del_data) and an estimate of how many bytes are in the * network. */ - del_data = tp->sackhint.delivered_data; - if (V_tcp_do_newsack) - pipe = tcp_compute_pipe(tp); - else - pipe = (tp->snd_nxt - tp->snd_fack) + tp->sackhint.sack_bytes_rexmit; + if (((tp->t_flags & TF_SACK_PERMIT) && + (to->to_flags & TOF_SACK)) || + (IN_CONGRECOVERY(tp->t_flags) && + !IN_FASTRECOVERY(tp->t_flags))) { + del_data = tp->sackhint.delivered_data; + if (V_tcp_do_newsack) + pipe = tcp_compute_pipe(tp); + else + pipe = (tp->snd_nxt - tp->snd_fack) + + tp->sackhint.sack_bytes_rexmit; + } else { + if (tp->sackhint.prr_delivered < (tcprexmtthresh * maxseg + + tp->snd_recover - tp->snd_una)) + del_data = maxseg; + pipe = imax(0, tp->snd_max - tp->snd_una - + imin(INT_MAX / 65536, tp->t_dupacks) * maxseg); + } tp->sackhint.prr_delivered += del_data; /* * Proportional Rate Reduction @@ -3985,9 +4004,9 @@ tp->snd_ssthresh, tp->sackhint.recover_fs) - tp->sackhint.prr_out; } else { - if (V_tcp_do_prr_conservative) + if (V_tcp_do_prr_conservative || (del_data == 0)) limit = tp->sackhint.prr_delivered - - tp->sackhint.prr_out; + tp->sackhint.prr_out; else limit = imax(tp->sackhint.prr_delivered - tp->sackhint.prr_out, del_data) + @@ -4001,11 +4020,18 @@ * accordingly. */ if (IN_FASTRECOVERY(tp->t_flags)) { - tp->snd_cwnd = imax(maxseg, tp->snd_nxt - tp->snd_recover + - tp->sackhint.sack_bytes_rexmit + (snd_cnt * maxseg)); + if ((tp->t_flags & TF_SACK_PERMIT) && + (to->to_flags & TOF_SACK)) { + tp->snd_cwnd = tp->snd_nxt - tp->snd_recover + + tp->sackhint.sack_bytes_rexmit + + (snd_cnt * maxseg); + } else { + tp->snd_cwnd = (tp->snd_max - tp->snd_una) + + (snd_cnt * maxseg); + } } else if (IN_CONGRECOVERY(tp->t_flags)) - tp->snd_cwnd = imax(maxseg, pipe - del_data + - (snd_cnt * maxseg)); + tp->snd_cwnd = pipe - del_data + (snd_cnt * maxseg); + tp->snd_cwnd = imax(maxseg, tp->snd_cwnd); } /*