diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index a5c50ff..245685e 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -336,6 +336,18 @@ static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 		.need_lock = 1,
 		.type = "mlx5_flow_tnl_tbl_ipool",
 	},
+	{
+		.size = sizeof(struct mlx5_shared_action_rss),
+		.trunk_size = 64,
+		.grow_trunk = 3,
+		.grow_shift = 2,
+		.need_lock = 1,
+		.release_mem_en = 1,
+		.malloc = mlx5_malloc,
+		.free = mlx5_free,
+		.type = "mlx5_shared_action_rss",
+	},
+
 };
 
 
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index cf6975d..9b1e5d5 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -53,6 +53,7 @@ enum mlx5_ipool_index {
 	MLX5_IPOOL_RSS_EXPANTION_FLOW_ID, /* Pool for Queue/RSS flow ID. */
 	MLX5_IPOOL_TUNNEL_ID, /* Pool for flow tunnel ID. */
 	MLX5_IPOOL_TNL_TBL_ID, /* Pool for tunnel table ID. */
+	MLX5_IPOOL_RSS_SHARED_ACTIONS, /* Pool for RSS shared actions. */
 	MLX5_IPOOL_MAX,
 };
 
@@ -895,8 +896,6 @@ enum mlx5_txq_modify_type {
 	MLX5_TXQ_MOD_ERR2RDY, /* modify state from error to ready. */
 };
 
-
-
 /* HW objects operations structure. */
 struct mlx5_obj_ops {
 	int (*rxq_obj_modify_vlan_strip)(struct mlx5_rxq_obj *rxq_obj, int on);
@@ -922,6 +921,8 @@ struct mlx5_obj_ops {
 	void (*txq_obj_release)(struct mlx5_txq_obj *txq_obj);
 };
 
+#define MLX5_RSS_HASH_FIELDS_LEN RTE_DIM(mlx5_rss_hash_fields)
+
 struct mlx5_priv {
 	struct rte_eth_dev_data *dev_data;  /* Pointer to device data. */
 	struct mlx5_dev_ctx_shared *sh; /* Shared device context. */
@@ -998,8 +999,7 @@ struct mlx5_priv {
 	struct mlx5_mp_id mp_id; /* ID of a multi-process process */
 	LIST_HEAD(fdir, mlx5_fdir_flow) fdir_flows; /* fdir flows. */
 	rte_spinlock_t shared_act_sl; /* Shared actions spinlock. */
-	LIST_HEAD(shared_action, rte_flow_shared_action) shared_actions;
-	/* shared actions */
+	uint32_t rss_shared_actions; /* RSS shared actions. */
 };
 
 #define PORT_ID(priv) ((priv)->dev_data->port_id)
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index a6e60af..29e67f4 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -3306,6 +3306,8 @@ struct mlx5_translated_shared_action {
  * action handling should be preformed on *shared* actions list returned
  * from this call.
  *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
  * @param[in] actions
  *   List of actions to translate.
  * @param[out] shared
@@ -3323,12 +3325,14 @@ struct mlx5_translated_shared_action {
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 static int
-flow_shared_actions_translate(const struct rte_flow_action actions[],
-	struct mlx5_translated_shared_action *shared,
-	int *shared_n,
-	struct rte_flow_action **translated_actions,
-	struct rte_flow_error *error)
+flow_shared_actions_translate(struct rte_eth_dev *dev,
+			      const struct rte_flow_action actions[],
+			      struct mlx5_translated_shared_action *shared,
+			      int *shared_n,
+			      struct rte_flow_action **translated_actions,
+			      struct rte_flow_error *error)
 {
+	struct mlx5_priv *priv = dev->data->dev_private;
 	struct rte_flow_action *translated = NULL;
 	size_t actions_size;
 	int n;
@@ -3360,15 +3364,20 @@ struct mlx5_translated_shared_action {
 	}
 	memcpy(translated, actions, actions_size);
 	for (shared_end = shared + copied_n; shared < shared_end; shared++) {
-		const struct rte_flow_shared_action *shared_action;
-
-		shared_action = shared->action;
-		switch (shared_action->type) {
-		case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
+		struct mlx5_shared_action_rss *shared_rss;
+		uint32_t act_idx = (uint32_t)(uintptr_t)shared->action;
+		uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+		uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET)
+									   - 1);
+
+		switch (type) {
+		case MLX5_SHARED_ACTION_TYPE_RSS:
+			shared_rss = mlx5_ipool_get
+			  (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
 			translated[shared->index].type =
 				RTE_FLOW_ACTION_TYPE_RSS;
 			translated[shared->index].conf =
-				&shared_action->rss.origin;
+				&shared_rss->origin;
 			break;
 		default:
 			mlx5_free(translated);
@@ -3384,44 +3393,44 @@ struct mlx5_translated_shared_action {
 /**
  * Get Shared RSS action from the action list.
  *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
  * @param[in] shared
  *   Pointer to the list of actions.
  * @param[in] shared_n
  *   Actions list length.
  *
  * @return
- *   Pointer to the MLX5 RSS action if exists, otherwise return NULL.
+ *   The MLX5 RSS action ID if exists, otherwise return 0.
  */
-static struct mlx5_shared_action_rss *
-flow_get_shared_rss_action(struct mlx5_translated_shared_action *shared,
+static uint32_t
+flow_get_shared_rss_action(struct rte_eth_dev *dev,
+			   struct mlx5_translated_shared_action *shared,
 			   int shared_n)
 {
 	struct mlx5_translated_shared_action *shared_end;
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_shared_action_rss *shared_rss;
 
-	for (shared_end = shared + shared_n; shared < shared_end; shared++) {
-		struct rte_flow_shared_action *shared_action;
 
-		shared_action = shared->action;
-		switch (shared_action->type) {
-		case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
-			__atomic_add_fetch(&shared_action->refcnt, 1,
+	for (shared_end = shared + shared_n; shared < shared_end; shared++) {
+		uint32_t act_idx = (uint32_t)(uintptr_t)shared->action;
+		uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+		uint32_t idx = act_idx &
+				   ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1);
+		switch (type) {
+		case MLX5_SHARED_ACTION_TYPE_RSS:
+			shared_rss = mlx5_ipool_get
+				(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+									   idx);
+			__atomic_add_fetch(&shared_rss->refcnt, 1,
 					   __ATOMIC_RELAXED);
-			return &shared_action->rss;
+			return idx;
 		default:
 			break;
 		}
 	}
-	return NULL;
-}
-
-struct rte_flow_shared_action *
-mlx5_flow_get_shared_rss(struct rte_flow *flow)
-{
-	if (flow->shared_rss)
-		return container_of(flow->shared_rss,
-				    struct rte_flow_shared_action, rss);
-	else
-		return NULL;
+	return 0;
 }
 
 static unsigned int
@@ -5538,7 +5547,7 @@ struct tunnel_default_miss_ctx {
 
 	MLX5_ASSERT(wks);
 	rss_desc = &wks->rss_desc[fidx];
-	ret = flow_shared_actions_translate(original_actions,
+	ret = flow_shared_actions_translate(dev, original_actions,
 					    shared_actions,
 					    &shared_actions_n,
 					    &translated_actions, error);
@@ -5599,7 +5608,7 @@ struct tunnel_default_miss_ctx {
 		buf->entries = 1;
 		buf->entry[0].pattern = (void *)(uintptr_t)items;
 	}
-	flow->shared_rss = flow_get_shared_rss_action(shared_actions,
+	flow->shared_rss = flow_get_shared_rss_action(dev, shared_actions,
 						      shared_actions_n);
 	/*
 	 * Record the start index when there is a nested call. All sub-flows
@@ -5787,7 +5796,7 @@ struct rte_flow *
 	int shared_actions_n = MLX5_MAX_SHARED_ACTIONS;
 	const struct rte_flow_action *actions;
 	struct rte_flow_action *translated_actions = NULL;
-	int ret = flow_shared_actions_translate(original_actions,
+	int ret = flow_shared_actions_translate(dev, original_actions,
 						shared_actions,
 						&shared_actions_n,
 						&translated_actions, error);
@@ -7856,25 +7865,11 @@ struct mlx5_meter_domains_infos *
 			flow_get_drv_ops(flow_get_drv_type(dev, &attr));
 	int ret;
 
-	switch (shared_action->type) {
-	case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
-		if (action->type != RTE_FLOW_ACTION_TYPE_RSS) {
-			return rte_flow_error_set(error, EINVAL,
-						  RTE_FLOW_ERROR_TYPE_ACTION,
-						  NULL,
-						  "update action type invalid");
-		}
-		ret = flow_drv_action_validate(dev, NULL, action, fops, error);
-		if (ret)
-			return ret;
-		return flow_drv_action_update(dev, shared_action, action->conf,
-					      fops, error);
-	default:
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
-					  NULL,
-					  "action type not supported");
-	}
+	ret = flow_drv_action_validate(dev, NULL, action, fops, error);
+	if (ret)
+		return ret;
+	return flow_drv_action_update(dev, shared_action, action->conf, fops,
+				      error);
 }
 
 /**
@@ -7906,17 +7901,10 @@ struct mlx5_meter_domains_infos *
 			 struct rte_flow_error *error)
 {
 	(void)dev;
-	switch (action->type) {
-	case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
-		__atomic_load(&action->refcnt, (uint32_t *)data,
-			      __ATOMIC_RELAXED);
-		return 0;
-	default:
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
-					  NULL,
-					  "action type not supported");
-	}
+	(void)action;
+	(void)data;
+	return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
+				  NULL, "action type query not supported");
 }
 
 /**
@@ -7933,12 +7921,14 @@ struct mlx5_meter_domains_infos *
 {
 	struct rte_flow_error error;
 	struct mlx5_priv *priv = dev->data->dev_private;
-	struct rte_flow_shared_action *action;
+	struct mlx5_shared_action_rss *action;
 	int ret = 0;
+	uint32_t idx;
 
-	while (!LIST_EMPTY(&priv->shared_actions)) {
-		action = LIST_FIRST(&priv->shared_actions);
-		ret = mlx5_shared_action_destroy(dev, action, &error);
+	ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+		      priv->rss_shared_actions, idx, action, next) {
+		ret |= mlx5_shared_action_destroy(dev,
+		       (struct rte_flow_shared_action *)(uintptr_t)idx, &error);
 	}
 	return ret;
 }
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 1b4a9d1..742971c 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -35,10 +35,15 @@ enum mlx5_rte_flow_action_type {
 	MLX5_RTE_FLOW_ACTION_TYPE_MARK,
 	MLX5_RTE_FLOW_ACTION_TYPE_COPY_MREG,
 	MLX5_RTE_FLOW_ACTION_TYPE_DEFAULT_MISS,
-	MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS,
 	MLX5_RTE_FLOW_ACTION_TYPE_TUNNEL_SET,
 };
 
+#define MLX5_SHARED_ACTION_TYPE_OFFSET 30
+
+enum {
+	MLX5_SHARED_ACTION_TYPE_RSS,
+};
+
 /* Matches on selected register. */
 struct mlx5_rte_flow_item_tag {
 	enum modify_reg id;
@@ -1024,7 +1029,7 @@ struct tunnel_tbl_entry {
 /* Flow structure. */
 struct rte_flow {
 	ILIST_ENTRY(uint32_t)next; /**< Index to the next flow structure. */
-	struct mlx5_shared_action_rss *shared_rss; /** < Shred RSS action. */
+	uint32_t shared_rss; /** < Shared RSS action ID. */
 	uint32_t dev_handles;
 	/**< Device flow handles that are part of the flow. */
 	uint32_t drv_type:2; /**< Driver type. */
@@ -1069,10 +1074,10 @@ struct rte_flow {
 	MLX5_RSS_HASH_NONE,
 };
 
-#define MLX5_RSS_HASH_FIELDS_LEN RTE_DIM(mlx5_rss_hash_fields)
-
 /* Shared RSS action structure */
 struct mlx5_shared_action_rss {
+	ILIST_ENTRY(uint32_t)next; /**< Index to the next RSS structure. */
+	uint32_t refcnt; /**< Atomically accessed refcnt. */
 	struct rte_flow_action_rss origin; /**< Original rte RSS action. */
 	uint8_t key[MLX5_RSS_HASH_KEY_LEN]; /**< RSS hash key. */
 	uint16_t *queue; /**< Queue indices to use. */
@@ -1083,15 +1088,7 @@ struct mlx5_shared_action_rss {
 };
 
 struct rte_flow_shared_action {
-	LIST_ENTRY(rte_flow_shared_action) next;
-		/**< Pointer to the next element. */
-	uint32_t refcnt; /**< Atomically accessed refcnt. */
-	uint64_t type;
-		/**< Shared action type (see MLX5_FLOW_ACTION_SHARED_*). */
-	union {
-		struct mlx5_shared_action_rss rss;
-			/**< Shared RSS action. */
-	};
+	uint32_t id;
 };
 
 /* Thread specific flow workspace intermediate data. */
@@ -1391,7 +1388,6 @@ int mlx5_flow_destroy_policer_rules(struct rte_eth_dev *dev,
 int mlx5_flow_meter_flush(struct rte_eth_dev *dev,
 			  struct rte_mtr_error *error);
 int mlx5_flow_dv_discover_counter_offset_support(struct rte_eth_dev *dev);
-struct rte_flow_shared_action *mlx5_flow_get_shared_rss(struct rte_flow *flow);
 int mlx5_shared_action_flush(struct rte_eth_dev *dev);
 void mlx5_release_tunnel_hub(struct mlx5_dev_ctx_shared *sh, uint16_t port_id);
 int mlx5_alloc_tunnel_hub(struct mlx5_dev_ctx_shared *sh);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index dcc397d..05f5871 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -10509,8 +10509,10 @@ struct mlx5_cache_entry *
  * Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)
  * and tunnel.
  *
- * @param[in] action
- *   Shred RSS action holding hash RX queue objects.
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] idx
+ *   Shared RSS action ID holding hash RX queue objects.
  * @param[in] hash_fields
  *   Defines combination of packet fields to participate in RX hash.
  * @param[in] tunnel
@@ -10520,11 +10522,15 @@ struct mlx5_cache_entry *
  *   Valid hash RX queue index, otherwise 0.
  */
 static uint32_t
-__flow_dv_action_rss_hrxq_lookup(const struct mlx5_shared_action_rss *action,
+__flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
 				 const uint64_t hash_fields,
 				 const int tunnel)
 {
-	const uint32_t *hrxqs = tunnel ? action->hrxq : action->hrxq_tunnel;
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_shared_action_rss *shared_rss =
+	    mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
+	const uint32_t *hrxqs = tunnel ? shared_rss->hrxq :
+							shared_rss->hrxq_tunnel;
 
 	switch (hash_fields & ~IBV_RX_HASH_INNER) {
 	case MLX5_RSS_HASH_IPV4:
@@ -10551,6 +10557,8 @@ struct mlx5_cache_entry *
  * If shared action configured for *flow* suitable hash RX queue will be
  * retrieved from attached shared action.
  *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
  * @param[in] flow
  *   Shred RSS action holding hash RX queue objects.
  * @param[in] dev_flow
@@ -10572,7 +10580,7 @@ struct mlx5_cache_entry *
 
 	if (flow->shared_rss) {
 		hrxq_idx = __flow_dv_action_rss_hrxq_lookup
-				(flow->shared_rss, dev_flow->hash_fields,
+				(dev, flow->shared_rss, dev_flow->hash_fields,
 				 !!(dev_flow->handle->layers &
 				    MLX5_FLOW_LAYER_TUNNEL));
 		if (hrxq_idx) {
@@ -11101,16 +11109,19 @@ struct mlx5_cache_entry *
 static void
 flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
 {
-	struct rte_flow_shared_action *shared;
 	struct mlx5_flow_handle *dev_handle;
 	struct mlx5_priv *priv = dev->data->dev_private;
 
 	if (!flow)
 		return;
 	flow_dv_remove(dev, flow);
-	shared = mlx5_flow_get_shared_rss(flow);
-	if (shared)
-		__atomic_sub_fetch(&shared->refcnt, 1, __ATOMIC_RELAXED);
+	if (flow->shared_rss) {
+		struct mlx5_shared_action_rss *shared_rss = mlx5_ipool_get
+				(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+							      flow->shared_rss);
+
+		__atomic_sub_fetch(&shared_rss->refcnt, 1, __ATOMIC_RELAXED);
+	}
 	if (flow->counter) {
 		flow_dv_counter_free(dev, flow->counter);
 		flow->counter = 0;
@@ -11281,56 +11292,69 @@ struct mlx5_cache_entry *
  *   error only.
  *
  * @return
- *   A valid shared action handle in case of success, NULL otherwise and
+ *   A valid shared action ID in case of success, 0 otherwise and
  *   rte_errno is set.
  */
-static struct rte_flow_shared_action *
+static uint32_t
 __flow_dv_action_rss_create(struct rte_eth_dev *dev,
 			    const struct rte_flow_shared_action_conf *conf,
 			    const struct rte_flow_action_rss *rss,
 			    struct rte_flow_error *error)
 {
-	struct rte_flow_shared_action *shared_action = NULL;
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_shared_action_rss *shared_action = NULL;
 	void *queue = NULL;
-	struct mlx5_shared_action_rss *shared_rss;
 	struct rte_flow_action_rss *origin;
 	const uint8_t *rss_key;
 	uint32_t queue_size = rss->queue_num * sizeof(uint16_t);
+	uint32_t idx;
 
 	RTE_SET_USED(conf);
 	queue = mlx5_malloc(0, RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
 			    0, SOCKET_ID_ANY);
-	shared_action = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*shared_action), 0,
-				    SOCKET_ID_ANY);
+	shared_action = mlx5_ipool_zmalloc
+			 (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
 	if (!shared_action || !queue) {
 		rte_flow_error_set(error, ENOMEM,
 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
 				   "cannot allocate resource memory");
 		goto error_rss_init;
 	}
-	shared_rss = &shared_action->rss;
-	shared_rss->queue = queue;
-	origin = &shared_rss->origin;
+	if (idx > (1u << MLX5_SHARED_ACTION_TYPE_OFFSET)) {
+		rte_flow_error_set(error, E2BIG,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "rss action number out of range");
+		goto error_rss_init;
+	}
+	shared_action->queue = queue;
+	origin = &shared_action->origin;
 	origin->func = rss->func;
 	origin->level = rss->level;
 	/* RSS type 0 indicates default RSS type (ETH_RSS_IP). */
 	origin->types = !rss->types ? ETH_RSS_IP : rss->types;
 	/* NULL RSS key indicates default RSS key. */
 	rss_key = !rss->key ? rss_hash_default_key : rss->key;
-	memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
-	origin->key = &shared_rss->key[0];
+	memcpy(shared_action->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
+	origin->key = &shared_action->key[0];
 	origin->key_len = MLX5_RSS_HASH_KEY_LEN;
-	memcpy(shared_rss->queue, rss->queue, queue_size);
-	origin->queue = shared_rss->queue;
+	memcpy(shared_action->queue, rss->queue, queue_size);
+	origin->queue = shared_action->queue;
 	origin->queue_num = rss->queue_num;
-	if (__flow_dv_action_rss_setup(dev, shared_rss, error))
+	if (__flow_dv_action_rss_setup(dev, shared_action, error))
 		goto error_rss_init;
-	shared_action->type = MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS;
-	return shared_action;
+	__atomic_add_fetch(&shared_action->refcnt, 2, __ATOMIC_RELAXED);
+	rte_spinlock_lock(&priv->shared_act_sl);
+	ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+		     &priv->rss_shared_actions, idx, shared_action, next);
+	rte_spinlock_unlock(&priv->shared_act_sl);
+	return idx;
 error_rss_init:
-	mlx5_free(shared_action);
-	mlx5_free(queue);
-	return NULL;
+	if (shared_action)
+		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+				idx);
+	if (queue)
+		mlx5_free(queue);
+	return 0;
 }
 
 /**
@@ -11339,8 +11363,8 @@ struct mlx5_cache_entry *
  *
  * @param[in] dev
  *   Pointer to the Ethernet device structure.
- * @param[in] shared_rss
- *   The shared RSS action object to be removed.
+ * @param[in] idx
+ *   The shared RSS action object ID to be removed.
  * @param[out] error
  *   Perform verbose error reporting if not NULL. Initialized in case of
  *   error only.
@@ -11349,31 +11373,39 @@ struct mlx5_cache_entry *
  *   0 on success, otherwise negative errno value.
  */
 static int
-__flow_dv_action_rss_release(struct rte_eth_dev *dev,
-			 struct mlx5_shared_action_rss *shared_rss,
-			 struct rte_flow_error *error)
+__flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx,
+			     struct rte_flow_error *error)
 {
-	struct rte_flow_shared_action *shared_action = NULL;
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_shared_action_rss *shared_rss =
+	    mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
 	uint32_t old_refcnt = 1;
-	int remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+	int remaining;
 
-	if (remaining) {
+	if (!shared_rss)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "invalid shared action");
+	remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+	if (remaining)
 		return rte_flow_error_set(error, ETOOMANYREFS,
 					  RTE_FLOW_ERROR_TYPE_ACTION,
 					  NULL,
 					  "shared rss hrxq has references");
-	}
-	shared_action = container_of(shared_rss,
-				     struct rte_flow_shared_action, rss);
-	if (!__atomic_compare_exchange_n(&shared_action->refcnt, &old_refcnt,
-					 0, 0,
-					 __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
+	if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt,
+					 0, 0, __ATOMIC_ACQUIRE,
+					 __ATOMIC_RELAXED))
 		return rte_flow_error_set(error, ETOOMANYREFS,
 					  RTE_FLOW_ERROR_TYPE_ACTION,
 					  NULL,
 					  "shared rss has references");
-	}
 	rte_free(shared_rss->queue);
+	rte_spinlock_lock(&priv->shared_act_sl);
+	ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+		     &priv->rss_shared_actions, idx, shared_rss, next);
+	rte_spinlock_unlock(&priv->shared_act_sl);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+			idx);
 	return 0;
 }
 
@@ -11400,30 +11432,23 @@ struct mlx5_cache_entry *
 flow_dv_action_create(struct rte_eth_dev *dev,
 		      const struct rte_flow_shared_action_conf *conf,
 		      const struct rte_flow_action *action,
-		      struct rte_flow_error *error)
+		      struct rte_flow_error *err)
 {
-	struct rte_flow_shared_action *shared_action = NULL;
-	struct mlx5_priv *priv = dev->data->dev_private;
+	uint32_t idx = 0;
+	uint32_t ret = 0;
 
 	switch (action->type) {
 	case RTE_FLOW_ACTION_TYPE_RSS:
-		shared_action = __flow_dv_action_rss_create(dev, conf,
-							    action->conf,
-							    error);
+		ret = __flow_dv_action_rss_create(dev, conf, action->conf, err);
+		idx = (MLX5_SHARED_ACTION_TYPE_RSS <<
+		       MLX5_SHARED_ACTION_TYPE_OFFSET) | ret;
 		break;
 	default:
-		rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
+		rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
 				   NULL, "action type not supported");
 		break;
 	}
-	if (shared_action) {
-		__atomic_add_fetch(&shared_action->refcnt, 1,
-				   __ATOMIC_RELAXED);
-		rte_spinlock_lock(&priv->shared_act_sl);
-		LIST_INSERT_HEAD(&priv->shared_actions, shared_action, next);
-		rte_spinlock_unlock(&priv->shared_act_sl);
-	}
-	return shared_action;
+	return ret ? (struct rte_flow_shared_action *)(uintptr_t)idx : NULL;
 }
 
 /**
@@ -11448,12 +11473,14 @@ struct mlx5_cache_entry *
 		       struct rte_flow_shared_action *action,
 		       struct rte_flow_error *error)
 {
-	struct mlx5_priv *priv = dev->data->dev_private;
+	uint32_t act_idx = (uint32_t)(uintptr_t)action;
+	uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+	uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1);
 	int ret;
 
-	switch (action->type) {
-	case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
-		ret = __flow_dv_action_rss_release(dev, &action->rss, error);
+	switch (type) {
+	case MLX5_SHARED_ACTION_TYPE_RSS:
+		ret = __flow_dv_action_rss_release(dev, idx, error);
 		break;
 	default:
 		return rte_flow_error_set(error, ENOTSUP,
@@ -11463,10 +11490,6 @@ struct mlx5_cache_entry *
 	}
 	if (ret)
 		return ret;
-	rte_spinlock_lock(&priv->shared_act_sl);
-	LIST_REMOVE(action, next);
-	rte_spinlock_unlock(&priv->shared_act_sl);
-	rte_free(action);
 	return 0;
 }
 
@@ -11475,8 +11498,8 @@ struct mlx5_cache_entry *
  *
  * @param[in] dev
  *   Pointer to the Ethernet device structure.
- * @param[in] shared_rss
- *   The shared RSS action object to be updated.
+ * @param[in] idx
+ *   The shared RSS action object ID to be updated.
  * @param[in] action_conf
  *   RSS action specification used to modify *shared_rss*.
  * @param[out] error
@@ -11488,11 +11511,13 @@ struct mlx5_cache_entry *
  * @note: currently only support update of RSS queues.
  */
 static int
-__flow_dv_action_rss_update(struct rte_eth_dev *dev,
-			    struct mlx5_shared_action_rss *shared_rss,
+__flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx,
 			    const struct rte_flow_action_rss *action_conf,
 			    struct rte_flow_error *error)
 {
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_shared_action_rss *shared_rss =
+	    mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
 	size_t i;
 	int ret;
 	void *queue = NULL;
@@ -11500,6 +11525,10 @@ struct mlx5_cache_entry *
 	uint32_t rss_key_len;
 	uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);
 
+	if (!shared_rss)
+		return rte_flow_error_set(error, EINVAL,
+					  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+					  "invalid shared action to update");
 	queue = mlx5_malloc(MLX5_MEM_ZERO,
 			    RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
 			    0, SOCKET_ID_ANY);
@@ -11522,7 +11551,7 @@ struct mlx5_cache_entry *
 
 		for (tunnel = 0; tunnel < 2; tunnel++) {
 			hrxq_idx = __flow_dv_action_rss_hrxq_lookup
-					(shared_rss, hash_fields, tunnel);
+					(dev, idx, hash_fields, tunnel);
 			MLX5_ASSERT(hrxq_idx);
 			ret = mlx5_hrxq_modify
 				(dev, hrxq_idx,
@@ -11569,14 +11598,17 @@ struct mlx5_cache_entry *
 flow_dv_action_update(struct rte_eth_dev *dev,
 			struct rte_flow_shared_action *action,
 			const void *action_conf,
-			struct rte_flow_error *error)
+			struct rte_flow_error *err)
 {
-	switch (action->type) {
-	case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
-		return __flow_dv_action_rss_update(dev, &action->rss,
-						   action_conf, error);
+	uint32_t act_idx = (uint32_t)(uintptr_t)action;
+	uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+	uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1);
+
+	switch (type) {
+	case MLX5_SHARED_ACTION_TYPE_RSS:
+		return __flow_dv_action_rss_update(dev, idx, action_conf, err);
 	default:
-		return rte_flow_error_set(error, ENOTSUP,
+		return rte_flow_error_set(err, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION,
 					  NULL,
 					  "action type not supported");
