From 0999766ddfa4602637fc7ffb0148dc0b33870533 Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Sat, 23 Mar 2019 21:36:59 +0000 Subject: [PATCH] Add sysctl variable net.inet.tcp.rexmit_initial for setting RTO.Initial used by TCP. Reviewed by: rrs@, 0mp@ Sponsored by: Netflix, Inc. Differential Revision: https://reviews.freebsd.org/D19355 --- share/man/man4/tcp.4 | 5 +++-- sys/netinet/tcp_subr.c | 7 +++++-- sys/netinet/tcp_syncache.c | 13 +++++++------ sys/netinet/tcp_timer.c | 7 ++++++- sys/netinet/tcp_timer.h | 1 + 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/share/man/man4/tcp.4 b/share/man/man4/tcp.4 index 20ee4e139ee1..6319cfbd088f 100644 --- a/share/man/man4/tcp.4 +++ b/share/man/man4/tcp.4 @@ -34,7 +34,7 @@ .\" From: @(#)tcp.4 8.1 (Berkeley) 6/5/93 .\" $FreeBSD$ .\" -.Dd August 6, 2018 +.Dd March 23, 2019 .Dt TCP 4 .Os .Sh NAME @@ -459,7 +459,7 @@ The actual limit applied to a session's reassembly queue will be the lower of the system-calculated automatic limit and the user-specified .Va reass.maxqueuelen limit. -.It Va rexmit_min , rexmit_slop +.It Va rexmit_initial , rexmit_min , rexmit_slop Adjust the retransmit timer calculation for .Tn TCP . The slop is @@ -481,6 +481,7 @@ code. For this reason, we use 200ms of slop and a near-0 minimum, which gives us an effective minimum of 200ms (similar to .Tn Linux ) . +The initial value is used before an RTT measurement has been performed. .It Va initcwnd_segments Enable the ability to specify initial congestion window in number of segments. The default value is 10 as suggested by RFC 6928. diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 2e8441159f40..4ac87cb0d470 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1065,6 +1065,9 @@ tcp_init(void) tcp_keepintvl = TCPTV_KEEPINTVL; tcp_maxpersistidle = TCPTV_KEEP_IDLE; tcp_msl = TCPTV_MSL; + tcp_rexmit_initial = TCPTV_RTOBASE; + if (tcp_rexmit_initial < 1) + tcp_rexmit_initial = 1; tcp_rexmit_min = TCPTV_MIN; if (tcp_rexmit_min < 1) tcp_rexmit_min = 1; @@ -1645,9 +1648,9 @@ tcp_newtcpcb(struct inpcb *inp) * reasonable initial retransmit time. */ tp->t_srtt = TCPTV_SRTTBASE; - tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4; + tp->t_rttvar = ((tcp_rexmit_initial - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4; tp->t_rttmin = tcp_rexmit_min; - tp->t_rxtcur = TCPTV_RTOBASE; + tp->t_rxtcur = tcp_rexmit_initial; tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_rcvtime = ticks; diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 634db056ede2..1d4cad70b50d 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -155,10 +155,10 @@ static int syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch, /* * Transmit the SYN,ACK fewer times than TCP_MAXRXTSHIFT specifies. * 3 retransmits corresponds to a timeout with default values of - * TCPTV_RTOBASE * ( 1 + - * tcp_backoff[1] + - * tcp_backoff[2] + - * tcp_backoff[3]) + 3 * tcp_rexmit_slop, + * tcp_rexmit_initial * ( 1 + + * tcp_backoff[1] + + * tcp_backoff[2] + + * tcp_backoff[3]) + 3 * tcp_rexmit_slop, * 1000 ms * (1 + 2 + 4 + 8) + 3 * 200 ms = 15600 ms, * the odds are that the user has given up attempting to connect by then. */ @@ -424,9 +424,10 @@ syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout) int rexmt; if (sc->sc_rxmits == 0) - rexmt = TCPTV_RTOBASE; + rexmt = tcp_rexmit_initial; else - TCPT_RANGESET(rexmt, TCPTV_RTOBASE * tcp_backoff[sc->sc_rxmits], + TCPT_RANGESET(rexmt, + tcp_rexmit_initial * tcp_backoff[sc->sc_rxmits], tcp_rexmit_min, TCPTV_REXMTMAX); sc->sc_rxttime = ticks + rexmt; sc->sc_rxmits++; diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c index 804a6fd63e7f..cc9aafee6e04 100644 --- a/sys/netinet/tcp_timer.c +++ b/sys/netinet/tcp_timer.c @@ -110,6 +110,11 @@ int tcp_msl; SYSCTL_PROC(_net_inet_tcp, OID_AUTO, msl, CTLTYPE_INT|CTLFLAG_RW, &tcp_msl, 0, sysctl_msec_to_ticks, "I", "Maximum segment lifetime"); +int tcp_rexmit_initial; +SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_initial, CTLTYPE_INT|CTLFLAG_RW, + &tcp_rexmit_initial, 0, sysctl_msec_to_ticks, "I", + "Initial Retransmission Timeout"); + int tcp_rexmit_min; SYSCTL_PROC(_net_inet_tcp, OID_AUTO, rexmit_min, CTLTYPE_INT|CTLFLAG_RW, &tcp_rexmit_min, 0, sysctl_msec_to_ticks, "I", @@ -668,7 +673,7 @@ tcp_timer_rexmt(void * xtp) TCPSTAT_INC(tcps_rexmttimeo); if ((tp->t_state == TCPS_SYN_SENT) || (tp->t_state == TCPS_SYN_RECEIVED)) - rexmt = TCPTV_RTOBASE * tcp_backoff[tp->t_rxtshift]; + rexmt = tcp_rexmit_initial * tcp_backoff[tp->t_rxtshift]; else rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; TCPT_RANGESET(tp->t_rxtcur, rexmt, diff --git a/sys/netinet/tcp_timer.h b/sys/netinet/tcp_timer.h index b3ab2d43f21f..3e985bdfb826 100644 --- a/sys/netinet/tcp_timer.h +++ b/sys/netinet/tcp_timer.h @@ -194,6 +194,7 @@ extern int tcp_keepintvl; /* time between keepalive probes */ extern int tcp_keepcnt; /* number of keepalives */ extern int tcp_delacktime; /* time before sending a delayed ACK */ extern int tcp_maxpersistidle; +extern int tcp_rexmit_initial; extern int tcp_rexmit_min; extern int tcp_rexmit_slop; extern int tcp_msl;