]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CLEANUP: session: use an array for the stick counters
authorWilly Tarreau <w@1wt.eu>
Sun, 9 Dec 2012 14:55:40 +0000 (15:55 +0100)
committerWilly Tarreau <w@1wt.eu>
Sun, 9 Dec 2012 14:57:16 +0000 (15:57 +0100)
The stick counters were in two distinct sets of struct members,
causing some code to be duplicated. Now we use an array, which
enables some processing to be performed in loops. This allowed
the code to be shrunk by 700 bytes.

include/proto/session.h
include/types/session.h
src/peers.c
src/proto_tcp.c
src/session.c

index 3a1c985a5f4a4f946b229d9dd2c15f4dfa958d62..3b6e1fcbe1a0482fa54ba2aeac35fdc053de0727 100644 (file)
@@ -57,23 +57,17 @@ int parse_track_counters(char **args, int *arg,
 static inline void session_store_counters(struct session *s)
 {
        void *ptr;
+       int i;
 
-       if (s->stkctr2_entry) {
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_CONN_CUR);
+       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+               if (!s->stkctr[i].entry)
+                       continue;
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_CONN_CUR);
                if (ptr)
                        stktable_data_cast(ptr, conn_cur)--;
-               s->stkctr2_entry->ref_cnt--;
-               stksess_kill_if_expired(s->stkctr2_table, s->stkctr2_entry);
-               s->stkctr2_entry = NULL;
-       }
-
-       if (s->stkctr1_entry) {
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_CONN_CUR);
-               if (ptr)
-                       stktable_data_cast(ptr, conn_cur)--;
-               s->stkctr1_entry->ref_cnt--;
-               stksess_kill_if_expired(s->stkctr1_table, s->stkctr1_entry);
-               s->stkctr1_entry = NULL;
+               s->stkctr[i].entry->ref_cnt--;
+               stksess_kill_if_expired(s->stkctr[i].table, s->stkctr[i].entry);
+               s->stkctr[i].entry = NULL;
        }
 }
 
@@ -84,26 +78,27 @@ static inline void session_store_counters(struct session *s)
 static inline void session_stop_backend_counters(struct session *s)
 {
        void *ptr;
+       int i;
 
        if (!(s->flags & (SN_BE_TRACK_SC1|SN_BE_TRACK_SC2)))
                return;
 
-       if ((s->flags & SN_BE_TRACK_SC1) && s->stkctr1_entry) {
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_CONN_CUR);
-               if (ptr)
-                       stktable_data_cast(ptr, conn_cur)--;
-               s->stkctr1_entry->ref_cnt--;
-               stksess_kill_if_expired(s->stkctr1_table, s->stkctr1_entry);
-               s->stkctr1_entry = NULL;
-       }
+       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+               if (!s->stkctr[i].entry)
+                       continue;
+
+               if ((i == 0) && !(s->flags & SN_BE_TRACK_SC1))
+                       continue;
 
-       if ((s->flags & SN_BE_TRACK_SC2) && s->stkctr2_entry) {
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_CONN_CUR);
+               if ((i == 1) && !(s->flags & SN_BE_TRACK_SC2))
+                       continue;
+
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_CONN_CUR);
                if (ptr)
                        stktable_data_cast(ptr, conn_cur)--;
-               s->stkctr2_entry->ref_cnt--;
-               stksess_kill_if_expired(s->stkctr2_table, s->stkctr2_entry);
-               s->stkctr2_entry = NULL;
+               s->stkctr[i].entry->ref_cnt--;
+               stksess_kill_if_expired(s->stkctr[i].table, s->stkctr[i].entry);
+               s->stkctr[i].entry = NULL;
        }
        s->flags &= ~(SN_BE_TRACK_SC1|SN_BE_TRACK_SC2);
 }
@@ -132,33 +127,18 @@ static inline void session_start_counters(struct stktable *t, struct stksess *ts
                ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire));
 }
 
-/* Enable tracking of session counters as stkctr1 on stksess <ts>. The caller is
- * responsible for ensuring that <t> and <ts> are valid pointers. Some controls
- * are performed to ensure the state can still change.
- */
-static inline void session_track_stkctr1(struct session *s, struct stktable *t, struct stksess *ts)
-{
-       if (s->stkctr1_entry)
-               return;
-
-       ts->ref_cnt++;
-       s->stkctr1_table = t;
-       s->stkctr1_entry = ts;
-       session_start_counters(t, ts);
-}
-
-/* Enable tracking of session counters as stkctr1 on stksess <ts>. The caller is
+/* Enable tracking of session counters as <stkctr> on stksess <ts>. The caller is
  * responsible for ensuring that <t> and <ts> are valid pointers. Some controls
  * are performed to ensure the state can still change.
  */
-static inline void session_track_stkctr2(struct session *s, struct stktable *t, struct stksess *ts)
+static inline void session_track_stkctr(struct stkctr *ctr, struct stktable *t, struct stksess *ts)
 {
-       if (s->stkctr2_entry)
+       if (ctr->entry)
                return;
 
        ts->ref_cnt++;
-       s->stkctr2_table = t;
-       s->stkctr2_entry = ts;
+       ctr->table = t;
+       ctr->entry = ts;
        session_start_counters(t, ts);
 }
 
@@ -166,27 +146,20 @@ static inline void session_track_stkctr2(struct session *s, struct stktable *t,
 static void inline session_inc_http_req_ctr(struct session *s)
 {
        void *ptr;
+       int i;
 
-       if (s->stkctr2_entry) {
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_HTTP_REQ_CNT);
-               if (ptr)
-                       stktable_data_cast(ptr, http_req_cnt)++;
+       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+               if (!s->stkctr[i].entry)
+                       continue;
 
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_HTTP_REQ_RATE);
-               if (ptr)
-                       update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
-                                              s->stkctr2_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
-       }
-
-       if (s->stkctr1_entry) {
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_HTTP_REQ_CNT);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_HTTP_REQ_CNT);
                if (ptr)
                        stktable_data_cast(ptr, http_req_cnt)++;
 
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_HTTP_REQ_RATE);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_HTTP_REQ_RATE);
                if (ptr)
                        update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
-                                              s->stkctr1_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
+                                              s->stkctr[i].table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
        }
 }
 
@@ -194,30 +167,29 @@ static void inline session_inc_http_req_ctr(struct session *s)
 static void inline session_inc_be_http_req_ctr(struct session *s)
 {
        void *ptr;
+       int i;
 
        if (likely(!(s->flags & (SN_BE_TRACK_SC1|SN_BE_TRACK_SC2))))
                return;
 
-       if ((s->flags & SN_BE_TRACK_SC2) && s->stkctr2_entry) {
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_HTTP_REQ_CNT);
-               if (ptr)
-                       stktable_data_cast(ptr, http_req_cnt)++;
+       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+               if (!s->stkctr[i].entry)
+                       continue;
 
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_HTTP_REQ_RATE);
-               if (ptr)
-                       update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
-                                              s->stkctr2_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
-       }
+               if ((i == 0) && !(s->flags & SN_BE_TRACK_SC1))
+                       continue;
+
+               if ((i == 1) && !(s->flags & SN_BE_TRACK_SC2))
+                       continue;
 
-       if ((s->flags & SN_BE_TRACK_SC1) && s->stkctr1_entry) {
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_HTTP_REQ_CNT);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_HTTP_REQ_CNT);
                if (ptr)
                        stktable_data_cast(ptr, http_req_cnt)++;
 
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_HTTP_REQ_RATE);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_HTTP_REQ_RATE);
                if (ptr)
                        update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
-                                              s->stkctr1_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
+                                              s->stkctr[i].table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
        }
 }
 
@@ -230,27 +202,20 @@ static void inline session_inc_be_http_req_ctr(struct session *s)
 static void inline session_inc_http_err_ctr(struct session *s)
 {
        void *ptr;
+       int i;
 
-       if (s->stkctr2_entry) {
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_HTTP_ERR_CNT);
-               if (ptr)
-                       stktable_data_cast(ptr, http_err_cnt)++;
-
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_HTTP_ERR_RATE);
-               if (ptr)
-                       update_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
-                                              s->stkctr2_table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
-       }
+       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+               if (!s->stkctr[i].entry)
+                       continue;
 
-       if (s->stkctr1_entry) {
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_HTTP_ERR_CNT);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_HTTP_ERR_CNT);
                if (ptr)
                        stktable_data_cast(ptr, http_err_cnt)++;
 
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_HTTP_ERR_RATE);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_HTTP_ERR_RATE);
                if (ptr)
                        update_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
-                                              s->stkctr1_table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
+                                              s->stkctr[i].table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
        }
 }
 
index 4688dbf074c21d39a4d74851a3ebf152d89ffec0..7b521824345c8f9880b0585f81a1b4676f4ba472 100644 (file)
  * and freed in session_free() !
  */
 
+/* stick counter */
+struct stkctr {
+       struct stksess *entry;          /* entry containing counters currently being tracked  by this session */
+       struct stktable *table;         /* table the counters above belong to (undefined if counters are null) */
+};
+
 /*
  * Note: some session flags have dependencies :
  *  - SN_DIRECT cannot exist without SN_ASSIGNED, because a server is
@@ -135,10 +141,7 @@ struct session {
        } store[8];                             /* tracked stickiness values to store */
        int store_count;
 
-       struct stksess *stkctr1_entry;          /* entry containing counters currently being tracked as set 1 by this session */
-       struct stktable *stkctr1_table;         /* table the counters above belong to (undefined if counters are null) */
-       struct stksess *stkctr2_entry;          /* entry containing counters currently being tracked as set 2 by this session */
-       struct stktable *stkctr2_table;         /* table the counters above belong to (undefined if counters are null) */
+       struct stkctr stkctr[2];                /* stick counters */
 
        struct stream_interface si[2];          /* client and server stream interfaces */
        struct {
index 688d64cf9f9f3a8f6c6d3cc2af140cabe2857993..789fa8c57f4ac485483764083f1111b537687c37 100644 (file)
@@ -1196,8 +1196,8 @@ static struct session *peer_session_create(struct peer *peer, struct peer_sessio
 
        /* init store persistence */
        s->store_count = 0;
-       s->stkctr1_entry = NULL;
-       s->stkctr2_entry = NULL;
+       s->stkctr[0].entry = NULL;
+       s->stkctr[1].entry = NULL;
 
        /* FIXME: the logs are horribly complicated now, because they are
         * defined in <p>, <p>, and later <be> and <be>.
index de95d7f6ead012e42117a8d395bd8df2335efe37..12e92da1104872307e43449bb6b4eb43642b80e5 100644 (file)
@@ -836,8 +836,8 @@ int tcp_inspect_request(struct session *s, struct channel *req, int an_bit)
                                        s->flags |= SN_FINST_R;
                                return 0;
                        }
-                       else if ((rule->action == TCP_ACT_TRK_SC1 && !s->stkctr1_entry) ||
-                                (rule->action == TCP_ACT_TRK_SC2 && !s->stkctr2_entry)) {
+                       else if ((rule->action == TCP_ACT_TRK_SC1 && !s->stkctr[0].entry) ||
+                                (rule->action == TCP_ACT_TRK_SC2 && !s->stkctr[1].entry)) {
                                /* Note: only the first valid tracking parameter of each
                                 * applies.
                                 */
@@ -848,11 +848,11 @@ int tcp_inspect_request(struct session *s, struct channel *req, int an_bit)
 
                                if (key && (ts = stktable_get_entry(t, key))) {
                                        if (rule->action == TCP_ACT_TRK_SC1) {
-                                               session_track_stkctr1(s, t, ts);
+                                               session_track_stkctr(&s->stkctr[0], t, ts);
                                                if (s->fe != s->be)
                                                        s->flags |= SN_BE_TRACK_SC1;
                                        } else {
-                                               session_track_stkctr2(s, t, ts);
+                                               session_track_stkctr(&s->stkctr[1], t, ts);
                                                if (s->fe != s->be)
                                                        s->flags |= SN_BE_TRACK_SC2;
                                        }
@@ -996,8 +996,8 @@ int tcp_exec_req_rules(struct session *s)
                                result = 0;
                                break;
                        }
-                       else if ((rule->action == TCP_ACT_TRK_SC1 && !s->stkctr1_entry) ||
-                                (rule->action == TCP_ACT_TRK_SC2 && !s->stkctr2_entry)) {
+                       else if ((rule->action == TCP_ACT_TRK_SC1 && !s->stkctr[0].entry) ||
+                                (rule->action == TCP_ACT_TRK_SC2 && !s->stkctr[1].entry)) {
                                /* Note: only the first valid tracking parameter of each
                                 * applies.
                                 */
@@ -1008,9 +1008,9 @@ int tcp_exec_req_rules(struct session *s)
 
                                if (key && (ts = stktable_get_entry(t, key))) {
                                        if (rule->action == TCP_ACT_TRK_SC1)
-                                               session_track_stkctr1(s, t, ts);
+                                               session_track_stkctr(&s->stkctr[0], t, ts);
                                        else
-                                               session_track_stkctr2(s, t, ts);
+                                               session_track_stkctr(&s->stkctr[1], t, ts);
                                }
                        }
                        else {
index a4c53a16093db9bb0c5286b3e2c1f63bc27e58cc..7ef518d4b047edfa6c67d59c4d878a398e85ca40 100644 (file)
@@ -97,10 +97,10 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
         */
        s->flags = 0;
        s->logs.logwait = p->to_log;
-       s->stkctr1_entry = NULL;
-       s->stkctr2_entry = NULL;
-       s->stkctr1_table = NULL;
-       s->stkctr2_table = NULL;
+       s->stkctr[0].entry = NULL;
+       s->stkctr[1].entry = NULL;
+       s->stkctr[0].table = NULL;
+       s->stkctr[1].table = NULL;
 
        s->listener = l;
        s->fe  = p;
@@ -222,7 +222,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr)
        task_free(t);
  out_free_session:
        p->feconn--;
-       if (s->stkctr1_entry || s->stkctr2_entry)
+       if (s->stkctr[0].entry || s->stkctr[1].entry)
                session_store_counters(s);
        pool_free2(pool2_connection, s->si[1].conn);
  out_fail_conn1:
@@ -312,7 +312,7 @@ static void kill_mini_session(struct session *s)
        conn_full_close(s->si[0].conn);
 
        s->fe->feconn--;
-       if (s->stkctr1_entry || s->stkctr2_entry)
+       if (s->stkctr[0].entry || s->stkctr[1].entry)
                session_store_counters(s);
 
        if (!(s->listener->options & LI_O_UNLIMITED))
@@ -394,6 +394,7 @@ int session_complete(struct session *s)
        struct http_txn *txn;
        struct task *t = s->task;
        int ret;
+       int i;
 
        ret = -1; /* assume unrecoverable error by default */
 
@@ -419,30 +420,21 @@ int session_complete(struct session *s)
 
        /* Let's count a session now */
        proxy_inc_fe_sess_ctr(l, p);
-       if (s->stkctr1_entry) {
-               void *ptr;
-
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_CNT);
-               if (ptr)
-                       stktable_data_cast(ptr, sess_cnt)++;
 
-               ptr = stktable_data_ptr(s->stkctr1_table, s->stkctr1_entry, STKTABLE_DT_SESS_RATE);
-               if (ptr)
-                       update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
-                                              s->stkctr1_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
-       }
-
-       if (s->stkctr2_entry) {
+       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
                void *ptr;
 
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_CNT);
+               if (!s->stkctr[i].entry)
+                       continue;
+
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_SESS_CNT);
                if (ptr)
                        stktable_data_cast(ptr, sess_cnt)++;
 
-               ptr = stktable_data_ptr(s->stkctr2_table, s->stkctr2_entry, STKTABLE_DT_SESS_RATE);
+               ptr = stktable_data_ptr(s->stkctr[i].table, s->stkctr[i].entry, STKTABLE_DT_SESS_RATE);
                if (ptr)
                        update_freq_ctr_period(&stktable_data_cast(ptr, sess_rate),
-                                              s->stkctr2_table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
+                                              s->stkctr[i].table->data_arg[STKTABLE_DT_SESS_RATE].u, 1);
        }
 
        /* this part should be common with other protocols */
@@ -657,7 +649,7 @@ static void session_free(struct session *s)
                pool_free2(fe->req_cap_pool, txn->req.cap);
        }
 
-       if (s->stkctr1_entry || s->stkctr2_entry)
+       if (s->stkctr[0].entry || s->stkctr[1].entry)
                session_store_counters(s);
 
        list_for_each_entry_safe(bref, back, &s->back_refs, users) {
@@ -700,53 +692,39 @@ int init_session()
 void session_process_counters(struct session *s)
 {
        unsigned long long bytes;
+       void *ptr;
+       int i;
 
        if (s->req) {
                bytes = s->req->total - s->logs.bytes_in;
                s->logs.bytes_in = s->req->total;
                if (bytes) {
-                       s->fe->fe_counters.bytes_in                     += bytes;
+                       s->fe->fe_counters.bytes_in += bytes;
 
-                       s->be->be_counters.bytes_in                     += bytes;
+                       s->be->be_counters.bytes_in += bytes;
 
                        if (objt_server(s->target))
-                               objt_server(s->target)->counters.bytes_in               += bytes;
+                               objt_server(s->target)->counters.bytes_in += bytes;
 
                        if (s->listener->counters)
-                               s->listener->counters->bytes_in         += bytes;
+                               s->listener->counters->bytes_in += bytes;
 
-                       if (s->stkctr2_entry) {
-                               void *ptr;
+                       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+                               if (!s->stkctr[i].entry)
+                                       continue;
 
-                               ptr = stktable_data_ptr(s->stkctr2_table,
-                                                       s->stkctr2_entry,
-                                                       STKTABLE_DT_BYTES_IN_CNT);
+                               ptr = stktable_data_ptr(s->stkctr[i].table,
+                                                       s->stkctr[i].entry,
+                                                       STKTABLE_DT_BYTES_IN_CNT);
                                if (ptr)
                                        stktable_data_cast(ptr, bytes_in_cnt) += bytes;
 
-                               ptr = stktable_data_ptr(s->stkctr2_table,
-                                                       s->stkctr2_entry,
-                                                       STKTABLE_DT_BYTES_IN_RATE);
+                               ptr = stktable_data_ptr(s->stkctr[i].table,
+                                                       s->stkctr[i].entry,
+                                                       STKTABLE_DT_BYTES_IN_RATE);
                                if (ptr)
                                        update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
-                                                              s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
-                       }
-
-                       if (s->stkctr1_entry) {
-                               void *ptr;
-
-                               ptr = stktable_data_ptr(s->stkctr1_table,
-                                                       s->stkctr1_entry,
-                                                       STKTABLE_DT_BYTES_IN_CNT);
-                               if (ptr)
-                                       stktable_data_cast(ptr, bytes_in_cnt) += bytes;
-
-                               ptr = stktable_data_ptr(s->stkctr1_table,
-                                                       s->stkctr1_entry,
-                                                       STKTABLE_DT_BYTES_IN_RATE);
-                               if (ptr)
-                                       update_freq_ctr_period(&stktable_data_cast(ptr, bytes_in_rate),
-                                                              s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
+                                                              s->stkctr[i].table->data_arg[STKTABLE_DT_BYTES_IN_RATE].u, bytes);
                        }
                }
        }
@@ -755,48 +733,32 @@ void session_process_counters(struct session *s)
                bytes = s->rep->total - s->logs.bytes_out;
                s->logs.bytes_out = s->rep->total;
                if (bytes) {
-                       s->fe->fe_counters.bytes_out                    += bytes;
+                       s->fe->fe_counters.bytes_out += bytes;
 
-                       s->be->be_counters.bytes_out                    += bytes;
+                       s->be->be_counters.bytes_out += bytes;
 
                        if (objt_server(s->target))
-                               objt_server(s->target)->counters.bytes_out              += bytes;
+                               objt_server(s->target)->counters.bytes_out += bytes;
 
                        if (s->listener->counters)
-                               s->listener->counters->bytes_out        += bytes;
-
-                       if (s->stkctr2_entry) {
-                               void *ptr;
-
-                               ptr = stktable_data_ptr(s->stkctr2_table,
-                                                       s->stkctr2_entry,
-                                                       STKTABLE_DT_BYTES_OUT_CNT);
-                               if (ptr)
-                                       stktable_data_cast(ptr, bytes_out_cnt) += bytes;
-
-                               ptr = stktable_data_ptr(s->stkctr2_table,
-                                                       s->stkctr2_entry,
-                                                       STKTABLE_DT_BYTES_OUT_RATE);
-                               if (ptr)
-                                       update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
-                                                              s->stkctr2_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
-                       }
+                               s->listener->counters->bytes_out += bytes;
 
-                       if (s->stkctr1_entry) {
-                               void *ptr;
+                       for (i = 0; i < sizeof(s->stkctr) / sizeof(s->stkctr[0]); i++) {
+                               if (!s->stkctr[i].entry)
+                                       continue;
 
-                               ptr = stktable_data_ptr(s->stkctr1_table,
-                                                       s->stkctr1_entry,
-                                                       STKTABLE_DT_BYTES_OUT_CNT);
+                               ptr = stktable_data_ptr(s->stkctr[i].table,
+                                                       s->stkctr[i].entry,
+                                                       STKTABLE_DT_BYTES_OUT_CNT);
                                if (ptr)
                                        stktable_data_cast(ptr, bytes_out_cnt) += bytes;
 
-                               ptr = stktable_data_ptr(s->stkctr1_table,
-                                                       s->stkctr1_entry,
-                                                       STKTABLE_DT_BYTES_OUT_RATE);
+                               ptr = stktable_data_ptr(s->stkctr[i].table,
+                                                       s->stkctr[i].entry,
+                                                       STKTABLE_DT_BYTES_OUT_RATE);
                                if (ptr)
                                        update_freq_ctr_period(&stktable_data_cast(ptr, bytes_out_rate),
-                                                              s->stkctr1_table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
+                                                              s->stkctr[i].table->data_arg[STKTABLE_DT_BYTES_OUT_RATE].u, bytes);
                        }
                }
        }
@@ -2636,9 +2598,9 @@ static int
 acl_fetch_sc1_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
-       return acl_fetch_get_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_get_gpc0(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the General Purpose Counter 0 value from the session's tracked
@@ -2648,9 +2610,9 @@ static int
 acl_fetch_sc2_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
-       return acl_fetch_get_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_get_gpc0(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the General Purpose Counter 0 value from the session's source
@@ -2696,9 +2658,9 @@ static int
 acl_fetch_sc1_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
-       return acl_fetch_inc_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_inc_gpc0(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* Increment the General Purpose Counter 0 value from the session's tracked
@@ -2708,9 +2670,9 @@ static int
 acl_fetch_sc2_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
-       return acl_fetch_inc_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_inc_gpc0(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* Increment the General Purpose Counter 0 value from the session's source
@@ -2757,9 +2719,9 @@ static int
 acl_fetch_sc1_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
-       return acl_fetch_clr_gpc0(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_clr_gpc0(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* Clear the General Purpose Counter 0 value from the session's tracked
@@ -2769,9 +2731,9 @@ static int
 acl_fetch_sc2_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
-       return acl_fetch_clr_gpc0(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_clr_gpc0(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* Clear the General Purpose Counter 0 value from the session's source address
@@ -2813,10 +2775,10 @@ static int
 acl_fetch_sc1_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_conn_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_conn_cnt(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the cumulated number of connections from the session's tracked BE counters */
@@ -2824,10 +2786,10 @@ static int
 acl_fetch_sc2_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_conn_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_conn_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the cumulated number of connections from the session's source
@@ -2872,10 +2834,10 @@ static int
 acl_fetch_sc1_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_conn_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_conn_rate(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the connection rate from the session's tracked BE counters over
@@ -2885,10 +2847,10 @@ static int
 acl_fetch_sc2_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_conn_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_conn_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the connection rate from the session's source address in the
@@ -2963,10 +2925,10 @@ static int
 acl_fetch_sc1_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_conn_cur(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_conn_cur(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the number of concurrent connections from the session's tracked BE counters */
@@ -2974,10 +2936,10 @@ static int
 acl_fetch_sc2_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_conn_cur(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_conn_cur(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the number of concurrent connections from the session's source
@@ -3019,10 +2981,10 @@ static int
 acl_fetch_sc1_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_sess_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_sess_cnt(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
@@ -3030,10 +2992,10 @@ static int
 acl_fetch_sc2_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_sess_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_sess_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the cumulated number of session from the session's source
@@ -3078,10 +3040,10 @@ static int
 acl_fetch_sc1_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_sess_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_sess_rate(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the session rate from the session's tracked BE counters over
@@ -3091,10 +3053,10 @@ static int
 acl_fetch_sc2_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_sess_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_sess_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the session rate from the session's source address in the
@@ -3136,10 +3098,10 @@ static int
 acl_fetch_sc1_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                            const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_http_req_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_http_req_cnt(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
@@ -3147,10 +3109,10 @@ static int
 acl_fetch_sc2_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                            const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_http_req_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_http_req_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the cumulated number of session from the session's source
@@ -3195,10 +3157,10 @@ static int
 acl_fetch_sc1_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                             const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_http_req_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_http_req_rate(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the session rate from the session's tracked BE counters over
@@ -3208,10 +3170,10 @@ static int
 acl_fetch_sc2_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                             const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_http_req_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_http_req_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the session rate from the session's source address in the
@@ -3253,10 +3215,10 @@ static int
 acl_fetch_sc1_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                            const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_http_err_cnt(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_http_err_cnt(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
@@ -3264,10 +3226,10 @@ static int
 acl_fetch_sc2_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                            const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_http_err_cnt(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_http_err_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the cumulated number of session from the session's source
@@ -3312,10 +3274,10 @@ static int
 acl_fetch_sc1_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                             const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_http_err_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_http_err_rate(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the session rate from the session's tracked BE counters over
@@ -3325,10 +3287,10 @@ static int
 acl_fetch_sc2_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                             const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_http_err_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_http_err_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the session rate from the session's source address in the
@@ -3373,10 +3335,10 @@ static int
 acl_fetch_sc1_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_kbytes_in(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_kbytes_in(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the number of kbytes received from clients according to the
@@ -3386,10 +3348,10 @@ static int
 acl_fetch_sc2_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                         const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_kbytes_in(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_kbytes_in(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the number of kbytes received from the session's source
@@ -3436,10 +3398,10 @@ static int
 acl_fetch_sc1_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                             const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_bytes_in_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_bytes_in_rate(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the bytes rate from clients from the session's tracked BE
@@ -3449,10 +3411,10 @@ static int
 acl_fetch_sc2_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                             const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_bytes_in_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_bytes_in_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the bytes rate from clients from the session's source address
@@ -3497,10 +3459,10 @@ static int
 acl_fetch_sc1_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                          const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_kbytes_out(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_kbytes_out(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the number of kbytes sent to clients according to the session's
@@ -3510,10 +3472,10 @@ static int
 acl_fetch_sc2_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                          const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_kbytes_out(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_kbytes_out(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the number of kbytes sent to the session's source address in
@@ -3560,10 +3522,10 @@ static int
 acl_fetch_sc1_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                              const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return acl_fetch_bytes_out_rate(l4->stkctr1_table, smp, l4->stkctr1_entry);
+       return acl_fetch_bytes_out_rate(l4->stkctr[0].table, smp, l4->stkctr[0].entry);
 }
 
 /* set temp integer to the bytes rate to clients from the session's tracked BE counters
@@ -3573,10 +3535,10 @@ static int
 acl_fetch_sc2_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                              const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return acl_fetch_bytes_out_rate(l4->stkctr2_table, smp, l4->stkctr2_entry);
+       return acl_fetch_bytes_out_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
 /* set temp integer to the bytes rate to client from the session's source address in
@@ -3602,10 +3564,10 @@ static int
 acl_fetch_sc1_trackers(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr1_entry)
+       if (!l4->stkctr[0].entry)
                return 0;
 
-       return l4->stkctr1_entry->ref_cnt;
+       return l4->stkctr[0].entry->ref_cnt;
 }
 
 /* set temp integer to the number of active trackers on the SC1 entry */
@@ -3613,10 +3575,10 @@ static int
 acl_fetch_sc2_trackers(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
                        const struct arg *args, struct sample *smp)
 {
-       if (!l4->stkctr2_entry)
+       if (!l4->stkctr[1].entry)
                return 0;
 
-       return l4->stkctr2_entry->ref_cnt;
+       return l4->stkctr[1].entry->ref_cnt;
 }
 
 /* set temp integer to the number of used entries in the table pointed to by expr.