diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 4d6b22c4e3..a6b2ef4863 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -1545,7 +1545,8 @@ static rte_be32_t vlan_hdr_to_be32(const struct rte_flow_action *actions)
 static __rte_always_inline struct mlx5_aso_mtr *
 flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
 			 const struct rte_flow_action *action,
-			 void *user_data, bool push)
+			 void *user_data, bool push,
+			 struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
@@ -1554,6 +1555,11 @@ flow_hw_meter_mark_alloc(struct rte_eth_dev *dev, uint32_t queue,
 	struct mlx5_flow_meter_info *fm;
 	uint32_t mtr_id;

+	if (priv->shared_host) {
+		rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "Meter mark actions can only be created on the host port");
+		return NULL;
+	}
 	if (meter_mark->profile == NULL)
 		return NULL;
 	aso_mtr = mlx5_ipool_malloc(priv->hws_mpool->idx_pool, &mtr_id);
@@ -1592,13 +1598,14 @@ flow_hw_meter_mark_compile(struct rte_eth_dev *dev,
 			   const struct rte_flow_action *action,
 			   struct mlx5dr_rule_action *acts,
 			   uint32_t *index,
-			   uint32_t queue)
+			   uint32_t queue,
+			   struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_aso_mtr_pool *pool = priv->hws_mpool;
 	struct mlx5_aso_mtr *aso_mtr;

-	aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, NULL, true);
+	aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, NULL, true, error);
 	if (!aso_mtr)
 		return -1;

@@ -2474,7 +2481,8 @@ __flow_hw_actions_translate(struct rte_eth_dev *dev,
 								 dr_pos, actions,
 								 acts->rule_acts,
 								 &acts->mtr_id,
-								 MLX5_HW_INV_QUEUE);
+								 MLX5_HW_INV_QUEUE,
+								 error);
 				if (err)
 					goto err;
 			} else if (__flow_hw_act_data_general_append(priv, acts,
@@ -3197,7 +3205,8 @@ flow_hw_actions_construct(struct rte_eth_dev *dev,
 			 */
 			ret = flow_hw_meter_mark_compile(dev,
 				act_data->action_dst, action,
-				rule_acts, &job->flow->mtr_id, MLX5_HW_INV_QUEUE);
+				rule_acts, &job->flow->mtr_id,
+				MLX5_HW_INV_QUEUE, error);
 			if (ret != 0)
 				return ret;
 			break;
@@ -5322,6 +5331,8 @@ flow_hw_validate_action_count(struct rte_eth_dev *dev,
  *   Pointer to rte_eth_dev structure.
  * @param[in] action
  *   Pointer to the indirect action.
+ * @param[in] indirect
+ *   If true, then provided action was passed using an indirect action.
  * @param[out] error
  *   Pointer to error structure.
  *
@@ -5331,6 +5342,7 @@ flow_hw_validate_action_count(struct rte_eth_dev *dev,
 static int
 flow_hw_validate_action_meter_mark(struct rte_eth_dev *dev,
 			      const struct rte_flow_action *action,
+			      bool indirect,
 			      struct rte_flow_error *error)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
@@ -5341,6 +5353,9 @@ flow_hw_validate_action_meter_mark(struct rte_eth_dev *dev,
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
 					  "meter_mark action not supported");
+	if (!indirect && priv->shared_host)
+		return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, action,
+					  "meter_mark action can only be used on host port");
 	if (!priv->hws_mpool)
 		return rte_flow_error_set(error, EINVAL,
 					  RTE_FLOW_ERROR_TYPE_ACTION, action,
@@ -5384,7 +5399,7 @@ flow_hw_validate_action_indirect(struct rte_eth_dev *dev,
 	type = mask->type;
 	switch (type) {
 	case RTE_FLOW_ACTION_TYPE_METER_MARK:
-		ret = flow_hw_validate_action_meter_mark(dev, mask, error);
+		ret = flow_hw_validate_action_meter_mark(dev, mask, true, error);
 		if (ret < 0)
 			return ret;
 		*action_flags |= MLX5_FLOW_ACTION_METER;
@@ -5841,8 +5856,7 @@ mlx5_flow_hw_actions_validate(struct rte_eth_dev *dev,
 			action_flags |= MLX5_FLOW_ACTION_METER;
 			break;
 		case RTE_FLOW_ACTION_TYPE_METER_MARK:
-			ret = flow_hw_validate_action_meter_mark(dev, action,
-								 error);
+			ret = flow_hw_validate_action_meter_mark(dev, action, false, error);
 			if (ret < 0)
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_METER;
@@ -10138,7 +10152,7 @@ flow_hw_action_handle_validate(struct rte_eth_dev *dev, uint32_t queue,
 						  "CT pool not initialized");
 		return mlx5_validate_action_ct(dev, action->conf, error);
 	case RTE_FLOW_ACTION_TYPE_METER_MARK:
-		return flow_hw_validate_action_meter_mark(dev, action, error);
+		return flow_hw_validate_action_meter_mark(dev, action, true, error);
 	case RTE_FLOW_ACTION_TYPE_RSS:
 		return flow_dv_action_validate(dev, conf, action, error);
 	case RTE_FLOW_ACTION_TYPE_QUOTA:
@@ -10297,7 +10311,7 @@ flow_hw_action_handle_create(struct rte_eth_dev *dev, uint32_t queue,
 		break;
 	case RTE_FLOW_ACTION_TYPE_METER_MARK:
 		aso = true;
-		aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job, push);
+		aso_mtr = flow_hw_meter_mark_alloc(dev, queue, action, job, push, error);
 		if (!aso_mtr)
 			break;
 		mtr_id = (MLX5_INDIRECT_ACTION_TYPE_METER_MARK <<
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 9cb4614436..c0578ce6e9 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -17,11 +17,32 @@

 #ifdef HAVE_MLX5_HWS_SUPPORT

+static void
+mlx5_flow_meter_uninit_guest(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (priv->hws_mpool) {
+		if (priv->hws_mpool->action) {
+			claim_zero(mlx5dr_action_destroy(priv->hws_mpool->action));
+			priv->hws_mpool->action = NULL;
+		}
+		priv->hws_mpool->devx_obj = NULL;
+		priv->hws_mpool->idx_pool = NULL;
+		mlx5_free(priv->hws_mpool);
+		priv->hws_mpool = NULL;
+	}
+}
+
 void
 mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;

+	if (priv->shared_host) {
+		mlx5_flow_meter_uninit_guest(dev);
+		return;
+	}
 	if (priv->mtr_policy_arr) {
 		mlx5_free(priv->mtr_policy_arr);
 		priv->mtr_policy_arr = NULL;
@@ -52,6 +73,54 @@ mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
 	}
 }

+static int
+mlx5_flow_meter_init_guest(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct rte_eth_dev *host_dev = priv->shared_host;
+	struct mlx5_priv *host_priv = host_dev->data->dev_private;
+	int reg_id = 0;
+	uint32_t flags;
+	int ret = 0;
+
+	MLX5_ASSERT(priv->shared_host);
+	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+	if (reg_id < 0) {
+		rte_errno = ENOMEM;
+		ret = -rte_errno;
+		DRV_LOG(ERR, "Meter register is not available.");
+		goto err;
+	}
+	priv->hws_mpool = mlx5_malloc(MLX5_MEM_ZERO, sizeof(struct mlx5_aso_mtr_pool),
+				      RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
+	if (!priv->hws_mpool) {
+		rte_errno = ENOMEM;
+		ret = -rte_errno;
+		DRV_LOG(ERR, "Meter ipool allocation failed.");
+		goto err;
+	}
+	MLX5_ASSERT(host_priv->hws_mpool->idx_pool);
+	MLX5_ASSERT(host_priv->hws_mpool->devx_obj);
+	priv->hws_mpool->idx_pool = host_priv->hws_mpool->idx_pool;
+	priv->hws_mpool->devx_obj = host_priv->hws_mpool->devx_obj;
+	flags = MLX5DR_ACTION_FLAG_HWS_RX | MLX5DR_ACTION_FLAG_HWS_TX;
+	if (priv->sh->config.dv_esw_en && priv->master)
+		flags |= MLX5DR_ACTION_FLAG_HWS_FDB;
+	priv->hws_mpool->action = mlx5dr_action_create_aso_meter
+			(priv->dr_ctx, (struct mlx5dr_devx_obj *)priv->hws_mpool->devx_obj,
+			 reg_id - REG_C_0, flags);
+	if (!priv->hws_mpool->action) {
+		rte_errno = ENOMEM;
+		ret = -rte_errno;
+		DRV_LOG(ERR, "Meter action creation failed.");
+		goto err;
+	}
+	return 0;
+err:
+	mlx5_flow_meter_uninit(dev);
+	return ret;
+}
+
 int
 mlx5_flow_meter_init(struct rte_eth_dev *dev,
 		     uint32_t nb_meters,
@@ -81,6 +150,8 @@ mlx5_flow_meter_init(struct rte_eth_dev *dev,
 		.type = "mlx5_hw_mtr_mark_action",
 	};

+	if (priv->shared_host)
+		return mlx5_flow_meter_init_guest(dev);
 	if (!nb_meters) {
 		ret = ENOTSUP;
 		rte_flow_error_set(&error, ENOMEM,
@@ -850,6 +921,9 @@ mlx5_flow_meter_profile_hws_add(struct rte_eth_dev *dev,
 	struct mlx5_flow_meter_profile *fmp;
 	int ret;

+	if (priv->shared_host)
+		return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "Meter profiles cannot be created on guest port");
 	if (!priv->mtr_profile_arr)
 		return mlx5_flow_meter_profile_add(dev, meter_profile_id, profile, error);
 	/* Check input params. */
@@ -887,6 +961,9 @@ mlx5_flow_meter_profile_hws_delete(struct rte_eth_dev *dev,
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_meter_profile *fmp;

+	if (priv->shared_host)
+		return -rte_mtr_error_set(error, ENOTSUP, RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "Meter profiles cannot be destroyed through guest port");
 	if (!priv->mtr_profile_arr)
 		return mlx5_flow_meter_profile_delete(dev, meter_profile_id, error);
 	/* Meter profile must exist. */
