MINOR: tcp: add further tcp info fetchers
authorJoe Williams <joe.williams@github.com>
Wed, 10 Aug 2016 14:06:44 +0000 (07:06 -0700)
committerWilly Tarreau <w@1wt.eu>
Wed, 10 Aug 2016 21:02:46 +0000 (23:02 +0200)
Adding on to Thierry's work (http://git.haproxy.org/?p=haproxy.git;h=6310bef5)
I have added a few more fetchers for counters based on the tcp_info struct
maintained by the kernel :

  fc_unacked, fc_sacked, fc_retrans, fc_fackets, fc_lost,
  fc_reordering

Two fields were not added because they're version-dependant :
  fc_rcv_rtt, fc_total_retrans

The fields name depend on the operating system. FreeBSD and NetBSD prefix
all the field names with "__" so we have to rely on a few #ifdef for
portability.

doc/configuration.txt
src/proto_tcp.c

index 430b0ca..9809360 100644 (file)
@@ -12767,6 +12767,42 @@ fc_rttvar(<unit>) : integer
   operating system does not support TCP_INFO, for example Linux kernels before
   2.4, the sample fetch fails.
 
+fc_unacked(<unit>) : integer
+  Returns the unacked counter measured by the kernel for the client connection.
+  If the server connection is not established, if the connection is not TCP or
+  if the operating system does not support TCP_INFO, for example Linux kernels
+  before 2.4, the sample fetch fails.
+
+fc_sacked(<unit>) : integer
+  Returns the sacked counter measured by the kernel for the client connection.
+  If the server connection is not established, if the connection is not TCP or
+  if the operating system does not support TCP_INFO, for example Linux kernels
+  before 2.4, the sample fetch fails.
+
+fc_retrans(<unit>) : integer
+  Returns the retransmits counter measured by the kernel for the client
+  connection. If the server connection is not established, if the connection is
+  not TCP or if the operating system does not support TCP_INFO, for example
+  Linux kernels before 2.4, the sample fetch fails.
+
+fc_fackets(<unit>) : integer
+  Returns the fack counter measured by the kernel for the client
+  connection. If the server connection is not established, if the connection is
+  not TCP or if the operating system does not support TCP_INFO, for example
+  Linux kernels before 2.4, the sample fetch fails.
+
+fc_lost(<unit>) : integer
+  Returns the lost counter measured by the kernel for the client
+  connection. If the server connection is not established, if the connection is
+  not TCP or if the operating system does not support TCP_INFO, for example
+  Linux kernels before 2.4, the sample fetch fails.
+
+fc_reordering(<unit>) : integer
+  Returns the reordering counter measured by the kernel for the client
+  connection. If the server connection is not established, if the connection is
+  not TCP or if the operating system does not support TCP_INFO, for example
+  Linux kernels before 2.4, the sample fetch fails.
+
 fe_id : integer
   Returns an integer containing the current frontend's id. It can be used in
   backends to check from which backend it was called, or to stick all users
index 797ddcb..9c5ea98 100644 (file)
@@ -2395,8 +2395,25 @@ static inline int get_tcp_info(const struct arg *args, struct sample *smp,
        /* extract the value. */
        smp->data.type = SMP_T_SINT;
        switch (val) {
-       case 0:  smp->data.u.sint = info.tcpi_rtt;    break;
-       case 1:  smp->data.u.sint = info.tcpi_rttvar; break;
+       case 0:  smp->data.u.sint = info.tcpi_rtt;            break;
+       case 1:  smp->data.u.sint = info.tcpi_rttvar;         break;
+#if defined(__linux__)
+       /* these ones are common to all Linux versions */
+       case 2:  smp->data.u.sint = info.tcpi_unacked;        break;
+       case 3:  smp->data.u.sint = info.tcpi_sacked;         break;
+       case 4:  smp->data.u.sint = info.tcpi_lost;           break;
+       case 5:  smp->data.u.sint = info.tcpi_retrans;        break;
+       case 6:  smp->data.u.sint = info.tcpi_fackets;        break;
+       case 7:  smp->data.u.sint = info.tcpi_reordering;     break;
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+       /* the ones are found on FreeBSD and NetBSD featuring TCP_INFO */
+       case 2:  smp->data.u.sint = info.__tcpi_unacked;      break;
+       case 3:  smp->data.u.sint = info.__tcpi_sacked;       break;
+       case 4:  smp->data.u.sint = info.__tcpi_lost;         break;
+       case 5:  smp->data.u.sint = info.__tcpi_retrans;      break;
+       case 6:  smp->data.u.sint = info.__tcpi_fackets;      break;
+       case 7:  smp->data.u.sint = info.__tcpi_reordering;   break;
+#endif
        default: return 0;
        }
 
@@ -2435,7 +2452,64 @@ smp_fetch_fc_rttvar(const struct arg *args, struct sample *smp, const char *kw,
                return 0;
        return 1;
 }
-#endif
+
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
+
+/* get the unacked counter on a client connexion */
+static int
+smp_fetch_fc_unacked(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       if (!get_tcp_info(args, smp, 0, 2))
+               return 0;
+       return 1;
+}
+
+/* get the sacked counter on a client connexion */
+static int
+smp_fetch_fc_sacked(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       if (!get_tcp_info(args, smp, 0, 3))
+               return 0;
+       return 1;
+}
+
+/* get the lost counter on a client connexion */
+static int
+smp_fetch_fc_lost(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       if (!get_tcp_info(args, smp, 0, 4))
+               return 0;
+       return 1;
+}
+
+/* get the retrans counter on a client connexion */
+static int
+smp_fetch_fc_retrans(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       if (!get_tcp_info(args, smp, 0, 5))
+               return 0;
+       return 1;
+}
+
+/* get the fackets counter on a client connexion */
+static int
+smp_fetch_fc_fackets(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       if (!get_tcp_info(args, smp, 0, 6))
+               return 0;
+       return 1;
+}
+
+/* get the reordering counter on a client connexion */
+static int
+smp_fetch_fc_reordering(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+       if (!get_tcp_info(args, smp, 0, 7))
+               return 0;
+       return 1;
+}
+#endif // linux || freebsd || netbsd
+#endif // TCP_INFO
 
 #ifdef IPV6_V6ONLY
 /* parse the "v4v6" bind keyword */
@@ -2667,9 +2741,17 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, {
        { "src_is_local", smp_fetch_src_is_local, 0, NULL, SMP_T_BOOL, SMP_USE_L4CLI },
        { "src_port", smp_fetch_sport, 0, NULL, SMP_T_SINT, SMP_USE_L4CLI },
 #ifdef TCP_INFO
-       { "fc_rtt",    smp_fetch_fc_rtt,    ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
-       { "fc_rttvar", smp_fetch_fc_rttvar, ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
-#endif
+       { "fc_rtt",           smp_fetch_fc_rtt,           ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "fc_rttvar",        smp_fetch_fc_rttvar,        ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
+       { "fc_unacked",       smp_fetch_fc_unacked,       ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "fc_sacked",        smp_fetch_fc_sacked,        ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "fc_retrans",       smp_fetch_fc_retrans,       ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "fc_fackets",       smp_fetch_fc_fackets,       ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "fc_lost",          smp_fetch_fc_lost,          ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+       { "fc_reordering",    smp_fetch_fc_reordering,    ARG1(0,STR), NULL, SMP_T_SINT, SMP_USE_L4CLI },
+#endif // linux || freebsd || netbsd
+#endif // TCP_INFO
        { /* END */ },
 }};