Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -3494,7 +3494,7 @@ 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 Index: sys/netinet/tcp_timer.h =================================================================== --- sys/netinet/tcp_timer.h +++ sys/netinet/tcp_timer.h @@ -119,6 +119,15 @@ #define TCPTV_DELACK ( hz/10 ) /* 100ms timeout */ +/* Begin Isilon */ +/* + * 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) +/* End Isilon */ + #ifdef TCPTIMERS static const char *tcptimers[] = { "REXMT", "PERSIST", "KEEP", "2MSL", "DELACK" }; Index: sys/netinet/tcp_timer.c =================================================================== --- sys/netinet/tcp_timer.c +++ sys/netinet/tcp_timer.c @@ -845,20 +845,16 @@ (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;