aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a16b01b537ba..068c8fb0d158 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2856,7 +2856,8 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
2856 * left edge of the send window. 2856 * left edge of the send window.
2857 * See draft-ietf-tcplw-high-performance-00, section 3.3. 2857 * See draft-ietf-tcplw-high-performance-00, section 3.3.
2858 */ 2858 */
2859 if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) 2859 if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
2860 flag & FLAG_ACKED)
2860 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; 2861 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
2861 2862
2862 if (seq_rtt < 0) 2863 if (seq_rtt < 0)
@@ -2871,14 +2872,19 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
2871} 2872}
2872 2873
2873/* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ 2874/* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */
2874static void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req) 2875static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp)
2875{ 2876{
2876 struct tcp_sock *tp = tcp_sk(sk); 2877 struct tcp_sock *tp = tcp_sk(sk);
2877 s32 seq_rtt = -1; 2878 s32 seq_rtt = -1;
2878 2879
2879 if (tp->lsndtime && !tp->total_retrans) 2880 if (synack_stamp && !tp->total_retrans)
2880 seq_rtt = tcp_time_stamp - tp->lsndtime; 2881 seq_rtt = tcp_time_stamp - synack_stamp;
2881 tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1); 2882
2883 /* If the ACK acks both the SYNACK and the (Fast Open'd) data packets
2884 * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack()
2885 */
2886 if (!tp->srtt)
2887 tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
2882} 2888}
2883 2889
2884static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) 2890static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
@@ -2981,6 +2987,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
2981 s32 seq_rtt = -1; 2987 s32 seq_rtt = -1;
2982 s32 ca_seq_rtt = -1; 2988 s32 ca_seq_rtt = -1;
2983 ktime_t last_ackt = net_invalid_timestamp(); 2989 ktime_t last_ackt = net_invalid_timestamp();
2990 bool rtt_update;
2984 2991
2985 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { 2992 while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) {
2986 struct tcp_skb_cb *scb = TCP_SKB_CB(skb); 2993 struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
@@ -3057,14 +3064,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3057 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) 3064 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
3058 flag |= FLAG_SACK_RENEGING; 3065 flag |= FLAG_SACK_RENEGING;
3059 3066
3060 if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) || 3067 rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt);
3061 (flag & FLAG_ACKED))
3062 tcp_rearm_rto(sk);
3063 3068
3064 if (flag & FLAG_ACKED) { 3069 if (flag & FLAG_ACKED) {
3065 const struct tcp_congestion_ops *ca_ops 3070 const struct tcp_congestion_ops *ca_ops
3066 = inet_csk(sk)->icsk_ca_ops; 3071 = inet_csk(sk)->icsk_ca_ops;
3067 3072
3073 tcp_rearm_rto(sk);
3068 if (unlikely(icsk->icsk_mtup.probe_size && 3074 if (unlikely(icsk->icsk_mtup.probe_size &&
3069 !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) { 3075 !after(tp->mtu_probe.probe_seq_end, tp->snd_una))) {
3070 tcp_mtup_probe_success(sk); 3076 tcp_mtup_probe_success(sk);
@@ -3103,6 +3109,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3103 3109
3104 ca_ops->pkts_acked(sk, pkts_acked, rtt_us); 3110 ca_ops->pkts_acked(sk, pkts_acked, rtt_us);
3105 } 3111 }
3112 } else if (skb && rtt_update && sack_rtt >= 0 &&
3113 sack_rtt > (s32)(now - TCP_SKB_CB(skb)->when)) {
3114 /* Do not re-arm RTO if the sack RTT is measured from data sent
3115 * after when the head was last (re)transmitted. Otherwise the
3116 * timeout may continue to extend in loss recovery.
3117 */
3118 tcp_rearm_rto(sk);
3106 } 3119 }
3107 3120
3108#if FASTRETRANS_DEBUG > 0 3121#if FASTRETRANS_DEBUG > 0
@@ -5587,6 +5600,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5587 struct request_sock *req; 5600 struct request_sock *req;
5588 int queued = 0; 5601 int queued = 0;
5589 bool acceptable; 5602 bool acceptable;
5603 u32 synack_stamp;
5590 5604
5591 tp->rx_opt.saw_tstamp = 0; 5605 tp->rx_opt.saw_tstamp = 0;
5592 5606
@@ -5669,9 +5683,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5669 * so release it. 5683 * so release it.
5670 */ 5684 */
5671 if (req) { 5685 if (req) {
5686 synack_stamp = tcp_rsk(req)->snt_synack;
5672 tp->total_retrans = req->num_retrans; 5687 tp->total_retrans = req->num_retrans;
5673 reqsk_fastopen_remove(sk, req, false); 5688 reqsk_fastopen_remove(sk, req, false);
5674 } else { 5689 } else {
5690 synack_stamp = tp->lsndtime;
5675 /* Make sure socket is routed, for correct metrics. */ 5691 /* Make sure socket is routed, for correct metrics. */
5676 icsk->icsk_af_ops->rebuild_header(sk); 5692 icsk->icsk_af_ops->rebuild_header(sk);
5677 tcp_init_congestion_control(sk); 5693 tcp_init_congestion_control(sk);
@@ -5694,7 +5710,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
5694 tp->snd_una = TCP_SKB_CB(skb)->ack_seq; 5710 tp->snd_una = TCP_SKB_CB(skb)->ack_seq;
5695 tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale; 5711 tp->snd_wnd = ntohs(th->window) << tp->rx_opt.snd_wscale;
5696 tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); 5712 tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
5697 tcp_synack_rtt_meas(sk, req); 5713 tcp_synack_rtt_meas(sk, synack_stamp);
5698 5714
5699 if (tp->rx_opt.tstamp_ok) 5715 if (tp->rx_opt.tstamp_ok)
5700 tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; 5716 tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;