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 },