diff --git a/include/types/stick_table.h b/include/types/stick_table.h index fba6e2467..a1bfc1acf 100644 --- a/include/types/stick_table.h +++ b/include/types/stick_table.h @@ -43,6 +43,7 @@ enum { /* The types of extra data we can store in a stick table */ enum { STKTABLE_DT_SERVER_ID, /* the server ID to use with this session if > 0 */ + STKTABLE_DT_GPC0, /* General Purpose Counter 0 (unsigned 32-bit integer) */ STKTABLE_DT_CONN_CNT, /* cumulated number of connections */ STKTABLE_DT_CONN_RATE, /* incoming connection rate */ STKTABLE_DT_CONN_CUR, /* concurrent number of connections */ @@ -65,6 +66,7 @@ enum { /* stick_table extra data. This is mainly used for casting or size computation */ union stktable_data { int server_id; + unsigned int gpc0; unsigned int conn_cnt; struct freq_ctr_period conn_rate; unsigned int conn_cur; diff --git a/src/session.c b/src/session.c index 2c115767c..aaa0622b8 100644 --- a/src/session.c +++ b/src/session.c @@ -2102,6 +2102,106 @@ void default_srv_error(struct session *s, struct stream_interface *si) /* All supported ACL keywords must be declared here. */ /************************************************************************/ +/* set test->i to the General Purpose Counter 0 value in the stksess entry */ +static int +acl_fetch_get_gpc0(struct stktable *table, struct acl_test *test, struct stksess *ts) +{ + test->flags = ACL_TEST_F_VOL_TEST; + test->i = 0; + if (ts != NULL) { + void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0); + if (!ptr) + return 0; /* parameter not stored */ + test->i = stktable_data_cast(ptr, gpc0); + } + return 1; +} + +/* set test->i to the General Purpose Counter 0 value from the session's tracked + * counters. + */ +static int +acl_fetch_trk_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + if (!l4->tracked_counters) + return 0; + return acl_fetch_get_gpc0(l4->tracked_table, test, l4->tracked_counters); +} + +/* set test->i to the General Purpose Counter 0 value from the session's source + * address in the table pointed to by expr. + */ +static int +acl_fetch_src_get_gpc0(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + struct stktable_key *key; + + key = tcpv4_src_to_stktable_key(l4); + if (!key) + return 0; /* only TCPv4 is supported right now */ + + if (expr->arg_len) + px = find_stktable(expr->arg.str); + + if (!px) + return 0; /* table not found */ + + return acl_fetch_get_gpc0(&px->table, test, stktable_lookup_key(&px->table, key)); +} + +/* Increment the General Purpose Counter 0 value in the stksess entry and + * return it into test->i. + */ +static int +acl_fetch_inc_gpc0(struct stktable *table, struct acl_test *test, struct stksess *ts) +{ + test->flags = ACL_TEST_F_VOL_TEST; + test->i = 0; + if (ts != NULL) { + void *ptr = stktable_data_ptr(table, ts, STKTABLE_DT_GPC0); + if (!ptr) + return 0; /* parameter not stored */ + test->i = ++stktable_data_cast(ptr, gpc0); + } + return 1; +} + +/* Increment the General Purpose Counter 0 value from the session's tracked + * counters and return it into test->i. + */ +static int +acl_fetch_trk_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + if (!l4->tracked_counters) + return 0; + return acl_fetch_inc_gpc0(l4->tracked_table, test, l4->tracked_counters); +} + +/* Increment the General Purpose Counter 0 value from the session's source + * address in the table pointed to by expr, and return it into test->i. + */ +static int +acl_fetch_src_inc_gpc0(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + struct stktable_key *key; + + key = tcpv4_src_to_stktable_key(l4); + if (!key) + return 0; /* only TCPv4 is supported right now */ + + if (expr->arg_len) + px = find_stktable(expr->arg.str); + + if (!px) + return 0; /* table not found */ + + return acl_fetch_inc_gpc0(&px->table, test, stktable_update_key(&px->table, key)); +} + /* set test->i to the cumulated number of connections in the stksess entry */ static int acl_fetch_conn_cnt(struct stktable *table, struct acl_test *test, struct stksess *ts) @@ -2594,6 +2694,10 @@ acl_fetch_src_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, int /* Note: must not be declared as its list will be overwritten */ static struct acl_kw_list acl_kws = {{ },{ + { "trk_get_gpc0", acl_parse_int, acl_fetch_trk_get_gpc0, acl_match_int, ACL_USE_NOTHING }, + { "src_get_gpc0", acl_parse_int, acl_fetch_src_get_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE }, + { "trk_inc_gpc0", acl_parse_int, acl_fetch_trk_inc_gpc0, acl_match_int, ACL_USE_NOTHING }, + { "src_inc_gpc0", acl_parse_int, acl_fetch_src_inc_gpc0, acl_match_int, ACL_USE_TCP4_VOLATILE }, { "trk_conn_cnt", acl_parse_int, acl_fetch_trk_conn_cnt, acl_match_int, ACL_USE_NOTHING }, { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE }, { "trk_conn_rate", acl_parse_int, acl_fetch_trk_conn_rate, acl_match_int, ACL_USE_NOTHING }, diff --git a/src/stick_table.c b/src/stick_table.c index 471424a83..8b216aede 100644 --- a/src/stick_table.c +++ b/src/stick_table.c @@ -546,6 +546,7 @@ int stktable_compatible_pattern(struct pattern_expr *expr, unsigned long table_t /* Extra data types processing */ struct stktable_data_type stktable_data_types[STKTABLE_DATA_TYPES] = { [STKTABLE_DT_SERVER_ID] = { .name = "server_id", .data_length = stktable_data_size(server_id) }, + [STKTABLE_DT_GPC0] = { .name = "gpc0", .data_length = stktable_data_size(gpc0) }, [STKTABLE_DT_CONN_CNT] = { .name = "conn_cnt", .data_length = stktable_data_size(conn_cnt) }, [STKTABLE_DT_CONN_RATE] = { .name = "conn_rate", .data_length = stktable_data_size(conn_rate), .arg_type = ARG_T_DELAY }, [STKTABLE_DT_CONN_CUR] = { .name = "conn_cur", .data_length = stktable_data_size(conn_cur) },