Fix a bug in the restart window computation of TCP New Reno

When implementing support for IW10, an update in the computation
of the restart window used after an idle phase was missed. To
minimize code duplication, implement the logic in tcp_compute_initwnd()
and call it. This fixes a bug in NewReno, which was not aware of
IW10.

Submitted by:		Richard Scheffenegger
Reviewed by:		tuexen@
MFC after:		1 week
Differential Revision:	https://reviews.freebsd.org/D18940
This commit is contained in:
Michael Tuexen 2019-01-25 13:57:09 +00:00
parent 86d535ab47
commit 7dc90a1de0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=343428
4 changed files with 35 additions and 40 deletions

View File

@ -199,7 +199,7 @@ newreno_ack_received(struct cc_var *ccv, uint16_t type)
static void
newreno_after_idle(struct cc_var *ccv)
{
int rw;
uint32_t rw;
/*
* If we've been idle for more than one retransmit timeout the old
@ -214,11 +214,7 @@ newreno_after_idle(struct cc_var *ccv)
*
* See RFC5681 Section 4.1. "Restarting Idle Connections".
*/
if (V_tcp_do_rfc3390)
rw = min(4 * CCV(ccv, t_maxseg),
max(2 * CCV(ccv, t_maxseg), 4380));
else
rw = CCV(ccv, t_maxseg) * 2;
rw = tcp_compute_initwnd(tcp_maxseg(ccv->ccvc.tcp));
CCV(ccv, snd_cwnd) = min(rw, CCV(ccv, snd_cwnd));
}

View File

@ -371,31 +371,14 @@ cc_conn_init(struct tcpcb *tp)
/*
* Set the initial slow-start flight size.
*
* RFC5681 Section 3.1 specifies the default conservative values.
* RFC3390 specifies slightly more aggressive values.
* RFC6928 increases it to ten segments.
* Support for user specified value for initial flight size.
*
* If a SYN or SYN/ACK was lost and retransmitted, we have to
* reduce the initial CWND to one segment as congestion is likely
* requiring us to be cautious.
*/
if (tp->snd_cwnd == 1)
tp->snd_cwnd = maxseg; /* SYN(-ACK) lost */
else if (V_tcp_initcwnd_segments)
tp->snd_cwnd = min(V_tcp_initcwnd_segments * maxseg,
max(2 * maxseg, V_tcp_initcwnd_segments * 1460));
else if (V_tcp_do_rfc3390)
tp->snd_cwnd = min(4 * maxseg, max(2 * maxseg, 4380));
else {
/* Per RFC5681 Section 3.1 */
if (maxseg > 2190)
tp->snd_cwnd = 2 * maxseg;
else if (maxseg > 1095)
tp->snd_cwnd = 3 * maxseg;
else
tp->snd_cwnd = 4 * maxseg;
}
else
tp->snd_cwnd = tcp_compute_initwnd(maxseg);
if (CC_ALGO(tp)->conn_init != NULL)
CC_ALGO(tp)->conn_init(tp->ccv);
@ -3818,3 +3801,30 @@ tcp_compute_pipe(struct tcpcb *tp)
tp->sackhint.sack_bytes_rexmit -
tp->sackhint.sacked_bytes);
}
uint32_t
tcp_compute_initwnd(uint32_t maxseg)
{
/*
* Calculate the Initial Window, also used as Restart Window
*
* RFC5681 Section 3.1 specifies the default conservative values.
* RFC3390 specifies slightly more aggressive values.
* RFC6928 increases it to ten segments.
* Support for user specified value for initial flight size.
*/
if (V_tcp_initcwnd_segments)
return min(V_tcp_initcwnd_segments * maxseg,
max(2 * maxseg, V_tcp_initcwnd_segments * 1460));
else if (V_tcp_do_rfc3390)
return min(4 * maxseg, max(2 * maxseg, 4380));
else {
/* Per RFC5681 Section 3.1 */
if (maxseg > 2190)
return (2 * maxseg);
else if (maxseg > 1095)
return (3 * maxseg);
else
return (4 * maxseg);
}
}

View File

@ -1425,21 +1425,9 @@ rack_cc_after_idle(struct tcpcb *tp, int reduce_largest)
if (tp->snd_cwnd == 1)
i_cwnd = tp->t_maxseg; /* SYN(-ACK) lost */
else if (V_tcp_initcwnd_segments)
i_cwnd = min((V_tcp_initcwnd_segments * tp->t_maxseg),
max(2 * tp->t_maxseg, V_tcp_initcwnd_segments * 1460));
else if (V_tcp_do_rfc3390)
i_cwnd = min(4 * tp->t_maxseg,
max(2 * tp->t_maxseg, 4380));
else {
/* Per RFC5681 Section 3.1 */
if (tp->t_maxseg > 2190)
i_cwnd = 2 * tp->t_maxseg;
else if (tp->t_maxseg > 1095)
i_cwnd = 3 * tp->t_maxseg;
else
i_cwnd = 4 * tp->t_maxseg;
}
else
i_cwnd = tcp_compute_initwnd(tcp_maxseg(tp));
if (reduce_largest) {
/*
* Do we reduce the largest cwnd to make

View File

@ -942,6 +942,7 @@ void tcp_sack_partialack(struct tcpcb *, struct tcphdr *);
void tcp_free_sackholes(struct tcpcb *tp);
int tcp_newreno(struct tcpcb *, struct tcphdr *);
int tcp_compute_pipe(struct tcpcb *);
uint32_t tcp_compute_initwnd(uint32_t);
void tcp_sndbuf_autoscale(struct tcpcb *, struct socket *, uint32_t);
struct mbuf *
tcp_m_copym(struct mbuf *m, int32_t off0, int32_t *plen,