diff --git a/doc/configuration.txt b/doc/configuration.txt
index 9f0aa724b5..184d454077 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -20001,6 +20001,21 @@ table_expire(
[,])
input sample in the designated table.
See also the table_idle sample fetch keyword.
+table_glitch_cnt()
+ Uses the string representation of the input sample to perform a look up in
+ the specified table. If the key is not found in the table, integer value zero
+ is returned. Otherwise the converter returns the cumulative number of front
+ connection glitches associated with the input sample in the designated table.
+ See also the sc_glitch_cnt sample fetch keyword and fc_glitches for the value
+ measured on the current front connection.
+
+table_glitch_rate()
+ Uses the string representation of the input sample to perform a look up in
+ the specified table. If the key is not found in the table, integer value zero
+ is returned. Otherwise the converter returns the average front connection
+ glitch rate associated with the input sample in the designated table. See
+ also the sc_glitch_rate sample fetch keyword.
+
table_gpc(,)
Uses the string representation of the input sample to perform a lookup in
the specified table. If the key is not found in the table, integer value zero
@@ -21122,6 +21137,14 @@ sc_get_gpt0([,]) integer
sc0_get_gpt0([]) integer
sc1_get_gpt0([]) integer
sc2_get_gpt0([]) integer
+sc_glitch_cnt([,]) integer
+sc0_glitch_cnt([]) integer
+sc1_glitch_cnt([]) integer
+sc2_glitch_cnt([]) integer
+sc_glitch_rate([,]) integer
+sc0_glitch_rate([]) integer
+sc1_glitch_rate([]) integer
+sc2_glitch_rate([]) integer
sc_gpc_rate(,[,]) integer
sc_gpc0_rate([,]) integer
sc0_gpc0_rate([]) integer
@@ -21770,6 +21793,34 @@ sc2_get_gpt0([]) : integer
Returns the value of the first General Purpose Tag associated to the
currently tracked counters. See also src_get_gpt0.
+sc_glitch_cnt([,]) : integer
+sc0_glitch_cnt([]) : integer
+sc1_glitch_cnt([]) : integer
+sc2_glitch_cnt([]) : integer
+ Returns the cumulative number of front connection glitches that were observed
+ on connections associated with the currently tracked counters. Usually these
+ result in requests or connections to be aborted so the returned value will
+ often correspond to past connections. There is no good nor bad value, but a
+ poor quality client may occasionally cause a few glitches per connection,
+ while a very bogus or malevolent client may quickly cause thousands of events
+ to be added on a connection. See also fc_glitches for the number affecting
+ the current connection, src_glitch_cnt to look them up per source, and
+ sc_glitch_rate for the event rate measurements.
+
+sc_glitch_rate([,]) : integer
+sc0_glitch_rate([]) : integer
+sc1_glitch_rate([]) : integer
+sc2_glitch_rate([]) : integer
+ Returns the average rate at which front connection glitches were observed for
+ the currently tracked counters, measured in amount of events over the period
+ configured in the table. Usually these glitches result in requests or
+ connections to be aborted so the returned value will often be related to past
+ connections. There is no good nor bad value, but a poor quality client may
+ occasionally cause a few glitches per connection, hence a low rate is
+ generally expected. However, a very bogus or malevolent client may quickly
+ cause thousands of events to be added per connection, and maintain a high
+ rate here. See also src_glitch_rate and sc_glitch_cnt.
+
sc_gpc_rate(,[,]) : integer
Returns the average increment rate of the General Purpose Counter at the
index of the array associated to the tracked counter of ID from
@@ -22084,6 +22135,29 @@ src_get_gpt0([]) : integer
the designated stick-table. If the address is not found, zero is returned.
See also sc/sc0/sc1/sc2_get_gpt0.
+src_glitch_cnt([]) : integer
+ Returns the cumulative number of front connection glitches that were observed
+ on connections from the current connection's source address. Usually these
+ result in requests or connections to be aborted so the returned value will
+ often correspond to past connections. There is no good nor bad value, but a
+ poor quality client may occasionally cause a few glitches per connection,
+ while a very bogus or malevolent client may quickly cause thousands of events
+ to be added on a connection. See also fc_glitches for the number affecting
+ the current connection, sc_glitch_cnt to look them up in currently tracked
+ counters, and src_glitch_rate for the event rate measurements.
+
+src_glitch_rate([]) : integer
+ Returns the average rate at which front connection glitches were observed for
+ on connections from the current connection's source address, measured in
+ amount of events over the period configured in the table. Usually these
+ glitches result in requests or connections to be aborted so the returned
+ value will often be related to past connections. There is no good nor bad
+ value, but a poor quality client may occasionally cause a few glitches per
+ connection, hence a low rate is generally expected. However, a very bogus or
+ malevolent client may quickly cause thousands of events to be added per
+ connection, and maintain a high rate here. See also sc_glitch_rate and
+ src_glitch_cnt.
+
src_gpc_rate([,]) : integer
Returns the average increment rate of the General Purpose Counter at the
index of the array associated to the incoming connection's
diff --git a/doc/peers-v2.0.txt b/doc/peers-v2.0.txt
index 711c949b46..3b82369e4f 100644
--- a/doc/peers-v2.0.txt
+++ b/doc/peers-v2.0.txt
@@ -227,6 +227,8 @@ bit
22: gpt array
23: gpc array
24: gpc rate array
+ 25: glitch counter
+ 26: glitch rate
d) Table Switch Message
diff --git a/include/haproxy/stick_table-t.h b/include/haproxy/stick_table-t.h
index 749cb9a557..e170fcdea0 100644
--- a/include/haproxy/stick_table-t.h
+++ b/include/haproxy/stick_table-t.h
@@ -58,7 +58,8 @@ enum {
STKTABLE_DT_GPT, /* array of gpt */
STKTABLE_DT_GPC, /* array of gpc */
STKTABLE_DT_GPC_RATE, /* array of gpc_rate */
-
+ STKTABLE_DT_GLITCH_CNT, /* cumulated number of front glitches */
+ STKTABLE_DT_GLITCH_RATE, /* rate of front glitches */
STKTABLE_STATIC_DATA_TYPES,/* number of types above */
/* up to STKTABLE_EXTRA_DATA_TYPES types may be registered here, always
diff --git a/include/haproxy/stick_table.h b/include/haproxy/stick_table.h
index 320043726c..1c1ed61ce3 100644
--- a/include/haproxy/stick_table.h
+++ b/include/haproxy/stick_table.h
@@ -401,4 +401,36 @@ static inline int stkctr_inc_bytes_out_ctr(struct stkctr *stkctr, unsigned long
return 1;
}
+/* Add to the number of cumulated front glitches in the tracked counter
+ * . It returns 0 if the entry pointer does not exist and nothing is
+ * performed. Otherwise it returns 1.
+ */
+static inline int stkctr_add_glitch_ctr(struct stkctr *stkctr, uint inc)
+{
+ struct stksess *ts;
+ void *ptr1, *ptr2;
+
+ ts = stkctr_entry(stkctr);
+ if (!ts)
+ return 0;
+
+ HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock);
+
+ ptr1 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_GLITCH_CNT);
+ if (ptr1)
+ stktable_data_cast(ptr1, std_t_uint) += inc;
+
+ ptr2 = stktable_data_ptr(stkctr->table, ts, STKTABLE_DT_GLITCH_RATE);
+ if (ptr2)
+ update_freq_ctr_period(&stktable_data_cast(ptr2, std_t_frqp),
+ stkctr->table->data_arg[STKTABLE_DT_GLITCH_RATE].u, inc);
+
+ HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
+
+ /* If data was modified, we need to touch to re-schedule sync */
+ if (ptr1 || ptr2)
+ stktable_touch_local(stkctr->table, ts, 0);
+ return 1;
+}
+
#endif /* _HAPROXY_STICK_TABLE_H */
diff --git a/src/stick_table.c b/src/stick_table.c
index 8707ce5eba..4c77dfb6b5 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -1448,6 +1448,8 @@ struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES] = {
[STKTABLE_DT_GPT] = { .name = "gpt", .std_type = STD_T_UINT, .is_array = 1, .as_is = 1 },
[STKTABLE_DT_GPC] = { .name = "gpc", .std_type = STD_T_UINT, .is_array = 1 },
[STKTABLE_DT_GPC_RATE] = { .name = "gpc_rate", .std_type = STD_T_FRQP, .is_array = 1, .arg_type = ARG_T_DELAY },
+ [STKTABLE_DT_GLITCH_CNT] = { .name = "glitch_cnt", .std_type = STD_T_UINT },
+ [STKTABLE_DT_GLITCH_RATE] = { .name = "glitch_rate", .std_type = STD_T_FRQP, .arg_type = ARG_T_DELAY },
};
/* Registers stick-table extra data type with index , name , type
@@ -1787,6 +1789,79 @@ static int sample_conv_table_bytes_out_rate(const struct arg *arg_p, struct samp
return !!ptr;
}
+/* Casts sample to the type of the table specified in arg(0), and looks
+ * it up into this table. Returns the cumulated number of front glitches for the
+ * key if the key is present in the table, otherwise zero, so that comparisons
+ * can be easily performed. If the inspected parameter is not stored in the
+ * table, is returned.
+ */
+static int sample_conv_table_glitch_cnt(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ struct stktable *t;
+ struct stktable_key *key;
+ struct stksess *ts;
+ void *ptr;
+
+ t = arg_p[0].data.t;
+
+ key = smp_to_stkey(smp, t);
+ if (!key)
+ return 0;
+
+ ts = stktable_lookup_key(t, key);
+
+ smp->flags = SMP_F_VOL_TEST;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = 0;
+
+ if (!ts) /* key not present */
+ return 1;
+
+ ptr = stktable_data_ptr(t, ts, STKTABLE_DT_GLITCH_CNT);
+ if (ptr)
+ smp->data.u.sint = stktable_data_cast(ptr, std_t_uint);
+
+ stktable_release(t, ts);
+ return !!ptr;
+}
+
+/* Casts sample to the type of the table specified in arg(0), and looks
+ * it up into this table. Returns the front glitch rate the key if the key is
+ * present in the table, otherwise zero, so that comparisons can be easily
+ * performed. If the inspected parameter is not stored in the table,
+ * is returned.
+ */
+static int sample_conv_table_glitch_rate(const struct arg *arg_p, struct sample *smp, void *private)
+{
+ struct stktable *t;
+ struct stktable_key *key;
+ struct stksess *ts;
+ void *ptr;
+
+ t = arg_p[0].data.t;
+
+ key = smp_to_stkey(smp, t);
+ if (!key)
+ return 0;
+
+ ts = stktable_lookup_key(t, key);
+
+ smp->flags = SMP_F_VOL_TEST;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = 0;
+
+ if (!ts) /* key not present */
+ return 1;
+
+ ptr = stktable_data_ptr(t, ts, STKTABLE_DT_GLITCH_RATE);
+ if (ptr)
+ smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
+ t->data_arg[STKTABLE_DT_GLITCH_RATE].u);
+
+ stktable_release(t, ts);
+ return !!ptr;
+}
+
/* Casts sample to the type of the table specified in arg_p(1), and looks
* it up into this table. Returns the value of the GPT[arg_p(0)] tag for the key
* if the key is present in the table, otherwise false, so that comparisons can
@@ -4264,6 +4339,85 @@ smp_fetch_sc_conn_cur(const struct arg *args, struct sample *smp, const char *kw
return 1;
}
+/* set to the cumulated number of glitches from the stream or session's
+ * tracked frontend counters. Supports being called as "sc[0-9]_glitch_cnt" or
+ * "src_glitch_cnt" only.
+ */
+static int
+smp_fetch_sc_glitch_cnt(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+ struct stkctr tmpstkctr;
+ struct stkctr *stkctr;
+
+ stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
+ if (!stkctr)
+ return 0;
+
+ smp->flags = SMP_F_VOL_TEST;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = 0;
+ if (stkctr_entry(stkctr) != NULL) {
+ void *ptr;
+
+ ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GLITCH_CNT);
+ if (!ptr) {
+ if (stkctr == &tmpstkctr)
+ stktable_release(stkctr->table, stkctr_entry(stkctr));
+ return 0; /* parameter not stored */
+ }
+
+ HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
+
+ smp->data.u.sint = stktable_data_cast(ptr, std_t_uint);
+
+ HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
+
+ if (stkctr == &tmpstkctr)
+ stktable_release(stkctr->table, stkctr_entry(stkctr));
+ }
+ return 1;
+}
+
+/* set to the rate of glitches from the stream or session's tracked
+ * frontend counters. Supports being called as "sc[0-9]_glitch_rate" or
+ * "src_glitch_rate" only.
+ */
+static int
+smp_fetch_sc_glitch_rate(const struct arg *args, struct sample *smp, const char *kw, void *private)
+{
+ struct stkctr tmpstkctr;
+ struct stkctr *stkctr;
+
+ stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw, &tmpstkctr);
+ if (!stkctr)
+ return 0;
+
+ smp->flags = SMP_F_VOL_TEST;
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = 0;
+ if (stkctr_entry(stkctr) != NULL) {
+ void *ptr;
+
+ ptr = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GLITCH_RATE);
+ if (!ptr) {
+ if (stkctr == &tmpstkctr)
+ stktable_release(stkctr->table, stkctr_entry(stkctr));
+ return 0; /* parameter not stored */
+ }
+
+ HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
+
+ smp->data.u.sint = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
+ stkctr->table->data_arg[STKTABLE_DT_GLITCH_RATE].u);
+
+ HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &stkctr_entry(stkctr)->lock);
+
+ if (stkctr == &tmpstkctr)
+ stktable_release(stkctr->table, stkctr_entry(stkctr));
+ }
+ return 1;
+}
+
/* set to the cumulated number of streams from the stream's tracked
* frontend counters. Supports being called as "sc[0-9]_sess_cnt" or
* "src_sess_cnt" only.
@@ -5573,6 +5727,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc_get_gpc", smp_fetch_sc_get_gpc, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_get_gpc0", smp_fetch_sc_get_gpc0, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_get_gpc1", smp_fetch_sc_get_gpc1, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN },
+ { "sc_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc_glitch_rate", smp_fetch_sc_glitch_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_gpc_rate", smp_fetch_sc_gpc_rate, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@@ -5601,6 +5757,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc0_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_get_gpc0", smp_fetch_sc_get_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_get_gpc1", smp_fetch_sc_get_gpc1, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc0_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc0_glitch_rate", smp_fetch_sc_glitch_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@@ -5628,6 +5786,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc1_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_get_gpc0", smp_fetch_sc_get_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_get_gpc1", smp_fetch_sc_get_gpc1, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc1_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc1_glitch_rate", smp_fetch_sc_glitch_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@@ -5654,6 +5814,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc2_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_get_gpc0", smp_fetch_sc_get_gpc0, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_get_gpc1", smp_fetch_sc_get_gpc1, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc2_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
+ { "sc2_glitch_rate", smp_fetch_sc_glitch_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@@ -5683,6 +5845,8 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "src_get_gpc", smp_fetch_sc_get_gpc, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_get_gpc0", smp_fetch_sc_get_gpc0, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_get_gpc1", smp_fetch_sc_get_gpc1, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
+ { "src_glitch_cnt", smp_fetch_sc_glitch_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
+ { "src_glitch_rate", smp_fetch_sc_glitch_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_gpc_rate", smp_fetch_sc_gpc_rate, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_gpc0_rate", smp_fetch_sc_gpc0_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
{ "src_gpc1_rate", smp_fetch_sc_gpc1_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },
@@ -5724,6 +5888,8 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
{ "table_gpc_rate", sample_conv_table_gpc_rate, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_gpc0_rate", sample_conv_table_gpc0_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_gpc1_rate", sample_conv_table_gpc1_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
+ { "table_glitch_cnt", sample_conv_table_glitch_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
+ { "table_glitch_rate", sample_conv_table_glitch_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_err_cnt", sample_conv_table_http_err_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_err_rate", sample_conv_table_http_err_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },
{ "table_http_fail_cnt", sample_conv_table_http_fail_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },