aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
authorNeal Cardwell <ncardwell@google.com>2016-09-19 23:39:10 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-21 00:22:59 -0400
commit6403389211e1f4d40ed963fe47a96fce1a3ba7a9 (patch)
treefedf5ec551ae7c7b99dd0c89aa8934724d523929 /net/ipv4/tcp_input.c
parenta4f1f9ac8153e22869b6408832b5a9bb9c762bf6 (diff)
tcp: use windowed min filter library for TCP min_rtt estimation
Refactor the TCP min_rtt code to reuse the new win_minmax library in lib/win_minmax.c to simplify the TCP code. This is a pure refactor: the functionality is exactly the same. We just moved the windowed min code to make TCP easier to read and maintain, and to allow other parts of the kernel to use the windowed min/max filter code. Signed-off-by: Van Jacobson <vanj@google.com> Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: Yuchung Cheng <ycheng@google.com> Signed-off-by: Nandita Dukkipati <nanditad@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
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,