tcp_cubic: add SNMP counters to track how effective is Hystart
authorEric Dumazet <edumazet@google.com>
Fri, 5 Dec 2014 00:13:23 +0000 (16:13 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Dec 2014 19:58:23 +0000 (14:58 -0500)
When deploying FQ pacing, one thing we noticed is that CUBIC Hystart
triggers too soon.

Having SNMP counters to have an idea of how often the various Hystart
methods trigger is useful prior to any modifications.

This patch adds SNMP counters tracking, how many time "ack train" or
"Delay" based Hystart triggers, and cumulative sum of cwnd at the time
Hystart decided to end SS (Slow Start)

myhost:~# nstat -a | grep Hystart
TcpExtTCPHystartTrainDetect     9                  0.0
TcpExtTCPHystartTrainCwnd       20650              0.0
TcpExtTCPHystartDelayDetect     10                 0.0
TcpExtTCPHystartDelayCwnd       360                0.0

->
 Train detection was triggered 9 times, and average cwnd was
 20650/9=2294,
 Delay detection was triggered 10 times and average cwnd was 36

Signed-off-by: Eric Dumazet <edumazet@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/snmp.h
net/ipv4/proc.c
net/ipv4/tcp_cubic.c

index 30f541b328956a8ace4639eb703649671d837bba..b22224100011b9dc3b620c0c930344414889afb8 100644 (file)
@@ -266,6 +266,10 @@ enum
        LINUX_MIB_TCPWANTZEROWINDOWADV,         /* TCPWantZeroWindowAdv */
        LINUX_MIB_TCPSYNRETRANS,                /* TCPSynRetrans */
        LINUX_MIB_TCPORIGDATASENT,              /* TCPOrigDataSent */
+       LINUX_MIB_TCPHYSTARTTRAINDETECT,        /* TCPHystartTrainDetect */
+       LINUX_MIB_TCPHYSTARTTRAINCWND,          /* TCPHystartTrainCwnd */
+       LINUX_MIB_TCPHYSTARTDELAYDETECT,        /* TCPHystartDelayDetect */
+       LINUX_MIB_TCPHYSTARTDELAYCWND,          /* TCPHystartDelayCwnd */
        __LINUX_MIB_MAX
 };
 
index 6513ade8d6dc9ec774bb7fd0e5d4cb32b73b6b05..8f9cd200ce20118f5e5af7d2faa115d0f19d57f0 100644 (file)
@@ -288,6 +288,10 @@ static const struct snmp_mib snmp4_net_list[] = {
        SNMP_MIB_ITEM("TCPWantZeroWindowAdv", LINUX_MIB_TCPWANTZEROWINDOWADV),
        SNMP_MIB_ITEM("TCPSynRetrans", LINUX_MIB_TCPSYNRETRANS),
        SNMP_MIB_ITEM("TCPOrigDataSent", LINUX_MIB_TCPORIGDATASENT),
+       SNMP_MIB_ITEM("TCPHystartTrainDetect", LINUX_MIB_TCPHYSTARTTRAINDETECT),
+       SNMP_MIB_ITEM("TCPHystartTrainCwnd", LINUX_MIB_TCPHYSTARTTRAINCWND),
+       SNMP_MIB_ITEM("TCPHystartDelayDetect", LINUX_MIB_TCPHYSTARTDELAYDETECT),
+       SNMP_MIB_ITEM("TCPHystartDelayCwnd", LINUX_MIB_TCPHYSTARTDELAYCWND),
        SNMP_MIB_SENTINEL
 };
 
index 20de0118c98e455447128513610ba04b13f3cd61..c1d07c7ed03d7d37fa28d1509093e686f78134d2 100644 (file)
@@ -363,16 +363,28 @@ static void hystart_update(struct sock *sk, u32 delay)
        struct tcp_sock *tp = tcp_sk(sk);
        struct bictcp *ca = inet_csk_ca(sk);
 
-       if (!(ca->found & hystart_detect)) {
+       if (ca->found & hystart_detect)
+               return;
+
+       if (hystart_detect & HYSTART_ACK_TRAIN) {
                u32 now = bictcp_clock();
 
                /* first detection parameter - ack-train detection */
                if ((s32)(now - ca->last_ack) <= hystart_ack_delta) {
                        ca->last_ack = now;
-                       if ((s32)(now - ca->round_start) > ca->delay_min >> 4)
+                       if ((s32)(now - ca->round_start) > ca->delay_min >> 4) {
                                ca->found |= HYSTART_ACK_TRAIN;
+                               NET_INC_STATS_BH(sock_net(sk),
+                                                LINUX_MIB_TCPHYSTARTTRAINDETECT);
+                               NET_ADD_STATS_BH(sock_net(sk),
+                                                LINUX_MIB_TCPHYSTARTTRAINCWND,
+                                                tp->snd_cwnd);
+                               tp->snd_ssthresh = tp->snd_cwnd;
+                       }
                }
+       }
 
+       if (hystart_detect & HYSTART_DELAY) {
                /* obtain the minimum delay of more than sampling packets */
                if (ca->sample_cnt < HYSTART_MIN_SAMPLES) {
                        if (ca->curr_rtt == 0 || ca->curr_rtt > delay)
@@ -381,15 +393,16 @@ static void hystart_update(struct sock *sk, u32 delay)
                        ca->sample_cnt++;
                } else {
                        if (ca->curr_rtt > ca->delay_min +
-                           HYSTART_DELAY_THRESH(ca->delay_min>>4))
+                           HYSTART_DELAY_THRESH(ca->delay_min>>4)) {
                                ca->found |= HYSTART_DELAY;
+                               NET_INC_STATS_BH(sock_net(sk),
+                                                LINUX_MIB_TCPHYSTARTDELAYDETECT);
+                               NET_ADD_STATS_BH(sock_net(sk),
+                                                LINUX_MIB_TCPHYSTARTDELAYCWND,
+                                                tp->snd_cwnd);
+                               tp->snd_ssthresh = tp->snd_cwnd;
+                       }
                }
-               /*
-                * Either one of two conditions are met,
-                * we exit from slow start immediately.
-                */
-               if (ca->found & hystart_detect)
-                       tp->snd_ssthresh = tp->snd_cwnd;
        }
 }