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