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 @@ -2596,7 +2596,7 @@ if (V_tcp_do_prr && IN_FASTRECOVERY(tp->t_flags) && (tp->t_flags & TF_SACK_PERMIT)) { - tcp_do_prr_ack(tp, th, &to, sack_changed); + tcp_do_prr_ack(tp, th, &to, sack_changed, maxseg); } else if (tcp_is_sack_recovery(tp, &to) && IN_FASTRECOVERY(tp->t_flags)) { int awnd; @@ -2802,14 +2802,18 @@ if (IN_FASTRECOVERY(tp->t_flags)) { if (SEQ_LT(th->th_ack, tp->snd_recover)) { if (tp->t_flags & TF_SACK_PERMIT) + if (maxseg == 0) { + maxseg = tcp_maxseg(tp); + } if (V_tcp_do_prr && to.to_flags & TOF_SACK) { tcp_timer_activate(tp, TT_REXMT, 0); tp->t_rtttime = 0; - tcp_do_prr_ack(tp, th, &to, sack_changed); + tcp_do_prr_ack(tp, th, &to, sack_changed, + maxseg); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); } else - tcp_sack_partialack(tp, th); + tcp_sack_partialack(tp, th, maxseg); else tcp_newreno_partial_ack(tp, th); } else @@ -2823,7 +2827,10 @@ * During ECN cwnd reduction * always use PRR-SSRB */ - tcp_do_prr_ack(tp, th, &to, SACK_CHANGE); + if (maxseg == 0) { + maxseg = tcp_maxseg(tp); + } + tcp_do_prr_ack(tp, th, &to, SACK_CHANGE, maxseg); (void) tcp_output(tp); } } else @@ -3946,10 +3953,9 @@ } void -tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, sackstatus_t sack_changed) +tcp_do_prr_ack(struct tcpcb *tp, struct tcphdr *th, struct tcpopt *to, sackstatus_t sack_changed, u_int maxseg) { int snd_cnt = 0, limit = 0, del_data = 0, pipe = 0; - int maxseg = tcp_maxseg(tp); INP_WLOCK_ASSERT(tptoinpcb(tp)); 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 @@ -936,13 +936,13 @@ * the midst of sack recovery. */ void -tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th) +tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th, u_int maxseg) { struct sackhole *temp; int num_segs = 1; - u_int maxseg = tcp_maxseg(tp); INP_WLOCK_ASSERT(tptoinpcb(tp)); + tcp_timer_activate(tp, TT_REXMT, 0); tp->t_rtttime = 0; /* Send one or 2 segments based on how much new data was acked. */ diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1486,9 +1486,9 @@ void tcp_clean_sackreport(struct tcpcb *tp); void tcp_sack_adjust(struct tcpcb *tp); struct sackhole *tcp_sack_output(struct tcpcb *tp, int *sack_bytes_rexmt); -void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, sackstatus_t); +void tcp_do_prr_ack(struct tcpcb *, struct tcphdr *, struct tcpopt *, sackstatus_t, u_int); void tcp_lost_retransmission(struct tcpcb *, struct tcphdr *); -void tcp_sack_partialack(struct tcpcb *, struct tcphdr *); +void tcp_sack_partialack(struct tcpcb *, struct tcphdr *, u_int); void tcp_resend_sackholes(struct tcpcb *tp); void tcp_free_sackholes(struct tcpcb *tp); void tcp_sack_lost_retransmission(struct tcpcb *, struct tcphdr *);