From: Willy Tarreau Date: Fri, 18 Jun 2010 15:46:06 +0000 (+0200) Subject: [MEDIUM] session: move counter ACL fetches from proto_tcp X-Git-Tag: v1.5-dev8~525 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8b22a71a4d100847b14e325496d942d4e78fdc97;p=thirdparty%2Fhaproxy.git [MEDIUM] session: move counter ACL fetches from proto_tcp It was not normal to have counter fetches in proto_tcp.c. The only reason was that the key based on the source address was fetched there, but now we have split the key extraction and data processing, we must move that to a more appropriate place. Session seems OK since the counters are all manipulated from here. Also, since we're precisely counting number of connections with these ACLs, we rename them src_conn_cnt and src_updt_conn_cnt. This is not a problem right now since no version was emitted with these keywords. --- diff --git a/src/proto_tcp.c b/src/proto_tcp.c index 7adb0f9990..20fcd6aa7c 100644 --- a/src/proto_tcp.c +++ b/src/proto_tcp.c @@ -1034,84 +1034,6 @@ pattern_fetch_dport(struct proxy *px, struct session *l4, void *l7, int dir, return 1; } -/* set test->i to the number of connections from the session's source address - * in the table pointed to by expr. - */ -static int -acl_fetch_src_count(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - struct stksess *ts; - - /* right now we only support IPv4 */ - if (l4->cli_addr.ss_family != AF_INET) - return 0; - - if (expr->arg_len) { - /* another table was designated, we must look for it */ - for (px = proxy; px; px = px->next) - if (strcmp(px->id, expr->arg.str) == 0) - break; - } - if (!px) - return 0; /* table not found */ - - static_table_key.key = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr; - test->flags = ACL_TEST_F_VOL_TEST; - test->i = 0; - if ((ts = stktable_lookup_key(&px->table, &static_table_key)) != NULL) { - void *ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CUM); - if (!ptr) - return 0; /* parameter not stored */ - test->i = stktable_data_cast(ptr, conn_cum); - } - - return 1; -} - -/* set test->i to the number of connections from the session's source address - * in the table pointed to by expr, after updating it. - */ -static int -acl_fetch_src_update_count(struct proxy *px, struct session *l4, void *l7, int dir, - struct acl_expr *expr, struct acl_test *test) -{ - struct stksess *ts; - void *ptr; - - /* right now we only support IPv4 */ - if (l4->cli_addr.ss_family != AF_INET) - return 0; - - if (expr->arg_len) { - /* another table was designated, we must look for it */ - for (px = proxy; px; px = px->next) - if (strcmp(px->id, expr->arg.str) == 0) - break; - } - if (!px) - return 0; - - static_table_key.key = (void *)&((struct sockaddr_in *)&l4->frt_addr)->sin_addr; - if ((ts = stktable_lookup_key(&px->table, &static_table_key)) == NULL) { - /* entry does not exist, initialize a new one */ - ts = stksess_new(&px->table, &static_table_key); - if (!ts) - return 0; - stktable_store(&px->table, ts); - } - else - stktable_touch(&px->table, ts); - - ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CUM); - if (!ptr) - return 0; /* parameter not stored in this table */ - - test->i = ++stktable_data_cast(ptr, conn_cum); - test->flags = ACL_TEST_F_VOL_TEST; - return 1; -} - static struct cfg_kw_list cfg_kws = {{ },{ { CFG_LISTEN, "tcp-request", tcp_parse_tcp_req }, { 0, NULL, NULL }, @@ -1123,8 +1045,6 @@ static struct acl_kw_list acl_kws = {{ },{ { "src", acl_parse_ip, acl_fetch_src, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP }, { "dst", acl_parse_ip, acl_fetch_dst, acl_match_ip, ACL_USE_TCP4_PERMANENT|ACL_MAY_LOOKUP }, { "dst_port", acl_parse_int, acl_fetch_dport, acl_match_int, ACL_USE_TCP_PERMANENT }, - { "src_count", acl_parse_int, acl_fetch_src_count,acl_match_int, ACL_USE_TCP4_VOLATILE }, - { "src_update_count", acl_parse_int, acl_fetch_src_update_count, acl_match_int, ACL_USE_TCP4_VOLATILE }, { NULL, NULL, NULL, NULL }, }}; diff --git a/src/session.c b/src/session.c index 4e2bedd652..9d583b5f05 100644 --- a/src/session.c +++ b/src/session.c @@ -2051,6 +2051,91 @@ void default_srv_error(struct session *s, struct stream_interface *si) } +/************************************************************************/ +/* All supported ACL keywords must be declared here. */ +/************************************************************************/ + +/* set test->i to the number of connections from the session's source address + * in the table pointed to by expr. + */ +static int +acl_fetch_src_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + struct stksess *ts; + 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 */ + + test->flags = ACL_TEST_F_VOL_TEST; + test->i = 0; + if ((ts = stktable_lookup_key(&px->table, key)) != NULL) { + void *ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT); + if (!ptr) + return 0; /* parameter not stored */ + test->i = stktable_data_cast(ptr, conn_cnt); + } + + return 1; +} + +/* set test->i to the number of connections from the session's source address + * in the table pointed to by expr, after updating it. + */ +static int +acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int dir, + struct acl_expr *expr, struct acl_test *test) +{ + struct stksess *ts; + struct stktable_key *key; + void *ptr; + + 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 */ + + if ((ts = stktable_lookup_key(&px->table, key)) == NULL) { + /* entry does not exist, initialize a new one */ + ts = stksess_new(&px->table, key); + if (!ts) + return 0; + stktable_store(&px->table, ts); + } + else + stktable_touch(&px->table, ts); + + ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT); + if (!ptr) + return 0; /* parameter not stored in this table */ + + test->i = ++stktable_data_cast(ptr, conn_cnt); + test->flags = ACL_TEST_F_VOL_TEST; + return 1; +} + + +/* Note: must not be declared as its list will be overwritten */ +static struct acl_kw_list acl_kws = {{ },{ + { "src_conn_cnt", acl_parse_int, acl_fetch_src_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE }, + { "src_updt_conn_cnt", acl_parse_int, acl_fetch_src_updt_conn_cnt, acl_match_int, ACL_USE_TCP4_VOLATILE }, + { NULL, NULL, NULL, NULL }, +}}; + + /* Parse a "track-counters" line starting with "track-counters" in args[arg-1]. * Returns the number of warnings emitted, or -1 in case of fatal errors. The * struct is fed with the table name if any. If unspecified, the caller @@ -2100,6 +2185,12 @@ int parse_track_counters(char **args, int *arg, return 0; } +__attribute__((constructor)) +static void __session_init(void) +{ + acl_register_keywords(&acl_kws); +} + /* * Local variables: * c-indent-level: 8