diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 8e7d649d15..b638abf677 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -5934,7 +5934,8 @@ flow_check_match_action(const struct rte_flow_action actions[],
 			ratio = sample->ratio;
 			sub_type = ((const struct rte_flow_action *)
 					(sample->actions))->type;
-			if (ratio == 1 && attr->transfer)
+			if (ratio == 1 && attr->transfer &&
+			    sub_type != RTE_FLOW_ACTION_TYPE_END)
 				fdb_mirror = 1;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
@@ -6106,9 +6107,11 @@ flow_sample_split_prep(struct rte_eth_dev *dev,
 				break;
 			case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
 			case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
-				push_vlan_idx = action_idx;
-				if (push_vlan_idx < sample_action_pos)
+				if (action_idx < sample_action_pos &&
+				    push_vlan_idx == -1) {
 					set_tag_idx = action_idx;
+					push_vlan_idx = action_idx;
+				}
 				break;
 			default:
 				break;
@@ -6171,18 +6174,20 @@ flow_sample_split_prep(struct rte_eth_dev *dev,
 			.data = tag_id,
 		};
 		/* Prepare the suffix subflow items. */
+		tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM);
+		tag_spec->data = tag_id;
+		tag_spec->id = set_tag->id;
+		tag_mask = tag_spec + 1;
+		tag_mask->data = UINT32_MAX;
 		for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
 			if (items->type == RTE_FLOW_ITEM_TYPE_PORT_ID ||
-			    items->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
+			    items->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR ||
+			    items->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) {
 				memcpy(sfx_items, items, sizeof(*sfx_items));
 				sfx_items++;
+				break;
 			}
 		}
-		tag_spec = (void *)(sfx_items + SAMPLE_SUFFIX_ITEM);
-		tag_spec->data = tag_id;
-		tag_spec->id = set_tag->id;
-		tag_mask = tag_spec + 1;
-		tag_mask->data = UINT32_MAX;
 		sfx_items[0] = (struct rte_flow_item){
 			.type = (enum rte_flow_item_type)
 				MLX5_RTE_FLOW_ITEM_TYPE_TAG,
@@ -6757,6 +6762,8 @@ flow_create_split_sample(struct rte_eth_dev *dev,
 	uint16_t jump_table = 0;
 	const uint32_t next_ft_step = 1;
 	int ret = 0;
+	struct mlx5_priv *item_port_priv = NULL;
+	const struct rte_flow_item *item;
 
 	if (priv->sampler_en)
 		actions_n = flow_check_match_action(actions, attr,
@@ -6776,8 +6783,36 @@ flow_create_split_sample(struct rte_eth_dev *dev,
 						  RTE_FLOW_ERROR_TYPE_ACTION,
 						  NULL, "no memory to split "
 						  "sample flow");
+		for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
+			if (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID) {
+				const struct rte_flow_item_port_id *spec;
+
+				spec = (const struct rte_flow_item_port_id *)item->spec;
+				if (spec)
+					item_port_priv =
+						mlx5_port_to_eswitch_info(spec->id, true);
+				break;
+			} else if (item->type == RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT) {
+				const struct rte_flow_item_ethdev *spec;
+
+				spec = (const struct rte_flow_item_ethdev *)item->spec;
+				if (spec)
+					item_port_priv =
+						mlx5_port_to_eswitch_info(spec->port_id, true);
+				break;
+			} else if (item->type == RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR) {
+				const struct rte_flow_item_ethdev *spec;
+
+				spec = (const struct rte_flow_item_ethdev *)item->spec;
+				if (spec)
+					item_port_priv =
+						mlx5_port_to_eswitch_info(spec->port_id, true);
+				break;
+			}
+		}
 		/* The representor_id is UINT16_MAX for uplink. */
-		fdb_tx = (attr->transfer && priv->representor_id != UINT16_MAX);
+		fdb_tx = (attr->transfer &&
+			  flow_source_vport_representor(priv, item_port_priv));
 		/*
 		 * When reg_c_preserve is set, metadata registers Cx preserve
 		 * their value even through packet duplication.
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index da9b65d8fe..178c9afeff 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -2118,6 +2118,25 @@ rte_col_2_mlx5_col(enum rte_color rcol)
 	return MLX5_FLOW_COLOR_UNDEFINED;
 }
 
+/**
+ * Indicates whether flow source vport is representor port.
+ *
+ * @param[in] priv
+ *   Pointer to device private context structure.
+ * @param[in] act_priv
+ *   Pointer to actual device private context structure if have.
+ *
+ * @return
+ *   True when the flow source vport is representor port, false otherwise.
+ */
+static inline bool
+flow_source_vport_representor(struct mlx5_priv *priv, struct mlx5_priv *act_priv)
+{
+	MLX5_ASSERT(priv);
+	return (!act_priv ? (priv->representor_id != UINT16_MAX) :
+		 (act_priv->representor_id != UINT16_MAX));
+}
+
 /* All types of Ethernet patterns used in control flow rules. */
 enum mlx5_flow_ctrl_rx_eth_pattern_type {
 	MLX5_FLOW_HW_CTRL_RX_ETH_PATTERN_ALL = 0,
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1e52278191..a2b85207b1 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -2208,6 +2208,7 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
 			      const struct rte_flow_item *item,
 			      const struct rte_flow_attr *attr,
 			      uint64_t item_flags,
+			      struct mlx5_priv **act_priv,
 			      struct rte_flow_error *error)
 {
 	const struct rte_flow_item_port_id *spec = item->spec;
@@ -2266,6 +2267,7 @@ flow_dv_validate_item_port_id(struct rte_eth_dev *dev,
 					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
 					  "cannot match on a port from a"
 					  " different E-Switch");
+	*act_priv = esw_priv;
 	return 0;
 }
 
@@ -2291,6 +2293,7 @@ flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
 				       const struct rte_flow_item *item,
 				       const struct rte_flow_attr *attr,
 				       uint64_t item_flags,
+				       struct mlx5_priv **act_priv,
 				       struct rte_flow_error *error)
 {
 	const struct rte_flow_item_ethdev *spec = item->spec;
@@ -2340,6 +2343,7 @@ flow_dv_validate_item_represented_port(struct rte_eth_dev *dev,
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ITEM_SPEC, spec,
 					  "cannot match on a port from a different E-Switch");
+	*act_priv = esw_priv;
 	return 0;
 }
 
@@ -2860,30 +2864,12 @@ flow_dv_validate_action_pop_vlan(struct rte_eth_dev *dev,
 				 struct rte_flow_error *error)
 {
 	const struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_dev_ctx_shared *sh = priv->sh;
-	bool direction_error = false;
 
 	if (!priv->sh->pop_vlan_action)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 					  NULL,
 					  "pop vlan action is not supported");
-	/* Pop VLAN is not supported in egress except for CX6 FDB mode. */
-	if (attr->transfer) {
-		bool fdb_tx = priv->representor_id != UINT16_MAX;
-		bool is_cx5 = sh->steering_format_version ==
-		    MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
-
-		if (fdb_tx && is_cx5)
-			direction_error = true;
-	} else if (attr->egress) {
-		direction_error = true;
-	}
-	if (direction_error)
-		return rte_flow_error_set(error, ENOTSUP,
-					  RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
-					  NULL,
-					  "pop vlan action not supported for egress");
 	if (action_flags & MLX5_FLOW_VLAN_ACTIONS)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5794,6 +5780,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
 			       const struct rte_flow_action_count **count,
 			       int *fdb_mirror_limit,
 			       bool root,
+			       struct mlx5_priv *act_priv,
 			       struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
@@ -5982,7 +5969,7 @@ flow_dv_validate_action_sample(uint64_t *action_flags,
 						  "E-Switch must has a dest "
 						  "port for mirroring");
 		if (!priv->sh->cdev->config.hca_attr.reg_c_preserve &&
-		     priv->representor_id != UINT16_MAX)
+		     flow_source_vport_representor(priv, act_priv))
 			*fdb_mirror_limit = 1;
 	}
 	/* Continue validation for Xcap actions.*/
@@ -7134,6 +7121,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 	uint32_t tag_id = 0;
 	const struct rte_flow_action_age *non_shared_age = NULL;
 	const struct rte_flow_action_count *count = NULL;
+	struct mlx5_priv *act_priv = NULL;
 
 	if (items == NULL)
 		return -1;
@@ -7183,7 +7171,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			break;
 		case RTE_FLOW_ITEM_TYPE_PORT_ID:
 			ret = flow_dv_validate_item_port_id
-					(dev, items, attr, item_flags, error);
+					(dev, items, attr, item_flags, &act_priv, error);
 			if (ret < 0)
 				return ret;
 			last_item = MLX5_FLOW_ITEM_PORT_ID;
@@ -7192,7 +7180,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 		case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
 		case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
 			ret = flow_dv_validate_item_represented_port
-					(dev, items, attr, item_flags, error);
+					(dev, items, attr, item_flags, &act_priv, error);
 			if (ret < 0)
 				return ret;
 			last_item = MLX5_FLOW_ITEM_REPRESENTED_PORT;
@@ -8070,6 +8058,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 							     &sample_count,
 							     &fdb_mirror_limit,
 							     is_root,
+							     act_priv,
 							     error);
 			if (ret < 0)
 				return ret;
@@ -8246,7 +8235,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 			bool direction_error = false;
 
 			if (attr->transfer) {
-				bool fdb_tx = priv->representor_id != UINT16_MAX;
+				bool fdb_tx = flow_source_vport_representor(priv, act_priv);
 				bool is_cx5 = sh->steering_format_version ==
 				    MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
 
@@ -8278,6 +8267,27 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
 						 "multiple VLAN actions");
 		}
 	}
+	/* Pop VLAN is not supported in egress except for NICs newer than CX5. */
+	if (action_flags & MLX5_FLOW_ACTION_OF_POP_VLAN) {
+		struct mlx5_dev_ctx_shared *sh = priv->sh;
+		bool direction_error = false;
+
+		if (attr->transfer) {
+			bool fdb_tx = flow_source_vport_representor(priv, act_priv);
+			bool is_cx5 = sh->steering_format_version ==
+					MLX5_STEERING_LOGIC_FORMAT_CONNECTX_5;
+
+			if (fdb_tx && is_cx5)
+				direction_error = true;
+		} else if (attr->egress) {
+			direction_error = true;
+		}
+		if (direction_error)
+			return rte_flow_error_set(error, ENOTSUP,
+						RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+						NULL,
+						"pop vlan action not supported for egress");
+	}
 	if (action_flags & MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY) {
 		if ((action_flags & (MLX5_FLOW_FATE_ACTIONS &
 			~MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)) &&
@@ -8396,6 +8406,7 @@ flow_dv_prepare(struct rte_eth_dev *dev,
 	wks->skip_matcher_reg = 0;
 	wks->policy = NULL;
 	wks->final_policy = NULL;
+	wks->vport_meta_tag = 0;
 	/* In case of corrupting the memory. */
 	if (wks->flow_idx >= MLX5_NUM_MAX_DEV_FLOWS) {
 		rte_flow_error_set(error, ENOSPC,
@@ -10081,10 +10092,12 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
 {
 	const struct rte_flow_item_port_id *pid_m = item ? item->mask : NULL;
 	const struct rte_flow_item_port_id *pid_v = item ? item->spec : NULL;
+	struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace();
 	struct mlx5_priv *priv;
 	uint16_t mask, id;
 	uint32_t vport_meta;
 
+	MLX5_ASSERT(wks);
 	if (pid_v && pid_v->id == MLX5_PORT_ESW_MGR) {
 		flow_dv_translate_item_source_vport(key,
 				key_type & MLX5_SET_MATCHER_V ?
@@ -10102,6 +10115,7 @@ flow_dv_translate_item_port_id(struct rte_eth_dev *dev, void *key,
 	} else {
 		id = priv->vport_id;
 		vport_meta = priv->vport_meta_tag;
+		wks->vport_meta_tag = vport_meta;
 	}
 	/*
 	 * Translate to vport field or to metadata, depending on mode.
@@ -12273,6 +12287,9 @@ flow_dv_translate_action_sample(struct rte_eth_dev *dev,
 			uint32_t action_in[MLX5_ST_SZ_DW(set_action_in)];
 			uint64_t set_action;
 		} action_ctx = { .set_action = 0 };
+		uint32_t vport_meta_tag = wks->vport_meta_tag ?
+					  wks->vport_meta_tag :
+					  priv->vport_meta_tag;
 
 		res->ft_type = MLX5DV_FLOW_TABLE_TYPE_FDB;
 		MLX5_SET(set_action_in, action_ctx.action_in, action_type,
@@ -12280,7 +12297,7 @@ flow_dv_translate_action_sample(struct rte_eth_dev *dev,
 		MLX5_SET(set_action_in, action_ctx.action_in, field,
 			 MLX5_MODI_META_REG_C_0);
 		MLX5_SET(set_action_in, action_ctx.action_in, data,
-			 priv->vport_meta_tag);
+			 vport_meta_tag);
 		res->set_action = action_ctx.set_action;
 	} else if (attr->ingress) {
 		res->ft_type = MLX5DV_FLOW_TABLE_TYPE_NIC_RX;
