operating system does not support TCP_INFO, for example Linux kernels before
2.4, the sample fetch fails.
-fc_unacked(<unit>) : integer
+fc_unacked : 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
+fc_sacked : 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
+fc_retrans : 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
+fc_fackets : 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
+fc_lost : 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
+fc_reordering : 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
#ifdef TCP_INFO
+
+/* Validates the arguments passed to "fc_*" fetch keywords returning a time
+ * value. These keywords support an optional string representing the unit of the
+ * result: "us" for microseconds and "ms" for milliseconds". Returns 0 on error
+ * and non-zero if OK.
+ */
+static int val_fc_time_value(struct arg *args, char **err)
+{
+ if (args[0].type == ARGT_STOP) {
+ args[0].type = ARGT_SINT;
+ args[0].data.sint = TIME_UNIT_MS;
+ }
+ if (args[0].type == ARGT_STR) {
+ if (strcmp(args[0].data.str.area, "us") == 0) {
+ free(args[0].data.str.area);
+ args[0].type = ARGT_SINT;
+ args[0].data.sint = TIME_UNIT_US;
+ }
+ else if (strcmp(args[0].data.str.area, "ms") == 0) {
+ free(args[0].data.str.area);
+ args[0].type = ARGT_SINT;
+ args[0].data.sint = TIME_UNIT_MS;
+ }
+ else {
+ memprintf(err, "expects 'us' or 'ms', got '%s'",
+ args[0].data.str.area);
+ return 0;
+ }
+ }
+ else {
+ memprintf(err, "Unexpected arg type");
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Validates the arguments passed to "fc_*" fetch keywords returning a
+ * counter. These keywords should be used without any keyword, but because of a
+ * bug in previous versions, an optional string argument may be passed. In such
+ * case, the argument is ignored and a warning is emitted. Returns 0 on error
+ * and non-zero if OK.
+ */
+static int var_fc_counter(struct arg *args, char **err)
+{
+ if (args[0].type != ARGT_STOP) {
+ ha_warning("no argument supported for 'fc_*' sample expressions returning counters.\n");
+ if (args[0].type == ARGT_STR)
+ free(args[0].data.str.area);
+ args[0].type = ARGT_STOP;
+ }
+
+ return 1;
+}
+
/* Returns some tcp_info data if it's available. "dir" must be set to 0 if
* the client connection is required, otherwise it is set to 1. "val" represents
- * the required value. Use 0 for rtt and 1 for rttavg. "unit" is the expected unit
- * by default, the rtt is in us. Id "unit" is set to 0, the unit is us, if it is
- * set to 1, the units are milliseconds.
+ * the required value.
* If the function fails it returns 0, otherwise it returns 1 and "result" is filled.
*/
static inline int get_tcp_info(const struct arg *args, struct sample *smp,
default: return 0;
}
- /* Convert the value as expected. */
- if (args) {
- if (args[0].type == ARGT_STR) {
- if (strcmp(args[0].data.str.area, "us") == 0) {
- /* Do nothing. */
- } else if (strcmp(args[0].data.str.area, "ms") == 0) {
- smp->data.u.sint = (smp->data.u.sint + 500) / 1000;
- } else
- return 0;
- } else if (args[0].type == ARGT_STOP) {
- smp->data.u.sint = (smp->data.u.sint + 500) / 1000;
- } else
- return 0;
- }
-
return 1;
}
{
if (!get_tcp_info(args, smp, 0, 0))
return 0;
+
+ /* By default or if explicitly specified, convert rtt to ms */
+ if (!args || args[0].type == ARGT_STOP || args[0].data.sint == TIME_UNIT_MS)
+ smp->data.u.sint = (smp->data.u.sint + 500) / 1000;
+
return 1;
}
{
if (!get_tcp_info(args, smp, 0, 1))
return 0;
+
+ /* By default or if explicitly specified, convert rttvar to ms */
+ if (!args || args[0].type == ARGT_STOP || args[0].data.sint == TIME_UNIT_MS)
+ smp->data.u.sint = (smp->data.u.sint + 500) / 1000;
+
return 1;
}
{ "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 },
+ { "fc_rtt", smp_fetch_fc_rtt, ARG1(0,STR), val_fc_time_value, SMP_T_SINT, SMP_USE_L4CLI },
+ { "fc_rttvar", smp_fetch_fc_rttvar, ARG1(0,STR), val_fc_time_value, 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 },
+ { "fc_unacked", smp_fetch_fc_unacked, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
+ { "fc_sacked", smp_fetch_fc_sacked, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
+ { "fc_retrans", smp_fetch_fc_retrans, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
+ { "fc_fackets", smp_fetch_fc_fackets, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
+ { "fc_lost", smp_fetch_fc_lost, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
+ { "fc_reordering", smp_fetch_fc_reordering, ARG1(0,STR), var_fc_counter, SMP_T_SINT, SMP_USE_L4CLI },
#endif // linux || freebsd || netbsd
#endif // TCP_INFO
{ /* END */ },