MEDIUM: counters: add support for tracking a third counter

We're often missin a third counter to track base, src and base+src at
the same time. Here we introduce track_sc3 to have this third counter.
It would be wise not to add much more counters because that slightly
increases the session size and processing time though the real issue
is more the declaration of the keywords in the code and in the doc.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 4561741..a031cde 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -6292,8 +6292,8 @@
                                  no    |    yes   |   yes  |   no
   Arguments :
     <action>    defines the action to perform if the condition applies. Valid
-                actions include : "accept", "reject", "track-sc1", "track-sc2".
-                See below for more details.
+                actions include : "accept", "reject", "track-sc1", "track-sc2",
+                and "track-sc3". See below for more details.
 
     <condition> is a standard layer4-only ACL-based condition (see section 7).
 
@@ -6331,7 +6331,7 @@
         logging is absolutely desired, then "tcp-request content" rules should
         be used instead.
 
-    - { track-sc1 | track-sc2 } <key> [table <table>] :
+    - { track-sc1 | track-sc2 | track-sc3 } <key> [table <table>] :
         enables tracking of sticky counters from current connection. These
         rules do not stop evaluation and do not change default action. Two sets
         of counters may be simultaneously tracked by the same connection. The
@@ -6340,6 +6340,7 @@
         enables tracking of the counters of the specified table as the second
         set. It is a recommended practice to use the first set of counters for
         the per-frontend counters and the second set for the per-backend ones.
+        But this is just a guideline, all may be used everywhere.
 
         These actions take one or two arguments :
           <key>   is mandatory, and is a pattern extraction rule as described
@@ -6401,8 +6402,9 @@
                                  no    |    yes   |   yes  |   yes
   Arguments :
     <action>    defines the action to perform if the condition applies. Valid
-                actions include : "accept", "reject", "track-sc1", "track-sc2".
-                See "tcp-request connection" above for their signification.
+                actions include : "accept", "reject", "track-sc1", "track-sc2",
+                and "track-sc3". See "tcp-request connection" above for their
+                signification.
 
     <condition> is a standard layer 4-7 ACL-based condition (see section 7).
 
@@ -6430,7 +6432,7 @@
   Three types of actions are supported :
     - accept :
     - reject :
-    - { track-sc1 | track-sc2 } <key> [table <table>]
+    - { track-sc1 | track-sc2 | track-sc3 } <key> [table <table>]
 
   They have the same meaning as their counter-parts in "tcp-request connection"
   so please refer to that section for a complete description.
@@ -6443,7 +6445,8 @@
   all the session, as opposed to the backend rules. The difference appears when
   some layer 7 information is tracked. While there is nothing mandatory about
   it, it is recommended to use the track-sc1 pointer to track per-frontend
-  counters and track-sc2 to track per-backend counters.
+  counters and track-sc2 to track per-backend counters, but this is just a
+  guideline and all counters may be used everywhere.
 
   Note that the "if/unless" condition is optional. If no condition is set on
   the action, it is simply performed unconditionally. That can be useful for
@@ -8471,18 +8474,21 @@
 
 sc1_bytes_in_rate <integer>
 sc2_bytes_in_rate <integer>
+sc3_bytes_in_rate <integer>
   Returns the average client-to-server bytes rate from the currently tracked
   counters, measured in amount of bytes over the period configured in the
   table. See also src_bytes_in_rate.
 
 sc1_bytes_out_rate <integer>
 sc2_bytes_out_rate <integer>
+sc3_bytes_out_rate <integer>
   Returns the average server-to-client bytes rate from the currently tracked
   counters, measured in amount of bytes over the period configured in the
   table. See also src_bytes_out_rate.
 
 sc1_clr_gpc0 <integer>
 sc2_clr_gpc0 <integer>
+sc3_clr_gpc0 <integer>
   Clears the first General Purpose Counter associated to the currently tracked
   counters, and returns its previous value. Before the first invocation, the
   stored value is zero, so first invocation will always return zero. This is
@@ -8499,34 +8505,40 @@
 
 sc1_conn_cnt <integer>
 sc2_conn_cnt <integer>
+sc3_conn_cnt <integer>
   Returns the cumulated number of incoming connections from currently tracked
   counters. See also src_conn_cnt.
 
 sc1_conn_cur <integer>
 sc2_conn_cur <integer>
+sc3_conn_cur <integer>
   Returns the current amount of concurrent connections tracking the same
   tracked counters. This number is automatically incremented when tracking
   begins and decremented when tracking stops. See also src_conn_cur.
 
 sc1_conn_rate <integer>
 sc2_conn_rate <integer>
+sc3_conn_rate <integer>
   Returns the average connection rate from the currently tracked counters,
   measured in amount of connections over the period configured in the table.
   See also src_conn_rate.
 
 sc1_get_gpc0 <integer>
 sc2_get_gpc0 <integer>
+sc3_get_gpc0 <integer>
   Returns the value of the first General Purpose Counter associated to the
   currently tracked counters. See also src_get_gpc0 and sc1/sc2_inc_gpc0.
 
 sc1_http_err_cnt <integer>
 sc2_http_err_cnt <integer>
+sc3_http_err_cnt <integer>
   Returns the cumulated number of HTTP errors from the currently tracked
   counters. This includes the both request errors and 4xx error responses.
   See also src_http_err_cnt.
 
 sc1_http_err_rate <integer>
 sc2_http_err_rate <integer>
+sc3_http_err_rate <integer>
   Returns the average rate of HTTP errors from the currently tracked counters,
   measured in amount of errors over the period configured in the table. This
   includes the both request errors and 4xx error responses. See also
@@ -8534,12 +8546,14 @@
 
 sc1_http_req_cnt <integer>
 sc2_http_req_cnt <integer>
+sc3_http_req_cnt <integer>
   Returns the cumulated number of HTTP requests from the currently tracked
   counters. This includes every started request, valid or not. See also
   src_http_req_cnt.
 
 sc1_http_req_rate <integer>
 sc2_http_req_rate <integer>
+sc3_http_req_rate <integer>
   Returns the average rate of HTTP requests from the currently tracked
   counters, measured in amount of requests over the period configured in
   the table. This includes every started request, valid or not. See also
@@ -8547,6 +8561,7 @@
 
 sc1_inc_gpc0 <integer>
 sc2_inc_gpc0 <integer>
+sc3_inc_gpc0 <integer>
   Increments the first General Purpose Counter associated to the currently
   tracked counters, and returns its new value. Before the first invocation,
   the stored value is zero, so first invocation will increase it to 1 and will
@@ -8559,6 +8574,7 @@
 
 sc1_kbytes_in <integer>
 sc2_kbytes_in <integer>
+sc3_kbytes_in <integer>
   Returns the amount of client-to-server data from the currently tracked
   counters, measured in kilobytes over the period configured in the table. The
   test is currently performed on 32-bit integers, which limits values to 4
@@ -8566,6 +8582,7 @@
 
 sc1_kbytes_out <integer>
 sc2_kbytes_out <integer>
+sc3_kbytes_out <integer>
   Returns the amount of server-to-client data from the currently tracked
   counters, measured in kilobytes over the period configured in the table. The
   test is currently performed on 32-bit integers, which limits values to 4
@@ -8573,6 +8590,7 @@
 
 sc1_sess_cnt <integer>
 sc2_sess_cnt <integer>
+sc3_sess_cnt <integer>
   Returns the cumulated number of incoming connections that were transformed
   into sessions, which means that they were accepted by a "tcp-request
   connection" rule, from the currently tracked counters. A backend may count
@@ -8582,6 +8600,7 @@
 
 sc1_sess_rate <integer>
 sc2_sess_rate <integer>
+sc3_sess_rate <integer>
   Returns the average session rate from the currently tracked counters,
   measured in amount of sessions over the period configured in the table. A
   session is a connection that got past the early "tcp-request connection"
@@ -8591,6 +8610,7 @@
 
 sc1_trackers <integer>
 sc2_trackers <integer>
+sc3_trackers <integer>
   Returns the current amount of concurrent connections tracking the same
   tracked counters. This number is automatically incremented when tracking
   begins and decremented when tracking stops. It differs from sc1_conn_cur in
@@ -10082,29 +10102,34 @@
 
   sc1_bytes_in_rate
   sc2_bytes_in_rate
+  sc3_bytes_in_rate
                Returns the average client-to-server bytes rate from the
                currently tracked counters, measured in amount of bytes over the
                period configured in the table. See also src_bytes_in_rate.
 
   sc1_bytes_out_rate
   sc2_bytes_out_rate
+  sc3_bytes_out_rate
                Returns the average server-to-client bytes rate from the
                currently tracked counters, measured in amount of bytes over the
                period configured in the table. See also src_bytes_out_rate.
 
   sc1_clr_gpc0
   sc2_clr_gpc0
+  sc3_clr_gpc0
                Clears the first General Purpose Counter associated to the
                currently tracked counters, and returns its previous value.
                This is only useful when used by ACLs.
 
   sc1_conn_cnt
   sc2_conn_cnt
+  sc3_conn_cnt
                Returns the cumulated number of incoming connections from
                currently tracked counters. See also src_conn_cnt.
 
   sc1_conn_cur
   sc2_conn_cur
+  sc3_conn_cur
                Returns the current amount of concurrent connections tracking
                the same tracked counters. This number is automatically
                incremented when tracking begins and decremented when tracking
@@ -10112,24 +10137,28 @@
 
   sc1_conn_rate
   sc2_conn_rate
+  sc3_conn_rate
                Returns the average connection rate from the currently tracked
                counters, measured in amount of connections over the period
                configured in the table. See also src_conn_rate.
 
   sc1_get_gpc0
   sc2_get_gpc0
+  sc3_get_gpc0
                Returns the value of the first General Purpose Counter
                associated to the currently tracked counters. See also
                src_get_gpc0 and sc1/sc2_inc_gpc0.
 
   sc1_http_err_cnt
   sc2_http_err_cnt
+  sc3_http_err_cnt
                Returns the cumulated number of HTTP errors from the currently
                tracked counters. This includes the both request errors and 4xx
                error responses. See also src_http_err_cnt.
 
   sc1_http_err_rate
   sc2_http_err_rate
+  sc3_http_err_rate
                Returns the average rate of HTTP errors from the currently
                tracked counters, measured in amount of errors over the period
                configured in the table. This includes the both request errors
@@ -10137,12 +10166,14 @@
 
   sc1_http_req_cnt
   sc2_http_req_cnt
+  sc3_http_req_cnt
                Returns the cumulated number of HTTP requests from the currently
                tracked counters. This includes every started request, valid or
                not. See also src_http_req_cnt.
 
   sc1_http_req_rate
   sc2_http_req_rate
+  sc3_http_req_rate
                Returns the average rate of HTTP requests from the currently
                tracked counters, measured in amount of requests over the period
                configured in the table. This includes every started request,
@@ -10150,12 +10181,14 @@
 
   sc1_inc_gpc0
   sc2_inc_gpc0
+  sc3_inc_gpc0
                Increments the first General Purpose Counter associated to the
                currently tracked counters, and returns its new value. This is
                only useful when used by ACLs.
 
   sc1_kbytes_in
   sc2_kbytes_in
+  sc3_kbytes_in
                Returns the amount of client-to-server data from the currently
                tracked counters, measured in kilobytes over the period
                configured in the table. The value being stored as a 32-bit
@@ -10163,6 +10196,7 @@
 
   sc1_kbytes_out
   sc2_kbytes_out
+  sc3_kbytes_out
                Returns the amount of server-to-client data from the currently
                tracked counters, measured in kilobytes over the period
                configured in the table. The value being stored as a 32-bit
@@ -10170,6 +10204,7 @@
 
   sc1_sess_cnt
   sc2_sess_cnt
+  sc3_sess_cnt
                Returns the cumulated number of incoming connections that were
                transformed into sessions, which means that they were accepted
                by a "tcp-request connection" rule, from the currently tracked
@@ -10180,6 +10215,7 @@
 
   sc1_sess_rate
   sc2_sess_rate
+  sc3_sess_rate
                Returns the average session rate from the currently tracked
                counters, measured in amount of sessions over the period
                configured in the table. A session is a connection that got past
@@ -10191,6 +10227,7 @@
 
   sc1_trackers
   sc2_trackers
+  sc3_trackers
                Returns the current amount of concurrent connections tracking
                the same tracked counters. This number is automatically
                incremented when tracking begins and decremented when tracking
diff --git a/include/types/proto_tcp.h b/include/types/proto_tcp.h
index 74863b4..ac9d328 100644
--- a/include/types/proto_tcp.h
+++ b/include/types/proto_tcp.h
@@ -34,6 +34,7 @@
 	TCP_ACT_REJECT = 2,
 	TCP_ACT_TRK_SC1 = 3, /* TCP request tracking : must be contiguous */
 	TCP_ACT_TRK_SC2 = 4,
+	TCP_ACT_TRK_SC3 = 5,
 };
 
 struct tcp_rule {
diff --git a/include/types/session.h b/include/types/session.h
index b5c7460..8fbca53 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -89,10 +89,11 @@
 
 #define SN_COMP_READY   0x00100000	/* the compression is initialized */
 
-/* session tracking flags: these ones must absolutely be contiguous */
+/* session tracking flags: these ones must absolutely be contiguous. See also s->stkctr */
 #define SN_BE_TRACK_SC1 0x00200000	/* backend tracks stick-counter 1 */
 #define SN_BE_TRACK_SC2 0x00400000	/* backend tracks stick-counter 2 */
-#define SN_BE_TRACK_ANY 0x00600000      /* union of all SN_BE_TRACK_* above */
+#define SN_BE_TRACK_SC3 0x00800000	/* backend tracks stick-counter 3 */
+#define SN_BE_TRACK_ANY 0x00E00000      /* union of all SN_BE_TRACK_* above */
 
 
 /* WARNING: if new fields are added, they must be initialized in event_accept()
@@ -144,7 +145,7 @@
 	} store[8];				/* tracked stickiness values to store */
 	int store_count;
 
-	struct stkctr stkctr[2];                /* stick counters */
+	struct stkctr stkctr[3];                /* stick counters */
 
 	struct stream_interface si[2];          /* client and server stream interfaces */
 	struct {
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 18fcedc..276766b 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -6335,7 +6335,7 @@
 		list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
 			struct proxy *target;
 
-			if (trule->action < TCP_ACT_TRK_SC1 || trule->action > TCP_ACT_TRK_SC2)
+			if (trule->action < TCP_ACT_TRK_SC1 || trule->action > TCP_ACT_TRK_SC3)
 				continue;
 
 			if (trule->act_prm.trk_ctr.table.n)
@@ -6374,7 +6374,7 @@
 		list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
 			struct proxy *target;
 
-			if (trule->action < TCP_ACT_TRK_SC1 || trule->action > TCP_ACT_TRK_SC2)
+			if (trule->action < TCP_ACT_TRK_SC1 || trule->action > TCP_ACT_TRK_SC3)
 				continue;
 
 			if (trule->act_prm.trk_ctr.table.n)
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 86a67c4..e1b5d8b 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -901,7 +901,7 @@
 					s->flags |= SN_FINST_R;
 				return 0;
 			}
-			else if ((rule->action >= TCP_ACT_TRK_SC1 && rule->action <= TCP_ACT_TRK_SC2) &&
+			else if ((rule->action >= TCP_ACT_TRK_SC1 && rule->action <= TCP_ACT_TRK_SC3) &&
 				 !s->stkctr[tcp_trk_idx(rule->action)].entry) {
 				/* Note: only the first valid tracking parameter of each
 				 * applies.
@@ -1055,7 +1055,7 @@
 				result = 0;
 				break;
 			}
-			else if ((rule->action >= TCP_ACT_TRK_SC1 && rule->action <= TCP_ACT_TRK_SC2) &&
+			else if ((rule->action >= TCP_ACT_TRK_SC1 && rule->action <= TCP_ACT_TRK_SC3) &&
 				 !s->stkctr[tcp_trk_idx(rule->action)].entry) {
 				/* Note: only the first valid tracking parameter of each
 				 * applies.
@@ -1143,7 +1143,7 @@
 		arg++;
 		rule->action = TCP_ACT_REJECT;
 	}
-	else if (strcmp(args[arg], "track-sc1") == 0 || strcmp(args[arg], "track-sc2") == 0) {
+	else if (strcmp(args[arg], "track-sc1") == 0 || strcmp(args[arg], "track-sc2") == 0 || strcmp(args[arg], "track-sc3") == 0) {
 		struct sample_expr *expr;
 		int kw = arg;
 
@@ -1187,8 +1187,8 @@
 	}
 	else {
 		memprintf(err,
-		          "'%s %s' expects 'accept', 'reject', 'track-sc1' "
-		          "or 'track-sc2' in %s '%s' (got '%s')",
+		          "'%s %s' expects 'accept', 'reject', 'track-sc1', 'track-sc2' "
+		          " or 'track-sc3' in %s '%s' (got '%s')",
 		          args[0], args[1], proxy_type_str(curpx), curpx->id, args[arg]);
 		return -1;
 	}
diff --git a/src/session.c b/src/session.c
index 404fd06..10d3feb 100644
--- a/src/session.c
+++ b/src/session.c
@@ -2615,6 +2615,18 @@
 	return smp_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 tracked
+ * backend counters.
+ */
+static int
+smp_fetch_sc3_get_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+	return smp_fetch_get_gpc0(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the General Purpose Counter 0 value from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -2675,6 +2687,18 @@
 	return smp_fetch_inc_gpc0(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* Increment the General Purpose Counter 0 value from the session's tracked
+ * backend counters and return it into temp integer.
+ */
+static int
+smp_fetch_sc3_inc_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+	return smp_fetch_inc_gpc0(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* Increment the General Purpose Counter 0 value from the session's source
  * address in the table pointed to by expr, and return it into temp integer.
  * Accepts exactly 1 argument of type table.
@@ -2736,6 +2760,18 @@
 	return smp_fetch_clr_gpc0(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* Clear the General Purpose Counter 0 value from the session's tracked
+ * backend counters and return its previous value into temp integer.
+ */
+static int
+smp_fetch_sc3_clr_gpc0(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+	return smp_fetch_clr_gpc0(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* Clear the General Purpose Counter 0 value from the session's source address
  * in the table pointed to by expr, and return its previous value into temp integer.
  * Accepts exactly 1 argument of type table.
@@ -2792,6 +2828,17 @@
 	return smp_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 tracked BE counters */
+static int
+smp_fetch_sc3_conn_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_conn_cnt(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the cumulated number of connections from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -2853,6 +2900,19 @@
 	return smp_fetch_conn_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the connection rate from the session's tracked BE counters over
+ * the configured period.
+ */
+static int
+smp_fetch_sc3_conn_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                        const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_conn_rate(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the connection rate from the session's source address in the
  * table pointed to by expr, over the configured period.
  * Accepts exactly 1 argument of type table.
@@ -2942,6 +3002,17 @@
 	return smp_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 tracked BE counters */
+static int
+smp_fetch_sc3_conn_cur(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_conn_cur(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the number of concurrent connections from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -2998,6 +3069,17 @@
 	return smp_fetch_sess_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
+static int
+smp_fetch_sc3_sess_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_sess_cnt(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -3059,6 +3141,19 @@
 	return smp_fetch_sess_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the session rate from the session's tracked BE counters over
+ * the configured period.
+ */
+static int
+smp_fetch_sc3_sess_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                        const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_sess_rate(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
  * Accepts exactly 1 argument of type table.
@@ -3115,6 +3210,17 @@
 	return smp_fetch_http_req_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
+static int
+smp_fetch_sc3_http_req_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                           const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_http_req_cnt(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -3176,6 +3282,19 @@
 	return smp_fetch_http_req_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the session rate from the session's tracked BE counters over
+ * the configured period.
+ */
+static int
+smp_fetch_sc3_http_req_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                            const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_http_req_rate(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
  * Accepts exactly 1 argument of type table.
@@ -3232,6 +3351,17 @@
 	return smp_fetch_http_err_cnt(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the cumulated number of sessions from the session's tracked BE counters */
+static int
+smp_fetch_sc3_http_err_cnt(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                           const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_http_err_cnt(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the cumulated number of session from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -3293,6 +3423,19 @@
 	return smp_fetch_http_err_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the session rate from the session's tracked BE counters over
+ * the configured period.
+ */
+static int
+smp_fetch_sc3_http_err_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                            const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_http_err_rate(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the session rate from the session's source address in the
  * table pointed to by expr, over the configured period.
  * Accepts exactly 1 argument of type table.
@@ -3354,6 +3497,19 @@
 	return smp_fetch_kbytes_in(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the number of kbytes received from clients according to the
+ * session's tracked BE counters.
+ */
+static int
+smp_fetch_sc3_kbytes_in(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                        const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_kbytes_in(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the number of kbytes received from the session's source
  * address in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -3417,6 +3573,19 @@
 	return smp_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 tracked BE
+ * counters over the configured period.
+ */
+static int
+smp_fetch_sc3_bytes_in_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                            const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_bytes_in_rate(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the bytes rate from clients from the session's source address
  * in the table pointed to by expr, over the configured period.
  * Accepts exactly 1 argument of type table.
@@ -3478,6 +3647,19 @@
 	return smp_fetch_kbytes_out(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the number of kbytes sent to clients according to the session's
+ * tracked BE counters.
+ */
+static int
+smp_fetch_sc3_kbytes_out(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                         const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_kbytes_out(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the number of kbytes sent to the session's source address in
  * the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
@@ -3541,6 +3723,19 @@
 	return smp_fetch_bytes_out_rate(l4->stkctr[1].table, smp, l4->stkctr[1].entry);
 }
 
+/* set temp integer to the bytes rate to clients from the session's tracked BE counters
+ * over the configured period.
+ */
+static int
+smp_fetch_sc3_bytes_out_rate(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                             const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return smp_fetch_bytes_out_rate(l4->stkctr[2].table, smp, l4->stkctr[2].entry);
+}
+
 /* set temp integer to the bytes rate to client from the session's source address in
  * the table pointed to by expr, over the configured period.
  * Accepts exactly 1 argument of type table.
@@ -3581,6 +3776,17 @@
 	return l4->stkctr[1].entry->ref_cnt;
 }
 
+/* set temp integer to the number of active trackers on the SC1 entry */
+static int
+smp_fetch_sc3_trackers(struct proxy *px, struct session *l4, void *l7, unsigned int opt,
+                       const struct arg *args, struct sample *smp)
+{
+	if (!l4->stkctr[2].entry)
+		return 0;
+
+	return l4->stkctr[2].entry->ref_cnt;
+}
+
 /* set temp integer to the number of used entries in the table pointed to by expr.
  * Accepts exactly 1 argument of type table.
  */
@@ -3646,6 +3852,23 @@
 	{ "sc2_sess_cnt",       NULL, acl_parse_int, acl_match_int },
 	{ "sc2_sess_rate",      NULL, acl_parse_int, acl_match_int },
 	{ "sc2_trackers",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_bytes_in_rate",  NULL, acl_parse_int, acl_match_int },
+	{ "sc3_bytes_out_rate", NULL, acl_parse_int, acl_match_int },
+	{ "sc3_clr_gpc0",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_conn_cnt",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_conn_cur",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_conn_rate",      NULL, acl_parse_int, acl_match_int },
+	{ "sc3_get_gpc0",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_http_err_cnt",   NULL, acl_parse_int, acl_match_int },
+	{ "sc3_http_err_rate",  NULL, acl_parse_int, acl_match_int },
+	{ "sc3_http_req_cnt",   NULL, acl_parse_int, acl_match_int },
+	{ "sc3_http_req_rate",  NULL, acl_parse_int, acl_match_int },
+	{ "sc3_inc_gpc0",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_kbytes_in",      NULL, acl_parse_int, acl_match_int },
+	{ "sc3_kbytes_out",     NULL, acl_parse_int, acl_match_int },
+	{ "sc3_sess_cnt",       NULL, acl_parse_int, acl_match_int },
+	{ "sc3_sess_rate",      NULL, acl_parse_int, acl_match_int },
+	{ "sc3_trackers",       NULL, acl_parse_int, acl_match_int },
 	{ "src_bytes_in_rate",  NULL, acl_parse_int, acl_match_int },
 	{ "src_bytes_out_rate", NULL, acl_parse_int, acl_match_int },
 	{ "src_clr_gpc0",       NULL, acl_parse_int, acl_match_int },
@@ -3706,6 +3929,23 @@
 	{ "sc2_sess_cnt",       smp_fetch_sc2_sess_cnt,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
 	{ "sc2_sess_rate",      smp_fetch_sc2_sess_rate,      0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
 	{ "sc2_trackers",       smp_fetch_sc2_trackers,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_bytes_in_rate",  smp_fetch_sc3_bytes_in_rate,  0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_bytes_out_rate", smp_fetch_sc3_bytes_out_rate, 0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_clr_gpc0",       smp_fetch_sc3_clr_gpc0,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_conn_cnt",       smp_fetch_sc3_conn_cnt,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_conn_cur",       smp_fetch_sc3_conn_cur,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_conn_rate",      smp_fetch_sc3_conn_rate,      0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_get_gpc0",       smp_fetch_sc3_get_gpc0,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_http_err_cnt",   smp_fetch_sc3_http_err_cnt,   0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_http_err_rate",  smp_fetch_sc3_http_err_rate,  0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_http_req_cnt",   smp_fetch_sc3_http_req_cnt,   0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_http_req_rate",  smp_fetch_sc3_http_req_rate,  0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_inc_gpc0",       smp_fetch_sc3_inc_gpc0,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_kbytes_in",      smp_fetch_sc3_kbytes_in,      0,           NULL, SMP_T_UINT, SMP_USE_L4CLI, },
+	{ "sc3_kbytes_out",     smp_fetch_sc3_kbytes_out,     0,           NULL, SMP_T_UINT, SMP_USE_L4CLI, },
+	{ "sc3_sess_cnt",       smp_fetch_sc3_sess_cnt,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_sess_rate",      smp_fetch_sc3_sess_rate,      0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
+	{ "sc3_trackers",       smp_fetch_sc3_trackers,       0,           NULL, SMP_T_UINT, SMP_USE_INTRN, },
 	{ "src_bytes_in_rate",  smp_fetch_src_bytes_in_rate,  ARG1(1,TAB), NULL, SMP_T_UINT, SMP_USE_L4CLI, },
 	{ "src_bytes_out_rate", smp_fetch_src_bytes_out_rate, ARG1(1,TAB), NULL, SMP_T_UINT, SMP_USE_L4CLI, },
 	{ "src_clr_gpc0",       smp_fetch_src_clr_gpc0,       ARG1(1,TAB), NULL, SMP_T_UINT, SMP_USE_L4CLI, },