DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 0/2] net/mlx5: add cross port meter mark action sharing
@ 2024-02-21 10:13 Dariusz Sosnowski
  2024-02-21 10:13 ` [PATCH 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-21 10:13 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patchset adds support for sharing indirect METER_MARK flow actions
between ports, when flow engine is configured with
RTE_FLOW_PORT_FLAG_SHARE_INDIRECT.

Dariusz Sosnowski (2):
  net/mlx5: move meter init functions
  net/mlx5: add cross port meter mark action sharing

 drivers/net/mlx5/mlx5_flow_hw.c    | 237 +++---------------------
 drivers/net/mlx5/mlx5_flow_meter.c | 284 +++++++++++++++++++++++++++++
 2 files changed, 308 insertions(+), 213 deletions(-)

--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] net/mlx5: move meter init functions
  2024-02-21 10:13 [PATCH 0/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
@ 2024-02-21 10:13 ` Dariusz Sosnowski
  2024-02-21 10:13 ` [PATCH 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  2024-02-21 10:21 ` [PATCH v2 0/2] " Dariusz Sosnowski
  2 siblings, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-21 10:13 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

Move mlx5_flow_meter_init() and mlx5_flow_meter_uinit()
to module for meter operations.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c    | 203 ----------------------------
 drivers/net/mlx5/mlx5_flow_meter.c | 207 +++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 203 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 3bb3a9a178..4d6b22c4e3 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -12859,209 +12859,6 @@ mlx5_flow_hw_ctrl_flows(struct rte_eth_dev *dev, uint32_t flags)
 	return 0;
 }

-void
-mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-
-	if (priv->mtr_policy_arr) {
-		mlx5_free(priv->mtr_policy_arr);
-		priv->mtr_policy_arr = NULL;
-	}
-	if (priv->mtr_profile_arr) {
-		mlx5_free(priv->mtr_profile_arr);
-		priv->mtr_profile_arr = NULL;
-	}
-	if (priv->hws_mpool) {
-		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
-		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
-		mlx5_free(priv->hws_mpool);
-		priv->hws_mpool = NULL;
-	}
-	if (priv->mtr_bulk.aso) {
-		mlx5_free(priv->mtr_bulk.aso);
-		priv->mtr_bulk.aso = NULL;
-		priv->mtr_bulk.size = 0;
-		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
-	}
-	if (priv->mtr_bulk.action) {
-		mlx5dr_action_destroy(priv->mtr_bulk.action);
-		priv->mtr_bulk.action = NULL;
-	}
-	if (priv->mtr_bulk.devx_obj) {
-		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
-		priv->mtr_bulk.devx_obj = NULL;
-	}
-}
-
-int
-mlx5_flow_meter_init(struct rte_eth_dev *dev,
-		     uint32_t nb_meters,
-		     uint32_t nb_meter_profiles,
-		     uint32_t nb_meter_policies,
-		     uint32_t nb_queues)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_devx_obj *dcs = NULL;
-	uint32_t log_obj_size;
-	int ret = 0;
-	int reg_id;
-	struct mlx5_aso_mtr *aso;
-	uint32_t i;
-	struct rte_flow_error error;
-	uint32_t flags;
-	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
-	struct mlx5_indexed_pool_config cfg = {
-		.size = sizeof(struct mlx5_aso_mtr),
-		.trunk_size = 1 << 12,
-		.per_core_cache = 1 << 13,
-		.need_lock = 1,
-		.release_mem_en = !!priv->sh->config.reclaim_mode,
-		.malloc = mlx5_malloc,
-		.max_idx = nb_meters,
-		.free = mlx5_free,
-		.type = "mlx5_hw_mtr_mark_action",
-	};
-
-	if (!nb_meters) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter configuration is invalid.");
-		goto err;
-	}
-	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO is not supported.");
-		goto err;
-	}
-	priv->mtr_config.nb_meters = nb_meters;
-	log_obj_size = rte_log2_u32(nb_meters >> 1);
-	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
-		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
-			log_obj_size);
-	if (!dcs) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO object allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.devx_obj = dcs;
-	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
-	if (reg_id < 0) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter register is not available.");
-		goto err;
-	}
-	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
-			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
-				reg_id - REG_C_0, flags);
-	if (!priv->mtr_bulk.action) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter action creation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
-					 sizeof(struct mlx5_aso_mtr) *
-					 nb_meters,
-					 RTE_CACHE_LINE_SIZE,
-					 SOCKET_ID_ANY);
-	if (!priv->mtr_bulk.aso) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter bulk ASO allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.size = nb_meters;
-	aso = priv->mtr_bulk.aso;
-	for (i = 0; i < priv->mtr_bulk.size; i++) {
-		aso->type = ASO_METER_DIRECT;
-		aso->state = ASO_METER_WAIT;
-		aso->offset = i;
-		aso++;
-	}
-	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) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ipool allocation failed.");
-		goto err;
-	}
-	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
-	priv->hws_mpool->action = priv->mtr_bulk.action;
-	priv->hws_mpool->nb_sq = nb_queues;
-	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
-				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO queue allocation failed.");
-		goto err;
-	}
-	/*
-	 * No need for local cache if Meter number is a small number.
-	 * Since flow insertion rate will be very limited in that case.
-	 * Here let's set the number to less than default trunk size 4K.
-	 */
-	if (nb_mtrs <= cfg.trunk_size) {
-		cfg.per_core_cache = 0;
-		cfg.trunk_size = nb_mtrs;
-	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
-		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
-	}
-	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
-	if (nb_meter_profiles) {
-		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
-		priv->mtr_profile_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_profile) *
-				    nb_meter_profiles,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_profile_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter profile allocation failed.");
-			goto err;
-		}
-	}
-	if (nb_meter_policies) {
-		priv->mtr_config.nb_meter_policies = nb_meter_policies;
-		priv->mtr_policy_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_policy) *
-				    nb_meter_policies,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_policy_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter policy allocation failed.");
-			goto err;
-		}
-	}
-	return 0;
-err:
-	mlx5_flow_meter_uninit(dev);
-	return ret;
-}
-
 static __rte_always_inline uint32_t
 mlx5_reformat_domain_to_tbl_type(const struct rte_flow_indir_action_conf *domain)
 {
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 7cbf772ea4..9cb4614436 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -15,6 +15,213 @@
 #include "mlx5.h"
 #include "mlx5_flow.h"

+#ifdef HAVE_MLX5_HWS_SUPPORT
+
+void
+mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (priv->mtr_policy_arr) {
+		mlx5_free(priv->mtr_policy_arr);
+		priv->mtr_policy_arr = NULL;
+	}
+	if (priv->mtr_profile_arr) {
+		mlx5_free(priv->mtr_profile_arr);
+		priv->mtr_profile_arr = NULL;
+	}
+	if (priv->hws_mpool) {
+		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
+		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
+		mlx5_free(priv->hws_mpool);
+		priv->hws_mpool = NULL;
+	}
+	if (priv->mtr_bulk.aso) {
+		mlx5_free(priv->mtr_bulk.aso);
+		priv->mtr_bulk.aso = NULL;
+		priv->mtr_bulk.size = 0;
+		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
+	}
+	if (priv->mtr_bulk.action) {
+		mlx5dr_action_destroy(priv->mtr_bulk.action);
+		priv->mtr_bulk.action = NULL;
+	}
+	if (priv->mtr_bulk.devx_obj) {
+		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
+		priv->mtr_bulk.devx_obj = NULL;
+	}
+}
+
+int
+mlx5_flow_meter_init(struct rte_eth_dev *dev,
+		     uint32_t nb_meters,
+		     uint32_t nb_meter_profiles,
+		     uint32_t nb_meter_policies,
+		     uint32_t nb_queues)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_devx_obj *dcs = NULL;
+	uint32_t log_obj_size;
+	int ret = 0;
+	int reg_id;
+	struct mlx5_aso_mtr *aso;
+	uint32_t i;
+	struct rte_flow_error error;
+	uint32_t flags;
+	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
+	struct mlx5_indexed_pool_config cfg = {
+		.size = sizeof(struct mlx5_aso_mtr),
+		.trunk_size = 1 << 12,
+		.per_core_cache = 1 << 13,
+		.need_lock = 1,
+		.release_mem_en = !!priv->sh->config.reclaim_mode,
+		.malloc = mlx5_malloc,
+		.max_idx = nb_meters,
+		.free = mlx5_free,
+		.type = "mlx5_hw_mtr_mark_action",
+	};
+
+	if (!nb_meters) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter configuration is invalid.");
+		goto err;
+	}
+	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO is not supported.");
+		goto err;
+	}
+	priv->mtr_config.nb_meters = nb_meters;
+	log_obj_size = rte_log2_u32(nb_meters >> 1);
+	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
+		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
+			log_obj_size);
+	if (!dcs) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO object allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.devx_obj = dcs;
+	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+	if (reg_id < 0) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter register is not available.");
+		goto err;
+	}
+	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
+			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
+				reg_id - REG_C_0, flags);
+	if (!priv->mtr_bulk.action) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter action creation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
+					 sizeof(struct mlx5_aso_mtr) *
+					 nb_meters,
+					 RTE_CACHE_LINE_SIZE,
+					 SOCKET_ID_ANY);
+	if (!priv->mtr_bulk.aso) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter bulk ASO allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.size = nb_meters;
+	aso = priv->mtr_bulk.aso;
+	for (i = 0; i < priv->mtr_bulk.size; i++) {
+		aso->type = ASO_METER_DIRECT;
+		aso->state = ASO_METER_WAIT;
+		aso->offset = i;
+		aso++;
+	}
+	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) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ipool allocation failed.");
+		goto err;
+	}
+	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
+	priv->hws_mpool->action = priv->mtr_bulk.action;
+	priv->hws_mpool->nb_sq = nb_queues;
+	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
+				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO queue allocation failed.");
+		goto err;
+	}
+	/*
+	 * No need for local cache if Meter number is a small number.
+	 * Since flow insertion rate will be very limited in that case.
+	 * Here let's set the number to less than default trunk size 4K.
+	 */
+	if (nb_mtrs <= cfg.trunk_size) {
+		cfg.per_core_cache = 0;
+		cfg.trunk_size = nb_mtrs;
+	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
+		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
+	}
+	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
+	if (nb_meter_profiles) {
+		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
+		priv->mtr_profile_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_profile) *
+				    nb_meter_profiles,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_profile_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter profile allocation failed.");
+			goto err;
+		}
+	}
+	if (nb_meter_policies) {
+		priv->mtr_config.nb_meter_policies = nb_meter_policies;
+		priv->mtr_policy_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_policy) *
+				    nb_meter_policies,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_policy_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter policy allocation failed.");
+			goto err;
+		}
+	}
+	return 0;
+err:
+	mlx5_flow_meter_uninit(dev);
+	return ret;
+}
+
+#endif /* HAVE_MLX5_HWS_SUPPORT */
+
 static int mlx5_flow_meter_disable(struct rte_eth_dev *dev,
 		uint32_t meter_id, struct rte_mtr_error *error);

--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/2] net/mlx5: add cross port meter mark action sharing
  2024-02-21 10:13 [PATCH 0/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  2024-02-21 10:13 ` [PATCH 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
@ 2024-02-21 10:13 ` Dariusz Sosnowski
  2024-02-21 10:21 ` [PATCH v2 0/2] " Dariusz Sosnowski
  2 siblings, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-21 10:13 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patch adds support for sharing meter mark actions between multiple
ports of the same physical NIC.

Meter objects pool, meter mark actions and meter profiles can be
created only on the host port. Guest ports are allowed to use meter
objects created on the host port through indirect actions. Direct use
of meter mark actions (e.g. putting meter mark action in actions
template), creation of indirect meters and meter profiles on the guest
port is not allowed.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c    | 34 +++++++++----
 drivers/net/mlx5/mlx5_flow_meter.c | 77 ++++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+), 10 deletions(-)

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. */
--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 0/2] net/mlx5: add cross port meter mark action sharing
  2024-02-21 10:13 [PATCH 0/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  2024-02-21 10:13 ` [PATCH 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
  2024-02-21 10:13 ` [PATCH 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
@ 2024-02-21 10:21 ` Dariusz Sosnowski
  2024-02-21 10:21   ` [PATCH v2 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
                     ` (2 more replies)
  2 siblings, 3 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-21 10:21 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patchset adds support for sharing indirect METER_MARK flow actions
between ports, when flow engine is configured with
RTE_FLOW_PORT_FLAG_SHARE_INDIRECT.

v2:
- Updated release notes.

Dariusz Sosnowski (2):
  net/mlx5: move meter init functions
  net/mlx5: add cross port meter mark action sharing

 doc/guides/rel_notes/release_24_03.rst |   3 +
 drivers/net/mlx5/mlx5_flow_hw.c        | 237 +++------------------
 drivers/net/mlx5/mlx5_flow_meter.c     | 284 +++++++++++++++++++++++++
 3 files changed, 311 insertions(+), 213 deletions(-)

--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/2] net/mlx5: move meter init functions
  2024-02-21 10:21 ` [PATCH v2 0/2] " Dariusz Sosnowski
@ 2024-02-21 10:21   ` Dariusz Sosnowski
  2024-02-21 10:21   ` [PATCH v2 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  2024-02-22 18:00   ` [PATCH v3 0/2] " Dariusz Sosnowski
  2 siblings, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-21 10:21 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

Move mlx5_flow_meter_init() and mlx5_flow_meter_uinit()
to module for meter operations.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c    | 203 ----------------------------
 drivers/net/mlx5/mlx5_flow_meter.c | 207 +++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 203 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 3bb3a9a178..4d6b22c4e3 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -12859,209 +12859,6 @@ mlx5_flow_hw_ctrl_flows(struct rte_eth_dev *dev, uint32_t flags)
 	return 0;
 }

-void
-mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-
-	if (priv->mtr_policy_arr) {
-		mlx5_free(priv->mtr_policy_arr);
-		priv->mtr_policy_arr = NULL;
-	}
-	if (priv->mtr_profile_arr) {
-		mlx5_free(priv->mtr_profile_arr);
-		priv->mtr_profile_arr = NULL;
-	}
-	if (priv->hws_mpool) {
-		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
-		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
-		mlx5_free(priv->hws_mpool);
-		priv->hws_mpool = NULL;
-	}
-	if (priv->mtr_bulk.aso) {
-		mlx5_free(priv->mtr_bulk.aso);
-		priv->mtr_bulk.aso = NULL;
-		priv->mtr_bulk.size = 0;
-		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
-	}
-	if (priv->mtr_bulk.action) {
-		mlx5dr_action_destroy(priv->mtr_bulk.action);
-		priv->mtr_bulk.action = NULL;
-	}
-	if (priv->mtr_bulk.devx_obj) {
-		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
-		priv->mtr_bulk.devx_obj = NULL;
-	}
-}
-
-int
-mlx5_flow_meter_init(struct rte_eth_dev *dev,
-		     uint32_t nb_meters,
-		     uint32_t nb_meter_profiles,
-		     uint32_t nb_meter_policies,
-		     uint32_t nb_queues)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_devx_obj *dcs = NULL;
-	uint32_t log_obj_size;
-	int ret = 0;
-	int reg_id;
-	struct mlx5_aso_mtr *aso;
-	uint32_t i;
-	struct rte_flow_error error;
-	uint32_t flags;
-	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
-	struct mlx5_indexed_pool_config cfg = {
-		.size = sizeof(struct mlx5_aso_mtr),
-		.trunk_size = 1 << 12,
-		.per_core_cache = 1 << 13,
-		.need_lock = 1,
-		.release_mem_en = !!priv->sh->config.reclaim_mode,
-		.malloc = mlx5_malloc,
-		.max_idx = nb_meters,
-		.free = mlx5_free,
-		.type = "mlx5_hw_mtr_mark_action",
-	};
-
-	if (!nb_meters) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter configuration is invalid.");
-		goto err;
-	}
-	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO is not supported.");
-		goto err;
-	}
-	priv->mtr_config.nb_meters = nb_meters;
-	log_obj_size = rte_log2_u32(nb_meters >> 1);
-	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
-		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
-			log_obj_size);
-	if (!dcs) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO object allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.devx_obj = dcs;
-	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
-	if (reg_id < 0) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter register is not available.");
-		goto err;
-	}
-	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
-			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
-				reg_id - REG_C_0, flags);
-	if (!priv->mtr_bulk.action) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter action creation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
-					 sizeof(struct mlx5_aso_mtr) *
-					 nb_meters,
-					 RTE_CACHE_LINE_SIZE,
-					 SOCKET_ID_ANY);
-	if (!priv->mtr_bulk.aso) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter bulk ASO allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.size = nb_meters;
-	aso = priv->mtr_bulk.aso;
-	for (i = 0; i < priv->mtr_bulk.size; i++) {
-		aso->type = ASO_METER_DIRECT;
-		aso->state = ASO_METER_WAIT;
-		aso->offset = i;
-		aso++;
-	}
-	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) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ipool allocation failed.");
-		goto err;
-	}
-	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
-	priv->hws_mpool->action = priv->mtr_bulk.action;
-	priv->hws_mpool->nb_sq = nb_queues;
-	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
-				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO queue allocation failed.");
-		goto err;
-	}
-	/*
-	 * No need for local cache if Meter number is a small number.
-	 * Since flow insertion rate will be very limited in that case.
-	 * Here let's set the number to less than default trunk size 4K.
-	 */
-	if (nb_mtrs <= cfg.trunk_size) {
-		cfg.per_core_cache = 0;
-		cfg.trunk_size = nb_mtrs;
-	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
-		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
-	}
-	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
-	if (nb_meter_profiles) {
-		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
-		priv->mtr_profile_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_profile) *
-				    nb_meter_profiles,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_profile_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter profile allocation failed.");
-			goto err;
-		}
-	}
-	if (nb_meter_policies) {
-		priv->mtr_config.nb_meter_policies = nb_meter_policies;
-		priv->mtr_policy_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_policy) *
-				    nb_meter_policies,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_policy_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter policy allocation failed.");
-			goto err;
-		}
-	}
-	return 0;
-err:
-	mlx5_flow_meter_uninit(dev);
-	return ret;
-}
-
 static __rte_always_inline uint32_t
 mlx5_reformat_domain_to_tbl_type(const struct rte_flow_indir_action_conf *domain)
 {
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 7cbf772ea4..9cb4614436 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -15,6 +15,213 @@
 #include "mlx5.h"
 #include "mlx5_flow.h"

+#ifdef HAVE_MLX5_HWS_SUPPORT
+
+void
+mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (priv->mtr_policy_arr) {
+		mlx5_free(priv->mtr_policy_arr);
+		priv->mtr_policy_arr = NULL;
+	}
+	if (priv->mtr_profile_arr) {
+		mlx5_free(priv->mtr_profile_arr);
+		priv->mtr_profile_arr = NULL;
+	}
+	if (priv->hws_mpool) {
+		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
+		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
+		mlx5_free(priv->hws_mpool);
+		priv->hws_mpool = NULL;
+	}
+	if (priv->mtr_bulk.aso) {
+		mlx5_free(priv->mtr_bulk.aso);
+		priv->mtr_bulk.aso = NULL;
+		priv->mtr_bulk.size = 0;
+		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
+	}
+	if (priv->mtr_bulk.action) {
+		mlx5dr_action_destroy(priv->mtr_bulk.action);
+		priv->mtr_bulk.action = NULL;
+	}
+	if (priv->mtr_bulk.devx_obj) {
+		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
+		priv->mtr_bulk.devx_obj = NULL;
+	}
+}
+
+int
+mlx5_flow_meter_init(struct rte_eth_dev *dev,
+		     uint32_t nb_meters,
+		     uint32_t nb_meter_profiles,
+		     uint32_t nb_meter_policies,
+		     uint32_t nb_queues)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_devx_obj *dcs = NULL;
+	uint32_t log_obj_size;
+	int ret = 0;
+	int reg_id;
+	struct mlx5_aso_mtr *aso;
+	uint32_t i;
+	struct rte_flow_error error;
+	uint32_t flags;
+	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
+	struct mlx5_indexed_pool_config cfg = {
+		.size = sizeof(struct mlx5_aso_mtr),
+		.trunk_size = 1 << 12,
+		.per_core_cache = 1 << 13,
+		.need_lock = 1,
+		.release_mem_en = !!priv->sh->config.reclaim_mode,
+		.malloc = mlx5_malloc,
+		.max_idx = nb_meters,
+		.free = mlx5_free,
+		.type = "mlx5_hw_mtr_mark_action",
+	};
+
+	if (!nb_meters) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter configuration is invalid.");
+		goto err;
+	}
+	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO is not supported.");
+		goto err;
+	}
+	priv->mtr_config.nb_meters = nb_meters;
+	log_obj_size = rte_log2_u32(nb_meters >> 1);
+	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
+		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
+			log_obj_size);
+	if (!dcs) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO object allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.devx_obj = dcs;
+	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+	if (reg_id < 0) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter register is not available.");
+		goto err;
+	}
+	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
+			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
+				reg_id - REG_C_0, flags);
+	if (!priv->mtr_bulk.action) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter action creation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
+					 sizeof(struct mlx5_aso_mtr) *
+					 nb_meters,
+					 RTE_CACHE_LINE_SIZE,
+					 SOCKET_ID_ANY);
+	if (!priv->mtr_bulk.aso) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter bulk ASO allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.size = nb_meters;
+	aso = priv->mtr_bulk.aso;
+	for (i = 0; i < priv->mtr_bulk.size; i++) {
+		aso->type = ASO_METER_DIRECT;
+		aso->state = ASO_METER_WAIT;
+		aso->offset = i;
+		aso++;
+	}
+	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) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ipool allocation failed.");
+		goto err;
+	}
+	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
+	priv->hws_mpool->action = priv->mtr_bulk.action;
+	priv->hws_mpool->nb_sq = nb_queues;
+	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
+				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO queue allocation failed.");
+		goto err;
+	}
+	/*
+	 * No need for local cache if Meter number is a small number.
+	 * Since flow insertion rate will be very limited in that case.
+	 * Here let's set the number to less than default trunk size 4K.
+	 */
+	if (nb_mtrs <= cfg.trunk_size) {
+		cfg.per_core_cache = 0;
+		cfg.trunk_size = nb_mtrs;
+	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
+		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
+	}
+	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
+	if (nb_meter_profiles) {
+		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
+		priv->mtr_profile_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_profile) *
+				    nb_meter_profiles,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_profile_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter profile allocation failed.");
+			goto err;
+		}
+	}
+	if (nb_meter_policies) {
+		priv->mtr_config.nb_meter_policies = nb_meter_policies;
+		priv->mtr_policy_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_policy) *
+				    nb_meter_policies,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_policy_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter policy allocation failed.");
+			goto err;
+		}
+	}
+	return 0;
+err:
+	mlx5_flow_meter_uninit(dev);
+	return ret;
+}
+
+#endif /* HAVE_MLX5_HWS_SUPPORT */
+
 static int mlx5_flow_meter_disable(struct rte_eth_dev *dev,
 		uint32_t meter_id, struct rte_mtr_error *error);

--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 2/2] net/mlx5: add cross port meter mark action sharing
  2024-02-21 10:21 ` [PATCH v2 0/2] " Dariusz Sosnowski
  2024-02-21 10:21   ` [PATCH v2 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
@ 2024-02-21 10:21   ` Dariusz Sosnowski
  2024-02-22 18:00   ` [PATCH v3 0/2] " Dariusz Sosnowski
  2 siblings, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-21 10:21 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patch adds support for sharing meter mark actions between multiple
ports of the same physical NIC.

Meter objects pool, meter mark actions and meter profiles can be
created only on the host port. Guest ports are allowed to use meter
objects created on the host port through indirect actions. Direct use
of meter mark actions (e.g. putting meter mark action in actions
template), creation of indirect meters and meter profiles on the guest
port is not allowed.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/rel_notes/release_24_03.rst |  3 +
 drivers/net/mlx5/mlx5_flow_hw.c        | 34 ++++++++----
 drivers/net/mlx5/mlx5_flow_meter.c     | 77 ++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 10 deletions(-)

diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 619459baae..2e73a7a37a 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -133,6 +133,9 @@ New Features
   * Added HW steering support for modify field ``RTE_FLOW_FIELD_ESP_SEQ_NUM`` flow action.
   * Added HW steering support for modify field ``RTE_FLOW_FIELD_ESP_PROTO`` flow action.

+  * Added support for sharing indirect action objects of type ``RTE_FLOW_ACTION_TYPE_METER_MARK``
+    with HW steering flow engine.
+

 Removed Items
 -------------
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. */
--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 0/2] net/mlx5: add cross port meter mark action sharing
  2024-02-21 10:21 ` [PATCH v2 0/2] " Dariusz Sosnowski
  2024-02-21 10:21   ` [PATCH v2 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
  2024-02-21 10:21   ` [PATCH v2 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
@ 2024-02-22 18:00   ` Dariusz Sosnowski
  2024-02-22 18:00     ` [PATCH v3 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
                       ` (2 more replies)
  2 siblings, 3 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-22 18:00 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patchset adds support for sharing indirect METER_MARK flow actions
between ports, when flow engine is configured with
RTE_FLOW_PORT_FLAG_SHARE_INDIRECT.

v3:
- Rebased on top of v24.03-rc1.
- Fixed completion polling issue with meter queues.

v2:
- Updated release notes.

Dariusz Sosnowski (2):
  net/mlx5: move meter init functions
  net/mlx5: add cross port meter mark action sharing

 doc/guides/rel_notes/release_24_03.rst |   2 +
 drivers/net/mlx5/mlx5_flow_hw.c        | 245 +++------------------
 drivers/net/mlx5/mlx5_flow_meter.c     | 284 +++++++++++++++++++++++++
 3 files changed, 315 insertions(+), 216 deletions(-)

--
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 1/2] net/mlx5: move meter init functions
  2024-02-22 18:00   ` [PATCH v3 0/2] " Dariusz Sosnowski
@ 2024-02-22 18:00     ` Dariusz Sosnowski
  2024-02-22 18:00     ` [PATCH v3 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  2024-02-27 13:37     ` [PATCH v4 0/2] " Dariusz Sosnowski
  2 siblings, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-22 18:00 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

Move mlx5_flow_meter_init() and mlx5_flow_meter_uinit()
to module for meter operations.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c    | 203 ----------------------------
 drivers/net/mlx5/mlx5_flow_meter.c | 207 +++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 203 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index bcf43f5457..10d9040028 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -12859,209 +12859,6 @@ mlx5_flow_hw_ctrl_flows(struct rte_eth_dev *dev, uint32_t flags)
 	return 0;
 }
 
-void
-mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-
-	if (priv->mtr_policy_arr) {
-		mlx5_free(priv->mtr_policy_arr);
-		priv->mtr_policy_arr = NULL;
-	}
-	if (priv->mtr_profile_arr) {
-		mlx5_free(priv->mtr_profile_arr);
-		priv->mtr_profile_arr = NULL;
-	}
-	if (priv->hws_mpool) {
-		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
-		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
-		mlx5_free(priv->hws_mpool);
-		priv->hws_mpool = NULL;
-	}
-	if (priv->mtr_bulk.aso) {
-		mlx5_free(priv->mtr_bulk.aso);
-		priv->mtr_bulk.aso = NULL;
-		priv->mtr_bulk.size = 0;
-		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
-	}
-	if (priv->mtr_bulk.action) {
-		mlx5dr_action_destroy(priv->mtr_bulk.action);
-		priv->mtr_bulk.action = NULL;
-	}
-	if (priv->mtr_bulk.devx_obj) {
-		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
-		priv->mtr_bulk.devx_obj = NULL;
-	}
-}
-
-int
-mlx5_flow_meter_init(struct rte_eth_dev *dev,
-		     uint32_t nb_meters,
-		     uint32_t nb_meter_profiles,
-		     uint32_t nb_meter_policies,
-		     uint32_t nb_queues)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_devx_obj *dcs = NULL;
-	uint32_t log_obj_size;
-	int ret = 0;
-	int reg_id;
-	struct mlx5_aso_mtr *aso;
-	uint32_t i;
-	struct rte_flow_error error;
-	uint32_t flags;
-	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
-	struct mlx5_indexed_pool_config cfg = {
-		.size = sizeof(struct mlx5_aso_mtr),
-		.trunk_size = 1 << 12,
-		.per_core_cache = 1 << 13,
-		.need_lock = 1,
-		.release_mem_en = !!priv->sh->config.reclaim_mode,
-		.malloc = mlx5_malloc,
-		.max_idx = nb_meters,
-		.free = mlx5_free,
-		.type = "mlx5_hw_mtr_mark_action",
-	};
-
-	if (!nb_meters) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter configuration is invalid.");
-		goto err;
-	}
-	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO is not supported.");
-		goto err;
-	}
-	priv->mtr_config.nb_meters = nb_meters;
-	log_obj_size = rte_log2_u32(nb_meters >> 1);
-	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
-		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
-			log_obj_size);
-	if (!dcs) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO object allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.devx_obj = dcs;
-	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
-	if (reg_id < 0) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter register is not available.");
-		goto err;
-	}
-	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
-			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
-				reg_id - REG_C_0, flags);
-	if (!priv->mtr_bulk.action) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter action creation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
-					 sizeof(struct mlx5_aso_mtr) *
-					 nb_meters,
-					 RTE_CACHE_LINE_SIZE,
-					 SOCKET_ID_ANY);
-	if (!priv->mtr_bulk.aso) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter bulk ASO allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.size = nb_meters;
-	aso = priv->mtr_bulk.aso;
-	for (i = 0; i < priv->mtr_bulk.size; i++) {
-		aso->type = ASO_METER_DIRECT;
-		aso->state = ASO_METER_WAIT;
-		aso->offset = i;
-		aso++;
-	}
-	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) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ipool allocation failed.");
-		goto err;
-	}
-	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
-	priv->hws_mpool->action = priv->mtr_bulk.action;
-	priv->hws_mpool->nb_sq = nb_queues;
-	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
-				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO queue allocation failed.");
-		goto err;
-	}
-	/*
-	 * No need for local cache if Meter number is a small number.
-	 * Since flow insertion rate will be very limited in that case.
-	 * Here let's set the number to less than default trunk size 4K.
-	 */
-	if (nb_mtrs <= cfg.trunk_size) {
-		cfg.per_core_cache = 0;
-		cfg.trunk_size = nb_mtrs;
-	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
-		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
-	}
-	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
-	if (nb_meter_profiles) {
-		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
-		priv->mtr_profile_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_profile) *
-				    nb_meter_profiles,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_profile_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter profile allocation failed.");
-			goto err;
-		}
-	}
-	if (nb_meter_policies) {
-		priv->mtr_config.nb_meter_policies = nb_meter_policies;
-		priv->mtr_policy_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_policy) *
-				    nb_meter_policies,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_policy_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter policy allocation failed.");
-			goto err;
-		}
-	}
-	return 0;
-err:
-	mlx5_flow_meter_uninit(dev);
-	return ret;
-}
-
 static __rte_always_inline uint32_t
 mlx5_reformat_domain_to_tbl_type(const struct rte_flow_indir_action_conf *domain)
 {
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 7cbf772ea4..9cb4614436 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -15,6 +15,213 @@
 #include "mlx5.h"
 #include "mlx5_flow.h"
 
+#ifdef HAVE_MLX5_HWS_SUPPORT
+
+void
+mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (priv->mtr_policy_arr) {
+		mlx5_free(priv->mtr_policy_arr);
+		priv->mtr_policy_arr = NULL;
+	}
+	if (priv->mtr_profile_arr) {
+		mlx5_free(priv->mtr_profile_arr);
+		priv->mtr_profile_arr = NULL;
+	}
+	if (priv->hws_mpool) {
+		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
+		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
+		mlx5_free(priv->hws_mpool);
+		priv->hws_mpool = NULL;
+	}
+	if (priv->mtr_bulk.aso) {
+		mlx5_free(priv->mtr_bulk.aso);
+		priv->mtr_bulk.aso = NULL;
+		priv->mtr_bulk.size = 0;
+		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
+	}
+	if (priv->mtr_bulk.action) {
+		mlx5dr_action_destroy(priv->mtr_bulk.action);
+		priv->mtr_bulk.action = NULL;
+	}
+	if (priv->mtr_bulk.devx_obj) {
+		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
+		priv->mtr_bulk.devx_obj = NULL;
+	}
+}
+
+int
+mlx5_flow_meter_init(struct rte_eth_dev *dev,
+		     uint32_t nb_meters,
+		     uint32_t nb_meter_profiles,
+		     uint32_t nb_meter_policies,
+		     uint32_t nb_queues)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_devx_obj *dcs = NULL;
+	uint32_t log_obj_size;
+	int ret = 0;
+	int reg_id;
+	struct mlx5_aso_mtr *aso;
+	uint32_t i;
+	struct rte_flow_error error;
+	uint32_t flags;
+	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
+	struct mlx5_indexed_pool_config cfg = {
+		.size = sizeof(struct mlx5_aso_mtr),
+		.trunk_size = 1 << 12,
+		.per_core_cache = 1 << 13,
+		.need_lock = 1,
+		.release_mem_en = !!priv->sh->config.reclaim_mode,
+		.malloc = mlx5_malloc,
+		.max_idx = nb_meters,
+		.free = mlx5_free,
+		.type = "mlx5_hw_mtr_mark_action",
+	};
+
+	if (!nb_meters) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter configuration is invalid.");
+		goto err;
+	}
+	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO is not supported.");
+		goto err;
+	}
+	priv->mtr_config.nb_meters = nb_meters;
+	log_obj_size = rte_log2_u32(nb_meters >> 1);
+	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
+		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
+			log_obj_size);
+	if (!dcs) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO object allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.devx_obj = dcs;
+	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+	if (reg_id < 0) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter register is not available.");
+		goto err;
+	}
+	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
+			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
+				reg_id - REG_C_0, flags);
+	if (!priv->mtr_bulk.action) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter action creation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
+					 sizeof(struct mlx5_aso_mtr) *
+					 nb_meters,
+					 RTE_CACHE_LINE_SIZE,
+					 SOCKET_ID_ANY);
+	if (!priv->mtr_bulk.aso) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter bulk ASO allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.size = nb_meters;
+	aso = priv->mtr_bulk.aso;
+	for (i = 0; i < priv->mtr_bulk.size; i++) {
+		aso->type = ASO_METER_DIRECT;
+		aso->state = ASO_METER_WAIT;
+		aso->offset = i;
+		aso++;
+	}
+	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) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ipool allocation failed.");
+		goto err;
+	}
+	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
+	priv->hws_mpool->action = priv->mtr_bulk.action;
+	priv->hws_mpool->nb_sq = nb_queues;
+	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
+				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO queue allocation failed.");
+		goto err;
+	}
+	/*
+	 * No need for local cache if Meter number is a small number.
+	 * Since flow insertion rate will be very limited in that case.
+	 * Here let's set the number to less than default trunk size 4K.
+	 */
+	if (nb_mtrs <= cfg.trunk_size) {
+		cfg.per_core_cache = 0;
+		cfg.trunk_size = nb_mtrs;
+	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
+		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
+	}
+	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
+	if (nb_meter_profiles) {
+		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
+		priv->mtr_profile_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_profile) *
+				    nb_meter_profiles,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_profile_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter profile allocation failed.");
+			goto err;
+		}
+	}
+	if (nb_meter_policies) {
+		priv->mtr_config.nb_meter_policies = nb_meter_policies;
+		priv->mtr_policy_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_policy) *
+				    nb_meter_policies,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_policy_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter policy allocation failed.");
+			goto err;
+		}
+	}
+	return 0;
+err:
+	mlx5_flow_meter_uninit(dev);
+	return ret;
+}
+
+#endif /* HAVE_MLX5_HWS_SUPPORT */
+
 static int mlx5_flow_meter_disable(struct rte_eth_dev *dev,
 		uint32_t meter_id, struct rte_mtr_error *error);
 
-- 
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 2/2] net/mlx5: add cross port meter mark action sharing
  2024-02-22 18:00   ` [PATCH v3 0/2] " Dariusz Sosnowski
  2024-02-22 18:00     ` [PATCH v3 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
@ 2024-02-22 18:00     ` Dariusz Sosnowski
  2024-02-27 13:37     ` [PATCH v4 0/2] " Dariusz Sosnowski
  2 siblings, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-22 18:00 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patch adds support for sharing meter mark actions between multiple
ports of the same physical NIC.

Meter objects pool, meter mark actions and meter profiles can be
created only on the host port. Guest ports are allowed to use meter
objects created on the host port through indirect actions. Direct use
of meter mark actions (e.g. putting meter mark action in actions
template), creation of indirect meters and meter profiles on the guest
port is not allowed.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/rel_notes/release_24_03.rst |  2 +
 drivers/net/mlx5/mlx5_flow_hw.c        | 42 +++++++++-----
 drivers/net/mlx5/mlx5_flow_meter.c     | 77 ++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 13 deletions(-)

diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index 879bb4944c..518b01dd54 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -130,6 +130,8 @@ New Features
   * Added support for matching a random value.
   * Added support for comparing result between packet fields or value.
   * Added support for accumulating value of field into another one.
+  * Added support for sharing indirect action objects of type ``RTE_FLOW_ACTION_TYPE_METER_MARK``
+    in HWS flow engine.
 
 * **Updated Marvell cnxk crypto driver.**
 
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 10d9040028..482db9cad9 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;
@@ -3832,9 +3841,11 @@ __flow_hw_pull_indir_action_comp(struct rte_eth_dev *dev,
 		res[i].user_data = user_data;
 		res[i].status = RTE_FLOW_OP_SUCCESS;
 	}
-	if (ret_comp < n_res && priv->hws_mpool)
-		ret_comp += mlx5_aso_pull_completion(&priv->hws_mpool->sq[queue],
-				&res[ret_comp], n_res - ret_comp);
+	if (!priv->shared_host) {
+		if (ret_comp < n_res && priv->hws_mpool)
+			ret_comp += mlx5_aso_pull_completion(&priv->hws_mpool->sq[queue],
+					&res[ret_comp], n_res - ret_comp);
+	}
 	if (ret_comp < n_res && priv->hws_ctpool)
 		ret_comp += mlx5_aso_pull_completion(&priv->ct_mng->aso_sqs[queue],
 				&res[ret_comp], n_res - ret_comp);
@@ -5322,6 +5333,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 +5344,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 +5355,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 +5401,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 +5858,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 +10154,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 +10313,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. */
-- 
2.34.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 0/2] net/mlx5: add cross port meter mark action sharing
  2024-02-22 18:00   ` [PATCH v3 0/2] " Dariusz Sosnowski
  2024-02-22 18:00     ` [PATCH v3 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
  2024-02-22 18:00     ` [PATCH v3 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
@ 2024-02-27 13:37     ` Dariusz Sosnowski
  2024-02-27 13:37       ` [PATCH v4 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
  2024-02-27 13:37       ` [PATCH v4 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  2 siblings, 2 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-27 13:37 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev


This patchset adds support for sharing indirect METER_MARK flow actions
between ports, when flow engine is configured with
RTE_FLOW_PORT_FLAG_SHARE_INDIRECT.

v4:
- Rebased.

v3:
- Rebased on top of v24.03-rc1.
- Fixed completion polling issue with meter queues.

v2:
- Updated release notes.

Dariusz Sosnowski (2):
  net/mlx5: move meter init functions
  net/mlx5: add cross port meter mark action sharing

 doc/guides/rel_notes/release_24_03.rst |   2 +
 drivers/net/mlx5/mlx5_flow_hw.c        | 245 +++------------------
 drivers/net/mlx5/mlx5_flow_meter.c     | 284 +++++++++++++++++++++++++
 3 files changed, 315 insertions(+), 216 deletions(-)

--
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 1/2] net/mlx5: move meter init functions
  2024-02-27 13:37     ` [PATCH v4 0/2] " Dariusz Sosnowski
@ 2024-02-27 13:37       ` Dariusz Sosnowski
  2024-02-28 10:12         ` Raslan Darawsheh
  2024-02-27 13:37       ` [PATCH v4 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
  1 sibling, 1 reply; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-27 13:37 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

Move mlx5_flow_meter_init() and mlx5_flow_meter_uinit()
to module for meter operations.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 drivers/net/mlx5/mlx5_flow_hw.c    | 203 ----------------------------
 drivers/net/mlx5/mlx5_flow_meter.c | 207 +++++++++++++++++++++++++++++
 2 files changed, 207 insertions(+), 203 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 769ec9ff94..49c164060b 100644
--- a/drivers/net/mlx5/mlx5_flow_hw.c
+++ b/drivers/net/mlx5/mlx5_flow_hw.c
@@ -13139,209 +13139,6 @@ mlx5_flow_hw_ctrl_flows(struct rte_eth_dev *dev, uint32_t flags)
 	return 0;
 }
 
-void
-mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-
-	if (priv->mtr_policy_arr) {
-		mlx5_free(priv->mtr_policy_arr);
-		priv->mtr_policy_arr = NULL;
-	}
-	if (priv->mtr_profile_arr) {
-		mlx5_free(priv->mtr_profile_arr);
-		priv->mtr_profile_arr = NULL;
-	}
-	if (priv->hws_mpool) {
-		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
-		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
-		mlx5_free(priv->hws_mpool);
-		priv->hws_mpool = NULL;
-	}
-	if (priv->mtr_bulk.aso) {
-		mlx5_free(priv->mtr_bulk.aso);
-		priv->mtr_bulk.aso = NULL;
-		priv->mtr_bulk.size = 0;
-		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
-	}
-	if (priv->mtr_bulk.action) {
-		mlx5dr_action_destroy(priv->mtr_bulk.action);
-		priv->mtr_bulk.action = NULL;
-	}
-	if (priv->mtr_bulk.devx_obj) {
-		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
-		priv->mtr_bulk.devx_obj = NULL;
-	}
-}
-
-int
-mlx5_flow_meter_init(struct rte_eth_dev *dev,
-		     uint32_t nb_meters,
-		     uint32_t nb_meter_profiles,
-		     uint32_t nb_meter_policies,
-		     uint32_t nb_queues)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_devx_obj *dcs = NULL;
-	uint32_t log_obj_size;
-	int ret = 0;
-	int reg_id;
-	struct mlx5_aso_mtr *aso;
-	uint32_t i;
-	struct rte_flow_error error;
-	uint32_t flags;
-	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
-	struct mlx5_indexed_pool_config cfg = {
-		.size = sizeof(struct mlx5_aso_mtr),
-		.trunk_size = 1 << 12,
-		.per_core_cache = 1 << 13,
-		.need_lock = 1,
-		.release_mem_en = !!priv->sh->config.reclaim_mode,
-		.malloc = mlx5_malloc,
-		.max_idx = nb_meters,
-		.free = mlx5_free,
-		.type = "mlx5_hw_mtr_mark_action",
-	};
-
-	if (!nb_meters) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter configuration is invalid.");
-		goto err;
-	}
-	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO is not supported.");
-		goto err;
-	}
-	priv->mtr_config.nb_meters = nb_meters;
-	log_obj_size = rte_log2_u32(nb_meters >> 1);
-	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
-		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
-			log_obj_size);
-	if (!dcs) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO object allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.devx_obj = dcs;
-	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
-	if (reg_id < 0) {
-		ret = ENOTSUP;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter register is not available.");
-		goto err;
-	}
-	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
-			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
-				reg_id - REG_C_0, flags);
-	if (!priv->mtr_bulk.action) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter action creation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
-					 sizeof(struct mlx5_aso_mtr) *
-					 nb_meters,
-					 RTE_CACHE_LINE_SIZE,
-					 SOCKET_ID_ANY);
-	if (!priv->mtr_bulk.aso) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter bulk ASO allocation failed.");
-		goto err;
-	}
-	priv->mtr_bulk.size = nb_meters;
-	aso = priv->mtr_bulk.aso;
-	for (i = 0; i < priv->mtr_bulk.size; i++) {
-		aso->type = ASO_METER_DIRECT;
-		aso->state = ASO_METER_WAIT;
-		aso->offset = i;
-		aso++;
-	}
-	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) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ipool allocation failed.");
-		goto err;
-	}
-	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
-	priv->hws_mpool->action = priv->mtr_bulk.action;
-	priv->hws_mpool->nb_sq = nb_queues;
-	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
-				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
-		ret = ENOMEM;
-		rte_flow_error_set(&error, ENOMEM,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL, "Meter ASO queue allocation failed.");
-		goto err;
-	}
-	/*
-	 * No need for local cache if Meter number is a small number.
-	 * Since flow insertion rate will be very limited in that case.
-	 * Here let's set the number to less than default trunk size 4K.
-	 */
-	if (nb_mtrs <= cfg.trunk_size) {
-		cfg.per_core_cache = 0;
-		cfg.trunk_size = nb_mtrs;
-	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
-		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
-	}
-	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
-	if (nb_meter_profiles) {
-		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
-		priv->mtr_profile_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_profile) *
-				    nb_meter_profiles,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_profile_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter profile allocation failed.");
-			goto err;
-		}
-	}
-	if (nb_meter_policies) {
-		priv->mtr_config.nb_meter_policies = nb_meter_policies;
-		priv->mtr_policy_arr =
-			mlx5_malloc(MLX5_MEM_ZERO,
-				    sizeof(struct mlx5_flow_meter_policy) *
-				    nb_meter_policies,
-				    RTE_CACHE_LINE_SIZE,
-				    SOCKET_ID_ANY);
-		if (!priv->mtr_policy_arr) {
-			ret = ENOMEM;
-			rte_flow_error_set(&error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					   NULL, "Meter policy allocation failed.");
-			goto err;
-		}
-	}
-	return 0;
-err:
-	mlx5_flow_meter_uninit(dev);
-	return ret;
-}
-
 static __rte_always_inline uint32_t
 mlx5_reformat_domain_to_tbl_type(const struct rte_flow_indir_action_conf *domain)
 {
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index 7cbf772ea4..9cb4614436 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -15,6 +15,213 @@
 #include "mlx5.h"
 #include "mlx5_flow.h"
 
+#ifdef HAVE_MLX5_HWS_SUPPORT
+
+void
+mlx5_flow_meter_uninit(struct rte_eth_dev *dev)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+
+	if (priv->mtr_policy_arr) {
+		mlx5_free(priv->mtr_policy_arr);
+		priv->mtr_policy_arr = NULL;
+	}
+	if (priv->mtr_profile_arr) {
+		mlx5_free(priv->mtr_profile_arr);
+		priv->mtr_profile_arr = NULL;
+	}
+	if (priv->hws_mpool) {
+		mlx5_aso_mtr_queue_uninit(priv->sh, priv->hws_mpool, NULL);
+		mlx5_ipool_destroy(priv->hws_mpool->idx_pool);
+		mlx5_free(priv->hws_mpool);
+		priv->hws_mpool = NULL;
+	}
+	if (priv->mtr_bulk.aso) {
+		mlx5_free(priv->mtr_bulk.aso);
+		priv->mtr_bulk.aso = NULL;
+		priv->mtr_bulk.size = 0;
+		mlx5_aso_queue_uninit(priv->sh, ASO_OPC_MOD_POLICER);
+	}
+	if (priv->mtr_bulk.action) {
+		mlx5dr_action_destroy(priv->mtr_bulk.action);
+		priv->mtr_bulk.action = NULL;
+	}
+	if (priv->mtr_bulk.devx_obj) {
+		claim_zero(mlx5_devx_cmd_destroy(priv->mtr_bulk.devx_obj));
+		priv->mtr_bulk.devx_obj = NULL;
+	}
+}
+
+int
+mlx5_flow_meter_init(struct rte_eth_dev *dev,
+		     uint32_t nb_meters,
+		     uint32_t nb_meter_profiles,
+		     uint32_t nb_meter_policies,
+		     uint32_t nb_queues)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_devx_obj *dcs = NULL;
+	uint32_t log_obj_size;
+	int ret = 0;
+	int reg_id;
+	struct mlx5_aso_mtr *aso;
+	uint32_t i;
+	struct rte_flow_error error;
+	uint32_t flags;
+	uint32_t nb_mtrs = rte_align32pow2(nb_meters);
+	struct mlx5_indexed_pool_config cfg = {
+		.size = sizeof(struct mlx5_aso_mtr),
+		.trunk_size = 1 << 12,
+		.per_core_cache = 1 << 13,
+		.need_lock = 1,
+		.release_mem_en = !!priv->sh->config.reclaim_mode,
+		.malloc = mlx5_malloc,
+		.max_idx = nb_meters,
+		.free = mlx5_free,
+		.type = "mlx5_hw_mtr_mark_action",
+	};
+
+	if (!nb_meters) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter configuration is invalid.");
+		goto err;
+	}
+	if (!priv->mtr_en || !priv->sh->meter_aso_en) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO is not supported.");
+		goto err;
+	}
+	priv->mtr_config.nb_meters = nb_meters;
+	log_obj_size = rte_log2_u32(nb_meters >> 1);
+	dcs = mlx5_devx_cmd_create_flow_meter_aso_obj
+		(priv->sh->cdev->ctx, priv->sh->cdev->pdn,
+			log_obj_size);
+	if (!dcs) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO object allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.devx_obj = dcs;
+	reg_id = mlx5_flow_get_reg_id(dev, MLX5_MTR_COLOR, 0, NULL);
+	if (reg_id < 0) {
+		ret = ENOTSUP;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter register is not available.");
+		goto err;
+	}
+	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->mtr_bulk.action = mlx5dr_action_create_aso_meter
+			(priv->dr_ctx, (struct mlx5dr_devx_obj *)dcs,
+				reg_id - REG_C_0, flags);
+	if (!priv->mtr_bulk.action) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter action creation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.aso = mlx5_malloc(MLX5_MEM_ZERO,
+					 sizeof(struct mlx5_aso_mtr) *
+					 nb_meters,
+					 RTE_CACHE_LINE_SIZE,
+					 SOCKET_ID_ANY);
+	if (!priv->mtr_bulk.aso) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter bulk ASO allocation failed.");
+		goto err;
+	}
+	priv->mtr_bulk.size = nb_meters;
+	aso = priv->mtr_bulk.aso;
+	for (i = 0; i < priv->mtr_bulk.size; i++) {
+		aso->type = ASO_METER_DIRECT;
+		aso->state = ASO_METER_WAIT;
+		aso->offset = i;
+		aso++;
+	}
+	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) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ipool allocation failed.");
+		goto err;
+	}
+	priv->hws_mpool->devx_obj = priv->mtr_bulk.devx_obj;
+	priv->hws_mpool->action = priv->mtr_bulk.action;
+	priv->hws_mpool->nb_sq = nb_queues;
+	if (mlx5_aso_mtr_queue_init(priv->sh, priv->hws_mpool,
+				    &priv->sh->mtrmng->pools_mng, nb_queues)) {
+		ret = ENOMEM;
+		rte_flow_error_set(&error, ENOMEM,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL, "Meter ASO queue allocation failed.");
+		goto err;
+	}
+	/*
+	 * No need for local cache if Meter number is a small number.
+	 * Since flow insertion rate will be very limited in that case.
+	 * Here let's set the number to less than default trunk size 4K.
+	 */
+	if (nb_mtrs <= cfg.trunk_size) {
+		cfg.per_core_cache = 0;
+		cfg.trunk_size = nb_mtrs;
+	} else if (nb_mtrs <= MLX5_HW_IPOOL_SIZE_THRESHOLD) {
+		cfg.per_core_cache = MLX5_HW_IPOOL_CACHE_MIN;
+	}
+	priv->hws_mpool->idx_pool = mlx5_ipool_create(&cfg);
+	if (nb_meter_profiles) {
+		priv->mtr_config.nb_meter_profiles = nb_meter_profiles;
+		priv->mtr_profile_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_profile) *
+				    nb_meter_profiles,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_profile_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter profile allocation failed.");
+			goto err;
+		}
+	}
+	if (nb_meter_policies) {
+		priv->mtr_config.nb_meter_policies = nb_meter_policies;
+		priv->mtr_policy_arr =
+			mlx5_malloc(MLX5_MEM_ZERO,
+				    sizeof(struct mlx5_flow_meter_policy) *
+				    nb_meter_policies,
+				    RTE_CACHE_LINE_SIZE,
+				    SOCKET_ID_ANY);
+		if (!priv->mtr_policy_arr) {
+			ret = ENOMEM;
+			rte_flow_error_set(&error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					   NULL, "Meter policy allocation failed.");
+			goto err;
+		}
+	}
+	return 0;
+err:
+	mlx5_flow_meter_uninit(dev);
+	return ret;
+}
+
+#endif /* HAVE_MLX5_HWS_SUPPORT */
+
 static int mlx5_flow_meter_disable(struct rte_eth_dev *dev,
 		uint32_t meter_id, struct rte_mtr_error *error);
 
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v4 2/2] net/mlx5: add cross port meter mark action sharing
  2024-02-27 13:37     ` [PATCH v4 0/2] " Dariusz Sosnowski
  2024-02-27 13:37       ` [PATCH v4 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
@ 2024-02-27 13:37       ` Dariusz Sosnowski
  1 sibling, 0 replies; 13+ messages in thread
From: Dariusz Sosnowski @ 2024-02-27 13:37 UTC (permalink / raw)
  To: Viacheslav Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad; +Cc: dev

This patch adds support for sharing meter mark actions between multiple
ports of the same physical NIC.

Meter objects pool, meter mark actions and meter profiles can be
created only on the host port. Guest ports are allowed to use meter
objects created on the host port through indirect actions. Direct use
of meter mark actions (e.g. putting meter mark action in actions
template), creation of indirect meters and meter profiles on the guest
port is not allowed.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Ori Kam <orika@nvidia.com>
---
 doc/guides/rel_notes/release_24_03.rst |  2 +
 drivers/net/mlx5/mlx5_flow_hw.c        | 42 +++++++++-----
 drivers/net/mlx5/mlx5_flow_meter.c     | 77 ++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 13 deletions(-)

diff --git a/doc/guides/rel_notes/release_24_03.rst b/doc/guides/rel_notes/release_24_03.rst
index ff9c6552e4..76d2e60f59 100644
--- a/doc/guides/rel_notes/release_24_03.rst
+++ b/doc/guides/rel_notes/release_24_03.rst
@@ -133,6 +133,8 @@ New Features
   * Added support for comparing result between packet fields or value.
   * Added support for accumulating value of field into another one.
   * Added support for copy inner fields in HWS flow engine.
+  * Added support for sharing indirect action objects of type ``RTE_FLOW_ACTION_TYPE_METER_MARK``
+    in HWS flow engine.
 
 * **Updated Marvell cnxk crypto driver.**
 
diff --git a/drivers/net/mlx5/mlx5_flow_hw.c b/drivers/net/mlx5/mlx5_flow_hw.c
index 49c164060b..2a1281732a 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;
@@ -3832,9 +3841,11 @@ __flow_hw_pull_indir_action_comp(struct rte_eth_dev *dev,
 		res[i].user_data = user_data;
 		res[i].status = RTE_FLOW_OP_SUCCESS;
 	}
-	if (ret_comp < n_res && priv->hws_mpool)
-		ret_comp += mlx5_aso_pull_completion(&priv->hws_mpool->sq[queue],
-				&res[ret_comp], n_res - ret_comp);
+	if (!priv->shared_host) {
+		if (ret_comp < n_res && priv->hws_mpool)
+			ret_comp += mlx5_aso_pull_completion(&priv->hws_mpool->sq[queue],
+					&res[ret_comp], n_res - ret_comp);
+	}
 	if (ret_comp < n_res && priv->hws_ctpool)
 		ret_comp += mlx5_aso_pull_completion(&priv->ct_mng->aso_sqs[queue],
 				&res[ret_comp], n_res - ret_comp);
@@ -5450,6 +5461,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.
  *
@@ -5459,6 +5472,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;
@@ -5469,6 +5483,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,
@@ -5512,7 +5529,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;
@@ -5969,8 +5986,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;
@@ -10418,7 +10434,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:
@@ -10577,7 +10593,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. */
-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: [PATCH v4 1/2] net/mlx5: move meter init functions
  2024-02-27 13:37       ` [PATCH v4 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
@ 2024-02-28 10:12         ` Raslan Darawsheh
  0 siblings, 0 replies; 13+ messages in thread
From: Raslan Darawsheh @ 2024-02-28 10:12 UTC (permalink / raw)
  To: Dariusz Sosnowski, Slava Ovsiienko, Ori Kam, Suanming Mou, Matan Azrad
  Cc: dev

Hi,

> -----Original Message-----
> From: Dariusz Sosnowski <dsosnowski@nvidia.com>
> Sent: Tuesday, February 27, 2024 3:37 PM
> To: Slava Ovsiienko <viacheslavo@nvidia.com>; Ori Kam <orika@nvidia.com>;
> Suanming Mou <suanmingm@nvidia.com>; Matan Azrad
> <matan@nvidia.com>
> Cc: dev@dpdk.org
> Subject: [PATCH v4 1/2] net/mlx5: move meter init functions
> 
> Move mlx5_flow_meter_init() and mlx5_flow_meter_uinit() to module for
> meter operations.
> 
> Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>

Series applied to next-net-mlx,

Kindest regards
Raslan Darawsheh

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-02-28 10:12 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-21 10:13 [PATCH 0/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
2024-02-21 10:13 ` [PATCH 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
2024-02-21 10:13 ` [PATCH 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
2024-02-21 10:21 ` [PATCH v2 0/2] " Dariusz Sosnowski
2024-02-21 10:21   ` [PATCH v2 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
2024-02-21 10:21   ` [PATCH v2 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
2024-02-22 18:00   ` [PATCH v3 0/2] " Dariusz Sosnowski
2024-02-22 18:00     ` [PATCH v3 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
2024-02-22 18:00     ` [PATCH v3 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski
2024-02-27 13:37     ` [PATCH v4 0/2] " Dariusz Sosnowski
2024-02-27 13:37       ` [PATCH v4 1/2] net/mlx5: move meter init functions Dariusz Sosnowski
2024-02-28 10:12         ` Raslan Darawsheh
2024-02-27 13:37       ` [PATCH v4 2/2] net/mlx5: add cross port meter mark action sharing Dariusz Sosnowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).