Don't zero out srtt after excess retransmits

If the TCP stack has retransmitted more than 1/4 of the total
number of retransmits before a connection drop, it decides that
its current RTT estimate is hopelessly out of date and decides
to recalculate it from scratch starting with the next ACK.

Unfortunately, it implements this by zeroing out the current RTT
estimate.  Drop this hack entirely, as it makes it significantly more
difficult to debug connection issues.  Instead check for excessive
retransmits at the point where srtt is updated from an ACK being
received.  If we've exceeded 1/4 of the maximum retransmits,
discard the previous srtt estimate and replace it with the latest
rtt measurement.

Differential Revision:	https://reviews.freebsd.org/D9519
Reviewed by:	gnn
Sponsored by:	Dell EMC Isilon
This commit is contained in:
Ryan Stone 2017-02-11 17:05:08 +00:00
parent c05d666747
commit 5ede40dcf2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313646
3 changed files with 11 additions and 8 deletions

View File

@ -3494,7 +3494,7 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt)
TCPSTAT_INC(tcps_rttupdated);
tp->t_rttupdated++;
if (tp->t_srtt != 0) {
if ((tp->t_srtt != 0) && (tp->t_rxtshift <= TCP_RTT_INVALIDATE)) {
/*
* srtt is stored as fixed point with 5 bits after the
* binary point (i.e., scaled by 8). The following magic

View File

@ -845,20 +845,16 @@ tcp_timer_rexmt(void * xtp)
(tp->t_rxtshift == 3))
tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_SACK_PERMIT);
/*
* If we backed off this far, our srtt estimate is probably bogus.
* Clobber it so we'll take the next rtt measurement as our srtt;
* move the current srtt into rttvar to keep the current
* retransmit times until then.
* If we backed off this far, notify the L3 protocol that we're having
* connection problems.
*/
if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) {
if (tp->t_rxtshift > TCP_RTT_INVALIDATE) {
#ifdef INET6
if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
in6_losing(tp->t_inpcb);
else
#endif
in_losing(tp->t_inpcb);
tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
tp->t_srtt = 0;
}
tp->snd_nxt = tp->snd_una;
tp->snd_recover = tp->snd_max;

View File

@ -119,6 +119,13 @@
#define TCPTV_DELACK ( hz/10 ) /* 100ms timeout */
/*
* If we exceed this number of retransmits for a single segment, we'll consider
* the current srtt measurement no longer valid and will recalculate from
* scratch starting with the next ACK.
*/
#define TCP_RTT_INVALIDATE (TCP_MAXRXTSHIFT / 4)
#ifdef TCPTIMERS
static const char *tcptimers[] =
{ "REXMT", "PERSIST", "KEEP", "2MSL", "DELACK" };