Index: head/sys/netinet/tcp_input.c =================================================================== --- head/sys/netinet/tcp_input.c +++ head/sys/netinet/tcp_input.c @@ -1682,6 +1682,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); } /* * Process options only when we get SYN/ACK back. The SYN case @@ -1794,9 +1797,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); @@ -2787,8 +2791,10 @@ * original cwnd and ssthresh, and proceed to transmit where * we left off. */ - if (tp->t_rxtshift == 1 && tp->t_flags & TF_PREVVALID && - (int)(ticks - tp->t_badrxtwin) < 0) + if (tp->t_rxtshift == 1 && + tp->t_flags & TF_PREVVALID && + tp->t_badrxtwin && + SEQ_LT(to.to_tsecr, tp->t_badrxtwin)) cc_cong_signal(tp, th, CC_RTO_ERR); /* Index: head/sys/netinet/tcp_output.c =================================================================== --- head/sys/netinet/tcp_output.c +++ head/sys/netinet/tcp_output.c @@ -206,7 +206,7 @@ #if defined(IPSEC) || defined(IPSEC_SUPPORT) unsigned ipsec_optlen = 0; #endif - int idle, sendalot; + int idle, sendalot, curticks; int sack_rxmit, sack_bytes_rxmt; struct sackhole *p; int tso, mtu; @@ -808,9 +808,12 @@ /* 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; + curticks = tcp_ts_getticks(); + to.to_tsval = curticks + tp->ts_offset; to.to_tsecr = tp->ts_recent; to.to_flags |= TOF_TS; + if (tp->t_rxtshift == 1) + tp->t_badrxtwin = curticks; } /* Set receive buffer autosizing timestamp. */ Index: head/sys/netinet/tcp_timer.c =================================================================== --- head/sys/netinet/tcp_timer.c +++ head/sys/netinet/tcp_timer.c @@ -693,7 +693,12 @@ 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)); + /* In the event that we've negotiated timestamps + * badrxtwin will be set to the value that we set + * the retransmitted packet's to_tsval to by tcp_output + */ tp->t_flags |= TF_PREVVALID; } else tp->t_flags &= ~TF_PREVVALID;