tcp: do not use cached RTT for RTT estimation
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / tcp_metrics.c
index f6a005c485a94e77c3ed73358048ad4d4b6d7b37..273ed735cca2f036b53f62170d0ab39a24c1e617 100644 (file)
@@ -443,7 +443,7 @@ void tcp_init_metrics(struct sock *sk)
        struct dst_entry *dst = __sk_dst_get(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_metrics_block *tm;
-       u32 val;
+       u32 val, crtt = 0; /* cached RTT scaled by 8 */
 
        if (dst == NULL)
                goto reset;
@@ -478,40 +478,18 @@ void tcp_init_metrics(struct sock *sk)
                tp->reordering = val;
        }
 
-       val = tcp_metric_get(tm, TCP_METRIC_RTT);
-       if (val == 0 || tp->srtt == 0) {
-               rcu_read_unlock();
-               goto reset;
-       }
-       /* Initial rtt is determined from SYN,SYN-ACK.
-        * The segment is small and rtt may appear much
-        * less than real one. Use per-dst memory
-        * to make it more realistic.
-        *
-        * A bit of theory. RTT is time passed after "normal" sized packet
-        * is sent until it is ACKed. In normal circumstances sending small
-        * packets force peer to delay ACKs and calculation is correct too.
-        * The algorithm is adaptive and, provided we follow specs, it
-        * NEVER underestimate RTT. BUT! If peer tries to make some clever
-        * tricks sort of "quick acks" for time long enough to decrease RTT
-        * to low value, and then abruptly stops to do it and starts to delay
-        * ACKs, wait for troubles.
-        */
-       val = msecs_to_jiffies(val);
-       if (val > tp->srtt) {
-               tp->srtt = val;
-               tp->rtt_seq = tp->snd_nxt;
-       }
-       val = tcp_metric_get_jiffies(tm, TCP_METRIC_RTTVAR);
-       if (val > tp->mdev) {
-               tp->mdev = val;
-               tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk));
-       }
+       crtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT);
        rcu_read_unlock();
-
-       tcp_set_rto(sk);
 reset:
-       if (tp->srtt == 0) {
+       if (crtt > tp->srtt) {
+               /* Initial RTT (tp->srtt) from SYN usually don't measure
+                * serialization delay on low BW links well so RTO may be
+                * under-estimated. Stay conservative and seed RTO with
+                * the RTTs from past data exchanges, using the same seeding
+                * formula in tcp_rtt_estimator().
+                */
+               inet_csk(sk)->icsk_rto = crtt + max(crtt >> 2, tcp_rto_min(sk));
+       } else if (tp->srtt == 0) {
                /* RFC6298: 5.7 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