diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 8d5f517..601f6c6 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -252,6 +252,17 @@ static LIST_HEAD(, mlx5_dev_ctx_shared) mlx5_dev_ctx_list =
 		.free = mlx5_free,
 		.type = "mlx5_sample_ipool",
 	},
+	{
+		.size = sizeof(struct mlx5_flow_dv_dest_array_resource),
+		.trunk_size = 64,
+		.grow_trunk = 3,
+		.grow_shift = 2,
+		.need_lock = 0,
+		.release_mem_en = 1,
+		.malloc = mlx5_malloc,
+		.free = mlx5_free,
+		.type = "mlx5_dest_array_ipool",
+	},
 #endif
 	{
 		.size = sizeof(struct mlx5_flow_meter),
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 8dbbcd0..031d77e 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -40,6 +40,7 @@ enum mlx5_ipool_index {
 	MLX5_IPOOL_PORT_ID, /* Pool for port id resource. */
 	MLX5_IPOOL_JUMP, /* Pool for jump resource. */
 	MLX5_IPOOL_SAMPLE, /* Pool for sample resource. */
+	MLX5_IPOOL_DEST_ARRAY, /* Pool for destination array resource. */
 #endif
 	MLX5_IPOOL_MTR, /* Pool for meter resource. */
 	MLX5_IPOOL_MCP, /* Pool for metadata resource. */
@@ -643,6 +644,7 @@ struct mlx5_dev_ctx_shared {
 	uint32_t port_id_action_list; /* List of port ID actions. */
 	uint32_t push_vlan_action_list; /* List of push VLAN actions. */
 	uint32_t sample_action_list; /* List of sample actions. */
+	uint32_t dest_array_list; /* List of destination array actions. */
 	struct mlx5_flow_counter_mng cmng; /* Counters management structure. */
 	struct mlx5_flow_default_miss_resource default_miss;
 	/* Default miss action resource structure. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 85f9f45..e6d165d 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -527,6 +527,8 @@ struct mlx5_flow_sub_actions_list {
 	void *dr_queue_action;
 	void *dr_tag_action;
 	void *dr_cnt_action;
+	void *dr_port_id_action;
+	void *dr_encap_action;
 };
 
 /* Sample sub-actions resource list. */
@@ -534,6 +536,8 @@ struct mlx5_flow_sub_actions_idx {
 	uint32_t rix_hrxq; /**< Hash Rx queue object index. */
 	uint32_t rix_tag; /**< Index to the tag action. */
 	uint32_t cnt;
+	uint32_t rix_port_id_action; /**< Index to port ID action resource. */
+	uint32_t rix_encap_decap; /**< Index to encap/decap resource. */
 };
 
 /* Sample action resource structure. */
@@ -553,6 +557,21 @@ struct mlx5_flow_dv_sample_resource {
 	/**< Action resources. */
 };
 
+#define MLX5_MAX_DEST_NUM	2
+
+/* Destination array action resource structure. */
+struct mlx5_flow_dv_dest_array_resource {
+	ILIST_ENTRY(uint32_t)next; /**< Pointer to next element. */
+	rte_atomic32_t refcnt; /**< Reference counter. */
+	uint8_t ft_type; /** Flow Table Type */
+	uint8_t num_of_dest; /**< Number of destination actions. */
+	void *action; /**< Pointer to the rdma core action. */
+	struct mlx5_flow_sub_actions_idx sample_idx[MLX5_MAX_DEST_NUM];
+	/**< Action index resources. */
+	struct mlx5_flow_sub_actions_list sample_act[MLX5_MAX_DEST_NUM];
+	/**< Action resources. */
+};
+
 /* Verbs specification header. */
 struct ibv_spec_header {
 	enum ibv_flow_spec_type type;
@@ -587,6 +606,8 @@ struct mlx5_flow_handle_dv {
 	/**< Index to the tag action. */
 	uint32_t rix_sample;
 	/**< Index to sample action resource in cache. */
+	uint32_t rix_dest_array;
+	/**< Index to destination array resource in cache. */
 } __rte_packed;
 
 /** Device flow handle structure: used both for creating & destroying. */
@@ -654,6 +675,8 @@ struct mlx5_flow_dv_workspace {
 	/**< Holds the value that the packet is compared to. */
 	struct mlx5_flow_dv_sample_resource *sample_res;
 	/**< Pointer to the sample action resource. */
+	struct mlx5_flow_dv_dest_array_resource *dest_array_res;
+	/**< Pointer to the destination array resource. */
 };
 
 /*
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 819f09d..ac8c508 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -80,6 +80,10 @@
 flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev,
 				      uint32_t encap_decap_idx);
 
+static int
+flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
+					uint32_t port_id);
+
 /**
  * Initialize flow attributes structure according to flow items' types.
  *
@@ -8377,9 +8381,9 @@ struct field_modify_info modify_tcp[] = {
  */
 static struct mlx5_hrxq *
 flow_dv_handle_rx_queue(struct rte_eth_dev *dev,
-			  struct mlx5_flow *dev_flow,
-			  struct mlx5_flow_rss_desc *rss_desc,
-			  uint32_t *hrxq_idx)
+			struct mlx5_flow *dev_flow,
+			struct mlx5_flow_rss_desc *rss_desc,
+			uint32_t *hrxq_idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_handle *dh = dev_flow->handle;
@@ -8387,19 +8391,19 @@ struct field_modify_info modify_tcp[] = {
 
 	MLX5_ASSERT(rss_desc->queue_num);
 	*hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,
-				 MLX5_RSS_HASH_KEY_LEN,
-				 dev_flow->hash_fields,
-				 rss_desc->queue,
-				 rss_desc->queue_num);
+				  MLX5_RSS_HASH_KEY_LEN,
+				  dev_flow->hash_fields,
+				  rss_desc->queue,
+				  rss_desc->queue_num);
 	if (!*hrxq_idx) {
 		*hrxq_idx = mlx5_hrxq_new
 				(dev, rss_desc->key,
-				MLX5_RSS_HASH_KEY_LEN,
-				dev_flow->hash_fields,
-				rss_desc->queue,
-				rss_desc->queue_num,
-				!!(dh->layers &
-				MLX5_FLOW_LAYER_TUNNEL));
+				 MLX5_RSS_HASH_KEY_LEN,
+				 dev_flow->hash_fields,
+				 rss_desc->queue,
+				 rss_desc->queue_num,
+				 !!(dh->layers &
+				 MLX5_FLOW_LAYER_TUNNEL));
 		if (!*hrxq_idx)
 			return NULL;
 	}
@@ -8553,6 +8557,153 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Find existing destination array resource or create and register a new one.
+ *
+ * @param[in, out] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] attr
+ *   Attributes of flow that includes this item.
+ * @param[in] resource
+ *   Pointer to destination array resource.
+ * @parm[in, out] dev_flow
+ *   Pointer to the dev_flow.
+ * @param[out] error
+ *   pointer to error structure.
+ *
+ * @return
+ *   0 on success otherwise -errno and errno is set.
+ */
+static int
+flow_dv_dest_array_resource_register(struct rte_eth_dev *dev,
+			 const struct rte_flow_attr *attr,
+			 struct mlx5_flow_dv_dest_array_resource *resource,
+			 struct mlx5_flow *dev_flow,
+			 struct rte_flow_error *error)
+{
+	struct mlx5_flow_dv_dest_array_resource *cache_resource;
+	struct mlx5dv_dr_action_dest_attr *dest_attr[MLX5_MAX_DEST_NUM] = { 0 };
+	struct mlx5dv_dr_action_dest_reformat dest_reformat[MLX5_MAX_DEST_NUM];
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_dev_ctx_shared *sh = priv->sh;
+	struct mlx5_flow_sub_actions_list *sample_act;
+	struct mlx5dv_dr_domain *domain;
+	uint32_t idx = 0;
+
+	/* Lookup a matching resource from cache. */
+	ILIST_FOREACH(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
+		      sh->dest_array_list,
+		      idx, cache_resource, next) {
+		if (resource->num_of_dest == cache_resource->num_of_dest &&
+		    resource->ft_type == cache_resource->ft_type &&
+		    !memcmp((void *)cache_resource->sample_act,
+			    (void *)resource->sample_act,
+			   (resource->num_of_dest *
+			   sizeof(struct mlx5_flow_sub_actions_list)))) {
+			DRV_LOG(DEBUG, "sample resource %p: refcnt %d++",
+				(void *)cache_resource,
+				rte_atomic32_read(&cache_resource->refcnt));
+			rte_atomic32_inc(&cache_resource->refcnt);
+			dev_flow->handle->dvh.rix_dest_array = idx;
+			dev_flow->dv.dest_array_res = cache_resource;
+			return 0;
+		}
+	}
+	/* Register new destination array resource. */
+	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
+				       &dev_flow->handle->dvh.rix_dest_array);
+	if (!cache_resource)
+		return rte_flow_error_set(error, ENOMEM,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "cannot allocate resource memory");
+	*cache_resource = *resource;
+	if (attr->transfer)
+		domain = sh->fdb_domain;
+	else if (attr->ingress)
+		domain = sh->rx_domain;
+	else
+		domain = sh->tx_domain;
+	for (idx = 0; idx < resource->num_of_dest; idx++) {
+		dest_attr[idx] = (struct mlx5dv_dr_action_dest_attr *)
+				 mlx5_malloc(MLX5_MEM_ZERO,
+				 sizeof(struct mlx5dv_dr_action_dest_attr),
+				 0, SOCKET_ID_ANY);
+		if (!dest_attr[idx]) {
+			rte_flow_error_set(error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL,
+					   "cannot allocate resource memory");
+			goto error;
+		}
+		dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST;
+		sample_act = &resource->sample_act[idx];
+		if (sample_act->action_flags == MLX5_FLOW_ACTION_QUEUE) {
+			dest_attr[idx]->dest = sample_act->dr_queue_action;
+		} else if (sample_act->action_flags ==
+			  (MLX5_FLOW_ACTION_PORT_ID | MLX5_FLOW_ACTION_ENCAP)) {
+			dest_attr[idx]->type = MLX5DV_DR_ACTION_DEST_REFORMAT;
+			dest_attr[idx]->dest_reformat = &dest_reformat[idx];
+			dest_attr[idx]->dest_reformat->reformat =
+					sample_act->dr_encap_action;
+			dest_attr[idx]->dest_reformat->dest =
+					sample_act->dr_port_id_action;
+		} else if (sample_act->action_flags ==
+			   MLX5_FLOW_ACTION_PORT_ID) {
+			dest_attr[idx]->dest = sample_act->dr_port_id_action;
+		}
+	}
+	/* create a dest array actioin */
+	cache_resource->action = mlx5_glue->dr_create_flow_action_dest_array
+						(domain,
+						 cache_resource->num_of_dest,
+						 dest_attr);
+	if (!cache_resource->action) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "cannot create destination array action");
+		goto error;
+	}
+	rte_atomic32_init(&cache_resource->refcnt);
+	rte_atomic32_inc(&cache_resource->refcnt);
+	ILIST_INSERT(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
+		     &sh->dest_array_list,
+		     dev_flow->handle->dvh.rix_dest_array, cache_resource,
+		     next);
+	dev_flow->dv.dest_array_res = cache_resource;
+	DRV_LOG(DEBUG, "new destination array resource %p: refcnt %d++",
+		(void *)cache_resource,
+		rte_atomic32_read(&cache_resource->refcnt));
+	for (idx = 0; idx < resource->num_of_dest; idx++)
+		mlx5_free(dest_attr[idx]);
+	return 0;
+error:
+	for (idx = 0; idx < resource->num_of_dest; idx++) {
+		struct mlx5_flow_sub_actions_idx *act_res =
+					&cache_resource->sample_idx[idx];
+		if (act_res->rix_hrxq &&
+		    !mlx5_hrxq_release(dev,
+				act_res->rix_hrxq))
+			act_res->rix_hrxq = 0;
+		if (act_res->rix_encap_decap &&
+			flow_dv_encap_decap_resource_release(dev,
+				act_res->rix_encap_decap))
+			act_res->rix_encap_decap = 0;
+		if (act_res->rix_port_id_action &&
+			!flow_dv_port_id_action_resource_release(dev,
+				act_res->rix_port_id_action))
+			act_res->rix_port_id_action = 0;
+		if (dest_attr[idx])
+			mlx5_free(dest_attr[idx]);
+	}
+
+	mlx5_ipool_free(sh->ipool[MLX5_IPOOL_DEST_ARRAY],
+				dev_flow->handle->dvh.rix_dest_array);
+	dev_flow->handle->dvh.rix_dest_array = 0;
+	return -rte_errno;
+}
+
+/**
  * Convert Sample action to DV specification.
  *
  * @param[in] dev
@@ -8563,6 +8714,8 @@ struct field_modify_info modify_tcp[] = {
  *   Pointer to the mlx5_flow.
  * @param[in] attr
  *   Pointer to the flow attributes.
+ * @param[in, out] num_of_dest
+ *   Pointer to the num of destination.
  * @param[in, out] sample_actions
  *   Pointer to sample actions list.
  * @param[in, out] res
@@ -8578,6 +8731,7 @@ struct field_modify_info modify_tcp[] = {
 				const struct rte_flow_action *action,
 				struct mlx5_flow *dev_flow,
 				const struct rte_flow_attr *attr,
+				uint32_t *num_of_dest,
 				void **sample_actions,
 				struct mlx5_flow_dv_sample_resource *res,
 				struct rte_flow_error *error)
@@ -8623,6 +8777,7 @@ struct field_modify_info modify_tcp[] = {
 			sample_idx->rix_hrxq = hrxq_idx;
 			sample_actions[sample_act->actions_num++] =
 						hrxq->action;
+			(*num_of_dest)++;
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
 			if (action_flags & MLX5_FLOW_ACTION_MARK)
 				dev_flow->handle->rix_hrxq = hrxq_idx;
@@ -8635,6 +8790,7 @@ struct field_modify_info modify_tcp[] = {
 			uint32_t tag_be = mlx5_flow_mark_set
 				(((const struct rte_flow_action_mark *)
 				(sub_actions->conf))->id);
+
 			dev_flow->handle->mark = 1;
 			pre_rix = dev_flow->handle->dvh.rix_tag;
 			/* Save the mark resource before sample */
@@ -8677,6 +8833,56 @@ struct field_modify_info modify_tcp[] = {
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			break;
 		}
+		case RTE_FLOW_ACTION_TYPE_PORT_ID:
+		{
+			struct mlx5_flow_dv_port_id_action_resource
+					port_id_resource;
+			uint32_t port_id = 0;
+
+			memset(&port_id_resource, 0, sizeof(port_id_resource));
+			/* Save the port id resource before sample */
+			pre_rix = dev_flow->handle->rix_port_id_action;
+			pre_r = dev_flow->dv.port_id_action;
+			if (flow_dv_translate_action_port_id(dev, sub_actions,
+							     &port_id, error))
+				return -rte_errno;
+			port_id_resource.port_id = port_id;
+			if (flow_dv_port_id_action_resource_register
+			    (dev, &port_id_resource, dev_flow, error))
+				return -rte_errno;
+			sample_act->dr_port_id_action =
+				dev_flow->dv.port_id_action->action;
+			sample_idx->rix_port_id_action =
+				dev_flow->handle->rix_port_id_action;
+			sample_actions[sample_act->actions_num++] =
+						sample_act->dr_port_id_action;
+			/* Recover the port id resource after sample */
+			dev_flow->dv.port_id_action = pre_r;
+			dev_flow->handle->rix_port_id_action = pre_rix;
+			(*num_of_dest)++;
+			action_flags |= MLX5_FLOW_ACTION_PORT_ID;
+			break;
+		}
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			/* Save the encap resource before sample */
+			pre_rix = dev_flow->handle->dvh.rix_encap_decap;
+			pre_r = dev_flow->dv.encap_decap;
+			if (flow_dv_create_action_l2_encap(dev, sub_actions,
+							   dev_flow,
+							   attr->transfer,
+							   error))
+				return -rte_errno;
+			sample_act->dr_encap_action =
+				dev_flow->dv.encap_decap->action;
+			sample_idx->rix_encap_decap =
+				dev_flow->handle->dvh.rix_encap_decap;
+			sample_actions[sample_act->actions_num++] =
+						sample_act->dr_encap_action;
+			/* Recover the encap resource after sample */
+			dev_flow->dv.encap_decap = pre_r;
+			dev_flow->handle->dvh.rix_encap_decap = pre_rix;
+			action_flags |= MLX5_FLOW_ACTION_ENCAP;
+			break;
 		default:
 			return rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
@@ -8715,10 +8921,16 @@ struct field_modify_info modify_tcp[] = {
  *   Pointer to the mlx5_flow.
  * @param[in] attr
  *   Pointer to the flow attributes.
+ * @param[in] num_of_dest
+ *   The num of destination.
  * @param[in, out] res
  *   Pointer to sample resource.
+ * @param[in, out] mdest_res
+ *   Pointer to destination array resource.
  * @param[in] sample_actions
  *   Pointer to sample path actions list.
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
  * @param[out] error
  *   Pointer to the error structure.
  *
@@ -8727,17 +8939,81 @@ struct field_modify_info modify_tcp[] = {
  */
 static int
 flow_dv_create_action_sample(struct rte_eth_dev *dev,
-				struct mlx5_flow *dev_flow,
-				const struct rte_flow_attr *attr,
-				struct mlx5_flow_dv_sample_resource *res,
-				void **sample_actions,
-				struct rte_flow_error *error)
+			     struct mlx5_flow *dev_flow,
+			     const struct rte_flow_attr *attr,
+			     uint32_t num_of_dest,
+			     struct mlx5_flow_dv_sample_resource *res,
+			     struct mlx5_flow_dv_dest_array_resource *mdest_res,
+			     void **sample_actions,
+			     uint64_t action_flags,
+			     struct rte_flow_error *error)
 {
-	if (flow_dv_sample_resource_register(dev, attr, res, dev_flow,
-						sample_actions, error))
-		return rte_flow_error_set(error, EINVAL,
-					  RTE_FLOW_ERROR_TYPE_ACTION,
-					  NULL, "can't create sample action");
+	struct mlx5_priv *priv = dev->data->dev_private;
+	/* update normal path action resource into last index of array */
+	uint32_t dest_index = MLX5_MAX_DEST_NUM - 1;
+	struct mlx5_flow_sub_actions_list *sample_act =
+					&mdest_res->sample_act[dest_index];
+	struct mlx5_flow_rss_desc *rss_desc = &((struct mlx5_flow_rss_desc *)
+					      priv->rss_desc)
+					      [!!priv->flow_nested_idx];
+	uint32_t normal_idx = 0;
+	struct mlx5_hrxq *hrxq;
+	uint32_t hrxq_idx;
+
+	if (num_of_dest > 1) {
+		if (sample_act->action_flags & MLX5_FLOW_ACTION_QUEUE) {
+			/* Handle QP action for mirroring */
+			hrxq = flow_dv_handle_rx_queue(dev, dev_flow,
+						       rss_desc, &hrxq_idx);
+			if (!hrxq)
+				return rte_flow_error_set
+				     (error, rte_errno,
+				      RTE_FLOW_ERROR_TYPE_ACTION,
+				      NULL,
+				      "cannot create rx queue");
+			normal_idx++;
+			mdest_res->sample_idx[dest_index].rix_hrxq = hrxq_idx;
+			sample_act->dr_queue_action = hrxq->action;
+			if (action_flags & MLX5_FLOW_ACTION_MARK)
+				dev_flow->handle->rix_hrxq = hrxq_idx;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
+		}
+		if (sample_act->action_flags & MLX5_FLOW_ACTION_ENCAP) {
+			normal_idx++;
+			mdest_res->sample_idx[dest_index].rix_encap_decap =
+				dev_flow->handle->dvh.rix_encap_decap;
+			sample_act->dr_encap_action =
+				dev_flow->dv.encap_decap->action;
+		}
+		if (sample_act->action_flags & MLX5_FLOW_ACTION_PORT_ID) {
+			normal_idx++;
+			mdest_res->sample_idx[dest_index].rix_port_id_action =
+				dev_flow->handle->rix_port_id_action;
+			sample_act->dr_port_id_action =
+				dev_flow->dv.port_id_action->action;
+		}
+		sample_act->actions_num = normal_idx;
+		/* update sample action resource into first index of array */
+		mdest_res->ft_type = res->ft_type;
+		memcpy(&mdest_res->sample_idx[0], &res->sample_idx,
+				sizeof(struct mlx5_flow_sub_actions_idx));
+		memcpy(&mdest_res->sample_act[0], &res->sample_act,
+				sizeof(struct mlx5_flow_sub_actions_list));
+		mdest_res->num_of_dest = num_of_dest;
+		if (flow_dv_dest_array_resource_register(dev, attr, mdest_res,
+							 dev_flow, error))
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  NULL, "can't create sample "
+						  "action");
+	} else {
+		if (flow_dv_sample_resource_register(dev, attr, res, dev_flow,
+						     sample_actions, error))
+			return rte_flow_error_set(error, EINVAL,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  NULL,
+						  "can't create sample action");
+	}
 	return 0;
 }
 
@@ -8805,15 +9081,22 @@ struct field_modify_info modify_tcp[] = {
 	void *match_value = dev_flow->dv.value.buf;
 	uint8_t next_protocol = 0xff;
 	struct rte_vlan_hdr vlan = { 0 };
+	struct mlx5_flow_dv_dest_array_resource mdest_res;
 	struct mlx5_flow_dv_sample_resource sample_res;
 	void *sample_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
+	struct mlx5_flow_sub_actions_list *sample_act;
 	uint32_t sample_act_pos = UINT32_MAX;
+	uint32_t num_of_dest = 0;
+	int tmp_actions_n = 0;
 	uint32_t table;
 	int ret = 0;
 
+	memset(&mdest_res, 0, sizeof(struct mlx5_flow_dv_dest_array_resource));
 	memset(&sample_res, 0, sizeof(struct mlx5_flow_dv_sample_resource));
 	mhdr_res->ft_type = attr->egress ? MLX5DV_FLOW_TABLE_TYPE_NIC_TX :
 					   MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
+	/* update normal path action resource into last index of array */
+	sample_act = &mdest_res.sample_act[MLX5_MAX_DEST_NUM - 1];
 	ret = mlx5_flow_group_to_table(attr, dev_flow->external, attr->group,
 				       !!priv->fdb_def_rule, &table, error);
 	if (ret)
@@ -8860,6 +9143,8 @@ struct field_modify_info modify_tcp[] = {
 					dev_flow->dv.port_id_action->action;
 			action_flags |= MLX5_FLOW_ACTION_PORT_ID;
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;
+			sample_act->action_flags |= MLX5_FLOW_ACTION_PORT_ID;
+			num_of_dest++;
 			break;
 		case RTE_FLOW_ACTION_TYPE_FLAG:
 			action_flags |= MLX5_FLOW_ACTION_FLAG;
@@ -8945,6 +9230,8 @@ struct field_modify_info modify_tcp[] = {
 			rss_desc->queue[0] = queue->index;
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
+			sample_act->action_flags |= MLX5_FLOW_ACTION_QUEUE;
+			num_of_dest++;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			rss = actions->conf;
@@ -9032,6 +9319,9 @@ struct field_modify_info modify_tcp[] = {
 			dev_flow->dv.actions[actions_n++] =
 					dev_flow->dv.encap_decap->action;
 			action_flags |= MLX5_FLOW_ACTION_ENCAP;
+			if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+				sample_act->action_flags |=
+							MLX5_FLOW_ACTION_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
@@ -9061,6 +9351,9 @@ struct field_modify_info modify_tcp[] = {
 					dev_flow->dv.encap_decap->action;
 			}
 			action_flags |= MLX5_FLOW_ACTION_ENCAP;
+			if (action_flags & MLX5_FLOW_ACTION_SAMPLE)
+				sample_act->action_flags |=
+							MLX5_FLOW_ACTION_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
 			while ((++action)->type == RTE_FLOW_ACTION_TYPE_VOID)
@@ -9253,6 +9546,7 @@ struct field_modify_info modify_tcp[] = {
 			ret = flow_dv_translate_action_sample(dev,
 							      actions,
 							      dev_flow, attr,
+							      &num_of_dest,
 							      sample_actions,
 							      &sample_res,
 							      error);
@@ -9260,6 +9554,11 @@ struct field_modify_info modify_tcp[] = {
 				return ret;
 			actions_n++;
 			action_flags |= MLX5_FLOW_ACTION_SAMPLE;
+			/* put encap action into group if work with port id */
+			if ((action_flags & MLX5_FLOW_ACTION_ENCAP) &&
+			    (action_flags & MLX5_FLOW_ACTION_PORT_ID))
+				sample_act->action_flags |=
+							MLX5_FLOW_ACTION_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_END:
 			actions_end = true;
@@ -9283,15 +9582,19 @@ struct field_modify_info modify_tcp[] = {
 						NULL,
 						"cannot create counter"
 						" object.");
-				dev_flow->dv.actions[actions_n++] =
+				dev_flow->dv.actions[actions_n] =
 					  (flow_dv_counter_get_by_idx(dev,
 					  flow->counter, NULL))->action;
+				actions_n++;
 			}
 			if (action_flags & MLX5_FLOW_ACTION_SAMPLE) {
 				ret = flow_dv_create_action_sample(dev,
 							  dev_flow, attr,
+							  num_of_dest,
 							  &sample_res,
+							  &mdest_res,
 							  sample_actions,
+							  action_flags,
 							  error);
 				if (ret < 0)
 					return rte_flow_error_set
@@ -9299,8 +9602,13 @@ struct field_modify_info modify_tcp[] = {
 						RTE_FLOW_ERROR_TYPE_ACTION,
 						NULL,
 						"cannot create sample action");
-				dev_flow->dv.actions[sample_act_pos] =
+				if (num_of_dest > 1) {
+					dev_flow->dv.actions[sample_act_pos] =
+					dev_flow->dv.dest_array_res->action;
+				} else {
+					dev_flow->dv.actions[sample_act_pos] =
 					dev_flow->dv.sample_res->verbs_action;
+				}
 			}
 			break;
 		default:
@@ -9310,6 +9618,31 @@ struct field_modify_info modify_tcp[] = {
 		    modify_action_position == UINT32_MAX)
 			modify_action_position = actions_n++;
 	}
+	/*
+	 * For multiple destination (sample action with ratio=1), the encap
+	 * action and port id action will be combined into group action.
+	 * So need remove the original these actions in the flow and only
+	 * use the sample action instead of.
+	 */
+	if (num_of_dest > 1 && sample_act->dr_port_id_action) {
+		int i;
+		void *temp_actions[MLX5_DV_MAX_NUMBER_OF_ACTIONS] = {0};
+
+		for (i = 0; i < actions_n; i++) {
+			if ((sample_act->dr_encap_action &&
+				sample_act->dr_encap_action ==
+				dev_flow->dv.actions[i]) ||
+				(sample_act->dr_port_id_action &&
+				sample_act->dr_port_id_action ==
+				dev_flow->dv.actions[i]))
+				continue;
+			temp_actions[tmp_actions_n++] = dev_flow->dv.actions[i];
+		}
+		memcpy((void *)dev_flow->dv.actions,
+				(void *)temp_actions,
+				tmp_actions_n * sizeof(void *));
+		actions_n = tmp_actions_n;
+	}
 	dev_flow->dv.actions_n = actions_n;
 	dev_flow->act_flags = action_flags;
 	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
@@ -9614,7 +9947,7 @@ struct field_modify_info modify_tcp[] = {
 				dv->actions[n++] = drop_hrxq->action;
 			}
 		} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE &&
-			   !dv_h->rix_sample) {
+			   !dv_h->rix_sample && !dv_h->rix_dest_array) {
 			struct mlx5_hrxq *hrxq;
 			uint32_t hrxq_idx;
 			struct mlx5_flow_rss_desc *rss_desc =
@@ -9900,11 +10233,11 @@ struct field_modify_info modify_tcp[] = {
  */
 static int
 flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev,
-					struct mlx5_flow_handle *handle)
+					uint32_t port_id)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_dv_port_id_action_resource *cache_resource;
-	uint32_t idx = handle->rix_port_id_action;
+	uint32_t idx = port_id;
 
 	cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
 					idx);
@@ -9994,7 +10327,8 @@ struct field_modify_info modify_tcp[] = {
 		flow_dv_jump_tbl_resource_release(dev, handle);
 		break;
 	case MLX5_FLOW_FATE_PORT_ID:
-		flow_dv_port_id_action_resource_release(dev, handle);
+		flow_dv_port_id_action_resource_release(dev,
+				handle->rix_port_id_action);
 		break;
 	case MLX5_FLOW_FATE_DEFAULT_MISS:
 		flow_dv_default_miss_resource_release(dev);
@@ -10072,6 +10406,73 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Release an destination array resource.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param handle
+ *   Pointer to mlx5_flow_handle.
+ *
+ * @return
+ *   1 while a reference on it exists, 0 when freed.
+ */
+static int
+flow_dv_dest_array_resource_release(struct rte_eth_dev *dev,
+				     struct mlx5_flow_handle *handle)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_flow_dv_dest_array_resource *cache_resource;
+	struct mlx5_flow_sub_actions_idx *mdest_act_res;
+	uint32_t idx = handle->dvh.rix_dest_array;
+	uint32_t i = 0;
+
+	cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],
+			 idx);
+	if (!cache_resource)
+		return 0;
+	MLX5_ASSERT(cache_resource->action);
+	DRV_LOG(DEBUG, "destination array resource %p: refcnt %d--",
+		(void *)cache_resource,
+		rte_atomic32_read(&cache_resource->refcnt));
+	if (rte_atomic32_dec_and_test(&cache_resource->refcnt)) {
+		if (cache_resource->action)
+			claim_zero(mlx5_glue->destroy_flow_action
+						(cache_resource->action));
+		for (; i < cache_resource->num_of_dest; i++) {
+			mdest_act_res = &cache_resource->sample_idx[i];
+			if (mdest_act_res->rix_hrxq) {
+				mlx5_hrxq_release(dev,
+					mdest_act_res->rix_hrxq);
+				mdest_act_res->rix_hrxq = 0;
+			}
+			if (mdest_act_res->rix_encap_decap) {
+				flow_dv_encap_decap_resource_release(dev,
+					mdest_act_res->rix_encap_decap);
+				mdest_act_res->rix_encap_decap = 0;
+			}
+			if (mdest_act_res->rix_port_id_action) {
+				flow_dv_port_id_action_resource_release(dev,
+					mdest_act_res->rix_port_id_action);
+				mdest_act_res->rix_port_id_action = 0;
+			}
+			if (mdest_act_res->rix_tag) {
+				flow_dv_tag_release(dev,
+					mdest_act_res->rix_tag);
+				mdest_act_res->rix_tag = 0;
+			}
+		}
+		ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY],
+			     &priv->sh->dest_array_list, idx,
+			     cache_resource, next);
+		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_DEST_ARRAY], idx);
+		DRV_LOG(DEBUG, "destination array resource %p: removed",
+			(void *)cache_resource);
+		return 0;
+	}
+	return 1;
+}
+
+/**
  * Remove the flow from the NIC but keeps it in memory.
  * Lock free, (mutex should be acquired by caller).
  *
@@ -10152,6 +10553,8 @@ struct field_modify_info modify_tcp[] = {
 			flow_dv_matcher_release(dev, dev_handle);
 		if (dev_handle->dvh.rix_sample)
 			flow_dv_sample_resource_release(dev, dev_handle);
+		if (dev_handle->dvh.rix_dest_array)
+			flow_dv_dest_array_resource_release(dev, dev_handle);
 		if (dev_handle->dvh.rix_encap_decap)
 			flow_dv_encap_decap_resource_release(dev,
 				dev_handle->dvh.rix_encap_decap);
