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> ]
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.
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> ]
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
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.
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).
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>
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).
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
- 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.
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
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
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
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];
#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>
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
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 },
{ "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 },
__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);
}
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
{ "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, },
{ "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, },
{ "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, },
{ "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, },
{ "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, },