Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c +++ sys/netinet/tcp_input.c @@ -1644,6 +1644,9 @@ to.to_tsecr -= tp->ts_offset; if (TSTMP_GT(to.to_tsecr, tcp_ts_getticks())) to.to_tsecr = 0; + else if (tp->t_flags & TF_PREVVALID && + tp->t_badrxtwin != 0 && SEQ_LT(to.to_tsecr, tp->t_badrxtwin)) + cc_cong_signal(tp, th, CC_RTO_ERR); } /* * If timestamps were negotiated during SYN/ACK they should @@ -1749,9 +1752,10 @@ TCPSTAT_INC(tcps_predack); /* - * "bad retransmit" recovery. + * "bad retransmit" recovery without timestamps. */ - if (tp->t_rxtshift == 1 && + if ((to.to_flags & TOF_TS) == 0 && + tp->t_rxtshift == 1 && tp->t_flags & TF_PREVVALID && (int)(ticks - tp->t_badrxtwin) < 0) { cc_cong_signal(tp, th, CC_RTO_ERR); Index: sys/netinet/tcp_output.c =================================================================== --- sys/netinet/tcp_output.c +++ sys/netinet/tcp_output.c @@ -203,7 +203,7 @@ #ifdef IPSEC unsigned ipsec_optlen = 0; #endif - int idle, sendalot; + int idle, sendalot, curticks; int sack_rxmit, sack_bytes_rxmt; struct sackhole *p; int tso, mtu; @@ -253,6 +253,9 @@ } } again: + curticks = tcp_ts_getticks(); + if (tp->t_rxtshift == 1 && (tp->t_flags & TF_RCVD_TSTMP)) + tp->t_badrxtwin = curticks; /* * If we've recently taken a timeout, snd_max will be greater than * snd_nxt. There may be SACK information that allows us to avoid @@ -803,13 +806,13 @@ /* Timestamps. */ if ((tp->t_flags & TF_RCVD_TSTMP) || ((flags & TH_SYN) && (tp->t_flags & TF_REQ_TSTMP))) { - to.to_tsval = tcp_ts_getticks() + tp->ts_offset; + to.to_tsval = curticks + tp->ts_offset; to.to_tsecr = tp->ts_recent; to.to_flags |= TOF_TS; /* Set receive buffer autosizing timestamp. */ if (tp->rfbuf_ts == 0 && (so->so_rcv.sb_flags & SB_AUTOSIZE)) - tp->rfbuf_ts = tcp_ts_getticks(); + tp->rfbuf_ts = curticks; } /* Selective ACK's. */ if (tp->t_flags & TF_SACK_PERMIT) { Index: sys/netinet/tcp_timer.c =================================================================== --- sys/netinet/tcp_timer.c +++ sys/netinet/tcp_timer.c @@ -715,7 +715,8 @@ tp->t_flags |= TF_WASCRECOVERY; else tp->t_flags &= ~TF_WASCRECOVERY; - tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1)); + if ((tp->t_flags & TF_RCVD_TSTMP) == 0) + tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1)); tp->t_flags |= TF_PREVVALID; } else tp->t_flags &= ~TF_PREVVALID;