MINOR: stick-tables: Add GPT0 access

This patch adds acces to GPT0. The access can be done with http and
tcp actions, and through a converter.
This commit is contained in:
Thierry FOURNIER 2015-08-19 08:25:14 +02:00 committed by Willy Tarreau
parent 3cf1111eb3
commit 236657b5e0
4 changed files with 236 additions and 5 deletions

View File

@ -3365,6 +3365,7 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
set-map(<file name>) <key fmt> <value fmt> |
set-var(<var name>) <expr> |
{ track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] |
sc-set-gpt0(<sc-id>) <int> |
lua <function name>
}
[ { if | unless } <condition> ]
@ -3628,6 +3629,12 @@ http-request { allow | deny | tarpit | auth [realm <realm>] | redirect <rule> |
advantage over just checking the keys, because only one table lookup is
performed for all ACL checks that make use of it.
- sc-set-gpt0(<sc-id>) <int> :
This action sets the GPT0 tag according to the sticky counter designated
by <sc-id> and the value of <int>. The expected result is a boolean. If
an error occurs, this action silently fails and the actions evaluation
continues.
- "lua" is used to run a Lua function if the action is executed. The single
parameter is the name of the function to run. The prototype of the
function is documented in the API documentation.
@ -3738,6 +3745,7 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
del-map(<file name>) <key fmt> |
set-map(<file name>) <key fmt> <value fmt> |
set-var(<var-name>) <expr> |
sc-set-gpt0(<sc-id>) <int> |
lua <function name>
}
[ { if | unless } <condition> ]
@ -3936,6 +3944,12 @@ http-response { allow | deny | add-header <name> <fmt> | set-nice <nice> |
http-response set-var(sess.last_redir) res.hdr(location)
- sc-set-gpt0(<sc-id>) <int> :
This action sets the GPT0 tag according to the sticky counter designated
by <sc-id> and the value of <int>. The expected result is a boolean. If
an error occurs, this action silently fails and the actions evaluation
continues.
There is no limit to the number of http-response statements per instance.
It is important to know that http-response rules are processed very early in
@ -8298,6 +8312,12 @@ tcp-request connection <action> [{if | unless} <condition>]
advantage over just checking the keys, because only one table lookup is
performed for all ACL checks that make use of it.
- sc-set-gpt0(<sc-id>) <int>:
This action sets the GPT0 tag according to the sticky counter designated
by <sc-id> and the value of <int>. The expected result is a boolean. If
an error occurs, this action silently fails and the actions evaluation
continues.
Note that the "if/unless" condition is optional. If no condition is set on
the action, it is simply performed unconditionally. That can be useful for
"track-sc*" actions as well as for changing the default action to a reject.
@ -8334,8 +8354,8 @@ tcp-request content <action> [{if | unless} <condition>]
Arguments :
<action> defines the action to perform if the condition applies. Valid
actions include : "accept", "reject", "track-sc0", "track-sc1",
"track-sc2", "capture" and "lua". See "tcp-request connection"
above for their signification.
"track-sc2", "sc-set-gpt0", "capture" and "lua". See
"tcp-request connection" above for their signification.
<condition> is a standard layer 4-7 ACL-based condition (see section 7).
@ -8363,11 +8383,12 @@ tcp-request content <action> [{if | unless} <condition>]
contents. There is no specific limit to the number of rules which may be
inserted.
Four types of actions are supported :
Several types of actions are supported :
- accept : the request is accepted
- reject : the request is rejected and the connection is closed
- capture : the specified sample expression is captured
- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]
- set-gpt0(<sc-id>) <int>
- lua <function>
- set-var(<var-name>) <expr>
@ -8535,7 +8556,8 @@ tcp-response content <action> [{if | unless} <condition>]
no | no | yes | yes
Arguments :
<action> defines the action to perform if the condition applies. Valid
actions include : "accept", "close", "reject", "lua".
actions include : "accept", "close", "reject", "lua", and
"sc-set-gpt0".
<condition> is a standard layer 4-7 ACL-based condition (see section 7).
@ -8552,7 +8574,7 @@ tcp-response content <action> [{if | unless} <condition>]
contents. There is no specific limit to the number of rules which may be
inserted.
Two types of actions are supported :
Several types of actions are supported :
- accept :
accepts the response if the condition is true (when used with "if")
or false (when used with "unless"). The first such rule executed ends
@ -8579,6 +8601,12 @@ tcp-response content <action> [{if | unless} <condition>]
- set-var(<var-name>) <expr>
Sets a variable.
- sc-set-gpt0(<sc-id>) <int> :
This action sets the GPT0 tag according to the sticky counter designated
by <sc-id> and the value of <int>. The expected result is a boolean. If
an error occurs, this action silently fails and the actions evaluation
continues.
Note that the "if/unless" condition is optional. If no condition is set on
the action, it is simply performed unconditionally. That can be useful for
for changing the default action to a reject.
@ -11545,6 +11573,13 @@ table_conn_rate(<table>)
rate associated with the input sample in the designated table. See also the
sc_conn_rate sample fetch keyword.
table_gpt0(<table>)
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
is returned. Otherwise the converter returns the current value of the first
general purpose tag associated with the input sample in the designated table.
See also the sc_get_gpt0 sample fetch keyword.
table_gpc0(<table>)
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
@ -12069,6 +12104,13 @@ sc2_get_gpc0([<table>]) : integer
Returns the value of the first General Purpose Counter associated to the
currently tracked counters. See also src_get_gpc0 and sc/sc0/sc1/sc2_inc_gpc0.
sc_get_gpt0(<ctr>[,<table>]) : integer
sc0_get_gpt0([<table>]) : integer
sc1_get_gpt0([<table>]) : integer
sc2_get_gpt0([<table>]) : integer
Returns the value of the first General Purpose Tag associated to the
currently tracked counters. See also src_get_gpt0.
sc_gpc0_rate(<ctr>[,<table>]) : integer
sc0_gpc0_rate([<table>]) : integer
sc1_gpc0_rate([<table>]) : integer
@ -12257,6 +12299,12 @@ src_get_gpc0([<table>]) : integer
the designated stick-table. If the address is not found, zero is returned.
See also sc/sc0/sc1/sc2_get_gpc0 and src_inc_gpc0.
src_get_gpt0([<table>]) : 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
the designated stick-table. If the address is not found, zero is returned.
See also sc/sc0/sc1/sc2_get_gpt0.
src_gpc0_rate([<table>]) : integer
Returns the average increment rate of the first General Purpose Counter
associated to the incoming connection's source address in the current proxy's

View File

@ -130,6 +130,10 @@ struct act_rule {
const char *name;
enum vars_scope scope;
} vars;
struct {
int sc;
long long int value;
} gpt;
struct track_ctr_prm trk_ctr;
struct {
void *p[4];

View File

@ -23,6 +23,8 @@
#include <ebsttree.h>
#include <proto/arg.h>
#include <proto/proto_http.h>
#include <proto/proto_tcp.h>
#include <proto/proxy.h>
#include <proto/sample.h>
#include <proto/stream.h>
@ -854,6 +856,41 @@ static int sample_conv_table_bytes_out_rate(const struct arg *arg_p, struct samp
return 1;
}
/* Casts sample <smp> 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
* be easily performed. If the inspected parameter is not stored in the table,
* <not found> is returned.
*/
static int sample_conv_table_gpt0(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.prx->table;
key = smp_to_stkey(smp, t);
if (!key)
return 0;
smp->flags = SMP_F_VOL_TEST;
smp->data.type = SMP_T_SINT;
smp->data.u.sint = 0;
ts = stktable_lookup_key(t, key);
if (!ts) /* key not present */
return 1;
ptr = stktable_data_ptr(t, ts, STKTABLE_DT_GPT0);
if (!ptr)
return 0; /* parameter not stored */
smp->data.u.sint = stktable_data_cast(ptr, gpt0);
return 1;
}
/* Casts sample <smp> to the type of the table specified in arg(0), and looks
* it up into this table. Returns the value of the GPC0 counter for the key
* if the key is present in the table, otherwise zero, so that comparisons can
@ -1272,6 +1309,109 @@ static int sample_conv_table_trackers(const struct arg *arg_p, struct sample *sm
return 1;
}
/* Always returns 1. */
static enum act_return action_set_gpt0(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s)
{
void *ptr;
struct stksess *ts;
struct stkctr *stkctr;
/* 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(stkctr->table, ts, STKTABLE_DT_GPT0);
if (ptr)
stktable_data_cast(ptr, gpt0) = rule->arg.gpt.value;
return ACT_RET_CONT;
}
/* This function is a common parser for using variables. It understands
* the format:
*
* set-gpt0(<stick-table ID>) <expression>
*
* It returns 0 if fails and <err> is filled with an error message. Otherwise,
* it returns 1 and the variable <expr> is filled with the pointer to the
* expression to execute.
*/
static enum act_parse_ret parse_set_gpt0(const char **args, int *arg, struct proxy *px,
struct act_rule *rule, char **err)
{
const char *cmd_name = args[*arg-1];
char *error;
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(<Track ID>)", 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(<Track ID>)", args[*arg-1]);
return ACT_RET_PRS_ERR;
}
if (rule->arg.gpt.sc >= ACT_ACTION_TRK_SCMAX) {
memprintf(err, "invalid stick table track ID '%s'. The max allowed ID is %d",
args[*arg-1], ACT_ACTION_TRK_SCMAX-1);
return ACT_RET_PRS_ERR;
}
}
rule->arg.gpt.value = strtol(args[*arg], &error, 10);
if (*error != '\0') {
memprintf(err, "invalid integer value '%s'", args[*arg]);
return ACT_RET_PRS_ERR;
}
(*arg)++;
rule->action = ACT_ACTION_CONT;
rule->action_ptr = action_set_gpt0;
return ACT_RET_PRS_OK;
}
static struct action_kw_list tcp_conn_kws = { { }, {
{ "sc-set-gpt0", parse_set_gpt0, 1 },
{ /* END */ }
}};
static struct action_kw_list tcp_req_kws = { { }, {
{ "sc-set-gpt0", parse_set_gpt0, 1 },
{ /* END */ }
}};
static struct action_kw_list tcp_res_kws = { { }, {
{ "sc-set-gpt0", parse_set_gpt0, 1 },
{ /* END */ }
}};
static struct action_kw_list http_req_kws = { { }, {
{ "sc-set-gpt0", parse_set_gpt0, 1 },
{ /* END */ }
}};
static struct action_kw_list http_res_kws = { { }, {
{ "sc-set-gpt0", parse_set_gpt0, 1 },
{ /* END */ }
}};
/* Note: must not be declared <const> as its list will be overwritten */
static struct sample_conv_kw_list sample_conv_kws = {ILH, {
{ "in_table", sample_conv_in_table, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_BOOL },
@ -1280,6 +1420,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_STR, SMP_T_SINT },
{ "table_conn_cur", sample_conv_table_conn_cur, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_SINT },
{ "table_conn_rate", sample_conv_table_conn_rate, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_SINT },
{ "table_gpt0", sample_conv_table_gpt0, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_SINT },
{ "table_gpc0", sample_conv_table_gpc0, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_SINT },
{ "table_gpc0_rate", sample_conv_table_gpc0_rate, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_SINT },
{ "table_http_err_cnt", sample_conv_table_http_err_cnt, ARG1(1,TAB), NULL, SMP_T_STR, SMP_T_SINT },
@ -1298,6 +1439,13 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, {
__attribute__((constructor))
static void __stick_table_init(void)
{
/* register som action keywords. */
tcp_req_conn_keywords_register(&tcp_conn_kws);
tcp_req_cont_keywords_register(&tcp_req_kws);
tcp_res_cont_keywords_register(&tcp_res_kws);
http_req_keywords_register(&http_req_kws);
http_res_keywords_register(&http_res_kws);
/* register sample fetch and format conversion keywords */
sample_register_convs(&sample_conv_kws);
}

View File

@ -2694,6 +2694,32 @@ smp_fetch_sc_tracked(const struct arg *args, struct sample *smp, const char *kw,
return 1;
}
/* set <smp> 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
* zero is returned if the key is new.
*/
static int
smp_fetch_sc_get_gpt0(const struct arg *args, struct sample *smp, const char *kw, void *private)
{
struct stkctr *stkctr = smp_fetch_sc_stkctr(smp->sess, smp->strm, args, kw);
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 = stktable_data_ptr(stkctr->table, stkctr_entry(stkctr), STKTABLE_DT_GPT0);
if (!ptr)
return 0; /* parameter not stored */
smp->data.u.sint = stktable_data_cast(ptr, gpt0);
}
return 1;
}
/* set <smp> to the General Purpose Counter 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_gpc0" only. Value
@ -3240,6 +3266,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_gpt0", smp_fetch_sc_get_gpt0, ARG2(1,SINT,TAB), NULL, SMP_T_BOOL, SMP_USE_INTRN, },
{ "sc_get_gpc0", smp_fetch_sc_get_gpc0, ARG2(1,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_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG2(1,SINT,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -3259,6 +3286,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc0_conn_cnt", smp_fetch_sc_conn_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_conn_cur", smp_fetch_sc_conn_cur, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_conn_rate", smp_fetch_sc_conn_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc0_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(0,TAB), NULL, SMP_T_BOOL, SMP_USE_INTRN, },
{ "sc0_get_gpc0", smp_fetch_sc_get_gpc0, 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_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -3278,6 +3306,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc1_conn_cnt", smp_fetch_sc_conn_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_conn_cur", smp_fetch_sc_conn_cur, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_conn_rate", smp_fetch_sc_conn_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc1_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(0,TAB), NULL, SMP_T_BOOL, SMP_USE_INTRN, },
{ "sc1_get_gpc0", smp_fetch_sc_get_gpc0, 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_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -3297,6 +3326,7 @@ static struct sample_fetch_kw_list smp_fetch_keywords = {ILH, {
{ "sc2_conn_cnt", smp_fetch_sc_conn_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_conn_cur", smp_fetch_sc_conn_cur, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_conn_rate", smp_fetch_sc_conn_rate, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
{ "sc2_get_gpt0", smp_fetch_sc_get_gpt0, ARG1(0,TAB), NULL, SMP_T_BOOL, SMP_USE_INTRN, },
{ "sc2_get_gpc0", smp_fetch_sc_get_gpc0, 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_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(0,TAB), NULL, SMP_T_SINT, SMP_USE_INTRN, },
@ -3316,6 +3346,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_gpt0", smp_fetch_sc_get_gpt0, ARG1(1,TAB), NULL, SMP_T_BOOL, SMP_USE_L4CLI, },
{ "src_get_gpc0", smp_fetch_sc_get_gpc0, ARG1(1,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_http_err_cnt", smp_fetch_sc_http_err_cnt, ARG1(1,TAB), NULL, SMP_T_SINT, SMP_USE_L4CLI, },