MEDIUM: stick-table: Stop handling stick-tables as proxies.

This patch adds the support for the "table" line parsing in "peers" sections
to declare stick-table in such sections. This also prevents the user from having
to declare dummy backends sections with a unique stick-table inside.
Even if still supported, this usage will become deprecated.

To do so, the ->table member of proxy struct which is a stktable struct is replaced
by a pointer to a stktable struct allocated at parsing time in src/cfgparse-listen.c
for the dummy stick-table backends and in src/cfgparse.c for "peers" sections.
This has an impact on the code for stick-table sample converters and on the stickiness
rules parsers which first store the name of the dummy before resolving the rules.
This patch replaces proxy_tbl_by_name() calls by stktable_find_by_name() calls
to lookup for stick-tables stored in "stktable_by_name" ebtree at parsing time.
There is only one remaining place where proxy_tbl_by_name() is used: src/hlua.c.

At several places in the code we relied on the fact that ->size member of stick-table
was equal to zero to consider the stick-table was present by not configured,
this do not make sense anymore as ->table member of struct proxyis fow now on a pointer.
These tests are replaced by a test on ->table value itself.

In "peers" section we do not have to temporary store the name of the section the
stick-table are attached to because this name is obviously already known just after
having entered this "peers" section.

About the CLI stick-table I/O handler, the pointer to proxy struct is replaced by
a pointer to a stktable struct.
diff --git a/include/proto/stick_table.h b/include/proto/stick_table.h
index 962c95a..3010d81 100644
--- a/include/proto/stick_table.h
+++ b/include/proto/stick_table.h
@@ -28,9 +28,13 @@
 #include <common/time.h>
 #include <types/stick_table.h>
 
+extern struct stktable *stktables_list;
+
 #define stktable_data_size(type) (sizeof(((union stktable_data*)0)->type))
 #define stktable_data_cast(ptr, type) ((union stktable_data*)(ptr))->type
 
+void stktable_store_name(struct stktable *t);
+struct stktable *stktable_find_by_name(const char *name);
 struct stksess *stksess_new(struct stktable *t, struct stktable_key *key);
 void stksess_setkey(struct stktable *t, struct stksess *ts, struct stktable_key *key);
 void stksess_free(struct stktable *t, struct stksess *ts);
diff --git a/include/types/applet.h b/include/types/applet.h
index 4786b31..b7b297c 100644
--- a/include/types/applet.h
+++ b/include/types/applet.h
@@ -144,7 +144,7 @@
 		} errors;
 		struct {
 			void *target;		/* table we want to dump, or NULL for all */
-			struct proxy *proxy;	/* table being currently dumped (first if NULL) */
+			struct stktable *t;	/* table being currently dumped (first if NULL) */
 			struct stksess *entry;	/* last entry we were trying to dump (or first if NULL) */
 			long long value;	/* value to compare against */
 			signed char data_type;	/* type of data to compare, or -1 if none */
diff --git a/include/types/arg.h b/include/types/arg.h
index 6580c15..a9778f2 100644
--- a/include/types/arg.h
+++ b/include/types/arg.h
@@ -30,6 +30,7 @@
 
 #include <types/vars.h>
 #include <types/protocol_buffers.h>
+#include <types/stick_table.h>
 
 /* encoding of each arg type : up to 31 types are supported */
 #define ARGT_BITS      5
@@ -99,6 +100,7 @@
 	struct in6_addr ipv6;
 	struct proxy *prx; /* used for fe, be, tables */
 	struct server *srv;
+	struct stktable *t;
 	struct userlist *usr;
 	struct map_descriptor *map;
 	struct my_regex *reg;
diff --git a/include/types/hlua.h b/include/types/hlua.h
index f9709bb..36554e2 100644
--- a/include/types/hlua.h
+++ b/include/types/hlua.h
@@ -11,6 +11,7 @@
 #include <types/proto_http.h>
 #include <types/proxy.h>
 #include <types/server.h>
+#include <types/stick_table.h>
 
 #define CLASS_CORE         "Core"
 #define CLASS_TXN          "TXN"
diff --git a/include/types/proxy.h b/include/types/proxy.h
index dababea..f6d2634 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -416,7 +416,7 @@
 	struct fe_counters fe_counters;		/* frontend statistics counters */
 
 	struct list listener_queue;		/* list of the temporarily limited listeners because of lack of a proxy resource */
-	struct stktable table;			/* table for storing sticking streams */
+	struct stktable *table;			/* table for storing sticking streams */
 
 	struct task *task;			/* the associated task, mandatory to manage rate limiting, stopping and resource shortage, NULL if disabled */
 	struct list tcpcheck_rules;		/* tcp-check send / expect rules */
diff --git a/include/types/stick_table.h b/include/types/stick_table.h
index a6a4a49..ff9546c 100644
--- a/include/types/stick_table.h
+++ b/include/types/stick_table.h
@@ -152,6 +152,7 @@
 		const char *file;     /* The file where the stick-table is declared. */
 		int line;             /* The line in this <file> the stick-table is declared. */
 	} conf;
+	struct ebpt_node name;    /* Stick-table are lookup by name here. */
 	struct eb_root keys;      /* head of sticky session tree */
 	struct eb_root exps;      /* head of sticky session expiration tree */
 	struct eb_root updates;   /* head of sticky updates sequence tree */
diff --git a/src/action.c b/src/action.c
index 9b6dcfd..4cce7a4 100644
--- a/src/action.c
+++ b/src/action.c
@@ -30,37 +30,34 @@
  */
 int check_trk_action(struct act_rule *rule, struct proxy *px, char **err)
 {
-	struct proxy *target;
+	struct stktable *target;
 
 	if (rule->arg.trk_ctr.table.n)
-		target = proxy_tbl_by_name(rule->arg.trk_ctr.table.n);
+		target = stktable_find_by_name(rule->arg.trk_ctr.table.n);
 	else
-		target = px;
+		target = px->table;
 
 	if (!target) {
 		memprintf(err, "unable to find table '%s' referenced by track-sc%d",
-			  rule->arg.trk_ctr.table.n, trk_idx(rule->action));
-		return 0;
-	}
-	else if (target->table.size == 0) {
-		memprintf(err, "table '%s' used but not configured",
-			  rule->arg.trk_ctr.table.n ? rule->arg.trk_ctr.table.n : px->id);
+			  rule->arg.trk_ctr.table.n ?  rule->arg.trk_ctr.table.n : px->id,
+			  trk_idx(rule->action));
 		return 0;
 	}
-	else if (!stktable_compatible_sample(rule->arg.trk_ctr.expr,  target->table.type)) {
+
+	if (!stktable_compatible_sample(rule->arg.trk_ctr.expr,  target->type)) {
 		memprintf(err, "stick-table '%s' uses a type incompatible with the 'track-sc%d' rule",
 			  rule->arg.trk_ctr.table.n ? rule->arg.trk_ctr.table.n : px->id,
 			  trk_idx(rule->action));
 		return 0;
 	}
-	else if (px->bind_proc & ~target->bind_proc) {
+	else if (target->proxy && (px->bind_proc & ~target->proxy->bind_proc)) {
 		memprintf(err, "stick-table '%s' referenced by 'track-sc%d' rule not present on all processes covered by proxy '%s'",
 			  target->id, trk_idx(rule->action), px->id);
 		return 0;
 	}
 	else {
 		free(rule->arg.trk_ctr.table.n);
-		rule->arg.trk_ctr.table.t = &target->table;
+		rule->arg.trk_ctr.table.t = target;
 		/* Note: if we decide to enhance the track-sc syntax, we may be
 		 * able to pass a list of counters to track and allocate them
 		 * right here using stktable_alloc_data_type().
diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c
index c0f4a46..2b2785a 100644
--- a/src/cfgparse-listen.c
+++ b/src/cfgparse-listen.c
@@ -1711,7 +1711,7 @@
 		LIST_ADDQ(&curproxy->persist_rules, &rule->list);
 	}
 	else if (!strcmp(args[0], "stick-table")) {
-		struct proxy *other;
+		struct stktable *other;
 
 		if (curproxy == &defproxy) {
 			ha_alert("parsing [%s:%d] : 'stick-table' is not supported in 'defaults' section.\n",
@@ -1720,20 +1720,35 @@
 			goto out;
 		}
 
-		other = proxy_tbl_by_name(curproxy->id);
+		other = stktable_find_by_name(curproxy->id);
 		if (other) {
 			ha_alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
-				 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
+				 file, linenum, curproxy->id,
+				 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
+				 other->proxy ? other->id : other->peers.p->id,
+				 other->conf.file, other->conf.line);
 			err_code |= ERR_ALERT | ERR_FATAL;
 			goto out;
 		}
 
-		err_code |= parse_stick_table(file, linenum, args, &curproxy->table, curproxy->id, NULL);
+		curproxy->table = calloc(1, sizeof *curproxy->table);
+		if (!curproxy->table) {
+			ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
+			         file, linenum, args[0], args[1]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+
+		err_code |= parse_stick_table(file, linenum, args, curproxy->table, curproxy->id, NULL);
 		if (err_code & ERR_FATAL)
 			goto out;
 
 		/* Store the proxy in the stick-table. */
 		curproxy->table->proxy = curproxy;
+
+		stktable_store_name(curproxy->table);
+		curproxy->table->next = stktables_list;
+		stktables_list = curproxy->table;
 	}
 	else if (!strcmp(args[0], "stick")) {
 		struct sticking_rule *rule;
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 24b5714..3e32633 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -856,7 +856,45 @@
 		l->default_target = curpeers->peers_fe->default_target;
 		l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
 		global.maxsock++; /* for the listening socket */
-	} /* neither "peer" nor "peers" */
+	}
+	else if (!strcmp(args[0], "table")) {
+		struct stktable *t, *other;
+		char *id;
+
+		/* Line number and peer ID are updated only if this peer is the local one. */
+		if (init_peers_frontend(file, -1, NULL, curpeers) != 0) {
+			err_code |= ERR_ALERT | ERR_ABORT;
+			goto out;
+		}
+
+		other = stktable_find_by_name(args[1]);
+		if (other) {
+			ha_alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
+				 file, linenum, args[1],
+				 other->proxy ? proxy_cap_str(other->proxy->cap) : "peers",
+				 other->proxy ? other->id : other->peers.p->id,
+				 other->conf.file, other->conf.line);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+
+		t = calloc(1, sizeof *t);
+		id = strdup(args[1]);
+		if (!t || !id) {
+			ha_alert("parsing [%s:%d]: '%s %s' : memory allocation failed\n",
+			         file, linenum, args[0], args[1]);
+			err_code |= ERR_ALERT | ERR_FATAL;
+			goto out;
+		}
+
+		err_code |= parse_stick_table(file, linenum, args, t, id, curpeers);
+		if (err_code & ERR_FATAL)
+			goto out;
+
+		stktable_store_name(t);
+		t->next = stktables_list;
+		stktables_list = t;
+	}
 	else if (!strcmp(args[0], "disabled")) {  /* disables this peers section */
 		curpeers->state = PR_STSTOPPED;
 	}
@@ -2171,6 +2209,7 @@
 {
 	int cfgerr = 0;
 	struct proxy *curproxy = NULL;
+	struct stktable *t;
 	struct server *newsrv = NULL;
 	int err_code = 0;
 	unsigned int next_pxid = 1;
@@ -2261,8 +2300,8 @@
 		if (curproxy->state == PR_STSTOPPED) {
 			/* ensure we don't keep listeners uselessly bound */
 			stop_proxy(curproxy);
-			free((void *)curproxy->table.peers.name);
-			curproxy->table.peers.p = NULL;
+			free((void *)curproxy->table->peers.name);
+			curproxy->table->peers.p = NULL;
 			continue;
 		}
 
@@ -2624,79 +2663,69 @@
 
 		/* find the target table for 'stick' rules */
 		list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
-			struct proxy *target;
+			struct stktable *target;
 
 			curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
 			if (mrule->flags & STK_IS_STORE)
 				curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
 
 			if (mrule->table.name)
-				target = proxy_tbl_by_name(mrule->table.name);
+				target = stktable_find_by_name(mrule->table.name);
 			else
-				target = curproxy;
+				target = curproxy->table;
 
 			if (!target) {
 				ha_alert("Proxy '%s': unable to find stick-table '%s'.\n",
 					 curproxy->id, mrule->table.name);
 				cfgerr++;
 			}
-			else if (target->table.size == 0) {
-				ha_alert("Proxy '%s': stick-table '%s' used but not configured.\n",
-					 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
-				cfgerr++;
-			}
-			else if (!stktable_compatible_sample(mrule->expr,  target->table.type)) {
+			else if (!stktable_compatible_sample(mrule->expr,  target->type)) {
 				ha_alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
 					 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
 				cfgerr++;
 			}
-			else if (curproxy->bind_proc & ~target->bind_proc) {
+			else if (target->proxy && curproxy->bind_proc & ~target->proxy->bind_proc) {
 				ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n",
 				         curproxy->id, target->id, curproxy->id);
 				cfgerr++;
 			}
 			else {
 				free((void *)mrule->table.name);
-				mrule->table.t = &(target->table);
-				stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
+				mrule->table.t = target;
+				stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL);
 			}
 		}
 
 		/* find the target table for 'store response' rules */
 		list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
-			struct proxy *target;
+			struct stktable *target;
 
 			curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
 
 			if (mrule->table.name)
-				target = proxy_tbl_by_name(mrule->table.name);
+				target = stktable_find_by_name(mrule->table.name);
 			else
-				target = curproxy;
+				target = curproxy->table;
 
 			if (!target) {
 				ha_alert("Proxy '%s': unable to find store table '%s'.\n",
 					 curproxy->id, mrule->table.name);
 				cfgerr++;
 			}
-			else if (target->table.size == 0) {
-				ha_alert("Proxy '%s': stick-table '%s' used but not configured.\n",
-					 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
-				cfgerr++;
-			}
-			else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
+			else if (!stktable_compatible_sample(mrule->expr, target->type)) {
 				ha_alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
 					 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
 				cfgerr++;
 			}
-			else if (curproxy->bind_proc & ~target->bind_proc) {
+			else if (target->proxy && (curproxy->bind_proc & ~target->proxy->bind_proc)) {
 				ha_alert("Proxy '%s': stick-table '%s' referenced 'stick-store' rule not present on all processes covered by proxy '%s'.\n",
 				         curproxy->id, target->id, curproxy->id);
 				cfgerr++;
 			}
 			else {
 				free((void *)mrule->table.name);
-				mrule->table.t = &(target->table);
-				stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
+				mrule->table.t = target;
+				stktable_alloc_data_type(target, STKTABLE_DT_SERVER_ID, NULL);
 			}
 		}
 
@@ -2760,32 +2789,32 @@
 			LIST_INIT(&curproxy->block_rules);
 		}
 
-		if (curproxy->table.peers.name) {
+		if (curproxy->table && curproxy->table->peers.name) {
 			struct peers *curpeers;
 
 			for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
-				if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
-					free((void *)curproxy->table.peers.name);
-					curproxy->table.peers.p = curpeers;
+				if (strcmp(curpeers->id, curproxy->table->peers.name) == 0) {
+					free((void *)curproxy->table->peers.name);
+					curproxy->table->peers.p = curpeers;
 					break;
 				}
 			}
 
 			if (!curpeers) {
 				ha_alert("Proxy '%s': unable to find sync peers '%s'.\n",
-					 curproxy->id, curproxy->table.peers.name);
-				free((void *)curproxy->table.peers.name);
-				curproxy->table.peers.p = NULL;
+					 curproxy->id, curproxy->table->peers.name);
+				free((void *)curproxy->table->peers.name);
+				curproxy->table->peers.p = NULL;
 				cfgerr++;
 			}
 			else if (curpeers->state == PR_STSTOPPED) {
 				/* silently disable this peers section */
-				curproxy->table.peers.p = NULL;
+				curproxy->table->peers.p = NULL;
 			}
 			else if (!curpeers->peers_fe) {
 				ha_alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
 					 curproxy->id, localpeer, curpeers->id);
-				curproxy->table.peers.p = NULL;
+				curproxy->table->peers.p = NULL;
 				cfgerr++;
 			}
 		}
@@ -3829,8 +3858,8 @@
 
 	/* compute the required process bindings for the peers */
 	for (curproxy = proxies_list; curproxy; curproxy = curproxy->next)
-		if (curproxy->table.peers.p)
-			curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
+		if (curproxy->table && curproxy->table->peers.p)
+			curproxy->table->peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
 
 	if (cfg_peers) {
 		struct peers *curpeers = cfg_peers, **last;
@@ -3920,15 +3949,24 @@
 		}
 	}
 
+	for (t = stktables_list; t; t = t->next) {
+		if (t->proxy)
+			continue;
+		if (!stktable_init(t)) {
+			ha_alert("Proxy '%s': failed to initialize stick-table.\n", t->id);
+			cfgerr++;
+		}
+	}
+
 	/* initialize stick-tables on backend capable proxies. This must not
 	 * be done earlier because the data size may be discovered while parsing
 	 * other proxies.
 	 */
 	for (curproxy = proxies_list; curproxy; curproxy = curproxy->next) {
-		if (curproxy->state == PR_STSTOPPED)
+		if (curproxy->state == PR_STSTOPPED || !curproxy->table)
 			continue;
 
-		if (!stktable_init(&curproxy->table)) {
+		if (!stktable_init(curproxy->table)) {
 			ha_alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
 			cfgerr++;
 		}
diff --git a/src/haproxy.c b/src/haproxy.c
index 33f9453..bf91c0b 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -2369,7 +2369,7 @@
 
 		pool_destroy(p->req_cap_pool);
 		pool_destroy(p->rsp_cap_pool);
-		pool_destroy(p->table.pool);
+		pool_destroy(p->table->pool);
 
 		p0 = p;
 		p = p->next;
diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c
index 472fb0c..60882f3 100644
--- a/src/hlua_fcn.c
+++ b/src/hlua_fcn.c
@@ -1269,9 +1269,9 @@
 	}
 	lua_settable(L, -3);
 
-	if (px->table.id) {
+	if (px->table && px->table->id) {
 		lua_pushstring(L, "stktable");
-		hlua_fcn_new_stktable(L, &px->table);
+		hlua_fcn_new_stktable(L, px->table);
 		lua_settable(L, -3);
 	}
 
diff --git a/src/proxy.c b/src/proxy.c
index 18f016c..3c599d6 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -587,7 +587,7 @@
 		if ((px->cap & cap) != cap)
 			continue;
 
-		if (table && !px->table.size)
+		if (table && (!px->table || !px->table->size))
 			continue;
 
 		return px;
@@ -620,7 +620,7 @@
 			if ((curproxy->cap & cap) != cap)
 				continue;
 
-			if (table && !curproxy->table.size)
+			if (table && (!curproxy->table || !curproxy->table->size))
 				continue;
 
 			return curproxy;
@@ -993,12 +993,12 @@
 	 * be in neither list. Any entry being dumped will have ref_cnt > 0.
 	 * However we protect tables that are being synced to peers.
 	 */
-	if (unlikely(stopping && p->state == PR_STSTOPPED && p->table.current)) {
-		if (!p->table.syncing) {
-			stktable_trash_oldest(&p->table, p->table.current);
+	if (unlikely(stopping && p->state == PR_STSTOPPED && p->table && p->table->current)) {
+		if (!p->table->syncing) {
+			stktable_trash_oldest(p->table, p->table->current);
 			pool_gc(NULL);
 		}
-		if (p->table.current) {
+		if (p->table->current) {
 			/* some entries still remain, let's recheck in one second */
 			next = tick_first(next, tick_add(now_ms, 1000));
 		}
@@ -1138,8 +1138,8 @@
 			/* Note: do not wake up stopped proxies' task nor their tables'
 			 * tasks as these ones might point to already released entries.
 			 */
-			if (p->table.size && p->table.sync_task)
-				task_wakeup(p->table.sync_task, TASK_WOKEN_MSG);
+			if (p->table && p->table->size && p->table->sync_task)
+				task_wakeup(p->table->sync_task, TASK_WOKEN_MSG);
 
 			if (p->task)
 				task_wakeup(p->task, TASK_WOKEN_MSG);
diff --git a/src/sample.c b/src/sample.c
index 54f7c9b..aa20d35 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -1109,7 +1109,8 @@
 	list_for_each_entry_safe(cur, bak, &p->conf.args.list, list) {
 		struct proxy *px;
 		struct server *srv;
-		char *pname, *sname;
+		struct stktable *t;
+		char *pname, *sname, *stktname;
 		char *err;
 
 		arg = cur->arg;
@@ -1244,30 +1245,35 @@
 			break;
 
 		case ARGT_TAB:
-			if (arg->data.str.data) {
-				pname = arg->data.str.area;
-				px = proxy_tbl_by_name(pname);
+			if (!arg->data.str.data) {
+				ha_alert("parsing [%s:%d] : missing table name in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
+					 cur->file, cur->line,
+					 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
+				cfgerr++;
+				continue;
 			}
 
-			if (!px) {
+			stktname = arg->data.str.area;
+			t = stktable_find_by_name(stktname);
+			if (!t) {
 				ha_alert("parsing [%s:%d] : unable to find table '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
-					 cur->file, cur->line, pname,
+					 cur->file, cur->line, stktname,
 					 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
 				cfgerr++;
 				break;
 			}
 
-			if (!px->table.size) {
+			if (!t->size) {
 				ha_alert("parsing [%s:%d] : no table in proxy '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
-					 cur->file, cur->line, pname,
+					 cur->file, cur->line, stktname,
 					 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
 				cfgerr++;
 				break;
 			}
 
-			if (p->bind_proc & ~px->bind_proc) {
+			if (t->proxy && (p->bind_proc & ~t->proxy->bind_proc)) {
 				ha_alert("parsing [%s:%d] : stick-table '%s' not present on all processes covered by proxy '%s'.\n",
-					 cur->file, cur->line, px->id, p->id);
+					 cur->file, cur->line, t->proxy->id, p->id);
 				cfgerr++;
 				break;
 			}
@@ -1275,7 +1281,7 @@
 			free(arg->data.str.area);
 			arg->data.str.area = NULL;
 			arg->unresolved = 0;
-			arg->data.prx = px;
+			arg->data.t = t;
 			break;
 
 		case ARGT_USR:
diff --git a/src/stick_table.c b/src/stick_table.c
index d8053dc..87a26e6 100644
--- a/src/stick_table.c
+++ b/src/stick_table.c
@@ -47,7 +47,36 @@
 /* structure used to return a table key built from a sample */
 static THREAD_LOCAL struct stktable_key static_table_key;
 
+struct stktable *stktables_list;
+struct eb_root stktable_by_name = EB_ROOT;
+
 #define round_ptr_size(i) (((i) + (sizeof(void *) - 1)) &~ (sizeof(void *) - 1))
+
+/* This function inserts stktable <t> into the tree of known stick-table.
+ * The stick-table ID is used as the storing key so it must already have
+ * been initialized.
+ */
+void stktable_store_name(struct stktable *t)
+{
+	t->name.key = t->id;
+	ebis_insert(&stktable_by_name, &t->name);
+}
+
+struct stktable *stktable_find_by_name(const char *name)
+{
+	struct ebpt_node *node;
+	struct stktable *t;
+
+	node = ebis_lookup(&stktable_by_name, name);
+	if (node) {
+		t = container_of(node, struct stktable, name);
+		if (!strcmp(t->id, name))
+			return t;
+	}
+
+	return NULL;
+}
+
 /*
  * Free an allocated sticky session <ts>, and decrease sticky sessions counter
  * in table <t>.
@@ -1063,7 +1092,7 @@
 	struct stktable_key *key;
 	struct stksess *ts;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1091,7 +1120,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1128,7 +1157,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1164,7 +1193,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1200,7 +1229,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1237,7 +1266,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1274,7 +1303,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1310,7 +1339,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1346,7 +1375,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1383,7 +1412,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1419,7 +1448,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1456,7 +1485,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1492,7 +1521,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1529,7 +1558,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1565,7 +1594,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1602,7 +1631,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1638,7 +1667,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1674,7 +1703,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1710,7 +1739,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1746,7 +1775,7 @@
 	struct stksess *ts;
 	void *ptr;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -1782,7 +1811,7 @@
 	struct stktable_key *key;
 	struct stksess *ts;
 
-	t = &arg_p[0].data.prx->table;
+	t = arg_p[0].data.t;
 
 	key = smp_to_stkey(smp, t);
 	if (!key)
@@ -2062,7 +2091,7 @@
 {
 	smp->flags = SMP_F_VOL_TEST;
 	smp->data.type = SMP_T_SINT;
-	smp->data.u.sint = args->data.prx->table.current;
+	smp->data.u.sint = args->data.t->current;
 	return 1;
 }
 
@@ -2072,12 +2101,12 @@
 static int
 smp_fetch_table_avl(const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
-	struct proxy *px;
+	struct stktable *t;
 
-	px = args->data.prx;
+	t = args->data.t;
 	smp->flags = SMP_F_VOL_TEST;
 	smp->data.type = SMP_T_SINT;
-	smp->data.u.sint = px->table.size - px->table.current;
+	smp->data.u.sint = t->size - t->current;
 	return 1;
 }
 
@@ -2125,11 +2154,11 @@
 			return NULL;
 
 		/* Converts into key. */
-		key = smp_to_stkey(&smp, &args->data.prx->table);
+		key = smp_to_stkey(&smp, args->data.t);
 		if (!key)
 			return NULL;
 
-		stkctr->table = &args->data.prx->table;
+		stkctr->table = args->data.t;
 		stkctr_set_entry(stkctr, stktable_lookup_key(stkctr->table, key));
 		return stkctr;
 	}
@@ -2154,7 +2183,7 @@
 
 	if (unlikely(args[arg].type == ARGT_TAB)) {
 		/* an alternate table was specified, let's look up the same key there */
-		stkctr->table = &args[arg].data.prx->table;
+		stkctr->table = args[arg].data.t;
 		stkctr_set_entry(stkctr, stktable_lookup(stkctr->table, stksess));
 		return stkctr;
 	}
@@ -2187,11 +2216,11 @@
 		return NULL;
 
 	/* Converts into key. */
-	key = smp_to_stkey(&smp, &args->data.prx->table);
+	key = smp_to_stkey(&smp, args->data.t);
 	if (!key)
 		return NULL;
 
-	stkctr->table = &args->data.prx->table;
+	stkctr->table = args->data.t;
 	stkctr_set_entry(stkctr, stktable_get_entry(stkctr->table, key));
 	return stkctr;
 }
@@ -2709,7 +2738,7 @@
 	struct stksess *ts;
 	struct stktable_key *key;
 	void *ptr;
-	struct proxy *px;
+	struct stktable *t;
 
 	if (!conn)
 		return 0;
@@ -2719,17 +2748,17 @@
 		return 0;
 
 	/* Converts into key. */
-	key = smp_to_stkey(smp, &args->data.prx->table);
+	key = smp_to_stkey(smp, args->data.t);
 	if (!key)
 		return 0;
 
-	px = args->data.prx;
+	t = args->data.t;
 
-	if ((ts = stktable_get_entry(&px->table, key)) == NULL)
+	if ((ts = stktable_get_entry(t, key)) == NULL)
 		/* entry does not exist and could not be created */
 		return 0;
 
-	ptr = stktable_data_ptr(&px->table, ts, STKTABLE_DT_CONN_CNT);
+	ptr = stktable_data_ptr(t, ts, STKTABLE_DT_CONN_CNT);
 	if (!ptr) {
 		return 0; /* parameter not stored in this table */
 	}
@@ -2744,7 +2773,7 @@
 
 	smp->flags = SMP_F_VOL_TEST;
 
-	stktable_touch_local(&px->table, ts, 1);
+	stktable_touch_local(t, ts, 1);
 
 	/* Touch was previously performed by stktable_update_key */
 	return 1;
@@ -3229,12 +3258,12 @@
  */
 static int table_dump_head_to_buffer(struct buffer *msg,
                                      struct stream_interface *si,
-                                     struct proxy *proxy, struct proxy *target)
+                                     struct stktable *t, struct stktable *target)
 {
 	struct stream *s = si_strm(si);
 
 	chunk_appendf(msg, "# table: %s, type: %s, size:%d, used:%d\n",
-		     proxy->id, stktable_types[proxy->table.type].kw, proxy->table.size, proxy->table.current);
+		     t->id, stktable_types[t->type].kw, t->size, t->current);
 
 	/* any other information should be dumped here */
 
@@ -3255,32 +3284,32 @@
  */
 static int table_dump_entry_to_buffer(struct buffer *msg,
                                       struct stream_interface *si,
-                                      struct proxy *proxy, struct stksess *entry)
+                                      struct stktable *t, struct stksess *entry)
 {
 	int dt;
 
 	chunk_appendf(msg, "%p:", entry);
 
-	if (proxy->table.type == SMP_T_IPV4) {
+	if (t->type == SMP_T_IPV4) {
 		char addr[INET_ADDRSTRLEN];
 		inet_ntop(AF_INET, (const void *)&entry->key.key, addr, sizeof(addr));
 		chunk_appendf(msg, " key=%s", addr);
 	}
-	else if (proxy->table.type == SMP_T_IPV6) {
+	else if (t->type == SMP_T_IPV6) {
 		char addr[INET6_ADDRSTRLEN];
 		inet_ntop(AF_INET6, (const void *)&entry->key.key, addr, sizeof(addr));
 		chunk_appendf(msg, " key=%s", addr);
 	}
-	else if (proxy->table.type == SMP_T_SINT) {
+	else if (t->type == SMP_T_SINT) {
 		chunk_appendf(msg, " key=%u", *(unsigned int *)entry->key.key);
 	}
-	else if (proxy->table.type == SMP_T_STR) {
+	else if (t->type == SMP_T_STR) {
 		chunk_appendf(msg, " key=");
-		dump_text(msg, (const char *)entry->key.key, proxy->table.key_size);
+		dump_text(msg, (const char *)entry->key.key, t->key_size);
 	}
 	else {
 		chunk_appendf(msg, " key=");
-		dump_binary(msg, (const char *)entry->key.key, proxy->table.key_size);
+		dump_binary(msg, (const char *)entry->key.key, t->key_size);
 	}
 
 	chunk_appendf(msg, " use=%d exp=%d", entry->ref_cnt - 1, tick_remain(now_ms, entry->expire));
@@ -3288,14 +3317,14 @@
 	for (dt = 0; dt < STKTABLE_DATA_TYPES; dt++) {
 		void *ptr;
 
-		if (proxy->table.data_ofs[dt] == 0)
+		if (t->data_ofs[dt] == 0)
 			continue;
 		if (stktable_data_types[dt].arg_type == ARG_T_DELAY)
-			chunk_appendf(msg, " %s(%d)=", stktable_data_types[dt].name, proxy->table.data_arg[dt].u);
+			chunk_appendf(msg, " %s(%d)=", stktable_data_types[dt].name, t->data_arg[dt].u);
 		else
 			chunk_appendf(msg, " %s=", stktable_data_types[dt].name);
 
-		ptr = stktable_data_ptr(&proxy->table, entry, dt);
+		ptr = stktable_data_ptr(t, entry, dt);
 		switch (stktable_data_types[dt].std_type) {
 		case STD_T_SINT:
 			chunk_appendf(msg, "%d", stktable_data_cast(ptr, std_t_sint));
@@ -3309,7 +3338,7 @@
 		case STD_T_FRQP:
 			chunk_appendf(msg, "%d",
 				     read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
-							  proxy->table.data_arg[dt].u));
+							  t->data_arg[dt].u));
 			break;
 		}
 	}
@@ -3330,7 +3359,7 @@
 static int table_process_entry_per_key(struct appctx *appctx, char **args)
 {
 	struct stream_interface *si = appctx->owner;
-	struct proxy *px = appctx->ctx.table.target;
+	struct stktable *t = appctx->ctx.table.target;
 	struct stksess *ts;
 	uint32_t uint32_key;
 	unsigned char ip6_key[sizeof(struct in6_addr)];
@@ -3347,7 +3376,7 @@
 		return 1;
 	}
 
-	switch (px->table.type) {
+	switch (t->type) {
 	case SMP_T_IPV4:
 		uint32_key = htonl(inetaddr_host(args[4]));
 		static_table_key.key = &uint32_key;
@@ -3408,30 +3437,30 @@
 
 	switch (appctx->ctx.table.action) {
 	case STK_CLI_ACT_SHOW:
-		ts = stktable_lookup_key(&px->table, &static_table_key);
+		ts = stktable_lookup_key(t, &static_table_key);
 		if (!ts)
 			return 1;
 		chunk_reset(&trash);
-		if (!table_dump_head_to_buffer(&trash, si, px, px)) {
-			stktable_release(&px->table, ts);
+		if (!table_dump_head_to_buffer(&trash, si, t, t)) {
+			stktable_release(t, ts);
 			return 0;
 		}
 		HA_RWLOCK_RDLOCK(STK_SESS_LOCK, &ts->lock);
-		if (!table_dump_entry_to_buffer(&trash, si, px, ts)) {
+		if (!table_dump_entry_to_buffer(&trash, si, t, ts)) {
 			HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
-			stktable_release(&px->table, ts);
+			stktable_release(t, ts);
 			return 0;
 		}
 		HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &ts->lock);
-		stktable_release(&px->table, ts);
+		stktable_release(t, ts);
 		break;
 
 	case STK_CLI_ACT_CLR:
-		ts = stktable_lookup_key(&px->table, &static_table_key);
+		ts = stktable_lookup_key(t, &static_table_key);
 		if (!ts)
 			return 1;
 
-		if (!stksess_kill(&px->table, ts, 1)) {
+		if (!stksess_kill(t, ts, 1)) {
 			/* don't delete an entry which is currently referenced */
 			appctx->ctx.cli.severity = LOG_ERR;
 			appctx->ctx.cli.msg = "Entry currently in use, cannot remove\n";
@@ -3442,7 +3471,7 @@
 		break;
 
 	case STK_CLI_ACT_SET:
-		ts = stktable_get_entry(&px->table, &static_table_key);
+		ts = stktable_get_entry(t, &static_table_key);
 		if (!ts) {
 			/* don't delete an entry which is currently referenced */
 			appctx->ctx.cli.severity = LOG_ERR;
@@ -3458,7 +3487,7 @@
 				appctx->ctx.cli.msg = "\"data.<type>\" followed by a value expected\n";
 				appctx->st0 = CLI_ST_PRINT;
 				HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
-				stktable_touch_local(&px->table, ts, 1);
+				stktable_touch_local(t, ts, 1);
 				return 1;
 			}
 
@@ -3468,16 +3497,16 @@
 				appctx->ctx.cli.msg = "Unknown data type\n";
 				appctx->st0 = CLI_ST_PRINT;
 				HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
-				stktable_touch_local(&px->table, ts, 1);
+				stktable_touch_local(t, ts, 1);
 				return 1;
 			}
 
-			if (!px->table.data_ofs[data_type]) {
+			if (!t->data_ofs[data_type]) {
 				appctx->ctx.cli.severity = LOG_ERR;
 				appctx->ctx.cli.msg = "Data type not stored in this table\n";
 				appctx->st0 = CLI_ST_PRINT;
 				HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
-				stktable_touch_local(&px->table, ts, 1);
+				stktable_touch_local(t, ts, 1);
 				return 1;
 			}
 
@@ -3486,11 +3515,11 @@
 				appctx->ctx.cli.msg = "Require a valid integer value to store\n";
 				appctx->st0 = CLI_ST_PRINT;
 				HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
-				stktable_touch_local(&px->table, ts, 1);
+				stktable_touch_local(t, ts, 1);
 				return 1;
 			}
 
-			ptr = stktable_data_ptr(&px->table, ts, data_type);
+			ptr = stktable_data_ptr(t, ts, data_type);
 
 			switch (stktable_data_types[data_type].std_type) {
 			case STD_T_SINT:
@@ -3520,7 +3549,7 @@
 			}
 		}
 		HA_RWLOCK_WRUNLOCK(STK_SESS_LOCK, &ts->lock);
-		stktable_touch_local(&px->table, ts, 1);
+		stktable_touch_local(t, ts, 1);
 		break;
 
 	default:
@@ -3553,7 +3582,7 @@
 		return 1;
 	}
 
-	if (!((struct proxy *)appctx->ctx.table.target)->table.data_ofs[appctx->ctx.table.data_type]) {
+	if (!((struct proxy *)appctx->ctx.table.target)->table->data_ofs[appctx->ctx.table.data_type]) {
 		appctx->ctx.cli.severity = LOG_ERR;
 		appctx->ctx.cli.msg = "Data type not stored in this table\n";
 		appctx->st0 = CLI_ST_PRINT;
@@ -3584,12 +3613,11 @@
 {
 	appctx->ctx.table.data_type = -1;
 	appctx->ctx.table.target = NULL;
-	appctx->ctx.table.proxy = NULL;
 	appctx->ctx.table.entry = NULL;
 	appctx->ctx.table.action = (long)private; // keyword argument, one of STK_CLI_ACT_*
 
 	if (*args[2]) {
-		appctx->ctx.table.target = proxy_tbl_by_name(args[2]);
+		appctx->ctx.table.target = stktable_find_by_name(args[2]);
 		if (!appctx->ctx.table.target) {
 			appctx->ctx.cli.severity = LOG_ERR;
 			appctx->ctx.cli.msg = "No such table\n";
@@ -3663,7 +3691,7 @@
 	if (unlikely(si_ic(si)->flags & (CF_WRITE_ERROR|CF_SHUTW))) {
 		/* in case of abort, remove any refcount we might have set on an entry */
 		if (appctx->st2 == STAT_ST_LIST) {
-			stksess_kill_if_expired(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry, 1);
+			stksess_kill_if_expired(appctx->ctx.table.t, appctx->ctx.table.entry, 1);
 		}
 		return 1;
 	}
@@ -3673,42 +3701,42 @@
 	while (appctx->st2 != STAT_ST_FIN) {
 		switch (appctx->st2) {
 		case STAT_ST_INIT:
-			appctx->ctx.table.proxy = appctx->ctx.table.target;
-			if (!appctx->ctx.table.proxy)
-				appctx->ctx.table.proxy = proxies_list;
+			appctx->ctx.table.t = appctx->ctx.table.target;
+			if (!appctx->ctx.table.t)
+				appctx->ctx.table.t = stktables_list;
 
 			appctx->ctx.table.entry = NULL;
 			appctx->st2 = STAT_ST_INFO;
 			break;
 
 		case STAT_ST_INFO:
-			if (!appctx->ctx.table.proxy ||
+			if (!appctx->ctx.table.t ||
 			    (appctx->ctx.table.target &&
-			     appctx->ctx.table.proxy != appctx->ctx.table.target)) {
+			     appctx->ctx.table.t != appctx->ctx.table.target)) {
 				appctx->st2 = STAT_ST_END;
 				break;
 			}
 
-			if (appctx->ctx.table.proxy->table.size) {
-				if (show && !table_dump_head_to_buffer(&trash, si, appctx->ctx.table.proxy, appctx->ctx.table.target))
+			if (appctx->ctx.table.t->size) {
+				if (show && !table_dump_head_to_buffer(&trash, si, appctx->ctx.table.t, appctx->ctx.table.target))
 					return 0;
 
 				if (appctx->ctx.table.target &&
 				    (strm_li(s)->bind_conf->level & ACCESS_LVL_MASK) >= ACCESS_LVL_OPER) {
 					/* dump entries only if table explicitly requested */
-					HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
-					eb = ebmb_first(&appctx->ctx.table.proxy->table.keys);
+					HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
+					eb = ebmb_first(&appctx->ctx.table.t->keys);
 					if (eb) {
 						appctx->ctx.table.entry = ebmb_entry(eb, struct stksess, key);
 						appctx->ctx.table.entry->ref_cnt++;
 						appctx->st2 = STAT_ST_LIST;
-						HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
+						HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
 						break;
 					}
-					HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
+					HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
 				}
 			}
-			appctx->ctx.table.proxy = appctx->ctx.table.proxy->next;
+			appctx->ctx.table.t = appctx->ctx.table.t->next;
 			break;
 
 		case STAT_ST_LIST:
@@ -3723,7 +3751,7 @@
 
 
 				dt = appctx->ctx.table.data_type;
-				ptr = stktable_data_ptr(&appctx->ctx.table.proxy->table,
+				ptr = stktable_data_ptr(appctx->ctx.table.t,
 							appctx->ctx.table.entry,
 							dt);
 
@@ -3740,7 +3768,7 @@
 					break;
 				case STD_T_FRQP:
 					data = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
-								    appctx->ctx.table.proxy->table.data_arg[dt].u);
+								    appctx->ctx.table.t->data_arg[dt].u);
 					break;
 				}
 
@@ -3761,14 +3789,14 @@
 			}
 
 			if (show && !skip_entry &&
-			    !table_dump_entry_to_buffer(&trash, si, appctx->ctx.table.proxy, appctx->ctx.table.entry)) {
+			    !table_dump_entry_to_buffer(&trash, si, appctx->ctx.table.t, appctx->ctx.table.entry)) {
 				HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &appctx->ctx.table.entry->lock);
 				return 0;
 			}
 
 			HA_RWLOCK_RDUNLOCK(STK_SESS_LOCK, &appctx->ctx.table.entry->lock);
 
-			HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
+			HA_SPIN_LOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
 			appctx->ctx.table.entry->ref_cnt--;
 
 			eb = ebmb_next(&appctx->ctx.table.entry->key);
@@ -3776,23 +3804,23 @@
 				struct stksess *old = appctx->ctx.table.entry;
 				appctx->ctx.table.entry = ebmb_entry(eb, struct stksess, key);
 				if (show)
-					__stksess_kill_if_expired(&appctx->ctx.table.proxy->table, old);
+					__stksess_kill_if_expired(appctx->ctx.table.t, old);
 				else if (!skip_entry && !appctx->ctx.table.entry->ref_cnt)
-					__stksess_kill(&appctx->ctx.table.proxy->table, old);
+					__stksess_kill(appctx->ctx.table.t, old);
 				appctx->ctx.table.entry->ref_cnt++;
-				HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
+				HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
 				break;
 			}
 
 
 			if (show)
-				__stksess_kill_if_expired(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry);
+				__stksess_kill_if_expired(appctx->ctx.table.t, appctx->ctx.table.entry);
 			else if (!skip_entry && !appctx->ctx.table.entry->ref_cnt)
-				__stksess_kill(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry);
+				__stksess_kill(appctx->ctx.table.t, appctx->ctx.table.entry);
 
-			HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.proxy->table.lock);
+			HA_SPIN_UNLOCK(STK_TABLE_LOCK, &appctx->ctx.table.t->lock);
 
-			appctx->ctx.table.proxy = appctx->ctx.table.proxy->next;
+			appctx->ctx.table.t = appctx->ctx.table.t->next;
 			appctx->st2 = STAT_ST_INFO;
 			break;
 
@@ -3807,7 +3835,7 @@
 static void cli_release_show_table(struct appctx *appctx)
 {
 	if (appctx->st2 == STAT_ST_LIST) {
-		stksess_kill_if_expired(&appctx->ctx.table.proxy->table, appctx->ctx.table.entry, 1);
+		stksess_kill_if_expired(appctx->ctx.table.t, appctx->ctx.table.entry, 1);
 	}
 }