[MAJOR] session-counters: split FE and BE track counters

Having a single tracking pointer for both frontend and backend counters
does not work. Instead let's have one for each. The keyword has changed
to "track-be-counters" and "track-fe-counters", and the ACL "trk_*"
changed to "trkfe_*" and "trkbe_*".
diff --git a/include/proto/session.h b/include/proto/session.h
index a5dd881..0959320 100644
--- a/include/proto/session.h
+++ b/include/proto/session.h
@@ -53,45 +53,97 @@
  */
 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);
+	void *ptr;
+
+	if (s->be_tracked_counters) {
+		ptr = stktable_data_ptr(s->be_tracked_table, s->be_tracked_counters, STKTABLE_DT_CONN_CUR);
+		if (ptr)
+			stktable_data_cast(ptr, conn_cur)--;
+		s->be_tracked_counters->ref_cnt--;
+		s->be_tracked_counters = NULL;
+	}
+
+	if (s->fe_tracked_counters) {
+		ptr = stktable_data_ptr(s->fe_tracked_table, s->fe_tracked_counters, STKTABLE_DT_CONN_CUR);
 		if (ptr)
 			stktable_data_cast(ptr, conn_cur)--;
+		s->fe_tracked_counters->ref_cnt--;
+		s->fe_tracked_counters = NULL;
 	}
-	s->tracked_counters->ref_cnt--;
-	s->tracked_counters = NULL;
 }
 
-/* Enable tracking of session counters on stksess <ts>. The caller is
- * responsible for ensuring that <t> and <ts> are valid pointers and that no
- * previous tracked_counters was assigned to the session.
+/* Remove the refcount from the session counters tracked only by the backend if
+ * any, and clear the pointer to ensure this is only performed once. The caller
+ * is responsible for ensuring that the pointer is valid first.
  */
-static inline void session_track_counters(struct session *s, struct stktable *t, struct stksess *ts)
+static inline void session_stop_backend_counters(struct session *s)
 {
-	ts->ref_cnt++;
-	s->tracked_table = t;
-	s->tracked_counters = ts;
-	if (ts) {
-		void *ptr;
+	void *ptr;
 
-		ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CUR);
-		if (ptr)
-			stktable_data_cast(ptr, conn_cur)++;
+	if (!s->be_tracked_counters)
+		return;
 
-		ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CNT);
-		if (ptr)
-			stktable_data_cast(ptr, conn_cnt)++;
+	ptr = stktable_data_ptr(s->be_tracked_table, s->be_tracked_counters, STKTABLE_DT_CONN_CUR);
+	if (ptr)
+		stktable_data_cast(ptr, conn_cur)--;
+	s->be_tracked_counters->ref_cnt--;
+	s->be_tracked_counters = NULL;
+}
 
-		ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_RATE);
-		if (ptr)
-			update_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
-					       t->data_arg[STKTABLE_DT_CONN_RATE].u, 1);
+/* Increase total and concurrent connection count for stick entry <ts> of table
+ * <t>. The caller is responsible for ensuring that <t> and <ts> are valid
+ * pointers, and for calling this only once per connection.
+ */
+static inline void session_start_counters(struct stktable *t, struct stksess *ts)
+{
+	void *ptr;
 
-		if (tick_isset(t->expire))
-			ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire));
-	}
+	ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CUR);
+	if (ptr)
+		stktable_data_cast(ptr, conn_cur)++;
+
+	ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CNT);
+	if (ptr)
+		stktable_data_cast(ptr, conn_cnt)++;
+
+	ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_RATE);
+	if (ptr)
+		update_freq_ctr_period(&stktable_data_cast(ptr, conn_rate),
+				       t->data_arg[STKTABLE_DT_CONN_RATE].u, 1);
+	if (tick_isset(t->expire))
+		ts->expire = tick_add(now_ms, MS_TO_TICKS(t->expire));
+}
+
+/* Enable frontend tracking of session counters 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_fe_counters(struct session *s, struct stktable *t, struct stksess *ts)
+{
+	if (s->fe_tracked_counters)
+		return;
+
+	ts->ref_cnt++;
+	s->fe_tracked_table = t;
+	s->fe_tracked_counters = ts;
+	session_start_counters(t, ts);
 }
 
+/* Enable backend tracking of session counters 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_be_counters(struct session *s, struct stktable *t, struct stksess *ts)
+{
+	if (s->be_tracked_counters)
+		return;
+
+	ts->ref_cnt++;
+	s->be_tracked_table = t;
+	s->be_tracked_counters = ts;
+	session_start_counters(t, ts);
+}
+
 static void inline trace_term(struct session *s, unsigned int code)
 {
 	s->term_trace <<= TT_BIT_SHIFT;
@@ -101,17 +153,28 @@
 /* Increase the number of cumulated HTTP requests in the tracked counters */
 static void inline session_inc_http_req_ctr(struct session *s)
 {
-	if (s->tracked_counters) {
-		void *ptr;
+	void *ptr;
+
+	if (s->be_tracked_counters) {
+		ptr = stktable_data_ptr(s->be_tracked_table, s->be_tracked_counters, STKTABLE_DT_HTTP_REQ_CNT);
+		if (ptr)
+			stktable_data_cast(ptr, http_req_cnt)++;
+
+		ptr = stktable_data_ptr(s->be_tracked_table, s->be_tracked_counters, STKTABLE_DT_HTTP_REQ_RATE);
+		if (ptr)
+			update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
+					       s->be_tracked_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
+	}
 
-		ptr = stktable_data_ptr(s->tracked_table, s->tracked_counters, STKTABLE_DT_HTTP_REQ_CNT);
+	if (s->fe_tracked_counters) {
+		ptr = stktable_data_ptr(s->fe_tracked_table, s->fe_tracked_counters, STKTABLE_DT_HTTP_REQ_CNT);
 		if (ptr)
 			stktable_data_cast(ptr, http_req_cnt)++;
 
-		ptr = stktable_data_ptr(s->tracked_table, s->tracked_counters, STKTABLE_DT_HTTP_REQ_RATE);
+		ptr = stktable_data_ptr(s->fe_tracked_table, s->fe_tracked_counters, STKTABLE_DT_HTTP_REQ_RATE);
 		if (ptr)
 			update_freq_ctr_period(&stktable_data_cast(ptr, http_req_rate),
-					       s->tracked_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
+					       s->fe_tracked_table->data_arg[STKTABLE_DT_HTTP_REQ_RATE].u, 1);
 	}
 }
 
@@ -123,17 +186,28 @@
  */
 static void inline session_inc_http_err_ctr(struct session *s)
 {
-	if (s->tracked_counters) {
-		void *ptr;
+	void *ptr;
+
+	if (s->be_tracked_counters) {
+		ptr = stktable_data_ptr(s->be_tracked_table, s->be_tracked_counters, STKTABLE_DT_HTTP_ERR_CNT);
+		if (ptr)
+			stktable_data_cast(ptr, http_err_cnt)++;
+
+		ptr = stktable_data_ptr(s->be_tracked_table, s->be_tracked_counters, STKTABLE_DT_HTTP_ERR_RATE);
+		if (ptr)
+			update_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
+					       s->be_tracked_table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
+	}
 
-		ptr = stktable_data_ptr(s->tracked_table, s->tracked_counters, STKTABLE_DT_HTTP_ERR_CNT);
+	if (s->fe_tracked_counters) {
+		ptr = stktable_data_ptr(s->fe_tracked_table, s->fe_tracked_counters, STKTABLE_DT_HTTP_ERR_CNT);
 		if (ptr)
 			stktable_data_cast(ptr, http_err_cnt)++;
 
-		ptr = stktable_data_ptr(s->tracked_table, s->tracked_counters, STKTABLE_DT_HTTP_ERR_RATE);
+		ptr = stktable_data_ptr(s->fe_tracked_table, s->fe_tracked_counters, STKTABLE_DT_HTTP_ERR_RATE);
 		if (ptr)
 			update_freq_ctr_period(&stktable_data_cast(ptr, http_err_rate),
-					       s->tracked_table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
+					       s->fe_tracked_table->data_arg[STKTABLE_DT_HTTP_ERR_RATE].u, 1);
 	}
 }
 
diff --git a/include/types/proto_tcp.h b/include/types/proto_tcp.h
index a7ca56a..bee52aa 100644
--- a/include/types/proto_tcp.h
+++ b/include/types/proto_tcp.h
@@ -32,7 +32,8 @@
 enum {
 	TCP_ACT_ACCEPT = 1,
 	TCP_ACT_REJECT = 2,
-	TCP_ACT_TRK_CTR = 3,
+	TCP_ACT_TRK_FE_CTR = 3,
+	TCP_ACT_TRK_BE_CTR = 4,
 };
 
 struct tcp_rule {
diff --git a/include/types/session.h b/include/types/session.h
index 4a1dc6e..7b6cf4f 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -184,8 +184,10 @@
 		int flags;
 	} store[8];				/* tracked stickiness values to store */
 	int store_count;
-	struct stksess *tracked_counters;       /* counters currently being tracked by this session */
-	struct stktable *tracked_table;         /* table the counters above belong to (undefined if counters are null) */
+	struct stksess *fe_tracked_counters;    /* counters currently being tracked by this session (frontend) */
+	struct stktable *fe_tracked_table;      /* table the counters above belong to (undefined if counters are null) */
+	struct stksess *be_tracked_counters;    /* counters currently being tracked by this session (backend) */
+	struct stktable *be_tracked_table;      /* table the counters above belong to (undefined if counters are null) */
 
 	struct {
 		int logwait;			/* log fields waiting to be collected : LW_* */