diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c
index 1c49622be7..e271cc50eb 100644
--- a/lib/pipeline/rte_swx_pipeline.c
+++ b/lib/pipeline/rte_swx_pipeline.c
@@ -2401,6 +2401,7 @@ instr_table_exec(struct rte_swx_pipeline *p)
 	struct table_statistics *stats = &p->table_stats[table_id];
 	uint64_t action_id, n_pkts_hit, n_pkts_action;
 	uint8_t *action_data;
+	size_t entry_id;
 	int done, hit;
 
 	/* Table. */
@@ -2409,6 +2410,7 @@ instr_table_exec(struct rte_swx_pipeline *p)
 			   table->key,
 			   &action_id,
 			   &action_data,
+			   &entry_id,
 			   &hit);
 	if (!done) {
 		/* Thread. */
@@ -2422,6 +2424,7 @@ instr_table_exec(struct rte_swx_pipeline *p)
 
 	action_id = hit ? action_id : ts->default_action_id;
 	action_data = hit ? action_data : ts->default_action_data;
+	entry_id = hit ? (1 + entry_id) : 0;
 	n_pkts_hit = stats->n_pkts_hit[hit];
 	n_pkts_action = stats->n_pkts_action[action_id];
 
@@ -2433,6 +2436,7 @@ instr_table_exec(struct rte_swx_pipeline *p)
 
 	t->action_id = action_id;
 	t->structs[0] = action_data;
+	t->entry_id = entry_id;
 	t->hit = hit;
 	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
 	stats->n_pkts_action[action_id] = n_pkts_action + 1;
@@ -2452,6 +2456,7 @@ instr_table_af_exec(struct rte_swx_pipeline *p)
 	struct table_statistics *stats = &p->table_stats[table_id];
 	uint64_t action_id, n_pkts_hit, n_pkts_action;
 	uint8_t *action_data;
+	size_t entry_id;
 	action_func_t action_func;
 	int done, hit;
 
@@ -2461,6 +2466,7 @@ instr_table_af_exec(struct rte_swx_pipeline *p)
 			   table->key,
 			   &action_id,
 			   &action_data,
+			   &entry_id,
 			   &hit);
 	if (!done) {
 		/* Thread. */
@@ -2474,6 +2480,7 @@ instr_table_af_exec(struct rte_swx_pipeline *p)
 
 	action_id = hit ? action_id : ts->default_action_id;
 	action_data = hit ? action_data : ts->default_action_data;
+	entry_id = hit ? (1 + entry_id) : 0;
 	action_func = p->action_funcs[action_id];
 	n_pkts_hit = stats->n_pkts_hit[hit];
 	n_pkts_action = stats->n_pkts_action[action_id];
@@ -2486,6 +2493,7 @@ instr_table_af_exec(struct rte_swx_pipeline *p)
 
 	t->action_id = action_id;
 	t->structs[0] = action_data;
+	t->entry_id = entry_id;
 	t->hit = hit;
 	stats->n_pkts_hit[hit] = n_pkts_hit + 1;
 	stats->n_pkts_action[action_id] = n_pkts_action + 1;
@@ -8283,6 +8291,7 @@ table_stub_lkp(void *table __rte_unused,
 	       uint8_t **key __rte_unused,
 	       uint64_t *action_id __rte_unused,
 	       uint8_t **action_data __rte_unused,
+	       size_t *entry_id __rte_unused,
 	       int *hit)
 {
 	*hit = 0;
diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h
index ef60288dca..8f96b67d76 100644
--- a/lib/pipeline/rte_swx_pipeline_internal.h
+++ b/lib/pipeline/rte_swx_pipeline_internal.h
@@ -1009,6 +1009,7 @@ struct thread {
 	struct learner_runtime *learners;
 	struct rte_swx_table_state *table_state;
 	uint64_t action_id;
+	size_t entry_id;
 	int hit; /* 0 = Miss, 1 = Hit. */
 	uint32_t learner_id;
 	uint64_t time;
diff --git a/lib/table/rte_swx_table.h b/lib/table/rte_swx_table.h
index 4b8dc06798..ac01e19781 100644
--- a/lib/table/rte_swx_table.h
+++ b/lib/table/rte_swx_table.h
@@ -233,6 +233,15 @@ typedef int
  * data likely to be read from the CPU cache with no CPU pipeline stall, which
  * significantly improves the table lookup performance.
  *
+ * The table entry consists of the action ID and the action data. Each table
+ * entry is unique, although different table entries can have identical content,
+ * i.e. same values for the action ID and the action data. The table entry ID is
+ * also returned by the table lookup operation. It can be used to index into an
+ * external array of resources such as counters, registers or meters to identify
+ * the resource directly associated with the current table entry with no need to
+ * store the corresponding index into the table entry. The index of the external
+ * resource is thus auto-generated instead of being stored in the table entry.
+ *
  * @param[in] table
  *   Table handle.
  * @param[in] mailbox
@@ -247,6 +256,9 @@ typedef int
  *   Action data for the *action_id* action. Must point to a valid array of
  *   table *action_data_size* bytes. Only valid when the function returns 1 and
  *   *hit* is set to true.
+ * @param[out] entry_id
+ *   Table entry unique ID. Must point to a valid 32-bit variable. Only valid
+ *   when the function returns 1 and *hit* is set to true.
  * @param[out] hit
  *   Only valid when the function returns 1. Set to non-zero (true) on table
  *   lookup hit and to zero (false) on table lookup miss.
@@ -260,6 +272,7 @@ typedef int
 			  uint8_t **key,
 			  uint64_t *action_id,
 			  uint8_t **action_data,
+			  size_t *entry_id,
 			  int *hit);
 
 /**
diff --git a/lib/table/rte_swx_table_em.c b/lib/table/rte_swx_table_em.c
index 568e76e249..2b5201e006 100644
--- a/lib/table/rte_swx_table_em.c
+++ b/lib/table/rte_swx_table_em.c
@@ -403,6 +403,7 @@ table_lookup_unoptimized(void *table,
 			 uint8_t **key,
 			 uint64_t *action_id,
 			 uint8_t **action_data,
+			 size_t *entry_id,
 			 int *hit)
 {
 	struct table *t = table;
@@ -431,6 +432,7 @@ table_lookup_unoptimized(void *table,
 				bkt_data = table_key_data(t, bkt_key_id);
 				*action_id = bkt_data[0];
 				*action_data = (uint8_t *)&bkt_data[1];
+				*entry_id = bkt_key_id;
 				*hit = 1;
 				return 1;
 			}
@@ -500,6 +502,7 @@ table_lookup(void *table,
 	     uint8_t **key,
 	     uint64_t *action_id,
 	     uint8_t **action_data,
+	     size_t *entry_id,
 	     int *hit)
 {
 	struct table *t = table;
@@ -576,6 +579,7 @@ table_lookup(void *table,
 		lkp_hit &= m->sig_match;
 		*action_id = bkt_data[0];
 		*action_data = (uint8_t *)&bkt_data[1];
+		*entry_id = bkt_key_id;
 		*hit = lkp_hit;
 
 		m->state = 0;
@@ -586,6 +590,7 @@ table_lookup(void *table,
 							key,
 							action_id,
 							action_data,
+							entry_id,
 							hit);
 
 		return 1;
diff --git a/lib/table/rte_swx_table_wm.c b/lib/table/rte_swx_table_wm.c
index ce2a78f94c..58afb35d46 100644
--- a/lib/table/rte_swx_table_wm.c
+++ b/lib/table/rte_swx_table_wm.c
@@ -436,6 +436,7 @@ table_lookup(void *table,
 	     const uint8_t **key,
 	     uint64_t *action_id,
 	     uint8_t **action_data,
+	     size_t *entry_id,
 	     int *hit)
 {
 	struct table *t = table;
@@ -451,6 +452,7 @@ table_lookup(void *table,
 	data = &t->data[(user_data - 1) * t->entry_data_size];
 	*action_id = ((uint64_t *)data)[0];
 	*action_data = &data[8];
+	*entry_id = user_data - 1;
 	*hit = 1;
 	return 1;
 }
