From 877b0b5a7b90f87d8801570e0560d33cab089af3 Mon Sep 17 00:00:00 2001 From: Emeric Brun Date: Wed, 30 Jun 2021 18:57:49 +0200 Subject: [PATCH] MEDIUM: stick-table: add the new array of gpt data_type This patch adds the definition of a new array data_type 'gpt'. This is an array of 32bits General Purpose Tags. Like for all arrays, it is limited to 100 elements. This patch also adds actions and fetches to handle elements of this array. Note: As documented, those new actions and fetches won't apply to the legacy 'gpt0' data type. --- doc/configuration.txt | 88 +++++++++++ include/haproxy/action-t.h | 1 + include/haproxy/stick_table-t.h | 2 + src/stick_table.c | 264 ++++++++++++++++++++++++++++---- 4 files changed, 321 insertions(+), 34 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 87a206736..e4be9bd64 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -6416,6 +6416,18 @@ http-request sc-inc-gpc1() [ { if | unless } ] counter designated by . If an error occurs, this action silently fails and the actions evaluation continues. +http-request sc-set-gpt(,) { | } + [ { if | unless } ] + This action sets the 32-bit unsigned GPT at the index of the array + associated to the sticky counter designated by at the value of + /. The expected result is a boolean. + If an error occurs, this action silently fails and the actions evaluation + continues. is an integer between 0 and 99 and is an integer + between 0 and 2. It also silently fails if the there is no GPT stored + at this index. + This action applies only to the 'gpt' array data_type (and not to the + legacy 'gpt0' data-type). + http-request sc-set-gpt0() { | } [ { if | unless } ] @@ -7115,6 +7127,19 @@ http-response sc-inc-gpc1() [ { if | unless } ] counter designated by . If an error occurs, this action silently fails and the actions evaluation continues. +http-response sc-set-gpt(,) { | } + [ { if | unless } ] + + This action sets the 32-bit unsigned GPT at the index of the array + associated to the sticky counter designated by at the value of + /. The expected result is a boolean. + If an error occurs, this action silently fails and the actions evaluation + continues. is an integer between 0 and 99 and is an integer + between 0 and 2. It also silently fails if the there is no GPT stored + at this index. + This action applies only to the 'gpt' array data_type (and not to the + legacy 'gpt0' data-type). + http-response sc-set-gpt0() { | } [ { if | unless } ] @@ -11182,6 +11207,17 @@ stick-table type {ip | integer | string [len ] | binary [len ]} incremented. Most of the time it will be used to measure the frequency of occurrence of certain events (e.g. requests to a specific URL). + - gpt() : General Purpose Tags Array of elements. This is an array + of positive 32-bit integers which may be used for anything. + Most of the time they will be used to put a special tags on some entries, + for instance to note that a specific behavior was detected and must be + known for future matches. This array is limited to a maximum of 100 + elements: gpt0 to gpt99, to ensure that the build of a peer update + message can fit into the buffer. Users should take in consideration + that a large amount of counters will increase the data size and the + traffic load using peers protocol since all data/counters are pushed + each time any of them is updated. + - gpt0 : first General Purpose Tag. It is a positive 32-bit integer integer which may be used for anything. Most of the time it will be used to put a special tag on some entries, for instance to note that a @@ -11901,6 +11937,17 @@ tcp-request connection [{if | unless} ] counter designated by . If an error occurs, this action silently fails and the actions evaluation continues. + - sc-set-gpt(,) { | }: + This action sets the 32-bit unsigned GPT at the index of the + array associated to the sticky counter designated by at the + value of /. The expected result is a boolean. + If an error occurs, this action silently fails and the actions + evaluation continues. is an integer between 0 and 99 and + is an integer between 0 and 2. It also silently fails if the there is + no GPT stored at this index. + This action applies only to the 'gpt' array data_type (and not to the + legacy 'gpt0' data-type). + - sc-set-gpt0() { | }: This action sets the 32-bit unsigned GPT0 tag according to the sticky counter designated by and the value of /. The @@ -12085,6 +12132,7 @@ tcp-request content [{if | unless} ] - { track-sc0 | track-sc1 | track-sc2 } [table ] - sc-inc-gpc0() - sc-inc-gpc1() + - sc-set-gpt(,) { | } - sc-set-gpt0() { | } - set-dst - set-dst-port @@ -12434,6 +12482,17 @@ tcp-response content [{if | unless} ] counter designated by . If an error occurs, this action fails silently and the actions evaluation continues. + - sc-set-gpt(,) { | } + This action sets the 32-bit unsigned GPT at the index of the + array associated to the sticky counter designated by at the + value of /. The expected result is a boolean. + If an error occurs, this action silently fails and the actions + evaluation continues. is an integer between 0 and 99 and + is an integer between 0 and 2. It also silently fails if the there is + no GPT stored at this index. + This action applies only to the 'gpt' array data_type (and not to the + legacy 'gpt0' data-type). + - sc-set-gpt0() { | } This action sets the 32-bit unsigned GPT0 tag according to the sticky counter designated by and the value of /. The @@ -12559,6 +12618,7 @@ tcp-request session [{if | unless} ] - { track-sc0 | track-sc1 | track-sc2 } [table
] - sc-inc-gpc0() - sc-inc-gpc1() + - sc-set-gpt(,) { | } - sc-set-gpt0() { | } - set-mark - set-dst @@ -16702,6 +16762,17 @@ table_conn_rate(
) rate associated with the input sample in the designated table. See also the sc_conn_rate sample fetch keyword. +table_gpt(,
) + 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, boolean value zero + is returned. Otherwise the converter returns the current value of the general + purpose tag at the index of the array associated to the input sample + in the designated
. is an integer between 0 and 99. + If there is no GPT stored at this index, it also returns the boolean value 0. + This applies only to the 'gpt' array data_type (and not on the legacy 'gpt0' + data-type). + See also the sc_get_gpt sample fetch keyword. + table_gpt0(
) 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, boolean value zero @@ -17753,6 +17824,15 @@ sc2_get_gpc1([
]) : integer Returns the value of the second General Purpose Counter associated to the currently tracked counters. See also src_get_gpc1 and sc/sc0/sc1/sc2_inc_gpc1. +sc_get_gpt(,[,
]) : integer + Returns the value of the first General Purpose Tag at the index of + the array associated to the tracked counter of ID and from the + current proxy's sitck-table or the designated stick-table
. + is an integer between 0 and 99 and an integer between 0 and 2. + If there is no GPT stored at this index, zero is returned. + This fetch applies only to the 'gpt' array data_type (and not on + the legacy 'gpt0' data-type). See also src_get_gpt. + sc_get_gpt0([,
]) : integer sc0_get_gpt0([
]) : integer sc1_get_gpt0([
]) : integer @@ -18014,6 +18094,14 @@ src_get_gpc1([
]) : integer the designated stick-table. If the address is not found, zero is returned. See also sc/sc0/sc1/sc2_get_gpc1 and src_inc_gpc1. +src_get_gpt([,
]) : integer + Returns the value of the first General Purpose Tag at the index of + the array associated to the incoming connection's source address in the + current proxy's stick-table or in the designated stick-table
. + is an integer between 0 and 99. + If the address is not found or the GPT is not stored, zero is returned. + See also the sc_get_gpt sample fetch keyword. + src_get_gpt0([
]) : integer Returns the value of the first General Purpose Tag associated to the incoming connection's source address in the current proxy's stick-table or in diff --git a/include/haproxy/action-t.h b/include/haproxy/action-t.h index 773ccd1a2..5494f76ad 100644 --- a/include/haproxy/action-t.h +++ b/include/haproxy/action-t.h @@ -171,6 +171,7 @@ struct act_rule { } gpc; struct { int sc; + unsigned int idx; long long int value; struct sample_expr *expr; } gpt; diff --git a/include/haproxy/stick_table-t.h b/include/haproxy/stick_table-t.h index 89d1b2a2a..fe21c9b20 100644 --- a/include/haproxy/stick_table-t.h +++ b/include/haproxy/stick_table-t.h @@ -60,6 +60,8 @@ enum { STKTABLE_DT_SERVER_KEY, /* The server key */ STKTABLE_DT_HTTP_FAIL_CNT, /* cumulated number of HTTP server failures */ STKTABLE_DT_HTTP_FAIL_RATE,/* HTTP server failures rate */ + STKTABLE_DT_GPT, /* array of gpt */ + STKTABLE_STATIC_DATA_TYPES,/* number of types above */ /* up to STKTABLE_EXTRA_DATA_TYPES types may be registered here, always diff --git a/src/stick_table.c b/src/stick_table.c index 349e138c8..7fcda827b 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -1143,6 +1143,7 @@ struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES] = { [STKTABLE_DT_SERVER_KEY] = { .name = "server_key", .std_type = STD_T_DICT }, [STKTABLE_DT_HTTP_FAIL_CNT] = { .name = "http_fail_cnt", .std_type = STD_T_UINT }, [STKTABLE_DT_HTTP_FAIL_RATE]= { .name = "http_fail_rate", .std_type = STD_T_FRQP, .arg_type = ARG_T_DELAY }, + [STKTABLE_DT_GPT] = { .name = "gpt", .std_type = STD_T_UINT, .is_array = 1 }, }; /* Registers stick-table extra data type with index , name , type @@ -1406,6 +1407,45 @@ 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_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 + * be easily performed. If the inspected parameter is not stored in the table, + * is returned. + */ +static int sample_conv_table_gpt(const struct arg *arg_p, struct sample *smp, void *private) +{ + struct stktable *t; + struct stktable_key *key; + struct stksess *ts; + void *ptr; + unsigned int idx; + + idx = arg_p[0].data.sint; + + t = arg_p[1].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_idx(t, ts, STKTABLE_DT_GPT, idx); + 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 value of the GPT0 tag for the key * if the key is present in the table, otherwise false, so that comparisons can @@ -2185,6 +2225,77 @@ static enum act_parse_ret parse_inc_gpc1(const char **args, int *arg, struct pro return ACT_RET_PRS_OK; } +/* This function sets the gpt at index 'rule->arg.gpt.idx' of the array on the + * tracksc counter of index 'rule->arg.gpt.sc' stored into the or + * directly in the session if is set to NULL. This gpt is + * set to the value computed by the expression 'rule->arg.gpt.expr' or if + * 'rule->arg.gpt.expr' is null directly to the value of 'rule->arg.gpt.value'. + * + * This function always returns ACT_RET_CONT and parameter flags is unused. + */ +static enum act_return action_set_gpt(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s, int flags) +{ + void *ptr; + struct stksess *ts; + struct stkctr *stkctr; + unsigned int value = 0; + struct sample *smp; + int smp_opt_dir; + + /* Extract the stksess, return OK if no stksess available. */ + if (s) + stkctr = &s->stkctr[rule->arg.gpt.sc]; + else + stkctr = &sess->stkctr[rule->arg.gpt.sc]; + + ts = stkctr_entry(stkctr); + if (!ts) + return ACT_RET_CONT; + + /* Store the sample in the required sc, and ignore errors. */ + ptr = stktable_data_ptr_idx(stkctr->table, ts, STKTABLE_DT_GPT, rule->arg.gpt.idx); + if (ptr) { + + if (!rule->arg.gpt.expr) + value = (unsigned int)(rule->arg.gpt.value); + else { + switch (rule->from) { + case ACT_F_TCP_REQ_SES: smp_opt_dir = SMP_OPT_DIR_REQ; break; + case ACT_F_TCP_REQ_CNT: smp_opt_dir = SMP_OPT_DIR_REQ; break; + case ACT_F_TCP_RES_CNT: smp_opt_dir = SMP_OPT_DIR_RES; break; + case ACT_F_HTTP_REQ: smp_opt_dir = SMP_OPT_DIR_REQ; break; + case ACT_F_HTTP_RES: smp_opt_dir = SMP_OPT_DIR_RES; break; + default: + send_log(px, LOG_ERR, "stick table: internal error while setting gpt%u.", rule->arg.gpt.idx); + if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) + ha_alert("stick table: internal error while executing setting gpt%u.\n", rule->arg.gpt.idx); + return ACT_RET_CONT; + } + + /* Fetch and cast the expression. */ + smp = sample_fetch_as_type(px, sess, s, smp_opt_dir|SMP_OPT_FINAL, rule->arg.gpt.expr, SMP_T_SINT); + if (!smp) { + send_log(px, LOG_WARNING, "stick table: invalid expression or data type while setting gpt%u.", rule->arg.gpt.idx); + if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) + ha_alert("stick table: invalid expression or data type while setting gpt%u.\n", rule->arg.gpt.idx); + return ACT_RET_CONT; + } + value = (unsigned int)(smp->data.u.sint); + } + + HA_RWLOCK_WRLOCK(STK_SESS_LOCK, &ts->lock); + + stktable_data_cast(ptr, std_t_uint) = value; + + HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock); + + stktable_touch_local(stkctr->table, ts, 0); + } + + return ACT_RET_CONT; +} + /* Always returns 1. */ static enum act_return action_set_gpt0(struct act_rule *rule, struct proxy *px, struct session *sess, struct stream *s, int flags) @@ -2248,46 +2359,78 @@ static enum act_return action_set_gpt0(struct act_rule *rule, struct proxy *px, return ACT_RET_CONT; } -/* This function is a common parser for using variables. It understands - * the format: +/* This function is a parser for the "sc-set-gpt" and "sc-set-gpt0" actions. + * It understands the formats: * - * set-gpt0() + * sc-set-gpt(,) + * sc-set-gpt0() * - * It returns 0 if fails and is filled with an error message. Otherwise, - * it returns 1 and the variable is filled with the pointer to the - * expression to execute. + * It returns ACT_RET_PRS_ERR if fails and is filled with an error message. + * Otherwise, it returns ACT_RET_PRS_OK and the variable 'rule->arg.gpt.expr' + * is filled with the pointer to the expression to execute or NULL if the arg + * is directly an integer stored into 'rule->arg.gpt.value'. */ -static enum act_parse_ret parse_set_gpt0(const char **args, int *arg, struct proxy *px, +static enum act_parse_ret parse_set_gpt(const char **args, int *arg, struct proxy *px, struct act_rule *rule, char **err) - - { const char *cmd_name = args[*arg-1]; char *error; int smp_val; - cmd_name += strlen("sc-set-gpt0"); - if (*cmd_name == '\0') { - /* default stick table id. */ - rule->arg.gpt.sc = 0; - } else { - /* parse the stick table id. */ - if (*cmd_name != '(') { - memprintf(err, "invalid stick table track ID '%s'. Expects sc-set-gpt0()", args[*arg-1]); - return ACT_RET_PRS_ERR; - } - cmd_name++; /* jump the '(' */ - rule->arg.gpt.sc = strtol(cmd_name, &error, 10); /* Convert stick table id. */ - if (*error != ')') { - memprintf(err, "invalid stick table track ID '%s'. Expects sc-set-gpt0()", args[*arg-1]); + cmd_name += strlen("sc-set-gpt"); + if (*cmd_name == '(') { + cmd_name++; /* skip the '(' */ + rule->arg.gpt.idx = strtoul(cmd_name, &error, 10); /* Convert stick table id. */ + if (*error != ',') { + memprintf(err, "Missing gpt ID '%s'. Expects sc-set-gpt(,)", args[*arg-1]); return ACT_RET_PRS_ERR; } + else { + cmd_name = error + 1; /* skip the ',' */ + rule->arg.gpt.sc = strtol(cmd_name, &error, 10); /* Convert stick table id. */ + if (*error != ')') { + memprintf(err, "invalid stick table track ID '%s'. Expects sc-set-gpt(,)", args[*arg-1]); + return ACT_RET_PRS_ERR; + } - if (rule->arg.gpt.sc >= MAX_SESS_STKCTR) { - memprintf(err, "invalid stick table track ID '%s'. The max allowed ID is %d", - args[*arg-1], MAX_SESS_STKCTR-1); - return ACT_RET_PRS_ERR; + if (rule->arg.gpt.sc >= MAX_SESS_STKCTR) { + memprintf(err, "invalid stick table track ID '%s'. The max allowed ID is %d", + args[*arg-1], MAX_SESS_STKCTR-1); + return ACT_RET_PRS_ERR; + } } + rule->action_ptr = action_set_gpt; + } + else if (*cmd_name == '0') { + cmd_name++; + if (*cmd_name == '\0') { + /* default stick table id. */ + rule->arg.gpt.sc = 0; + } else { + /* parse the stick table id. */ + if (*cmd_name != '(') { + memprintf(err, "invalid stick table track ID '%s'. Expects sc-set-gpt0()", args[*arg-1]); + return ACT_RET_PRS_ERR; + } + cmd_name++; /* jump the '(' */ + rule->arg.gpt.sc = strtol(cmd_name, &error, 10); /* Convert stick table id. */ + if (*error != ')') { + memprintf(err, "invalid stick table track ID '%s'. Expects sc-set-gpt0()", args[*arg-1]); + return ACT_RET_PRS_ERR; + } + + if (rule->arg.gpt.sc >= MAX_SESS_STKCTR) { + memprintf(err, "invalid stick table track ID '%s'. The max allowed ID is %d", + args[*arg-1], MAX_SESS_STKCTR-1); + return ACT_RET_PRS_ERR; + } + } + rule->action_ptr = action_set_gpt0; + } + else { + /* default stick table id. */ + memprintf(err, "invalid gpt ID '%s'. Expects sc-set-gpt(,)", args[*arg-1]); + return ACT_RET_PRS_ERR; } rule->arg.gpt.expr = NULL; @@ -2318,7 +2461,6 @@ static enum act_parse_ret parse_set_gpt0(const char **args, int *arg, struct pro (*arg)++; rule->action = ACT_CUSTOM; - rule->action_ptr = action_set_gpt0; return ACT_RET_PRS_OK; } @@ -2488,6 +2630,51 @@ smp_fetch_sc_tracked(const struct arg *args, struct sample *smp, const char *kw, return 1; } +/* set to the General Purpose Tag of index set as first arg + * to value from the stream's tracked frontend counters or from the src. + * Supports being called as "sc_get_gpt(,[,
])" or + * "src_get_gpt([,
])" only. Value zero is returned if + * the key is new or gpt is not stored. + */ +static int +smp_fetch_sc_get_gpt(const struct arg *args, struct sample *smp, const char *kw, void *private) +{ + struct stkctr tmpstkctr; + struct stkctr *stkctr; + unsigned int idx; + + idx = args[0].data.sint; + + stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args + 1, 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)) { + void *ptr; + + ptr = stktable_data_ptr_idx(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPT, idx); + 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 General Purpose Flag 0 value from the stream's tracked * frontend counters or from the src. * Supports being called as "sc[0-9]_get_gpc0" or "src_get_gpt0" only. Value @@ -4183,7 +4370,8 @@ INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws); static struct action_kw_list tcp_conn_kws = { { }, { { "sc-inc-gpc0", parse_inc_gpc0, KWF_MATCH_PREFIX }, { "sc-inc-gpc1", parse_inc_gpc1, KWF_MATCH_PREFIX }, - { "sc-set-gpt0", parse_set_gpt0, KWF_MATCH_PREFIX }, + { "sc-set-gpt", parse_set_gpt, KWF_MATCH_PREFIX }, + { "sc-set-gpt0", parse_set_gpt, KWF_MATCH_PREFIX }, { /* END */ } }}; @@ -4192,7 +4380,8 @@ INITCALL1(STG_REGISTER, tcp_req_conn_keywords_register, &tcp_conn_kws); static struct action_kw_list tcp_sess_kws = { { }, { { "sc-inc-gpc0", parse_inc_gpc0, KWF_MATCH_PREFIX }, { "sc-inc-gpc1", parse_inc_gpc1, KWF_MATCH_PREFIX }, - { "sc-set-gpt0", parse_set_gpt0, KWF_MATCH_PREFIX }, + { "sc-set-gpt", parse_set_gpt, KWF_MATCH_PREFIX }, + { "sc-set-gpt0", parse_set_gpt, KWF_MATCH_PREFIX }, { /* END */ } }}; @@ -4201,7 +4390,8 @@ INITCALL1(STG_REGISTER, tcp_req_sess_keywords_register, &tcp_sess_kws); static struct action_kw_list tcp_req_kws = { { }, { { "sc-inc-gpc0", parse_inc_gpc0, KWF_MATCH_PREFIX }, { "sc-inc-gpc1", parse_inc_gpc1, KWF_MATCH_PREFIX }, - { "sc-set-gpt0", parse_set_gpt0, KWF_MATCH_PREFIX }, + { "sc-set-gpt", parse_set_gpt, KWF_MATCH_PREFIX }, + { "sc-set-gpt0", parse_set_gpt, KWF_MATCH_PREFIX }, { /* END */ } }}; @@ -4210,7 +4400,8 @@ INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &tcp_req_kws); static struct action_kw_list tcp_res_kws = { { }, { { "sc-inc-gpc0", parse_inc_gpc0, KWF_MATCH_PREFIX }, { "sc-inc-gpc1", parse_inc_gpc1, KWF_MATCH_PREFIX }, - { "sc-set-gpt0", parse_set_gpt0, KWF_MATCH_PREFIX }, + { "sc-set-gpt", parse_set_gpt, KWF_MATCH_PREFIX }, + { "sc-set-gpt0", parse_set_gpt, KWF_MATCH_PREFIX }, { /* END */ } }}; @@ -4219,7 +4410,8 @@ INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &tcp_res_kws); static struct action_kw_list http_req_kws = { { }, { { "sc-inc-gpc0", parse_inc_gpc0, KWF_MATCH_PREFIX }, { "sc-inc-gpc1", parse_inc_gpc1, KWF_MATCH_PREFIX }, - { "sc-set-gpt0", parse_set_gpt0, KWF_MATCH_PREFIX }, + { "sc-set-gpt", parse_set_gpt, KWF_MATCH_PREFIX }, + { "sc-set-gpt0", parse_set_gpt, KWF_MATCH_PREFIX }, { /* END */ } }}; @@ -4228,7 +4420,8 @@ INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_kws); static struct action_kw_list http_res_kws = { { }, { { "sc-inc-gpc0", parse_inc_gpc0, KWF_MATCH_PREFIX }, { "sc-inc-gpc1", parse_inc_gpc1, KWF_MATCH_PREFIX }, - { "sc-set-gpt0", parse_set_gpt0, KWF_MATCH_PREFIX }, + { "sc-set-gpt", parse_set_gpt, KWF_MATCH_PREFIX }, + { "sc-set-gpt0", parse_set_gpt, KWF_MATCH_PREFIX }, { /* END */ } }}; @@ -4245,6 +4438,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "sc_conn_cnt", smp_fetch_sc_conn_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_conn_cur", smp_fetch_sc_conn_cur, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_conn_rate", smp_fetch_sc_conn_rate, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, + { "sc_get_gpt", smp_fetch_sc_get_gpt, ARG3(2,SINT,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, }, { "sc_get_gpt0", smp_fetch_sc_get_gpt0, ARG2(1,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 }, @@ -4349,6 +4543,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, { { "src_conn_cnt", smp_fetch_sc_conn_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_conn_cur", smp_fetch_sc_conn_cur, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_conn_rate", smp_fetch_sc_conn_rate, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, + { "src_get_gpt" , smp_fetch_sc_get_gpt, ARG2(2,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, }, { "src_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(1,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, }, @@ -4382,6 +4577,7 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "table_conn_cnt", sample_conv_table_conn_cnt, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_conn_cur", sample_conv_table_conn_cur, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_conn_rate", sample_conv_table_conn_rate, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, + { "table_gpt", sample_conv_table_gpt, ARG2(2,SINT,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_gpt0", sample_conv_table_gpt0, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_gpc0", sample_conv_table_gpc0, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT }, { "table_gpc1", sample_conv_table_gpc1, ARG1(1,TAB), NULL, SMP_T_ANY, SMP_T_SINT },