diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 6a8d8f4..e18e801 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -221,6 +221,17 @@ struct mlx5_dev_spawn_data {
 		.free = rte_free,
 		.type = "mlx5_push_vlan_ipool",
 	},
+	{
+		.size = sizeof(struct mlx5_flow_dv_tag_resource),
+		.trunk_size = 64,
+		.grow_trunk = 3,
+		.grow_shift = 2,
+		.need_lock = 0,
+		.release_mem_en = 1,
+		.malloc = rte_malloc_socket,
+		.free = rte_free,
+		.type = "mlx5_tag_ipool",
+	},
 };
 
 
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 86cf8ad..59ba9e2 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -47,6 +47,7 @@
 enum mlx5_ipool_index {
 	MLX5_IPOOL_DECAP_ENCAP = 0, /* Pool for encap/decap resource. */
 	MLX5_IPOOL_PUSH_VLAN, /* Pool for push vlan resource. */
+	MLX5_IPOOL_TAG, /* Pool for tag resource. */
 	MLX5_IPOOL_MAX,
 };
 
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 46fdab0..8f9f5e6 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -383,6 +383,7 @@ struct mlx5_flow_dv_tag_resource {
 	void *action;
 	/**< Verbs tag action object. */
 	rte_atomic32_t refcnt; /**< Reference counter. */
+	uint32_t idx; /**< Index for the index memory pool. */
 };
 
 /*
@@ -494,8 +495,8 @@ struct mlx5_flow_handle_dv {
 	/**< Structure for VF VLAN workaround. */
 	uint32_t push_vlan_res;
 	/**< Index to push VLAN action resource in cache. */
-	struct mlx5_flow_dv_tag_resource *tag_resource;
-	/**< pointer to the tag action. */
+	uint32_t tag_resource;
+	/**< Index to the tag action. */
 };
 
 /** Device flow handle structure: used both for creating & destroying. */
@@ -547,6 +548,8 @@ struct mlx5_flow_dv_workspace {
 	/**< Pointer to encap/decap resource in cache. */
 	struct mlx5_flow_dv_push_vlan_action_resource *push_vlan_res;
 	/**< Pointer to push VLAN action resource in cache. */
+	struct mlx5_flow_dv_tag_resource *tag_resource;
+	/**< pointer to the tag action. */
 	struct mlx5_flow_dv_match_params value;
 	/**< Holds the value that the packet is compared to. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 8688cab..5aa624d 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7092,14 +7092,16 @@ struct field_modify_info modify_tcp[] = {
 		cache_resource = container_of
 			(entry, struct mlx5_flow_dv_tag_resource, entry);
 		rte_atomic32_inc(&cache_resource->refcnt);
-		dev_flow->handle->dvh.tag_resource = cache_resource;
+		dev_flow->handle->dvh.tag_resource = cache_resource->idx;
+		dev_flow->dv.tag_resource = cache_resource;
 		DRV_LOG(DEBUG, "cached tag resource %p: refcnt now %d++",
 			(void *)cache_resource,
 			rte_atomic32_read(&cache_resource->refcnt));
 		return 0;
 	}
 	/* Register new resource. */
-	cache_resource = rte_calloc(__func__, 1, sizeof(*cache_resource), 0);
+	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG],
+				       &dev_flow->handle->dvh.tag_resource);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -7121,7 +7123,7 @@ struct field_modify_info modify_tcp[] = {
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 					  NULL, "cannot insert tag");
 	}
-	dev_flow->handle->dvh.tag_resource = cache_resource;
+	dev_flow->dv.tag_resource = cache_resource;
 	DRV_LOG(DEBUG, "new tag resource %p: refcnt now %d++",
 		(void *)cache_resource,
 		rte_atomic32_read(&cache_resource->refcnt));
@@ -7133,20 +7135,23 @@ struct field_modify_info modify_tcp[] = {
  *
  * @param dev
  *   Pointer to Ethernet device.
- * @param flow
- *   Pointer to mlx5_flow.
+ * @param tag_idx
+ *   Tag index.
  *
  * @return
  *   1 while a reference on it exists, 0 when freed.
  */
 static int
 flow_dv_tag_release(struct rte_eth_dev *dev,
-		    struct mlx5_flow_dv_tag_resource *tag)
+		    uint32_t tag_idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_ibv_shared *sh = priv->sh;
+	struct mlx5_flow_dv_tag_resource *tag;
 
-	MLX5_ASSERT(tag);
+	tag = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx);
+	if (!tag)
+		return 0;
 	DRV_LOG(DEBUG, "port %u tag %p: refcnt %d--",
 		dev->data->port_id, (void *)tag,
 		rte_atomic32_read(&tag->refcnt));
@@ -7155,7 +7160,7 @@ struct field_modify_info modify_tcp[] = {
 		mlx5_hlist_remove(sh->tag_table, &tag->entry);
 		DRV_LOG(DEBUG, "port %u tag %p: removed",
 			dev->data->port_id, (void *)tag);
-		rte_free(tag);
+		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_TAG], tag_idx);
 		return 0;
 	}
 	return 1;
@@ -7452,8 +7457,9 @@ struct field_modify_info modify_tcp[] = {
 			if (flow_dv_tag_resource_register(dev, tag_be,
 							  dev_flow, error))
 				return -rte_errno;
+			MLX5_ASSERT(dev_flow->dv.tag_resource);
 			dev_flow->dv.actions[actions_n++] =
-					handle->dvh.tag_resource->action;
+					dev_flow->dv.tag_resource->action;
 			break;
 		case RTE_FLOW_ACTION_TYPE_MARK:
 			action_flags |= MLX5_FLOW_ACTION_MARK;
@@ -7479,8 +7485,9 @@ struct field_modify_info modify_tcp[] = {
 			if (flow_dv_tag_resource_register(dev, tag_be,
 							  dev_flow, error))
 				return -rte_errno;
+			MLX5_ASSERT(dev_flow->dv.tag_resource);
 			dev_flow->dv.actions[actions_n++] =
-					handle->dvh.tag_resource->action;
+					dev_flow->dv.tag_resource->action;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_META:
 			if (flow_dv_convert_action_set_meta
