aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv4/tcp_input.c23
1 files changed, 14 insertions, 9 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index b85bc7c3736a..b61274b666f6 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2800,8 +2800,8 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked,
2800 tcp_xmit_retransmit_queue(sk); 2800 tcp_xmit_retransmit_queue(sk);
2801} 2801}
2802 2802
2803static inline void tcp_ack_update_rtt(struct sock *sk, const int flag, 2803static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,
2804 s32 seq_rtt) 2804 s32 seq_rtt, s32 sack_rtt)
2805{ 2805{
2806 const struct tcp_sock *tp = tcp_sk(sk); 2806 const struct tcp_sock *tp = tcp_sk(sk);
2807 2807
@@ -2813,6 +2813,9 @@ static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
2813 if (flag & FLAG_RETRANS_DATA_ACKED) 2813 if (flag & FLAG_RETRANS_DATA_ACKED)
2814 seq_rtt = -1; 2814 seq_rtt = -1;
2815 2815
2816 if (seq_rtt < 0)
2817 seq_rtt = sack_rtt;
2818
2816 /* RTTM Rule: A TSecr value received in a segment is used to 2819 /* RTTM Rule: A TSecr value received in a segment is used to
2817 * update the averaged RTT measurement only if the segment 2820 * update the averaged RTT measurement only if the segment
2818 * acknowledges some new data, i.e., only if it advances the 2821 * acknowledges some new data, i.e., only if it advances the
@@ -2823,13 +2826,14 @@ static inline void tcp_ack_update_rtt(struct sock *sk, const int flag,
2823 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; 2826 seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
2824 2827
2825 if (seq_rtt < 0) 2828 if (seq_rtt < 0)
2826 return; 2829 return false;
2827 2830
2828 tcp_rtt_estimator(sk, seq_rtt); 2831 tcp_rtt_estimator(sk, seq_rtt);
2829 tcp_set_rto(sk); 2832 tcp_set_rto(sk);
2830 2833
2831 /* RFC6298: only reset backoff on valid RTT measurement. */ 2834 /* RFC6298: only reset backoff on valid RTT measurement. */
2832 inet_csk(sk)->icsk_backoff = 0; 2835 inet_csk(sk)->icsk_backoff = 0;
2836 return true;
2833} 2837}
2834 2838
2835/* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */ 2839/* Compute time elapsed between (last) SYNACK and the ACK completing 3WHS. */
@@ -2840,7 +2844,7 @@ static void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req)
2840 2844
2841 if (tp->lsndtime && !tp->total_retrans) 2845 if (tp->lsndtime && !tp->total_retrans)
2842 seq_rtt = tcp_time_stamp - tp->lsndtime; 2846 seq_rtt = tcp_time_stamp - tp->lsndtime;
2843 tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt); 2847 tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1);
2844} 2848}
2845 2849
2846static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) 2850static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
@@ -2929,7 +2933,7 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb)
2929 * arrived at the other end. 2933 * arrived at the other end.
2930 */ 2934 */
2931static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, 2935static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
2932 u32 prior_snd_una) 2936 u32 prior_snd_una, s32 sack_rtt)
2933{ 2937{
2934 struct tcp_sock *tp = tcp_sk(sk); 2938 struct tcp_sock *tp = tcp_sk(sk);
2935 const struct inet_connection_sock *icsk = inet_csk(sk); 2939 const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -3019,6 +3023,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3019 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) 3023 if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED))
3020 flag |= FLAG_SACK_RENEGING; 3024 flag |= FLAG_SACK_RENEGING;
3021 3025
3026 if (tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt) ||
3027 (flag & FLAG_ACKED))
3028 tcp_rearm_rto(sk);
3029
3022 if (flag & FLAG_ACKED) { 3030 if (flag & FLAG_ACKED) {
3023 const struct tcp_congestion_ops *ca_ops 3031 const struct tcp_congestion_ops *ca_ops
3024 = inet_csk(sk)->icsk_ca_ops; 3032 = inet_csk(sk)->icsk_ca_ops;
@@ -3028,9 +3036,6 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
3028 tcp_mtup_probe_success(sk); 3036 tcp_mtup_probe_success(sk);
3029 } 3037 }
3030 3038
3031 tcp_ack_update_rtt(sk, flag, seq_rtt);
3032 tcp_rearm_rto(sk);
3033
3034 if (tcp_is_reno(tp)) { 3039 if (tcp_is_reno(tp)) {
3035 tcp_remove_reno_sacks(sk, pkts_acked); 3040 tcp_remove_reno_sacks(sk, pkts_acked);
3036 } else { 3041 } else {
@@ -3339,7 +3344,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
3339 3344
3340 /* See if we can take anything off of the retransmit queue. */ 3345 /* See if we can take anything off of the retransmit queue. */
3341 acked = tp->packets_out; 3346 acked = tp->packets_out;
3342 flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); 3347 flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_rtt);
3343 acked -= tp->packets_out; 3348 acked -= tp->packets_out;
3344 3349
3345 if (tcp_ack_is_dubious(sk, flag)) { 3350 if (tcp_ack_is_dubious(sk, flag)) {