|
@@ -880,6 +880,11 @@ static void tcp_init_metrics(struct sock *sk)
|
|
|
tp->snd_ssthresh = dst_metric(dst, RTAX_SSTHRESH);
|
|
|
if (tp->snd_ssthresh > tp->snd_cwnd_clamp)
|
|
|
tp->snd_ssthresh = tp->snd_cwnd_clamp;
|
|
|
+ } else {
|
|
|
+ /* ssthresh may have been reduced unnecessarily during.
|
|
|
+ * 3WHS. Restore it back to its initial default.
|
|
|
+ */
|
|
|
+ tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
|
|
|
}
|
|
|
if (dst_metric(dst, RTAX_REORDERING) &&
|
|
|
tp->reordering != dst_metric(dst, RTAX_REORDERING)) {
|
|
@@ -887,10 +892,7 @@ static void tcp_init_metrics(struct sock *sk)
|
|
|
tp->reordering = dst_metric(dst, RTAX_REORDERING);
|
|
|
}
|
|
|
|
|
|
- if (dst_metric(dst, RTAX_RTT) == 0)
|
|
|
- goto reset;
|
|
|
-
|
|
|
- if (!tp->srtt && dst_metric_rtt(dst, RTAX_RTT) < (TCP_TIMEOUT_INIT << 3))
|
|
|
+ if (dst_metric(dst, RTAX_RTT) == 0 || tp->srtt == 0)
|
|
|
goto reset;
|
|
|
|
|
|
/* Initial rtt is determined from SYN,SYN-ACK.
|
|
@@ -916,19 +918,26 @@ static void tcp_init_metrics(struct sock *sk)
|
|
|
tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
|
|
|
}
|
|
|
tcp_set_rto(sk);
|
|
|
- if (inet_csk(sk)->icsk_rto < TCP_TIMEOUT_INIT && !tp->rx_opt.saw_tstamp) {
|
|
|
reset:
|
|
|
- /* Play conservative. If timestamps are not
|
|
|
- * supported, TCP will fail to recalculate correct
|
|
|
- * rtt, if initial rto is too small. FORGET ALL AND RESET!
|
|
|
+ if (tp->srtt == 0) {
|
|
|
+ /* RFC2988bis: We've failed to get a valid RTT sample from
|
|
|
+ * 3WHS. This is most likely due to retransmission,
|
|
|
+ * including spurious one. Reset the RTO back to 3secs
|
|
|
+ * from the more aggressive 1sec to avoid more spurious
|
|
|
+ * retransmission.
|
|
|
*/
|
|
|
- if (!tp->rx_opt.saw_tstamp && tp->srtt) {
|
|
|
- tp->srtt = 0;
|
|
|
- tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_INIT;
|
|
|
- inet_csk(sk)->icsk_rto = TCP_TIMEOUT_INIT;
|
|
|
- }
|
|
|
+ tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK;
|
|
|
+ inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK;
|
|
|
}
|
|
|
- tp->snd_cwnd = tcp_init_cwnd(tp, dst);
|
|
|
+ /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been
|
|
|
+ * retransmitted. In light of RFC2988bis' more aggressive 1sec
|
|
|
+ * initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK
|
|
|
+ * retransmission has occurred.
|
|
|
+ */
|
|
|
+ if (tp->total_retrans > 1)
|
|
|
+ tp->snd_cwnd = 1;
|
|
|
+ else
|
|
|
+ tp->snd_cwnd = tcp_init_cwnd(tp, dst);
|
|
|
tp->snd_cwnd_stamp = tcp_time_stamp;
|
|
|
}
|
|
|
|
|
@@ -3112,12 +3121,13 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag)
|
|
|
tcp_xmit_retransmit_queue(sk);
|
|
|
}
|
|
|
|
|
|
-static void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
|
|
|
+void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt)
|
|
|
{
|
|
|
tcp_rtt_estimator(sk, seq_rtt);
|
|
|
tcp_set_rto(sk);
|
|
|
inet_csk(sk)->icsk_backoff = 0;
|
|
|
}
|
|
|
+EXPORT_SYMBOL(tcp_valid_rtt_meas);
|
|
|
|
|
|
/* Read draft-ietf-tcplw-high-performance before mucking
|
|
|
* with this code. (Supersedes RFC1323)
|
|
@@ -5806,12 +5816,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
|
|
|
tp->rx_opt.snd_wscale;
|
|
|
tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
|
|
|
|
|
|
- /* tcp_ack considers this ACK as duplicate
|
|
|
- * and does not calculate rtt.
|
|
|
- * Force it here.
|
|
|
- */
|
|
|
- tcp_ack_update_rtt(sk, 0, 0);
|
|
|
-
|
|
|
if (tp->rx_opt.tstamp_ok)
|
|
|
tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
|
|
|
|