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.c64
1 files changed, 5 insertions, 59 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index dad3e7eeed94..6886f386464f 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2879,67 +2879,13 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked,
2879 *rexmit = REXMIT_LOST; 2879 *rexmit = REXMIT_LOST;
2880} 2880}
2881 2881
2882/* Kathleen Nichols' algorithm for tracking the minimum value of
2883 * a data stream over some fixed time interval. (E.g., the minimum
2884 * RTT over the past five minutes.) It uses constant space and constant
2885 * time per update yet almost always delivers the same minimum as an
2886 * implementation that has to keep all the data in the window.
2887 *
2888 * The algorithm keeps track of the best, 2nd best & 3rd best min
2889 * values, maintaining an invariant that the measurement time of the
2890 * n'th best >= n-1'th best. It also makes sure that the three values
2891 * are widely separated in the time window since that bounds the worse
2892 * case error when that data is monotonically increasing over the window.
2893 *
2894 * Upon getting a new min, we can forget everything earlier because it
2895 * has no value - the new min is <= everything else in the window by
2896 * definition and it's the most recent. So we restart fresh on every new min
2897 * and overwrites 2nd & 3rd choices. The same property holds for 2nd & 3rd
2898 * best.
2899 */
2900static void tcp_update_rtt_min(struct sock *sk, u32 rtt_us) 2882static void tcp_update_rtt_min(struct sock *sk, u32 rtt_us)
2901{ 2883{
2902 const u32 now = tcp_time_stamp, wlen = sysctl_tcp_min_rtt_wlen * HZ; 2884 struct tcp_sock *tp = tcp_sk(sk);
2903 struct rtt_meas *m = tcp_sk(sk)->rtt_min; 2885 u32 wlen = sysctl_tcp_min_rtt_wlen * HZ;
2904 struct rtt_meas rttm = { 2886
2905 .rtt = likely(rtt_us) ? rtt_us : jiffies_to_usecs(1), 2887 minmax_running_min(&tp->rtt_min, wlen, tcp_time_stamp,
2906 .ts = now, 2888 rtt_us ? : jiffies_to_usecs(1));
2907 };
2908 u32 elapsed;
2909
2910 /* Check if the new measurement updates the 1st, 2nd, or 3rd choices */
2911 if (unlikely(rttm.rtt <= m[0].rtt))
2912 m[0] = m[1] = m[2] = rttm;
2913 else if (rttm.rtt <= m[1].rtt)
2914 m[1] = m[2] = rttm;
2915 else if (rttm.rtt <= m[2].rtt)
2916 m[2] = rttm;
2917
2918 elapsed = now - m[0].ts;
2919 if (unlikely(elapsed > wlen)) {
2920 /* Passed entire window without a new min so make 2nd choice
2921 * the new min & 3rd choice the new 2nd. So forth and so on.
2922 */
2923 m[0] = m[1];
2924 m[1] = m[2];
2925 m[2] = rttm;
2926 if (now - m[0].ts > wlen) {
2927 m[0] = m[1];
2928 m[1] = rttm;
2929 if (now - m[0].ts > wlen)
2930 m[0] = rttm;
2931 }
2932 } else if (m[1].ts == m[0].ts && elapsed > wlen / 4) {
2933 /* Passed a quarter of the window without a new min so
2934 * take 2nd choice from the 2nd quarter of the window.
2935 */
2936 m[2] = m[1] = rttm;
2937 } else if (m[2].ts == m[1].ts && elapsed > wlen / 2) {
2938 /* Passed half the window without a new min so take the 3rd
2939 * choice from the last half of the window.
2940 */
2941 m[2] = rttm;
2942 }
2943} 2889}
2944 2890
2945static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, 2891static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag,