]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] session: add concurrent connections counter
authorWilly Tarreau <w@1wt.eu>
Fri, 18 Jun 2010 14:35:43 +0000 (16:35 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 10 Aug 2010 16:04:12 +0000 (18:04 +0200)
The new "conn_cur" session counter has been added. It is automatically
updated upon "track XXX" directives, and the entry is touched at the
moment we increment the value so that we don't consider further counter
updates as real updates, otherwise we would end up updating upon completion,
which may not be desired. Probably that some other event counters (eg: HTTP
requests) will have to be updated upon each event though.

This counter can be matched against current session's source address using
the "src_conn_cur" ACL.

include/proto/session.h
include/types/stick_table.h
src/session.c
src/stick_table.c

index 3d56f8e030ed324adb65ef3817eccf1a31920ffc..0f218bb35836cdcad3a21401716df91bea2281c9 100644 (file)
@@ -52,6 +52,11 @@ int parse_track_counters(char **args, int *arg,
  */
 static inline void session_store_counters(struct session *s)
 {
+       if (s->tracked_counters) {
+               void *ptr = stktable_data_ptr(s->tracked_table, s->tracked_counters, STKTABLE_DT_CONN_CUR);
+               if (ptr)
+                       stktable_data_cast(ptr, conn_cur)--;
+       }
        s->tracked_counters->ref_cnt--;
        s->tracked_counters = NULL;
 }
@@ -65,6 +70,13 @@ static inline void session_track_counters(struct session *s, struct stktable *t,
        ts->ref_cnt++;
        s->tracked_table = t;
        s->tracked_counters = ts;
+       if (ts) {
+               void *ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CUR);
+               if (ptr)
+                       stktable_data_cast(ptr, conn_cur)++;
+               if (tick_isset(t->expire))
+                       ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire));
+       }
 }
 
 static void inline trace_term(struct session *s, unsigned int code)
index 071f74a5b2748181bf2a02e89defd62ccc5ee2ca..ca26f766fff324260571d825395e318b4bf9f572 100644 (file)
@@ -43,13 +43,15 @@ enum {
 enum {
        STKTABLE_DT_SERVER_ID,    /* the server ID to use with this session if > 0 */
        STKTABLE_DT_CONN_CNT,     /* cumulated number of connections */
+       STKTABLE_DT_CONN_CUR,     /* concurrent number of connections */
        STKTABLE_DATA_TYPES       /* Number of data types, must always be last */
 };
 
 /* stick_table extra data. This is mainly used for casting or size computation */
 union stktable_data {
-       unsigned int conn_cnt;
        int server_id;
+       unsigned int conn_cnt;
+       unsigned int conn_cur;
 };
 
 /* known data types */
index 9d583b5f05f101f70db88648b0905f9bc43e08af..6cb702dd1fa2fc70a768e0817e466cba56fc21e6 100644 (file)
@@ -2127,11 +2127,45 @@ acl_fetch_src_updt_conn_cnt(struct proxy *px, struct session *l4, void *l7, int
        return 1;
 }
 
+/* set test->i to the number of concurrent connections from the session's source
+ * address in the table pointed to by expr.
+ */
+static int
+acl_fetch_src_conn_cur(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_CUR);
+               if (!ptr)
+                       return 0; /* parameter not stored */
+               test->i = stktable_data_cast(ptr, conn_cur);
+       }
+
+       return 1;
+}
+
 
 /* Note: must not be declared <const> 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 },
+       { "src_conn_cur",       acl_parse_int,   acl_fetch_src_conn_cur,      acl_match_int, ACL_USE_TCP4_VOLATILE },
        { NULL, NULL, NULL, NULL },
 }};
 
index 9709b7381570e631042588dfb7429062c68c3259..4335b3639c516ad27c2978fdbb5208c498dc53cf 100644 (file)
@@ -525,8 +525,9 @@ 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_CONN_CNT]  = { .name = "conn_cnt", .data_length = stktable_data_size(conn_cnt) },
        [STKTABLE_DT_SERVER_ID] = { .name = "server_id", .data_length = stktable_data_size(server_id) },
+       [STKTABLE_DT_CONN_CNT]  = { .name = "conn_cnt",  .data_length = stktable_data_size(conn_cnt)  },
+       [STKTABLE_DT_CONN_CUR]  = { .name = "conn_cur",  .data_length = stktable_data_size(conn_cur)  },
 };
 
 /*