diff mbox series

[v2,13/22] net/mlx5: move modify header allocator to ipool

Message ID 20210630124609.8711-14-suanmingm@nvidia.com (mailing list archive)
State Superseded, archived
Delegated to: Raslan Darawsheh
Headers show
Series net/mlx5: insertion rate optimization | expand

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Suanming Mou June 30, 2021, 12:46 p.m. UTC
From: Matan Azrad <matan@nvidia.com>

Modify header actions are allocated by mlx5_malloc which has a big
overhead of memory and allocation time.

One of the action types under the modify header object is SET_TAG,

The SET_TAG action is commonly not reused by the flows and each flow has
its own value.

Hence, the mlx5_malloc becomes a bottleneck in flow insertion rate in
the common cases of SET_TAG.

Use ipool allocator for SET_TAG action.

Ipool allocator has less overhead of memory and insertion rate and has
better synchronization mechanism in multithread cases.

Different ipool is created for each optional size of modify header
handler.

Signed-off-by: Matan Azrad <matan@nvidia.com>
Acked-by: Suanming Mou <suanmingm@nvidia.com>
---
 drivers/net/mlx5/mlx5.c         |  4 ++
 drivers/net/mlx5/mlx5.h         | 14 ++++++
 drivers/net/mlx5/mlx5_flow.h    | 14 +-----
 drivers/net/mlx5/mlx5_flow_dv.c | 79 ++++++++++++++++++++++++++++-----
 4 files changed, 86 insertions(+), 25 deletions(-)
diff mbox series

Patch

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 0e80408511..713accf675 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -801,6 +801,7 @@  mlx5_flow_ipool_create(struct mlx5_dev_ctx_shared *sh,
 	}
 }
 
+
 /**
  * Release the flow resources' indexed mempool.
  *
@@ -814,6 +815,9 @@  mlx5_flow_ipool_destroy(struct mlx5_dev_ctx_shared *sh)
 
 	for (i = 0; i < MLX5_IPOOL_MAX; ++i)
 		mlx5_ipool_destroy(sh->ipool[i]);
+	for (i = 0; i < MLX5_MAX_MODIFY_NUM; ++i)
+		if (sh->mdh_ipools[i])
+			mlx5_ipool_destroy(sh->mdh_ipools[i]);
 }
 
 /*
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 896c0c2da1..5774f63244 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -36,6 +36,19 @@ 
 
 #define MLX5_SH(dev) (((struct mlx5_priv *)(dev)->data->dev_private)->sh)
 
+/*
+ * Number of modification commands.
+ * The maximal actions amount in FW is some constant, and it is 16 in the
+ * latest releases. In some old releases, it will be limited to 8.
+ * Since there is no interface to query the capacity, the maximal value should
+ * be used to allow PMD to create the flow. The validation will be done in the
+ * lower driver layer or FW. A failure will be returned if exceeds the maximal
+ * supported actions number on the root table.
+ * On non-root tables, there is no limitation, but 32 is enough right now.
+ */
+#define MLX5_MAX_MODIFY_NUM			32
+#define MLX5_ROOT_TBL_MODIFY_NUM		16
+
 enum mlx5_ipool_index {
 #if defined(HAVE_IBV_FLOW_DV_SUPPORT) || !defined(HAVE_INFINIBAND_VERBS_H)
 	MLX5_IPOOL_DECAP_ENCAP = 0, /* Pool for encap/decap resource. */
@@ -1123,6 +1136,7 @@  struct mlx5_dev_ctx_shared {
 	struct mlx5_flow_counter_mng cmng; /* Counters management structure. */
 	void *default_miss_action; /* Default miss action. */
 	struct mlx5_indexed_pool *ipool[MLX5_IPOOL_MAX];
+	struct mlx5_indexed_pool *mdh_ipools[MLX5_MAX_MODIFY_NUM];
 	/* Memory Pool for mlx5 flow resources. */
 	struct mlx5_l3t_tbl *cnt_id_tbl; /* Shared counter lookup table. */
 	/* Shared interrupt handler section. */
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index ab4e8c5c4f..4552aaa803 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -504,23 +504,11 @@  struct mlx5_flow_dv_tag_resource {
 	uint32_t tag_id; /**< Tag ID. */
 };
 
-/*
- * Number of modification commands.
- * The maximal actions amount in FW is some constant, and it is 16 in the
- * latest releases. In some old releases, it will be limited to 8.
- * Since there is no interface to query the capacity, the maximal value should
- * be used to allow PMD to create the flow. The validation will be done in the
- * lower driver layer or FW. A failure will be returned if exceeds the maximal
- * supported actions number on the root table.
- * On non-root tables, there is no limitation, but 32 is enough right now.
- */
-#define MLX5_MAX_MODIFY_NUM			32
-#define MLX5_ROOT_TBL_MODIFY_NUM		16
-
 /* Modify resource structure */
 struct mlx5_flow_dv_modify_hdr_resource {
 	struct mlx5_list_entry entry;
 	void *action; /**< Modify header action object. */
+	uint32_t idx;
 	/* Key area for hash list matching: */
 	uint8_t ft_type; /**< Flow table type, Rx or Tx. */
 	uint8_t actions_num; /**< Number of modification actions. */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1dfd5db361..08704d892a 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -5304,6 +5304,45 @@  flow_dv_modify_match_cb(void *tool_ctx __rte_unused,
 	       memcmp(&ref->ft_type, &resource->ft_type, key_len);
 }
 
+static struct mlx5_indexed_pool *
+flow_dv_modify_ipool_get(struct mlx5_dev_ctx_shared *sh, uint8_t index)
+{
+	struct mlx5_indexed_pool *ipool = __atomic_load_n
+				     (&sh->mdh_ipools[index], __ATOMIC_SEQ_CST);
+
+	if (!ipool) {
+		struct mlx5_indexed_pool *expected = NULL;
+		struct mlx5_indexed_pool_config cfg =
+		    (struct mlx5_indexed_pool_config) {
+		       .size = sizeof(struct mlx5_flow_dv_modify_hdr_resource) +
+								   (index + 1) *
+					   sizeof(struct mlx5_modification_cmd),
+		       .trunk_size = 64,
+		       .grow_trunk = 3,
+		       .grow_shift = 2,
+		       .need_lock = 1,
+		       .release_mem_en = 1,
+		       .malloc = mlx5_malloc,
+		       .free = mlx5_free,
+		       .type = "mlx5_modify_action_resource",
+		};
+
+		cfg.size = RTE_ALIGN(cfg.size, sizeof(ipool));
+		ipool = mlx5_ipool_create(&cfg);
+		if (!ipool)
+			return NULL;
+		if (!__atomic_compare_exchange_n(&sh->mdh_ipools[index],
+						 &expected, ipool, false,
+						 __ATOMIC_SEQ_CST,
+						 __ATOMIC_SEQ_CST)) {
+			mlx5_ipool_destroy(ipool);
+			ipool = __atomic_load_n(&sh->mdh_ipools[index],
+						__ATOMIC_SEQ_CST);
+		}
+	}
+	return ipool;
+}
+
 struct mlx5_list_entry *
 flow_dv_modify_create_cb(void *tool_ctx, void *cb_ctx)
 {
@@ -5312,12 +5351,20 @@  flow_dv_modify_create_cb(void *tool_ctx, void *cb_ctx)
 	struct mlx5dv_dr_domain *ns;
 	struct mlx5_flow_dv_modify_hdr_resource *entry;
 	struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
+	struct mlx5_indexed_pool *ipool = flow_dv_modify_ipool_get(sh,
+							  ref->actions_num - 1);
 	int ret;
 	uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
 	uint32_t key_len = sizeof(*ref) - offsetof(typeof(*ref), ft_type);
+	uint32_t idx;
 
-	entry = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*entry) + data_len, 0,
-			    SOCKET_ID_ANY);
+	if (unlikely(!ipool)) {
+		rte_flow_error_set(ctx->error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL, "cannot allocate modify ipool");
+		return NULL;
+	}
+	entry = mlx5_ipool_zmalloc(ipool, &idx);
 	if (!entry) {
 		rte_flow_error_set(ctx->error, ENOMEM,
 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -5337,25 +5384,29 @@  flow_dv_modify_create_cb(void *tool_ctx, void *cb_ctx)
 					(sh->ctx, ns, entry,
 					 data_len, &entry->action);
 	if (ret) {
-		mlx5_free(entry);
+		mlx5_ipool_free(sh->mdh_ipools[ref->actions_num - 1], idx);
 		rte_flow_error_set(ctx->error, ENOMEM,
 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 				   NULL, "cannot create modification action");
 		return NULL;
 	}
+	entry->idx = idx;
 	return &entry->entry;
 }
 
 struct mlx5_list_entry *
-flow_dv_modify_clone_cb(void *tool_ctx __rte_unused,
-			struct mlx5_list_entry *oentry, void *cb_ctx)
+flow_dv_modify_clone_cb(void *tool_ctx, struct mlx5_list_entry *oentry,
+			void *cb_ctx)
 {
+	struct mlx5_dev_ctx_shared *sh = tool_ctx;
 	struct mlx5_flow_cb_ctx *ctx = cb_ctx;
 	struct mlx5_flow_dv_modify_hdr_resource *entry;
 	struct mlx5_flow_dv_modify_hdr_resource *ref = ctx->data;
 	uint32_t data_len = ref->actions_num * sizeof(ref->actions[0]);
+	uint32_t idx;
 
-	entry = mlx5_malloc(0, sizeof(*entry) + data_len, 0, SOCKET_ID_ANY);
+	entry = mlx5_ipool_malloc(sh->mdh_ipools[ref->actions_num - 1],
+				  &idx);
 	if (!entry) {
 		rte_flow_error_set(ctx->error, ENOMEM,
 				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -5363,14 +5414,18 @@  flow_dv_modify_clone_cb(void *tool_ctx __rte_unused,
 		return NULL;
 	}
 	memcpy(entry, oentry, sizeof(*entry) + data_len);
+	entry->idx = idx;
 	return &entry->entry;
 }
 
 void
-flow_dv_modify_clone_free_cb(void *tool_ctx __rte_unused,
-			     struct mlx5_list_entry *entry)
+flow_dv_modify_clone_free_cb(void *tool_ctx, struct mlx5_list_entry *entry)
 {
-	mlx5_free(entry);
+	struct mlx5_dev_ctx_shared *sh = tool_ctx;
+	struct mlx5_flow_dv_modify_hdr_resource *res =
+		container_of(entry, typeof(*res), entry);
+
+	mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
 }
 
 /**
@@ -13699,14 +13754,14 @@  flow_dv_jump_tbl_resource_release(struct rte_eth_dev *dev,
 }
 
 void
-flow_dv_modify_remove_cb(void *tool_ctx __rte_unused,
-			 struct mlx5_list_entry *entry)
+flow_dv_modify_remove_cb(void *tool_ctx, struct mlx5_list_entry *entry)
 {
 	struct mlx5_flow_dv_modify_hdr_resource *res =
 		container_of(entry, typeof(*res), entry);
+	struct mlx5_dev_ctx_shared *sh = tool_ctx;
 
 	claim_zero(mlx5_flow_os_destroy_flow_action(res->action));
-	mlx5_free(entry);
+	mlx5_ipool_free(sh->mdh_ipools[res->actions_num - 1], res->idx);
 }
 
 /**