DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure
       [not found] <https://patches.dpdk.org/cover/68470/>
@ 2020-04-16  8:34 ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 01/10] net/mlx5: reorganize fate actions as union Suanming Mou
                     ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

This patch set is third part of the flow memory consumption optimization.
It mainly optimizes the rte flow and mlx5 flow handle structure.

For mlx5 flow handle structure:
1. As one flow has only one fate action, the fate actions are reorganized
as union.
2. The action flags are optimized to be the limited bits the flow needs.
3. The bits members are reorganized to align with bytes.

For rte flow structure:
1. Meter handle is converted to uint32_t type as unique meter id.
2. Fdir handle is converted to one bit to save the pointer to another list.
3. Metadata handle is converted to uint32_t type as indexed.
4. Remove the duplicated RSS member in rte flow.
5. The bit members are reorganized to align with bytes.

Some extra optimizations:
1. Allocate meter resource from indexed memory pool.
2. Allocate rte flow from indexed memory pool.
3. Split RSS type, level, key to common memory as they are not required
for the flow destroy.

This patch set should be applied after the patch series as below:
https://patches.dpdk.org/cover/68591/

v2:
 - Add unified routine for fate actions release.
 - Rmove RSS totally from rte flow.
 - Allocate rte flow totally from indexed memory pool.

Suanming Mou (9):
  net/mlx5: reorganize fate actions as union
  net/mlx5: optimize action flags in flow handle
  net/mlx5: reorganize the mlx5 flow handle struct
  net/mlx5: optimize flow meter handle type
  net/mlx5: allocate meter from indexed pool
  net/mlx5: convert mark copy resource to indexed
  net/mlx5: optimize mlx5 flow RSS struct
  net/mlx5: allocate rte flow from indexed pool
  net/mlx5: reorganize rte flow structure

Wentao Cui (1):
  net/mlx5: optimize flow director filter memory

 drivers/net/mlx5/mlx5.c            |  38 +++-
 drivers/net/mlx5/mlx5.h            |  19 +-
 drivers/net/mlx5/mlx5_flow.c       | 406 +++++++++++++++++++++++--------------
 drivers/net/mlx5/mlx5_flow.h       |  89 +++++---
 drivers/net/mlx5/mlx5_flow_dv.c    | 214 +++++++++++--------
 drivers/net/mlx5/mlx5_flow_meter.c |  11 +-
 drivers/net/mlx5/mlx5_flow_verbs.c |  98 +++++----
 7 files changed, 554 insertions(+), 321 deletions(-)

-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 01/10] net/mlx5: reorganize fate actions as union
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 02/10] net/mlx5: optimize action flags in flow handle Suanming Mou
                     ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

Currently, one flow only has one fate action, the fate actions members
in the flow struct can be reorganized as union to save the memory for
flow struct.

This commit reorganizes the fate actions as union, the act_flags helps
to identify the fate action type when flow destroys.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h       | 11 +++++----
 drivers/net/mlx5/mlx5_flow_dv.c    | 48 +++++++++++++++++++++++++-------------
 drivers/net/mlx5/mlx5_flow_verbs.c | 22 ++++++++++++-----
 3 files changed, 54 insertions(+), 27 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index a2ea122..fc97424 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -488,10 +488,6 @@ struct mlx5_flow_handle_dv {
 	/**< Index to encap/decap resource in cache. */
 	struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
 	/**< Pointer to modify header resource in cache. */
-	uint32_t jump;
-	/**< Index to the jump action resource. */
-	uint32_t port_id_action;
-	/**< Index to port ID action resource. */
 	struct mlx5_vf_vlan vf_vlan;
 	/**< Structure for VF VLAN workaround. */
 	uint32_t push_vlan_res;
@@ -509,12 +505,17 @@ struct mlx5_flow_handle {
 	uint64_t act_flags;
 	/**< Bit-fields of detected actions, see MLX5_FLOW_ACTION_*. */
 	void *ib_flow; /**< Verbs flow pointer. */
-	uint32_t hrxq; /**< Hash Rx queue object index. */
 	struct mlx5_vf_vlan vf_vlan; /**< Structure for VF VLAN workaround. */
 	union {
 		uint32_t qrss_id; /**< Uniqie Q/RSS suffix subflow tag. */
 		uint32_t mtr_flow_id; /**< Unique meter match flow id. */
 	};
+	union {
+		uint32_t hrxq; /**< Hash Rx queue object index. */
+		uint32_t jump; /**< Index to the jump action resource. */
+		uint32_t port_id_action;
+		/**< Index to port ID action resource. */
+	};
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5_flow_handle_dv dvh;
 #endif
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index f001b34..a44265b 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -2572,7 +2572,7 @@ struct field_modify_info modify_tcp[] = {
 			(void *)&tbl_data->jump, cnt);
 	}
 	rte_atomic32_inc(&tbl_data->jump.refcnt);
-	dev_flow->handle->dvh.jump = tbl_data->idx;
+	dev_flow->handle->jump = tbl_data->idx;
 	dev_flow->dv.jump = &tbl_data->jump;
 	return 0;
 }
@@ -2613,14 +2613,14 @@ struct field_modify_info modify_tcp[] = {
 				(void *)cache_resource,
 				rte_atomic32_read(&cache_resource->refcnt));
 			rte_atomic32_inc(&cache_resource->refcnt);
-			dev_flow->handle->dvh.port_id_action = idx;
+			dev_flow->handle->port_id_action = idx;
 			dev_flow->dv.port_id_action = cache_resource;
 			return 0;
 		}
 	}
 	/* Register new port id action resource. */
 	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID],
-				       &dev_flow->handle->dvh.port_id_action);
+				       &dev_flow->handle->port_id_action);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -2643,8 +2643,7 @@ struct field_modify_info modify_tcp[] = {
 	rte_atomic32_init(&cache_resource->refcnt);
 	rte_atomic32_inc(&cache_resource->refcnt);
 	ILIST_INSERT(sh->ipool[MLX5_IPOOL_PORT_ID], &sh->port_id_action_list,
-		     dev_flow->handle->dvh.port_id_action, cache_resource,
-		     next);
+		     dev_flow->handle->port_id_action, cache_resource, next);
 	dev_flow->dv.port_id_action = cache_resource;
 	DRV_LOG(DEBUG, "new port id action resource %p: refcnt %d++",
 		(void *)cache_resource,
@@ -7442,7 +7441,7 @@ struct field_modify_info modify_tcp[] = {
 			if (flow_dv_port_id_action_resource_register
 			    (dev, &port_id_resource, dev_flow, error))
 				return -rte_errno;
-			MLX5_ASSERT(!handle->dvh.port_id_action);
+			MLX5_ASSERT(!handle->port_id_action);
 			dev_flow->dv.actions[actions_n++] =
 					dev_flow->dv.port_id_action->action;
 			action_flags |= MLX5_FLOW_ACTION_PORT_ID;
@@ -8115,6 +8114,13 @@ struct field_modify_info modify_tcp[] = {
 						 "cannot get drop hash queue");
 					goto error;
 				}
+				/*
+				 * Drop queues will be released by the specify
+				 * mlx5_hrxq_drop_release() function. Assign
+				 * the special index to hrxq to mark the queue
+				 * has been allocated.
+				 */
+				dh->hrxq = UINT32_MAX;
 				dv->actions[n++] = drop_hrxq->action;
 			}
 		} else if (dh->act_flags &
@@ -8177,12 +8183,17 @@ struct field_modify_info modify_tcp[] = {
 	err = rte_errno; /* Save rte_errno before cleanup. */
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       handle_idx, dh, next) {
+		/* hrxq is union, don't clear it if the flag is not set. */
 		if (dh->hrxq) {
-			if (dh->act_flags & MLX5_FLOW_ACTION_DROP)
+			if (dh->act_flags & MLX5_FLOW_ACTION_DROP) {
 				mlx5_hrxq_drop_release(dev);
-			else
+				dh->hrxq = 0;
+			} else if (dh->act_flags &
+				  (MLX5_FLOW_ACTION_QUEUE |
+				  MLX5_FLOW_ACTION_RSS)) {
 				mlx5_hrxq_release(dev, dh->hrxq);
-			dh->hrxq = 0;
+				dh->hrxq = 0;
+			}
 		}
 		if (dh->vf_vlan.tag && dh->vf_vlan.created)
 			mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
@@ -8287,7 +8298,7 @@ struct field_modify_info modify_tcp[] = {
 	struct mlx5_flow_tbl_data_entry *tbl_data;
 
 	tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
-			     handle->dvh.jump);
+			     handle->jump);
 	if (!tbl_data)
 		return 0;
 	cache_resource = &tbl_data->jump;
@@ -8355,7 +8366,7 @@ struct field_modify_info modify_tcp[] = {
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_dv_port_id_action_resource *cache_resource;
-	uint32_t idx = handle->dvh.port_id_action;
+	uint32_t idx = handle->port_id_action;
 
 	cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
 					idx);
@@ -8448,12 +8459,17 @@ struct field_modify_info modify_tcp[] = {
 			claim_zero(mlx5_glue->dv_destroy_flow(dh->ib_flow));
 			dh->ib_flow = NULL;
 		}
+		/* hrxq is union, don't touch it only the flag is set. */
 		if (dh->hrxq) {
-			if (dh->act_flags & MLX5_FLOW_ACTION_DROP)
+			if (dh->act_flags & MLX5_FLOW_ACTION_DROP) {
 				mlx5_hrxq_drop_release(dev);
-			else
+				dh->hrxq = 0;
+			} else if (dh->act_flags &
+				  (MLX5_FLOW_ACTION_QUEUE |
+				  MLX5_FLOW_ACTION_RSS)) {
 				mlx5_hrxq_release(dev, dh->hrxq);
-			dh->hrxq = 0;
+				dh->hrxq = 0;
+			}
 		}
 		if (dh->vf_vlan.tag && dh->vf_vlan.created)
 			mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
@@ -8501,9 +8517,9 @@ struct field_modify_info modify_tcp[] = {
 			flow_dv_encap_decap_resource_release(dev, dev_handle);
 		if (dev_handle->dvh.modify_hdr)
 			flow_dv_modify_hdr_resource_release(dev_handle);
-		if (dev_handle->dvh.jump)
+		if (dev_handle->act_flags & MLX5_FLOW_ACTION_JUMP)
 			flow_dv_jump_tbl_resource_release(dev, dev_handle);
-		if (dev_handle->dvh.port_id_action)
+		if (dev_handle->act_flags & MLX5_FLOW_ACTION_PORT_ID)
 			flow_dv_port_id_action_resource_release(dev,
 								dev_handle);
 		if (dev_handle->dvh.push_vlan_res)
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 9525fd4..931d547 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -1754,12 +1754,17 @@
 			claim_zero(mlx5_glue->destroy_flow(handle->ib_flow));
 			handle->ib_flow = NULL;
 		}
+		/* hrxq is union, don't touch it only the flag is set. */
 		if (handle->hrxq) {
-			if (handle->act_flags & MLX5_FLOW_ACTION_DROP)
+			if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
 				mlx5_hrxq_drop_release(dev);
-			else
+				handle->hrxq = 0;
+			} else if (handle->act_flags &
+				  (MLX5_FLOW_ACTION_QUEUE |
+				  MLX5_FLOW_ACTION_RSS)) {
 				mlx5_hrxq_release(dev, handle->hrxq);
-			handle->hrxq = 0;
+				handle->hrxq = 0;
+			}
 		}
 		if (handle->vf_vlan.tag && handle->vf_vlan.created)
 			mlx5_vlan_vmwa_release(dev, &handle->vf_vlan);
@@ -1891,12 +1896,17 @@
 	err = rte_errno; /* Save rte_errno before cleanup. */
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       dev_handles, handle, next) {
+		/* hrxq is union, don't touch it only the flag is set. */
 		if (handle->hrxq) {
-			if (handle->act_flags & MLX5_FLOW_ACTION_DROP)
+			if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
 				mlx5_hrxq_drop_release(dev);
-			else
+				handle->hrxq = 0;
+			} else if (handle->act_flags &
+				  (MLX5_FLOW_ACTION_QUEUE |
+				  MLX5_FLOW_ACTION_RSS)) {
 				mlx5_hrxq_release(dev, handle->hrxq);
-			handle->hrxq = 0;
+				handle->hrxq = 0;
+			}
 		}
 		if (handle->vf_vlan.tag && handle->vf_vlan.created)
 			mlx5_vlan_vmwa_release(dev, &handle->vf_vlan);
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 02/10] net/mlx5: optimize action flags in flow handle
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 01/10] net/mlx5: reorganize fate actions as union Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 03/10] net/mlx5: reorganize the mlx5 flow handle struct Suanming Mou
                     ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

As only limited bits is used in act_flags for flow destroy, it's a bit
expensive to save the whole 64 bits. Move the act_flags out of flow
handle and save the needed bits for flow destroy to save some bytes for
the flow handle data struct.

The fate action type and mark bits are reserved as they will be used in
flow destroy.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c       |  8 ++---
 drivers/net/mlx5/mlx5_flow.h       | 18 ++++++++--
 drivers/net/mlx5/mlx5_flow_dv.c    | 68 ++++++++++++++++++++++++--------------
 drivers/net/mlx5/mlx5_flow_verbs.c | 23 +++++++------
 4 files changed, 75 insertions(+), 42 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index bf95a40..ffc2910 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -722,8 +722,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		       struct mlx5_flow_handle *dev_handle)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	const int mark = !!(dev_handle->act_flags &
-			    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));
+	const int mark = dev_handle->mark;
 	const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL);
 	unsigned int i;
 
@@ -800,8 +799,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 			struct mlx5_flow_handle *dev_handle)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	const int mark = !!(dev_handle->act_flags &
-			    (MLX5_FLOW_ACTION_FLAG | MLX5_FLOW_ACTION_MARK));
+	const int mark = dev_handle->mark;
 	const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL);
 	unsigned int i;
 
@@ -2718,7 +2716,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	 * help to do the optimization work for source code.
 	 * If no decap actions, use the layers directly.
 	 */
-	if (!(dev_flow->handle->act_flags & MLX5_FLOW_ACTION_DECAP))
+	if (!(dev_flow->act_flags & MLX5_FLOW_ACTION_DECAP))
 		return dev_flow->handle->layers;
 	/* Convert L3 layers with decap action. */
 	if (dev_flow->handle->layers & MLX5_FLOW_LAYER_INNER_L3_IPV4)
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index fc97424..67f767b 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -339,6 +339,16 @@ enum mlx5_flow_drv_type {
 	MLX5_FLOW_TYPE_MAX,
 };
 
+/* Fate action type. */
+enum mlx5_flow_fate_type {
+	MLX5_FLOW_FATE_NONE, /* Egress flow. */
+	MLX5_FLOW_FATE_QUEUE,
+	MLX5_FLOW_FATE_JUMP,
+	MLX5_FLOW_FATE_PORT_ID,
+	MLX5_FLOW_FATE_DROP,
+	MLX5_FLOW_FATE_MAX,
+};
+
 /* Matcher PRM representation */
 struct mlx5_flow_dv_match_params {
 	size_t size;
@@ -502,19 +512,21 @@ struct mlx5_flow_handle {
 	/**< Index to next device flow handle. */
 	uint64_t layers;
 	/**< Bit-fields of present layers, see MLX5_FLOW_LAYER_*. */
-	uint64_t act_flags;
-	/**< Bit-fields of detected actions, see MLX5_FLOW_ACTION_*. */
 	void *ib_flow; /**< Verbs flow pointer. */
 	struct mlx5_vf_vlan vf_vlan; /**< Structure for VF VLAN workaround. */
 	union {
 		uint32_t qrss_id; /**< Uniqie Q/RSS suffix subflow tag. */
 		uint32_t mtr_flow_id; /**< Unique meter match flow id. */
 	};
+	uint32_t mark:1; /**< Metadate rxq mark flag. */
+	uint32_t fate_action:3; /**< Fate action type. */
 	union {
 		uint32_t hrxq; /**< Hash Rx queue object index. */
 		uint32_t jump; /**< Index to the jump action resource. */
 		uint32_t port_id_action;
 		/**< Index to port ID action resource. */
+		uint32_t fate_idx;
+		/**< Generic value indicates the fate action. */
 	};
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5_flow_handle_dv dvh;
@@ -624,6 +636,8 @@ struct mlx5_flow_verbs_workspace {
 struct mlx5_flow {
 	struct rte_flow *flow; /**< Pointer to the main flow. */
 	uint64_t hash_fields; /**< Verbs hash Rx queue hash fields. */
+	uint64_t act_flags;
+	/**< Bit-fields of detected actions, see MLX5_FLOW_ACTION_*. */
 	bool external; /**< true if the flow is created external to PMD. */
 	uint8_t ingress; /**< 1 if the flow is ingress. */
 	union {
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index a44265b..e28f01d 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7445,9 +7445,11 @@ struct field_modify_info modify_tcp[] = {
 			dev_flow->dv.actions[actions_n++] =
 					dev_flow->dv.port_id_action->action;
 			action_flags |= MLX5_FLOW_ACTION_PORT_ID;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_PORT_ID;
 			break;
 		case RTE_FLOW_ACTION_TYPE_FLAG:
 			action_flags |= MLX5_FLOW_ACTION_FLAG;
+			dev_flow->handle->mark = 1;
 			if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
 				struct rte_flow_action_mark mark = {
 					.id = MLX5_FLOW_MARK_DEFAULT,
@@ -7476,6 +7478,7 @@ struct field_modify_info modify_tcp[] = {
 			break;
 		case RTE_FLOW_ACTION_TYPE_MARK:
 			action_flags |= MLX5_FLOW_ACTION_MARK;
+			dev_flow->handle->mark = 1;
 			if (dev_conf->dv_xmeta_en != MLX5_XMETA_MODE_LEGACY) {
 				const struct rte_flow_action_mark *mark =
 					(const struct rte_flow_action_mark *)
@@ -7520,6 +7523,7 @@ struct field_modify_info modify_tcp[] = {
 			break;
 		case RTE_FLOW_ACTION_TYPE_DROP:
 			action_flags |= MLX5_FLOW_ACTION_DROP;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
 			MLX5_ASSERT(flow->rss.queue);
@@ -7527,6 +7531,7 @@ struct field_modify_info modify_tcp[] = {
 			flow->rss.queue_num = 1;
 			(*flow->rss.queue)[0] = queue->index;
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			MLX5_ASSERT(flow->rss.queue);
@@ -7543,6 +7548,7 @@ struct field_modify_info modify_tcp[] = {
 			 * when expanding items for RSS.
 			 */
 			action_flags |= MLX5_FLOW_ACTION_RSS;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			if (!dev_conf->devx) {
@@ -7702,6 +7708,7 @@ struct field_modify_info modify_tcp[] = {
 			dev_flow->dv.actions[actions_n++] =
 					dev_flow->dv.jump->action;
 			action_flags |= MLX5_FLOW_ACTION_JUMP;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_JUMP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_MAC_DST:
@@ -7844,7 +7851,7 @@ struct field_modify_info modify_tcp[] = {
 			modify_action_position = actions_n++;
 	}
 	dev_flow->dv.actions_n = actions_n;
-	handle->act_flags = action_flags;
+	dev_flow->act_flags = action_flags;
 	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
 		int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
 		int item_type = items->type;
@@ -8100,7 +8107,7 @@ struct field_modify_info modify_tcp[] = {
 		dh = dev_flow->handle;
 		dv_h = &dh->dvh;
 		n = dv->actions_n;
-		if (dh->act_flags & MLX5_FLOW_ACTION_DROP) {
+		if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
 			if (dv->transfer) {
 				dv->actions[n++] = priv->sh->esw_drop_action;
 			} else {
@@ -8123,8 +8130,7 @@ struct field_modify_info modify_tcp[] = {
 				dh->hrxq = UINT32_MAX;
 				dv->actions[n++] = drop_hrxq->action;
 			}
-		} else if (dh->act_flags &
-			   (MLX5_FLOW_ACTION_QUEUE | MLX5_FLOW_ACTION_RSS)) {
+		} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) {
 			struct mlx5_hrxq *hrxq;
 			uint32_t hrxq_idx;
 
@@ -8185,12 +8191,10 @@ struct field_modify_info modify_tcp[] = {
 		       handle_idx, dh, next) {
 		/* hrxq is union, don't clear it if the flag is not set. */
 		if (dh->hrxq) {
-			if (dh->act_flags & MLX5_FLOW_ACTION_DROP) {
+			if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
 				mlx5_hrxq_drop_release(dev);
 				dh->hrxq = 0;
-			} else if (dh->act_flags &
-				  (MLX5_FLOW_ACTION_QUEUE |
-				  MLX5_FLOW_ACTION_RSS)) {
+			} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) {
 				mlx5_hrxq_release(dev, dh->hrxq);
 				dh->hrxq = 0;
 			}
@@ -8432,6 +8436,33 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Release the fate resource.
+ *
+ * @param dev
+ *   Pointer to Ethernet device.
+ * @param handle
+ *   Pointer to mlx5_flow_handle.
+ */
+static void
+flow_dv_fate_resource_release(struct rte_eth_dev *dev,
+			       struct mlx5_flow_handle *handle)
+{
+	if (!handle->fate_idx)
+		return;
+	if (handle->fate_action == MLX5_FLOW_FATE_DROP)
+		mlx5_hrxq_drop_release(dev);
+	else if (handle->fate_action == MLX5_FLOW_FATE_QUEUE)
+		mlx5_hrxq_release(dev, handle->hrxq);
+	else if (handle->fate_action == MLX5_FLOW_FATE_JUMP)
+		flow_dv_jump_tbl_resource_release(dev, handle);
+	else if (handle->fate_action == MLX5_FLOW_FATE_PORT_ID)
+		flow_dv_port_id_action_resource_release(dev, handle);
+	else
+		DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action);
+	handle->fate_idx = 0;
+}
+
+/**
  * Remove the flow from the NIC but keeps it in memory.
  * Lock free, (mutex should be acquired by caller).
  *
@@ -8459,18 +8490,9 @@ struct field_modify_info modify_tcp[] = {
 			claim_zero(mlx5_glue->dv_destroy_flow(dh->ib_flow));
 			dh->ib_flow = NULL;
 		}
-		/* hrxq is union, don't touch it only the flag is set. */
-		if (dh->hrxq) {
-			if (dh->act_flags & MLX5_FLOW_ACTION_DROP) {
-				mlx5_hrxq_drop_release(dev);
-				dh->hrxq = 0;
-			} else if (dh->act_flags &
-				  (MLX5_FLOW_ACTION_QUEUE |
-				  MLX5_FLOW_ACTION_RSS)) {
-				mlx5_hrxq_release(dev, dh->hrxq);
-				dh->hrxq = 0;
-			}
-		}
+		if (dh->fate_action == MLX5_FLOW_FATE_DROP ||
+		    dh->fate_action == MLX5_FLOW_FATE_QUEUE)
+			flow_dv_fate_resource_release(dev, dh);
 		if (dh->vf_vlan.tag && dh->vf_vlan.created)
 			mlx5_vlan_vmwa_release(dev, &dh->vf_vlan);
 		handle_idx = dh->next.next;
@@ -8517,17 +8539,13 @@ struct field_modify_info modify_tcp[] = {
 			flow_dv_encap_decap_resource_release(dev, dev_handle);
 		if (dev_handle->dvh.modify_hdr)
 			flow_dv_modify_hdr_resource_release(dev_handle);
-		if (dev_handle->act_flags & MLX5_FLOW_ACTION_JUMP)
-			flow_dv_jump_tbl_resource_release(dev, dev_handle);
-		if (dev_handle->act_flags & MLX5_FLOW_ACTION_PORT_ID)
-			flow_dv_port_id_action_resource_release(dev,
-								dev_handle);
 		if (dev_handle->dvh.push_vlan_res)
 			flow_dv_push_vlan_action_resource_release(dev,
 								  dev_handle);
 		if (dev_handle->dvh.tag_resource)
 			flow_dv_tag_release(dev,
 					    dev_handle->dvh.tag_resource);
+		flow_dv_fate_resource_release(dev, dev_handle);
 		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
 			   tmp_idx);
 	}
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 931d547..1d56b03 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -1589,22 +1589,27 @@
 		case RTE_FLOW_ACTION_TYPE_FLAG:
 			flow_verbs_translate_action_flag(dev_flow, actions);
 			action_flags |= MLX5_FLOW_ACTION_FLAG;
+			dev_flow->handle->mark = 1;
 			break;
 		case RTE_FLOW_ACTION_TYPE_MARK:
 			flow_verbs_translate_action_mark(dev_flow, actions);
 			action_flags |= MLX5_FLOW_ACTION_MARK;
+			dev_flow->handle->mark = 1;
 			break;
 		case RTE_FLOW_ACTION_TYPE_DROP:
 			flow_verbs_translate_action_drop(dev_flow, actions);
 			action_flags |= MLX5_FLOW_ACTION_DROP;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
 			flow_verbs_translate_action_queue(dev_flow, actions);
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			flow_verbs_translate_action_rss(dev_flow, actions);
 			action_flags |= MLX5_FLOW_ACTION_RSS;
+			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			ret = flow_verbs_translate_action_count(dev_flow,
@@ -1621,7 +1626,7 @@
 						  "action not supported");
 		}
 	}
-	dev_flow->handle->act_flags = action_flags;
+	dev_flow->act_flags = action_flags;
 	for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
 		int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
 
@@ -1756,12 +1761,11 @@
 		}
 		/* hrxq is union, don't touch it only the flag is set. */
 		if (handle->hrxq) {
-			if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
+			if (handle->fate_action == MLX5_FLOW_FATE_DROP) {
 				mlx5_hrxq_drop_release(dev);
 				handle->hrxq = 0;
-			} else if (handle->act_flags &
-				  (MLX5_FLOW_ACTION_QUEUE |
-				  MLX5_FLOW_ACTION_RSS)) {
+			} else if (handle->fate_action ==
+				   MLX5_FLOW_FATE_QUEUE) {
 				mlx5_hrxq_release(dev, handle->hrxq);
 				handle->hrxq = 0;
 			}
@@ -1833,7 +1837,7 @@
 	for (idx = priv->flow_idx - 1; idx >= priv->flow_nested_idx; idx--) {
 		dev_flow = &((struct mlx5_flow *)priv->inter_flows)[idx];
 		handle = dev_flow->handle;
-		if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
+		if (handle->fate_action == MLX5_FLOW_FATE_DROP) {
 			hrxq = mlx5_hrxq_drop_new(dev);
 			if (!hrxq) {
 				rte_flow_error_set
@@ -1898,12 +1902,11 @@
 		       dev_handles, handle, next) {
 		/* hrxq is union, don't touch it only the flag is set. */
 		if (handle->hrxq) {
-			if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
+			if (handle->fate_action == MLX5_FLOW_FATE_DROP) {
 				mlx5_hrxq_drop_release(dev);
 				handle->hrxq = 0;
-			} else if (handle->act_flags &
-				  (MLX5_FLOW_ACTION_QUEUE |
-				  MLX5_FLOW_ACTION_RSS)) {
+			} else if (handle->fate_action ==
+				   MLX5_FLOW_FATE_QUEUE) {
 				mlx5_hrxq_release(dev, handle->hrxq);
 				handle->hrxq = 0;
 			}
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 03/10] net/mlx5: reorganize the mlx5 flow handle struct
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 01/10] net/mlx5: reorganize fate actions as union Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 02/10] net/mlx5: optimize action flags in flow handle Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 04/10] net/mlx5: optimize flow meter handle type Suanming Mou
                     ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

Currently, the mlx5_flow_handle struct is not fully aligned and has some
bits wasted. The members can be optimized and reorganized to save memory.

1. As metadata and meter is sharing the same flow match id, now the flow
id is limited to 24 bits due to the 8 MSBs are used as for the meter color.
Align the flow id to other bit members to 32 bits to save the mlx5 flow
handle memory.

2. The vlan_vf in struct mlx5_flow_handle_dv was already moved to struct
mlx5_flow_handle. Remove the legacy vlan_vf in struct mlx5_flow_handle_dv.

3. Reorganize the vlan_vf in mlx5_flow_handle with member SILIST_ENTRY
next to make it align with 8 bytes.

4. Reorganize the header modify in mlx5_flow_handle_dv to ILIST_ENTRY next
to make it align to with bytes.

5. Introduce __rte_pack attribute to make the struct tightly organized.

It will totally save 20 bytes memory for mlx5_flow_handle struct.

For the resource objects which are converted to indexed, align the names
with the prefix of rix_.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.c       |  8 ++---
 drivers/net/mlx5/mlx5_flow.h       | 29 +++++++----------
 drivers/net/mlx5/mlx5_flow_dv.c    | 66 ++++++++++++++++++++------------------
 drivers/net/mlx5/mlx5_flow_verbs.c | 18 +++++------
 4 files changed, 59 insertions(+), 62 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index ffc2910..4205f23 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2323,8 +2323,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       handle_idx, dev_handle, next)
-		if (dev_handle->qrss_id)
-			flow_qrss_free_id(dev, dev_handle->qrss_id);
+		if (dev_handle->split_flow_id)
+			flow_qrss_free_id(dev, dev_handle->split_flow_id);
 }
 
 static int
@@ -3988,7 +3988,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 			 * reallocation becomes possible (for example, for
 			 * other flows in other threads).
 			 */
-			dev_flow->handle->qrss_id = qrss_id;
+			dev_flow->handle->split_flow_id = qrss_id;
 			ret = mlx5_flow_get_reg_id(dev, MLX5_COPY_MARK, 0,
 						   error);
 			if (ret < 0)
@@ -4101,7 +4101,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 			ret = -rte_errno;
 			goto exit;
 		}
-		dev_flow->handle->mtr_flow_id = mtr_tag_id;
+		dev_flow->handle->split_flow_id = mtr_tag_id;
 		/* Setting the sfx group atrr. */
 		sfx_attr.group = sfx_attr.transfer ?
 				(MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) :
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 67f767b..e78de85 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -494,44 +494,39 @@ struct mlx5_flow_rss {
 struct mlx5_flow_handle_dv {
 	/* Flow DV api: */
 	struct mlx5_flow_dv_matcher *matcher; /**< Cache to matcher. */
-	uint32_t encap_decap;
-	/**< Index to encap/decap resource in cache. */
 	struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
 	/**< Pointer to modify header resource in cache. */
-	struct mlx5_vf_vlan vf_vlan;
-	/**< Structure for VF VLAN workaround. */
-	uint32_t push_vlan_res;
+	uint32_t rix_encap_decap;
+	/**< Index to encap/decap resource in cache. */
+	uint32_t rix_push_vlan;
 	/**< Index to push VLAN action resource in cache. */
-	uint32_t tag_resource;
+	uint32_t rix_tag;
 	/**< Index to the tag action. */
-};
+} __rte_packed;
 
 /** Device flow handle structure: used both for creating & destroying. */
 struct mlx5_flow_handle {
 	SILIST_ENTRY(uint32_t)next;
+	struct mlx5_vf_vlan vf_vlan; /**< Structure for VF VLAN workaround. */
 	/**< Index to next device flow handle. */
 	uint64_t layers;
 	/**< Bit-fields of present layers, see MLX5_FLOW_LAYER_*. */
 	void *ib_flow; /**< Verbs flow pointer. */
-	struct mlx5_vf_vlan vf_vlan; /**< Structure for VF VLAN workaround. */
-	union {
-		uint32_t qrss_id; /**< Uniqie Q/RSS suffix subflow tag. */
-		uint32_t mtr_flow_id; /**< Unique meter match flow id. */
-	};
+	uint32_t split_flow_id:28; /**< Sub flow unique match flow id. */
 	uint32_t mark:1; /**< Metadate rxq mark flag. */
 	uint32_t fate_action:3; /**< Fate action type. */
 	union {
-		uint32_t hrxq; /**< Hash Rx queue object index. */
-		uint32_t jump; /**< Index to the jump action resource. */
-		uint32_t port_id_action;
+		uint32_t rix_hrxq; /**< Hash Rx queue object index. */
+		uint32_t rix_jump; /**< Index to the jump action resource. */
+		uint32_t rix_port_id_action;
 		/**< Index to port ID action resource. */
-		uint32_t fate_idx;
+		uint32_t rix_fate;
 		/**< Generic value indicates the fate action. */
 	};
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 	struct mlx5_flow_handle_dv dvh;
 #endif
-};
+} __rte_packed;
 
 /*
  * Size for Verbs device flow handle structure only. Do not use the DV only
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index e28f01d..a8e92f2 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -2490,14 +2490,14 @@ struct field_modify_info modify_tcp[] = {
 				(void *)cache_resource,
 				rte_atomic32_read(&cache_resource->refcnt));
 			rte_atomic32_inc(&cache_resource->refcnt);
-			dev_flow->handle->dvh.encap_decap = idx;
+			dev_flow->handle->dvh.rix_encap_decap = idx;
 			dev_flow->dv.encap_decap = cache_resource;
 			return 0;
 		}
 	}
 	/* Register new encap/decap resource. */
 	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
-				       &dev_flow->handle->dvh.encap_decap);
+				       &dev_flow->handle->dvh.rix_encap_decap);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -2518,7 +2518,8 @@ struct field_modify_info modify_tcp[] = {
 	rte_atomic32_init(&cache_resource->refcnt);
 	rte_atomic32_inc(&cache_resource->refcnt);
 	ILIST_INSERT(sh->ipool[MLX5_IPOOL_DECAP_ENCAP], &sh->encaps_decaps,
-		     dev_flow->handle->dvh.encap_decap, cache_resource, next);
+		     dev_flow->handle->dvh.rix_encap_decap, cache_resource,
+		     next);
 	dev_flow->dv.encap_decap = cache_resource;
 	DRV_LOG(DEBUG, "new encap/decap resource %p: refcnt %d++",
 		(void *)cache_resource,
@@ -2572,7 +2573,7 @@ struct field_modify_info modify_tcp[] = {
 			(void *)&tbl_data->jump, cnt);
 	}
 	rte_atomic32_inc(&tbl_data->jump.refcnt);
-	dev_flow->handle->jump = tbl_data->idx;
+	dev_flow->handle->rix_jump = tbl_data->idx;
 	dev_flow->dv.jump = &tbl_data->jump;
 	return 0;
 }
@@ -2613,14 +2614,14 @@ struct field_modify_info modify_tcp[] = {
 				(void *)cache_resource,
 				rte_atomic32_read(&cache_resource->refcnt));
 			rte_atomic32_inc(&cache_resource->refcnt);
-			dev_flow->handle->port_id_action = idx;
+			dev_flow->handle->rix_port_id_action = idx;
 			dev_flow->dv.port_id_action = cache_resource;
 			return 0;
 		}
 	}
 	/* Register new port id action resource. */
 	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PORT_ID],
-				       &dev_flow->handle->port_id_action);
+				       &dev_flow->handle->rix_port_id_action);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -2643,7 +2644,8 @@ struct field_modify_info modify_tcp[] = {
 	rte_atomic32_init(&cache_resource->refcnt);
 	rte_atomic32_inc(&cache_resource->refcnt);
 	ILIST_INSERT(sh->ipool[MLX5_IPOOL_PORT_ID], &sh->port_id_action_list,
-		     dev_flow->handle->port_id_action, cache_resource, next);
+		     dev_flow->handle->rix_port_id_action, cache_resource,
+		     next);
 	dev_flow->dv.port_id_action = cache_resource;
 	DRV_LOG(DEBUG, "new port id action resource %p: refcnt %d++",
 		(void *)cache_resource,
@@ -2689,14 +2691,14 @@ struct field_modify_info modify_tcp[] = {
 				(void *)cache_resource,
 				rte_atomic32_read(&cache_resource->refcnt));
 			rte_atomic32_inc(&cache_resource->refcnt);
-			dev_flow->handle->dvh.push_vlan_res = idx;
+			dev_flow->handle->dvh.rix_push_vlan = idx;
 			dev_flow->dv.push_vlan_res = cache_resource;
 			return 0;
 		}
 	}
 	/* Register new push_vlan action resource. */
 	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_PUSH_VLAN],
-				       &dev_flow->handle->dvh.push_vlan_res);
+				       &dev_flow->handle->dvh.rix_push_vlan);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -2721,7 +2723,7 @@ struct field_modify_info modify_tcp[] = {
 	rte_atomic32_inc(&cache_resource->refcnt);
 	ILIST_INSERT(sh->ipool[MLX5_IPOOL_PUSH_VLAN],
 		     &sh->push_vlan_action_list,
-		     dev_flow->handle->dvh.push_vlan_res,
+		     dev_flow->handle->dvh.rix_push_vlan,
 		     cache_resource, next);
 	dev_flow->dv.push_vlan_res = cache_resource;
 	DRV_LOG(DEBUG, "new push vlan action resource %p: refcnt %d++",
@@ -7103,7 +7105,7 @@ struct field_modify_info modify_tcp[] = {
 		cache_resource = container_of
 			(entry, struct mlx5_flow_dv_tag_resource, entry);
 		rte_atomic32_inc(&cache_resource->refcnt);
-		dev_flow->handle->dvh.tag_resource = cache_resource->idx;
+		dev_flow->handle->dvh.rix_tag = cache_resource->idx;
 		dev_flow->dv.tag_resource = cache_resource;
 		DRV_LOG(DEBUG, "cached tag resource %p: refcnt now %d++",
 			(void *)cache_resource,
@@ -7112,7 +7114,7 @@ struct field_modify_info modify_tcp[] = {
 	}
 	/* Register new resource. */
 	cache_resource = mlx5_ipool_zmalloc(sh->ipool[MLX5_IPOOL_TAG],
-				       &dev_flow->handle->dvh.tag_resource);
+				       &dev_flow->handle->dvh.rix_tag);
 	if (!cache_resource)
 		return rte_flow_error_set(error, ENOMEM,
 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -7441,7 +7443,7 @@ struct field_modify_info modify_tcp[] = {
 			if (flow_dv_port_id_action_resource_register
 			    (dev, &port_id_resource, dev_flow, error))
 				return -rte_errno;
-			MLX5_ASSERT(!handle->port_id_action);
+			MLX5_ASSERT(!handle->rix_port_id_action);
 			dev_flow->dv.actions[actions_n++] =
 					dev_flow->dv.port_id_action->action;
 			action_flags |= MLX5_FLOW_ACTION_PORT_ID;
@@ -7468,7 +7470,7 @@ struct field_modify_info modify_tcp[] = {
 			 * right now. So the pointer to the tag resource must be
 			 * zero before the register process.
 			 */
-			MLX5_ASSERT(!handle->dvh.tag_resource);
+			MLX5_ASSERT(!handle->dvh.rix_tag);
 			if (flow_dv_tag_resource_register(dev, tag_be,
 							  dev_flow, error))
 				return -rte_errno;
@@ -7497,7 +7499,7 @@ struct field_modify_info modify_tcp[] = {
 			tag_be = mlx5_flow_mark_set
 			      (((const struct rte_flow_action_mark *)
 			       (actions->conf))->id);
-			MLX5_ASSERT(!handle->dvh.tag_resource);
+			MLX5_ASSERT(!handle->dvh.rix_tag);
 			if (flow_dv_tag_resource_register(dev, tag_be,
 							  dev_flow, error))
 				return -rte_errno;
@@ -8127,7 +8129,7 @@ struct field_modify_info modify_tcp[] = {
 				 * the special index to hrxq to mark the queue
 				 * has been allocated.
 				 */
-				dh->hrxq = UINT32_MAX;
+				dh->rix_hrxq = UINT32_MAX;
 				dv->actions[n++] = drop_hrxq->action;
 			}
 		} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) {
@@ -8159,7 +8161,7 @@ struct field_modify_info modify_tcp[] = {
 					 "cannot get hash queue");
 				goto error;
 			}
-			dh->hrxq = hrxq_idx;
+			dh->rix_hrxq = hrxq_idx;
 			dv->actions[n++] = hrxq->action;
 		}
 		dh->ib_flow =
@@ -8190,13 +8192,13 @@ struct field_modify_info modify_tcp[] = {
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       handle_idx, dh, next) {
 		/* hrxq is union, don't clear it if the flag is not set. */
-		if (dh->hrxq) {
+		if (dh->rix_hrxq) {
 			if (dh->fate_action == MLX5_FLOW_FATE_DROP) {
 				mlx5_hrxq_drop_release(dev);
-				dh->hrxq = 0;
+				dh->rix_hrxq = 0;
 			} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) {
-				mlx5_hrxq_release(dev, dh->hrxq);
-				dh->hrxq = 0;
+				mlx5_hrxq_release(dev, dh->rix_hrxq);
+				dh->rix_hrxq = 0;
 			}
 		}
 		if (dh->vf_vlan.tag && dh->vf_vlan.created)
@@ -8257,7 +8259,7 @@ struct field_modify_info modify_tcp[] = {
 				     struct mlx5_flow_handle *handle)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint32_t idx = handle->dvh.encap_decap;
+	uint32_t idx = handle->dvh.rix_encap_decap;
 	struct mlx5_flow_dv_encap_decap_resource *cache_resource;
 
 	cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_DECAP_ENCAP],
@@ -8302,7 +8304,7 @@ struct field_modify_info modify_tcp[] = {
 	struct mlx5_flow_tbl_data_entry *tbl_data;
 
 	tbl_data = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_JUMP],
-			     handle->jump);
+			     handle->rix_jump);
 	if (!tbl_data)
 		return 0;
 	cache_resource = &tbl_data->jump;
@@ -8370,7 +8372,7 @@ struct field_modify_info modify_tcp[] = {
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_flow_dv_port_id_action_resource *cache_resource;
-	uint32_t idx = handle->port_id_action;
+	uint32_t idx = handle->rix_port_id_action;
 
 	cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PORT_ID],
 					idx);
@@ -8410,7 +8412,7 @@ struct field_modify_info modify_tcp[] = {
 					  struct mlx5_flow_handle *handle)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	uint32_t idx = handle->dvh.push_vlan_res;
+	uint32_t idx = handle->dvh.rix_push_vlan;
 	struct mlx5_flow_dv_push_vlan_action_resource *cache_resource;
 
 	cache_resource = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_PUSH_VLAN],
@@ -8447,19 +8449,19 @@ struct field_modify_info modify_tcp[] = {
 flow_dv_fate_resource_release(struct rte_eth_dev *dev,
 			       struct mlx5_flow_handle *handle)
 {
-	if (!handle->fate_idx)
+	if (!handle->rix_fate)
 		return;
 	if (handle->fate_action == MLX5_FLOW_FATE_DROP)
 		mlx5_hrxq_drop_release(dev);
 	else if (handle->fate_action == MLX5_FLOW_FATE_QUEUE)
-		mlx5_hrxq_release(dev, handle->hrxq);
+		mlx5_hrxq_release(dev, handle->rix_hrxq);
 	else if (handle->fate_action == MLX5_FLOW_FATE_JUMP)
 		flow_dv_jump_tbl_resource_release(dev, handle);
 	else if (handle->fate_action == MLX5_FLOW_FATE_PORT_ID)
 		flow_dv_port_id_action_resource_release(dev, handle);
 	else
 		DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action);
-	handle->fate_idx = 0;
+	handle->rix_fate = 0;
 }
 
 /**
@@ -8535,16 +8537,16 @@ struct field_modify_info modify_tcp[] = {
 		flow->dev_handles = dev_handle->next.next;
 		if (dev_handle->dvh.matcher)
 			flow_dv_matcher_release(dev, dev_handle);
-		if (dev_handle->dvh.encap_decap)
+		if (dev_handle->dvh.rix_encap_decap)
 			flow_dv_encap_decap_resource_release(dev, dev_handle);
 		if (dev_handle->dvh.modify_hdr)
 			flow_dv_modify_hdr_resource_release(dev_handle);
-		if (dev_handle->dvh.push_vlan_res)
+		if (dev_handle->dvh.rix_push_vlan)
 			flow_dv_push_vlan_action_resource_release(dev,
 								  dev_handle);
-		if (dev_handle->dvh.tag_resource)
+		if (dev_handle->dvh.rix_tag)
 			flow_dv_tag_release(dev,
-					    dev_handle->dvh.tag_resource);
+					    dev_handle->dvh.rix_tag);
 		flow_dv_fate_resource_release(dev, dev_handle);
 		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
 			   tmp_idx);
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 1d56b03..f70b879 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -1760,14 +1760,14 @@
 			handle->ib_flow = NULL;
 		}
 		/* hrxq is union, don't touch it only the flag is set. */
-		if (handle->hrxq) {
+		if (handle->rix_hrxq) {
 			if (handle->fate_action == MLX5_FLOW_FATE_DROP) {
 				mlx5_hrxq_drop_release(dev);
-				handle->hrxq = 0;
+				handle->rix_hrxq = 0;
 			} else if (handle->fate_action ==
 				   MLX5_FLOW_FATE_QUEUE) {
-				mlx5_hrxq_release(dev, handle->hrxq);
-				handle->hrxq = 0;
+				mlx5_hrxq_release(dev, handle->rix_hrxq);
+				handle->rix_hrxq = 0;
 			}
 		}
 		if (handle->vf_vlan.tag && handle->vf_vlan.created)
@@ -1872,7 +1872,7 @@
 					 "cannot get hash queue");
 				goto error;
 			}
-			handle->hrxq = hrxq_idx;
+			handle->rix_hrxq = hrxq_idx;
 		}
 		MLX5_ASSERT(hrxq);
 		handle->ib_flow = mlx5_glue->create_flow(hrxq->qp,
@@ -1901,14 +1901,14 @@
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       dev_handles, handle, next) {
 		/* hrxq is union, don't touch it only the flag is set. */
-		if (handle->hrxq) {
+		if (handle->rix_hrxq) {
 			if (handle->fate_action == MLX5_FLOW_FATE_DROP) {
 				mlx5_hrxq_drop_release(dev);
-				handle->hrxq = 0;
+				handle->rix_hrxq = 0;
 			} else if (handle->fate_action ==
 				   MLX5_FLOW_FATE_QUEUE) {
-				mlx5_hrxq_release(dev, handle->hrxq);
-				handle->hrxq = 0;
+				mlx5_hrxq_release(dev, handle->rix_hrxq);
+				handle->rix_hrxq = 0;
 			}
 		}
 		if (handle->vf_vlan.tag && handle->vf_vlan.created)
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 04/10] net/mlx5: optimize flow meter handle type
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (2 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 03/10] net/mlx5: reorganize the mlx5 flow handle struct Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 05/10] net/mlx5: allocate meter from indexed pool Suanming Mou
                     ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

While flow attaches the meter handle, the meter id can be the unique tag
for the flow to get the meter handle. It's no need for flow to save the
pointer of the meter handle.

Save the meter id instead of pointer helps reduce the size for rte flow
structure.

As the supported maximum meter rule is 4K, uint16_t type is selected for
the meter id.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow.h    |  2 +-
 drivers/net/mlx5/mlx5_flow_dv.c | 29 ++++++++++++++++++++++-------
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index e78de85..bf0345a 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -757,7 +757,7 @@ struct rte_flow {
 	uint32_t counter; /**< Holds flow counter. */
 	struct mlx5_flow_mreg_copy_resource *mreg_copy;
 	/**< pointer to metadata register copy table resource. */
-	struct mlx5_flow_meter *meter; /**< Holds flow meter. */
+	uint16_t meter; /**< Holds flow meter id. */
 	uint32_t dev_handles;
 	/**< Device flow handles that are part of the flow. */
 	struct mlx5_fdir *fdir; /**< Pointer to associated FDIR if any. */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index a8e92f2..23b69ba 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7430,6 +7430,7 @@ struct field_modify_info modify_tcp[] = {
 		struct mlx5_flow_dv_port_id_action_resource port_id_resource;
 		int action_type = actions->type;
 		const struct rte_flow_action *found_action = NULL;
+		struct mlx5_flow_meter *fm = NULL;
 
 		switch (action_type) {
 		case RTE_FLOW_ACTION_TYPE_VOID:
@@ -7806,20 +7807,30 @@ struct field_modify_info modify_tcp[] = {
 		case RTE_FLOW_ACTION_TYPE_METER:
 			mtr = actions->conf;
 			if (!flow->meter) {
-				flow->meter = mlx5_flow_meter_attach(priv,
-							mtr->mtr_id, attr,
-							error);
-				if (!flow->meter)
+				fm = mlx5_flow_meter_attach(priv, mtr->mtr_id,
+							    attr, error);
+				if (!fm)
 					return rte_flow_error_set(error,
 						rte_errno,
 						RTE_FLOW_ERROR_TYPE_ACTION,
 						NULL,
 						"meter not found "
 						"or invalid parameters");
+				flow->meter = fm->meter_id;
 			}
 			/* Set the meter action. */
+			if (!fm) {
+				fm = mlx5_flow_meter_find(priv, flow->meter);
+				if (!fm)
+					return rte_flow_error_set(error,
+						rte_errno,
+						RTE_FLOW_ERROR_TYPE_ACTION,
+						NULL,
+						"meter not found "
+						"or invalid parameters");
+			}
 			dev_flow->dv.actions[actions_n++] =
-				flow->meter->mfts->meter_action;
+				fm->mfts->meter_action;
 			action_flags |= MLX5_FLOW_ACTION_METER;
 			break;
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_DSCP:
@@ -8524,8 +8535,12 @@ struct field_modify_info modify_tcp[] = {
 		flow->counter = 0;
 	}
 	if (flow->meter) {
-		mlx5_flow_meter_detach(flow->meter);
-		flow->meter = NULL;
+		struct mlx5_flow_meter *fm;
+
+		fm  = mlx5_flow_meter_find(priv, flow->meter);
+		if (fm)
+			mlx5_flow_meter_detach(fm);
+		flow->meter = 0;
 	}
 	while (flow->dev_handles) {
 		uint32_t tmp_idx = flow->dev_handles;
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 05/10] net/mlx5: allocate meter from indexed pool
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (3 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 04/10] net/mlx5: optimize flow meter handle type Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 06/10] net/mlx5: convert mark copy resource to indexed Suanming Mou
                     ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

This patch allocate the meter object memory from indexed memory pool
which will help to save the MALLOC_ELEM_OVERHEAD memory taken by
rte_malloc().

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5.c            | 11 +++++++++++
 drivers/net/mlx5/mlx5.h            |  1 +
 drivers/net/mlx5/mlx5_flow.h       |  1 +
 drivers/net/mlx5/mlx5_flow_meter.c | 11 ++++++-----
 4 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 331318a..ac9391b 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -257,6 +257,17 @@ struct mlx5_dev_spawn_data {
 	},
 #endif
 	{
+		.size = sizeof(struct mlx5_flow_meter),
+		.trunk_size = 64,
+		.grow_trunk = 3,
+		.grow_shift = 2,
+		.need_lock = 0,
+		.release_mem_en = 1,
+		.malloc = rte_malloc_socket,
+		.free = rte_free,
+		.type = "mlx5_meter_ipool",
+	},
+	{
 		.size = (sizeof(struct mlx5_hrxq) + MLX5_RSS_HASH_KEY_LEN),
 		.trunk_size = 64,
 		.grow_trunk = 3,
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 2c4e823..009c1da 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -52,6 +52,7 @@ enum mlx5_ipool_index {
 	MLX5_IPOOL_PORT_ID, /* Pool for port id resource. */
 	MLX5_IPOOL_JUMP, /* Pool for jump resource. */
 #endif
+	MLX5_IPOOL_MTR, /* Pool for meter resource. */
 	MLX5_IPOOL_HRXQ, /* Pool for hrxq resource. */
 	MLX5_IPOOL_MLX5_FLOW, /* Pool for mlx5 flow handle. */
 	MLX5_IPOOL_MAX,
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index bf0345a..b508299 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -703,6 +703,7 @@ struct mlx5_meter_domains_infos {
 struct mlx5_flow_meter {
 	TAILQ_ENTRY(mlx5_flow_meter) next;
 	/**< Pointer to the next flow meter structure. */
+	uint32_t idx; /* Index to meter object. */
 	uint32_t meter_id;
 	/**< Meter id. */
 	struct rte_mtr_params params;
diff --git a/drivers/net/mlx5/mlx5_flow_meter.c b/drivers/net/mlx5/mlx5_flow_meter.c
index aa0fd7a..b5fbf5d 100644
--- a/drivers/net/mlx5/mlx5_flow_meter.c
+++ b/drivers/net/mlx5/mlx5_flow_meter.c
@@ -631,6 +631,7 @@
 			};
 	int ret;
 	unsigned int i;
+	uint32_t idx = 0;
 
 	if (!priv->mtr_en)
 		return -rte_mtr_error_set(error, ENOTSUP,
@@ -647,12 +648,12 @@
 					  RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
 					  NULL, "Meter profile id not valid.");
 	/* Allocate the flow meter memory. */
-	fm = rte_calloc(__func__, 1,
-			sizeof(struct mlx5_flow_meter), RTE_CACHE_LINE_SIZE);
+	fm = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MTR], &idx);
 	if (fm == NULL)
 		return -rte_mtr_error_set(error, ENOMEM,
 					  RTE_MTR_ERROR_TYPE_UNSPECIFIED, NULL,
 					  "Memory alloc failed for meter.");
+	fm->idx = idx;
 	/* Fill the flow meter parameters. */
 	fm->meter_id = meter_id;
 	fm->profile = fmp;
@@ -683,7 +684,7 @@
 	for (i = 0; i < RTE_DIM(fm->policer_stats.cnt); i++)
 		if (fm->policer_stats.cnt[i])
 			mlx5_counter_free(dev, fm->policer_stats.cnt[i]);
-	rte_free(fm);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], idx);
 	return -rte_mtr_error_set(error, -ret,
 				  RTE_MTR_ERROR_TYPE_UNSPECIFIED,
 				  NULL, "Failed to create devx meter.");
@@ -746,7 +747,7 @@
 	/* Free meter flow table */
 	mlx5_flow_destroy_policer_rules(dev, fm, &attr);
 	mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
-	rte_free(fm);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], fm->idx);
 	return 0;
 }
 
@@ -1274,7 +1275,7 @@ struct mlx5_flow_meter *
 		/* Free meter flow table. */
 		mlx5_flow_destroy_policer_rules(dev, fm, &attr);
 		mlx5_flow_destroy_mtr_tbls(dev, fm->mfts);
-		rte_free(fm);
+		mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MTR], fm->idx);
 	}
 	TAILQ_FOREACH_SAFE(fmp, fmps, next, tmp) {
 		/* Check unused. */
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 06/10] net/mlx5: convert mark copy resource to indexed
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (4 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 05/10] net/mlx5: allocate meter from indexed pool Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 07/10] net/mlx5: optimize flow director filter memory Suanming Mou
                     ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

Allocate mark copy resource from indexed pool helps rte flow saves the 4
bytes index instead of 8 bytes pointer. For mark copy resource itself, it
helps save MALLOC_ELEM_OVERHEAD bytes from rte_malloc().

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5.c      | 11 +++++++++++
 drivers/net/mlx5/mlx5.h      |  1 +
 drivers/net/mlx5/mlx5_flow.c | 40 ++++++++++++++++++++++++++++------------
 drivers/net/mlx5/mlx5_flow.h |  5 +++--
 4 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index ac9391b..1bb464d 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -268,6 +268,17 @@ struct mlx5_dev_spawn_data {
 		.type = "mlx5_meter_ipool",
 	},
 	{
+		.size = sizeof(struct mlx5_flow_meter),
+		.trunk_size = 64,
+		.grow_trunk = 3,
+		.grow_shift = 2,
+		.need_lock = 0,
+		.release_mem_en = 1,
+		.malloc = rte_malloc_socket,
+		.free = rte_free,
+		.type = "mlx5_mcp_ipool",
+	},
+	{
 		.size = (sizeof(struct mlx5_hrxq) + MLX5_RSS_HASH_KEY_LEN),
 		.trunk_size = 64,
 		.grow_trunk = 3,
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 009c1da..faf65f3 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -53,6 +53,7 @@ enum mlx5_ipool_index {
 	MLX5_IPOOL_JUMP, /* Pool for jump resource. */
 #endif
 	MLX5_IPOOL_MTR, /* Pool for meter resource. */
+	MLX5_IPOOL_MCP, /* Pool for metadata resource. */
 	MLX5_IPOOL_HRXQ, /* Pool for hrxq resource. */
 	MLX5_IPOOL_MLX5_FLOW, /* Pool for mlx5 flow handle. */
 	MLX5_IPOOL_MAX,
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 4205f23..eaf3d8d 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2962,6 +2962,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		[3] = { .type = RTE_FLOW_ACTION_TYPE_END, },
 	};
 	struct mlx5_flow_mreg_copy_resource *mcp_res;
+	uint32_t idx = 0;
 	int ret;
 
 	/* Fill the register fileds in the flow. */
@@ -3030,11 +3031,12 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		};
 	}
 	/* Build a new entry. */
-	mcp_res = rte_zmalloc(__func__, sizeof(*mcp_res), 0);
+	mcp_res = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MCP], &idx);
 	if (!mcp_res) {
 		rte_errno = ENOMEM;
 		return NULL;
 	}
+	mcp_res->idx = idx;
 	/*
 	 * The copy Flows are not included in any list. There
 	 * ones are referenced from other Flows and can not
@@ -3056,7 +3058,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 error:
 	if (mcp_res->flow)
 		flow_list_destroy(dev, NULL, mcp_res->flow);
-	rte_free(mcp_res);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
 	return NULL;
 }
 
@@ -3072,9 +3074,13 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 flow_mreg_del_copy_action(struct rte_eth_dev *dev,
 			  struct rte_flow *flow)
 {
-	struct mlx5_flow_mreg_copy_resource *mcp_res = flow->mreg_copy;
+	struct mlx5_flow_mreg_copy_resource *mcp_res;
 	struct mlx5_priv *priv = dev->data->dev_private;
 
+	if (!flow->rix_mreg_copy)
+		return;
+	mcp_res = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MCP],
+				 flow->rix_mreg_copy);
 	if (!mcp_res || !priv->mreg_cp_tbl)
 		return;
 	if (flow->copy_applied) {
@@ -3093,8 +3099,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	MLX5_ASSERT(mcp_res->flow);
 	flow_list_destroy(dev, NULL, mcp_res->flow);
 	mlx5_hlist_remove(priv->mreg_cp_tbl, &mcp_res->hlist_ent);
-	rte_free(mcp_res);
-	flow->mreg_copy = NULL;
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
+	flow->rix_mreg_copy = 0;
 }
 
 /**
@@ -3112,10 +3118,15 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 flow_mreg_start_copy_action(struct rte_eth_dev *dev,
 			    struct rte_flow *flow)
 {
-	struct mlx5_flow_mreg_copy_resource *mcp_res = flow->mreg_copy;
+	struct mlx5_flow_mreg_copy_resource *mcp_res;
+	struct mlx5_priv *priv = dev->data->dev_private;
 	int ret;
 
-	if (!mcp_res || flow->copy_applied)
+	if (!flow->rix_mreg_copy || flow->copy_applied)
+		return 0;
+	mcp_res = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MCP],
+				 flow->rix_mreg_copy);
+	if (!mcp_res)
 		return 0;
 	if (!mcp_res->appcnt) {
 		ret = flow_drv_apply(dev, mcp_res->flow, NULL);
@@ -3139,9 +3150,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 flow_mreg_stop_copy_action(struct rte_eth_dev *dev,
 			   struct rte_flow *flow)
 {
-	struct mlx5_flow_mreg_copy_resource *mcp_res = flow->mreg_copy;
+	struct mlx5_flow_mreg_copy_resource *mcp_res;
+	struct mlx5_priv *priv = dev->data->dev_private;
 
-	if (!mcp_res || !flow->copy_applied)
+	if (!flow->rix_mreg_copy || !flow->copy_applied)
+		return;
+	mcp_res = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MCP],
+				 flow->rix_mreg_copy);
+	if (!mcp_res)
 		return;
 	MLX5_ASSERT(mcp_res->appcnt);
 	--mcp_res->appcnt;
@@ -3172,7 +3188,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	MLX5_ASSERT(mcp_res->flow);
 	flow_list_destroy(dev, NULL, mcp_res->flow);
 	mlx5_hlist_remove(priv->mreg_cp_tbl, &mcp_res->hlist_ent);
-	rte_free(mcp_res);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
 }
 
 /**
@@ -3264,7 +3280,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				(dev, MLX5_FLOW_MARK_DEFAULT, error);
 			if (!mcp_res)
 				return -rte_errno;
-			flow->mreg_copy = mcp_res;
+			flow->rix_mreg_copy = mcp_res->idx;
 			if (dev->data->dev_started) {
 				mcp_res->appcnt++;
 				flow->copy_applied = 1;
@@ -3277,7 +3293,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				flow_mreg_add_copy_action(dev, mark->id, error);
 			if (!mcp_res)
 				return -rte_errno;
-			flow->mreg_copy = mcp_res;
+			flow->rix_mreg_copy = mcp_res->idx;
 			if (dev->data->dev_started) {
 				mcp_res->appcnt++;
 				flow->copy_applied = 1;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index b508299..c9b357d 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -460,6 +460,7 @@ struct mlx5_flow_mreg_copy_resource {
 	/* List entry for device flows. */
 	uint32_t refcnt; /* Reference counter. */
 	uint32_t appcnt; /* Apply/Remove counter. */
+	uint32_t idx;
 	struct rte_flow *flow; /* Built flow for copy. */
 };
 
@@ -756,8 +757,8 @@ struct rte_flow {
 	enum mlx5_flow_drv_type drv_type; /**< Driver type. */
 	struct mlx5_flow_rss rss; /**< RSS context. */
 	uint32_t counter; /**< Holds flow counter. */
-	struct mlx5_flow_mreg_copy_resource *mreg_copy;
-	/**< pointer to metadata register copy table resource. */
+	uint32_t rix_mreg_copy;
+	/**< Index to metadata register copy table resource. */
 	uint16_t meter; /**< Holds flow meter id. */
 	uint32_t dev_handles;
 	/**< Device flow handles that are part of the flow. */
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 07/10] net/mlx5: optimize flow director filter memory
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (5 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 06/10] net/mlx5: convert mark copy resource to indexed Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 08/10] net/mlx5: optimize mlx5 flow RSS struct Suanming Mou
                     ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

From: Wentao Cui <wentaoc@mellanox.com>

This commit is for mlx5 fdir flow memory optimization.

Currently for the fdir member in rte_flow structure. It saves the fdir
memory pointer directly. As fdir is fading away, use one bit help to
indicate the function in the flow and add the content to an extra list
save the memory for the other widely usage cases.

Signed-off-by: Wentao Cui <wentaoc@mellanox.com>
Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5.h      |  1 +
 drivers/net/mlx5/mlx5_flow.c | 62 ++++++++++++++++++++++++++++++++++++--------
 drivers/net/mlx5/mlx5_flow.h |  9 ++++++-
 3 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index faf65f3..bfb6c26 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -556,6 +556,7 @@ struct mlx5_priv {
 	uint8_t skip_default_rss_reta; /* Skip configuration of default reta. */
 	uint8_t fdb_def_rule; /* Whether fdb jump to table 1 is configured. */
 	struct mlx5_mp_id mp_id; /* ID of a multi-process process */
+	LIST_HEAD(fdir, mlx5_fdir_flow) fdir_flows; /* fdir flows. */
 };
 
 #define PORT_ID(priv) ((priv)->dev_data->port_id)
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index eaf3d8d..387a06d 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -4491,6 +4491,7 @@ struct rte_flow *
 		  struct rte_flow *flow)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
 
 	/*
 	 * Update RX queue flags only if port is started, otherwise it is
@@ -4505,7 +4506,17 @@ struct rte_flow *
 	if (list)
 		TAILQ_REMOVE(list, flow, next);
 	flow_mreg_del_copy_action(dev, flow);
-	rte_free(flow->fdir);
+	if (flow->fdir) {
+		LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
+			if (priv_fdir_flow->flow == flow)
+				break;
+		}
+		if (priv_fdir_flow) {
+			LIST_REMOVE(priv_fdir_flow, next);
+			rte_free(priv_fdir_flow->fdir);
+			rte_free(priv_fdir_flow);
+		}
+	}
 	rte_free(flow);
 }
 
@@ -5189,12 +5200,14 @@ struct rte_flow *
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct rte_flow *flow = NULL;
+	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
 
 	MLX5_ASSERT(fdir_flow);
-	TAILQ_FOREACH(flow, &priv->flows, next) {
-		if (flow->fdir && !flow_fdir_cmp(flow->fdir, fdir_flow)) {
+	LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
+		if (!flow_fdir_cmp(priv_fdir_flow->fdir, fdir_flow)) {
 			DRV_LOG(DEBUG, "port %u found FDIR flow %p",
 				dev->data->port_id, (void *)flow);
+			flow = priv_fdir_flow->flow;
 			break;
 		}
 	}
@@ -5219,6 +5232,7 @@ struct rte_flow *
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_fdir *fdir_flow;
 	struct rte_flow *flow;
+	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
 	int ret;
 
 	fdir_flow = rte_zmalloc(__func__, sizeof(*fdir_flow), 0);
@@ -5234,17 +5248,26 @@ struct rte_flow *
 		rte_errno = EEXIST;
 		goto error;
 	}
+	priv_fdir_flow = rte_zmalloc(__func__, sizeof(struct mlx5_fdir_flow),
+				     0);
+	if (!priv_fdir_flow) {
+		rte_errno = ENOMEM;
+		goto error;
+	}
 	flow = flow_list_create(dev, &priv->flows, &fdir_flow->attr,
 				fdir_flow->items, fdir_flow->actions, true,
 				NULL);
 	if (!flow)
 		goto error;
-	MLX5_ASSERT(!flow->fdir);
-	flow->fdir = fdir_flow;
+	flow->fdir = 1;
+	priv_fdir_flow->fdir = fdir_flow;
+	priv_fdir_flow->flow = flow;
+	LIST_INSERT_HEAD(&priv->fdir_flows, priv_fdir_flow, next);
 	DRV_LOG(DEBUG, "port %u created FDIR flow %p",
 		dev->data->port_id, (void *)flow);
 	return 0;
 error:
+	rte_free(priv_fdir_flow);
 	rte_free(fdir_flow);
 	return -rte_errno;
 }
@@ -5269,17 +5292,26 @@ struct rte_flow *
 	struct mlx5_fdir fdir_flow = {
 		.attr.group = 0,
 	};
+	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
 	int ret;
 
 	ret = flow_fdir_filter_convert(dev, fdir_filter, &fdir_flow);
 	if (ret)
 		return -rte_errno;
-	flow = flow_fdir_filter_lookup(dev, &fdir_flow);
-	if (!flow) {
-		rte_errno = ENOENT;
-		return -rte_errno;
+	LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
+		/* Find the fdir in priv list */
+		if (!flow_fdir_cmp(priv_fdir_flow->fdir, &fdir_flow))
+			break;
 	}
+	if (!priv_fdir_flow)
+		return 0;
+	LIST_REMOVE(priv_fdir_flow, next);
+	flow = priv_fdir_flow->flow;
+	/* Fdir resource will be releasd after flow destroy. */
+	flow->fdir = 0;
 	flow_list_destroy(dev, &priv->flows, flow);
+	rte_free(priv_fdir_flow->fdir);
+	rte_free(priv_fdir_flow);
 	DRV_LOG(DEBUG, "port %u deleted FDIR flow %p",
 		dev->data->port_id, (void *)flow);
 	return 0;
@@ -5318,8 +5350,16 @@ struct rte_flow *
 flow_fdir_filter_flush(struct rte_eth_dev *dev)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-
-	mlx5_flow_list_flush(dev, &priv->flows, false);
+	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
+
+	while (!LIST_EMPTY(&priv->fdir_flows)) {
+		priv_fdir_flow = LIST_FIRST(&priv->fdir_flows);
+		LIST_REMOVE(priv_fdir_flow, next);
+		priv_fdir_flow->flow->fdir = 0;
+		flow_list_destroy(dev, &priv->flows, priv_fdir_flow->flow);
+		rte_free(priv_fdir_flow->fdir);
+		rte_free(priv_fdir_flow);
+	}
 }
 
 /**
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index c9b357d..8a4f7cb 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -751,6 +751,13 @@ struct mlx5_flow_meter_profile {
 	uint32_t ref_cnt; /**< Use count. */
 };
 
+/* Fdir flow struture */
+struct mlx5_fdir_flow {
+	LIST_ENTRY(mlx5_fdir_flow) next; /* Pointer to the next element. */
+	struct mlx5_fdir *fdir; /* Pointer to fdir. */
+	struct rte_flow *flow; /* Pointer to flow. */
+};
+
 /* Flow structure. */
 struct rte_flow {
 	TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
@@ -762,7 +769,7 @@ struct rte_flow {
 	uint16_t meter; /**< Holds flow meter id. */
 	uint32_t dev_handles;
 	/**< Device flow handles that are part of the flow. */
-	struct mlx5_fdir *fdir; /**< Pointer to associated FDIR if any. */
+	uint32_t fdir:1; /**< Identifier of associated FDIR if any. */
 	uint32_t hairpin_flow_id; /**< The flow id used for hairpin. */
 	uint32_t copy_applied:1; /**< The MARK copy Flow os applied. */
 };
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 08/10] net/mlx5: optimize mlx5 flow RSS struct
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (6 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 07/10] net/mlx5: optimize flow director filter memory Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 09/10] net/mlx5: allocate rte flow from indexed pool Suanming Mou
                     ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

When destroy the flow with RSS, flow can invoke the queues information
from hrxq index table object, since the queue number and list are both
saved to the index table object. No need to save the duplicated data in
rte flow.

Save the RSS description information to the intermediate private data
when create the flow with RSS action helps to save the memory for rte
flow.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5.h            |  1 +
 drivers/net/mlx5/mlx5_flow.c       | 72 ++++++++++++++++++++++----------------
 drivers/net/mlx5/mlx5_flow.h       | 11 +++---
 drivers/net/mlx5/mlx5_flow_dv.c    | 59 ++++++++++++++++---------------
 drivers/net/mlx5/mlx5_flow_verbs.c | 59 +++++++++++++++----------------
 5 files changed, 108 insertions(+), 94 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index bfb6c26..164ca3a 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -515,6 +515,7 @@ struct mlx5_priv {
 	struct mlx5_flows flows; /* RTE Flow rules. */
 	struct mlx5_flows ctrl_flows; /* Control flow rules. */
 	void *inter_flows; /* Intermediate resources for flow creation. */
+	void *rss_desc; /* Intermediate rss description resources. */
 	int flow_idx; /* Intermediate device flow index. */
 	int flow_nested_idx; /* Intermediate device flow index, nested. */
 	LIST_HEAD(rxq, mlx5_rxq_ctrl) rxqsctrl; /* DPDK Rx queues. */
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 387a06d..4f74e6b 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -658,13 +658,12 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  *   The hash fields that should be used.
  */
 uint64_t
-mlx5_flow_hashfields_adjust(struct mlx5_flow *dev_flow,
+mlx5_flow_hashfields_adjust(struct mlx5_flow_rss_desc *rss_desc,
 			    int tunnel __rte_unused, uint64_t layer_types,
 			    uint64_t hash_fields)
 {
-	struct rte_flow *flow = dev_flow->flow;
 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
-	int rss_request_inner = flow->rss.level >= 2;
+	int rss_request_inner = rss_desc->level >= 2;
 
 	/* Check RSS hash level for tunnel. */
 	if (tunnel && rss_request_inner)
@@ -673,7 +672,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		return 0;
 #endif
 	/* Check if requested layer matches RSS hash fields. */
-	if (!(flow->rss.types & layer_types))
+	if (!(rss_desc->types & layer_types))
 		return 0;
 	return hash_fields;
 }
@@ -712,22 +711,27 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  *
  * @param[in] dev
  *   Pointer to the Ethernet device structure.
- * @param[in] flow
- *   Pointer to flow structure.
  * @param[in] dev_handle
  *   Pointer to device flow handle structure.
  */
 static void
-flow_drv_rxq_flags_set(struct rte_eth_dev *dev, struct rte_flow *flow,
+flow_drv_rxq_flags_set(struct rte_eth_dev *dev,
 		       struct mlx5_flow_handle *dev_handle)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	const int mark = dev_handle->mark;
 	const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL);
+	struct mlx5_hrxq *hrxq;
 	unsigned int i;
 
-	for (i = 0; i != flow->rss.queue_num; ++i) {
-		int idx = (*flow->rss.queue)[i];
+	if (dev_handle->fate_action != MLX5_FLOW_FATE_QUEUE)
+		return;
+	hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
+			      dev_handle->rix_hrxq);
+	if (!hrxq)
+		return;
+	for (i = 0; i != hrxq->ind_table->queues_n; ++i) {
+		int idx = hrxq->ind_table->queues[i];
 		struct mlx5_rxq_ctrl *rxq_ctrl =
 			container_of((*priv->rxqs)[idx],
 				     struct mlx5_rxq_ctrl, rxq);
@@ -780,7 +784,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       handle_idx, dev_handle, next)
-		flow_drv_rxq_flags_set(dev, flow, dev_handle);
+		flow_drv_rxq_flags_set(dev, dev_handle);
 }
 
 /**
@@ -789,23 +793,28 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  *
  * @param dev
  *   Pointer to Ethernet device.
- * @param[in] flow
- *   Pointer to flow structure.
  * @param[in] dev_handle
  *   Pointer to the device flow handle structure.
  */
 static void
-flow_drv_rxq_flags_trim(struct rte_eth_dev *dev, struct rte_flow *flow,
+flow_drv_rxq_flags_trim(struct rte_eth_dev *dev,
 			struct mlx5_flow_handle *dev_handle)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	const int mark = dev_handle->mark;
 	const int tunnel = !!(dev_handle->layers & MLX5_FLOW_LAYER_TUNNEL);
+	struct mlx5_hrxq *hrxq;
 	unsigned int i;
 
+	if (dev_handle->fate_action != MLX5_FLOW_FATE_QUEUE)
+		return;
+	hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
+			      dev_handle->rix_hrxq);
+	if (!hrxq)
+		return;
 	MLX5_ASSERT(dev->data->dev_started);
-	for (i = 0; i != flow->rss.queue_num; ++i) {
-		int idx = (*flow->rss.queue)[i];
+	for (i = 0; i != hrxq->ind_table->queues_n; ++i) {
+		int idx = hrxq->ind_table->queues[i];
 		struct mlx5_rxq_ctrl *rxq_ctrl =
 			container_of((*priv->rxqs)[idx],
 				     struct mlx5_rxq_ctrl, rxq);
@@ -854,7 +863,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 
 	SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
 		       handle_idx, dev_handle, next)
-		flow_drv_rxq_flags_trim(dev, flow, dev_handle);
+		flow_drv_rxq_flags_trim(dev, dev_handle);
 }
 
 /**
@@ -4239,9 +4248,9 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		uint8_t buffer[2048];
 	} items_tx;
 	struct rte_flow_expand_rss *buf = &expand_buffer.buf;
+	struct mlx5_flow_rss_desc *rss_desc = priv->rss_desc;
 	const struct rte_flow_action *p_actions_rx = actions;
 	uint32_t i;
-	uint32_t flow_size;
 	int hairpin_flow = 0;
 	uint32_t hairpin_id = 0;
 	struct rte_flow_attr attr_tx = { .priority = 0 };
@@ -4261,14 +4270,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				   &hairpin_id);
 		p_actions_rx = actions_rx.actions;
 	}
-	flow_size = sizeof(struct rte_flow);
-	rss = flow_get_rss_action(p_actions_rx);
-	if (rss)
-		flow_size += RTE_ALIGN_CEIL(rss->queue_num * sizeof(uint16_t),
-					    sizeof(void *));
-	else
-		flow_size += RTE_ALIGN_CEIL(sizeof(uint16_t), sizeof(void *));
-	flow = rte_calloc(__func__, 1, flow_size, 0);
+	flow = rte_calloc(__func__, 1, sizeof(struct rte_flow), 0);
 	if (!flow) {
 		rte_errno = ENOMEM;
 		goto error_before_flow;
@@ -4278,15 +4280,16 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		flow->hairpin_flow_id = hairpin_id;
 	MLX5_ASSERT(flow->drv_type > MLX5_FLOW_TYPE_MIN &&
 		    flow->drv_type < MLX5_FLOW_TYPE_MAX);
-	flow->rss.queue = (void *)(flow + 1);
+	memset(rss_desc, 0, sizeof(*rss_desc));
+	rss = flow_get_rss_action(p_actions_rx);
 	if (rss) {
 		/*
 		 * The following information is required by
 		 * mlx5_flow_hashfields_adjust() in advance.
 		 */
-		flow->rss.level = rss->level;
+		rss_desc->level = rss->level;
 		/* RSS type 0 indicates default RSS type (ETH_RSS_IP). */
-		flow->rss.types = !rss->types ? ETH_RSS_IP : rss->types;
+		rss_desc->types = !rss->types ? ETH_RSS_IP : rss->types;
 	}
 	flow->dev_handles = 0;
 	if (rss && rss->types) {
@@ -4650,9 +4653,18 @@ struct rte_flow *
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 
-	if (!priv->inter_flows)
+	if (!priv->inter_flows) {
 		priv->inter_flows = rte_calloc(__func__, MLX5_NUM_MAX_DEV_FLOWS,
-					       sizeof(struct mlx5_flow), 0);
+				    sizeof(struct mlx5_flow) +
+				    sizeof(struct mlx5_flow_rss_desc) +
+				    sizeof(uint16_t) * UINT16_MAX, 0);
+		if (!priv->inter_flows) {
+			DRV_LOG(ERR, "can't allocate intermediate memory.");
+			return;
+		}
+	}
+	priv->rss_desc = &((struct mlx5_flow *)priv->inter_flows)
+			 [MLX5_NUM_MAX_DEV_FLOWS];
 	/* Reset the index. */
 	priv->flow_idx = 0;
 	priv->flow_nested_idx = 0;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 8a4f7cb..759b0ce 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -483,14 +483,16 @@ struct ibv_spec_header {
 	uint16_t size;
 };
 
-struct mlx5_flow_rss {
+/* RSS description. */
+struct mlx5_flow_rss_desc {
 	uint32_t level;
 	uint32_t queue_num; /**< Number of entries in @p queue. */
 	uint64_t types; /**< Specific RSS hash types (see ETH_RSS_*). */
-	uint16_t (*queue)[]; /**< Destination queues to redirect traffic to. */
 	uint8_t key[MLX5_RSS_HASH_KEY_LEN]; /**< RSS hash key. */
+	uint16_t queue[]; /**< Destination queues to redirect traffic to. */
 };
 
+
 /** Device flow handle structure for DV mode only. */
 struct mlx5_flow_handle_dv {
 	/* Flow DV api: */
@@ -762,7 +764,6 @@ struct mlx5_fdir_flow {
 struct rte_flow {
 	TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
 	enum mlx5_flow_drv_type drv_type; /**< Driver type. */
-	struct mlx5_flow_rss rss; /**< RSS context. */
 	uint32_t counter; /**< Holds flow counter. */
 	uint32_t rix_mreg_copy;
 	/**< Index to metadata register copy table resource. */
@@ -855,8 +856,8 @@ uint32_t mlx5_flow_id_release(struct mlx5_flow_id_pool *pool,
 int mlx5_flow_group_to_table(const struct rte_flow_attr *attributes,
 			     bool external, uint32_t group, bool fdb_def_rule,
 			     uint32_t *table, struct rte_flow_error *error);
-uint64_t mlx5_flow_hashfields_adjust(struct mlx5_flow *dev_flow, int tunnel,
-				     uint64_t layer_types,
+uint64_t mlx5_flow_hashfields_adjust(struct mlx5_flow_rss_desc *rss_desc,
+				     int tunnel, uint64_t layer_types,
 				     uint64_t hash_fields);
 uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				   uint32_t subpriority);
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 23b69ba..cfc911c 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -7279,18 +7279,20 @@ struct field_modify_info modify_tcp[] = {
  *
  * @param[in] dev_flow
  *   Pointer to the mlx5_flow.
+ * @param[in] rss_desc
+ *   Pointer to the mlx5_flow_rss_desc.
  */
 static void
-flow_dv_hashfields_set(struct mlx5_flow *dev_flow)
+flow_dv_hashfields_set(struct mlx5_flow *dev_flow,
+		       struct mlx5_flow_rss_desc *rss_desc)
 {
-	struct rte_flow *flow = dev_flow->flow;
 	uint64_t items = dev_flow->handle->layers;
 	int rss_inner = 0;
-	uint64_t rss_types = rte_eth_rss_hf_refine(flow->rss.types);
+	uint64_t rss_types = rte_eth_rss_hf_refine(rss_desc->types);
 
 	dev_flow->hash_fields = 0;
 #ifdef HAVE_IBV_DEVICE_TUNNEL_SUPPORT
-	if (flow->rss.level >= 2) {
+	if (rss_desc->level >= 2) {
 		dev_flow->hash_fields |= IBV_RX_HASH_INNER;
 		rss_inner = 1;
 	}
@@ -7375,6 +7377,8 @@ struct field_modify_info modify_tcp[] = {
 	struct mlx5_dev_config *dev_conf = &priv->config;
 	struct rte_flow *flow = dev_flow->flow;
 	struct mlx5_flow_handle *handle = dev_flow->handle;
+	struct mlx5_flow_rss_desc *rss_desc = (struct mlx5_flow_rss_desc *)
+					      priv->rss_desc;
 	uint64_t item_flags = 0;
 	uint64_t last_item = 0;
 	uint64_t action_flags = 0;
@@ -7529,23 +7533,20 @@ struct field_modify_info modify_tcp[] = {
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
-			MLX5_ASSERT(flow->rss.queue);
 			queue = actions->conf;
-			flow->rss.queue_num = 1;
-			(*flow->rss.queue)[0] = queue->index;
+			rss_desc->queue_num = 1;
+			rss_desc->queue[0] = queue->index;
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
-			MLX5_ASSERT(flow->rss.queue);
 			rss = actions->conf;
-			if (flow->rss.queue)
-				memcpy((*flow->rss.queue), rss->queue,
-				       rss->queue_num * sizeof(uint16_t));
-			flow->rss.queue_num = rss->queue_num;
+			memcpy(rss_desc->queue, rss->queue,
+			       rss->queue_num * sizeof(uint16_t));
+			rss_desc->queue_num = rss->queue_num;
 			/* NULL RSS key indicates default RSS key. */
 			rss_key = !rss->key ? rss_hash_default_key : rss->key;
-			memcpy(flow->rss.key, rss_key, MLX5_RSS_HASH_KEY_LEN);
+			memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
 			/*
 			 * rss->level and rss.types should be set in advance
 			 * when expanding items for RSS.
@@ -7955,7 +7956,7 @@ struct field_modify_info modify_tcp[] = {
 		case RTE_FLOW_ITEM_TYPE_GRE:
 			flow_dv_translate_item_gre(match_mask, match_value,
 						   items, tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GRE;
 			break;
@@ -7967,14 +7968,14 @@ struct field_modify_info modify_tcp[] = {
 		case RTE_FLOW_ITEM_TYPE_NVGRE:
 			flow_dv_translate_item_nvgre(match_mask, match_value,
 						     items, tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GRE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 			flow_dv_translate_item_vxlan(match_mask, match_value,
 						     items, tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_VXLAN;
 			break;
@@ -7982,21 +7983,21 @@ struct field_modify_info modify_tcp[] = {
 			flow_dv_translate_item_vxlan_gpe(match_mask,
 							 match_value, items,
 							 tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_GENEVE:
 			flow_dv_translate_item_geneve(match_mask, match_value,
 						      items, tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GENEVE;
 			break;
 		case RTE_FLOW_ITEM_TYPE_MPLS:
 			flow_dv_translate_item_mpls(match_mask, match_value,
 						    items, last_item, tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_MPLS;
 			break;
@@ -8039,7 +8040,7 @@ struct field_modify_info modify_tcp[] = {
 		case RTE_FLOW_ITEM_TYPE_GTP:
 			flow_dv_translate_item_gtp(match_mask, match_value,
 						   items, tunnel);
-			matcher.priority = flow->rss.level >= 2 ?
+			matcher.priority = rss_desc->level >= 2 ?
 				    MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
 			last_item = MLX5_FLOW_LAYER_GTP;
 			break;
@@ -8071,7 +8072,7 @@ struct field_modify_info modify_tcp[] = {
 	 */
 	handle->layers |= item_flags;
 	if (action_flags & MLX5_FLOW_ACTION_RSS)
-		flow_dv_hashfields_set(dev_flow);
+		flow_dv_hashfields_set(dev_flow, rss_desc);
 	/* Register matcher. */
 	matcher.crc = rte_raw_cksum((const void *)matcher.mask.buf,
 				    matcher.mask.size);
@@ -8146,20 +8147,22 @@ struct field_modify_info modify_tcp[] = {
 		} else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) {
 			struct mlx5_hrxq *hrxq;
 			uint32_t hrxq_idx;
+			struct mlx5_flow_rss_desc *rss_desc =
+				(struct mlx5_flow_rss_desc *)priv->rss_desc;
 
-			MLX5_ASSERT(flow->rss.queue);
-			hrxq_idx = mlx5_hrxq_get(dev, flow->rss.key,
+			MLX5_ASSERT(rss_desc->queue_num);
+			hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,
 						 MLX5_RSS_HASH_KEY_LEN,
 						 dev_flow->hash_fields,
-						 (*flow->rss.queue),
-						 flow->rss.queue_num);
+						 rss_desc->queue,
+						 rss_desc->queue_num);
 			if (!hrxq_idx) {
 				hrxq_idx = mlx5_hrxq_new
-						(dev, flow->rss.key,
+						(dev, rss_desc->key,
 						MLX5_RSS_HASH_KEY_LEN,
 						dev_flow->hash_fields,
-						(*flow->rss.queue),
-						flow->rss.queue_num,
+						rss_desc->queue,
+						rss_desc->queue_num,
 						!!(dh->layers &
 						MLX5_FLOW_LAYER_TUNNEL));
 			}
diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index f70b879..a246917 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -941,21 +941,19 @@
  * the input is valid and that there is space to insert the requested action
  * into the flow.
  *
- * @param[in] dev_flow
- *   Pointer to mlx5_flow.
+ * @param[in] rss_desc
+ *   Pointer to mlx5_flow_rss_desc.
  * @param[in] action
  *   Action configuration.
  */
 static void
-flow_verbs_translate_action_queue(struct mlx5_flow *dev_flow,
+flow_verbs_translate_action_queue(struct mlx5_flow_rss_desc *rss_desc,
 				  const struct rte_flow_action *action)
 {
 	const struct rte_flow_action_queue *queue = action->conf;
-	struct rte_flow *flow = dev_flow->flow;
 
-	if (flow->rss.queue)
-		(*flow->rss.queue)[0] = queue->index;
-	flow->rss.queue_num = 1;
+	rss_desc->queue[0] = queue->index;
+	rss_desc->queue_num = 1;
 }
 
 /**
@@ -963,28 +961,23 @@
  * the input is valid and that there is space to insert the requested action
  * into the flow.
  *
+ * @param[in] rss_desc
+ *   Pointer to mlx5_flow_rss_desc.
  * @param[in] action
  *   Action configuration.
- * @param[in, out] action_flags
- *   Pointer to the detected actions.
- * @param[in] dev_flow
- *   Pointer to mlx5_flow.
  */
 static void
-flow_verbs_translate_action_rss(struct mlx5_flow *dev_flow,
+flow_verbs_translate_action_rss(struct mlx5_flow_rss_desc *rss_desc,
 				const struct rte_flow_action *action)
 {
 	const struct rte_flow_action_rss *rss = action->conf;
 	const uint8_t *rss_key;
-	struct rte_flow *flow = dev_flow->flow;
 
-	if (flow->rss.queue)
-		memcpy((*flow->rss.queue), rss->queue,
-		       rss->queue_num * sizeof(uint16_t));
-	flow->rss.queue_num = rss->queue_num;
+	memcpy(rss_desc->queue, rss->queue, rss->queue_num * sizeof(uint16_t));
+	rss_desc->queue_num = rss->queue_num;
 	/* NULL RSS key indicates default RSS key. */
 	rss_key = !rss->key ? rss_hash_default_key : rss->key;
-	memcpy(flow->rss.key, rss_key, MLX5_RSS_HASH_KEY_LEN);
+	memcpy(rss_desc->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
 	/*
 	 * rss->level and rss.types should be set in advance when expanding
 	 * items for RSS.
@@ -1577,6 +1570,8 @@
 	uint64_t priority = attr->priority;
 	uint32_t subpriority = 0;
 	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_flow_rss_desc *rss_desc = (struct mlx5_flow_rss_desc *)
+					      priv->rss_desc;
 
 	if (priority == MLX5_FLOW_PRIO_RSVD)
 		priority = priv->config.flow_prio - 1;
@@ -1602,12 +1597,12 @@
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_DROP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_QUEUE:
-			flow_verbs_translate_action_queue(dev_flow, actions);
+			flow_verbs_translate_action_queue(rss_desc, actions);
 			action_flags |= MLX5_FLOW_ACTION_QUEUE;
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
 		case RTE_FLOW_ACTION_TYPE_RSS:
-			flow_verbs_translate_action_rss(dev_flow, actions);
+			flow_verbs_translate_action_rss(rss_desc, actions);
 			action_flags |= MLX5_FLOW_ACTION_RSS;
 			dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE;
 			break;
@@ -1655,7 +1650,7 @@
 			subpriority = MLX5_PRIORITY_MAP_L3;
 			dev_flow->hash_fields |=
 				mlx5_flow_hashfields_adjust
-					(dev_flow, tunnel,
+					(rss_desc, tunnel,
 					 MLX5_IPV4_LAYER_TYPES,
 					 MLX5_IPV4_IBV_RX_HASH);
 			item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 :
@@ -1667,7 +1662,7 @@
 			subpriority = MLX5_PRIORITY_MAP_L3;
 			dev_flow->hash_fields |=
 				mlx5_flow_hashfields_adjust
-					(dev_flow, tunnel,
+					(rss_desc, tunnel,
 					 MLX5_IPV6_LAYER_TYPES,
 					 MLX5_IPV6_IBV_RX_HASH);
 			item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 :
@@ -1679,7 +1674,7 @@
 			subpriority = MLX5_PRIORITY_MAP_L4;
 			dev_flow->hash_fields |=
 				mlx5_flow_hashfields_adjust
-					(dev_flow, tunnel, ETH_RSS_TCP,
+					(rss_desc, tunnel, ETH_RSS_TCP,
 					 (IBV_RX_HASH_SRC_PORT_TCP |
 					  IBV_RX_HASH_DST_PORT_TCP));
 			item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_TCP :
@@ -1691,7 +1686,7 @@
 			subpriority = MLX5_PRIORITY_MAP_L4;
 			dev_flow->hash_fields |=
 				mlx5_flow_hashfields_adjust
-					(dev_flow, tunnel, ETH_RSS_UDP,
+					(rss_desc, tunnel, ETH_RSS_UDP,
 					 (IBV_RX_HASH_SRC_PORT_UDP |
 					  IBV_RX_HASH_DST_PORT_UDP));
 			item_flags |= tunnel ? MLX5_FLOW_LAYER_INNER_L4_UDP :
@@ -1848,19 +1843,21 @@
 			}
 		} else {
 			uint32_t hrxq_idx;
+			struct mlx5_flow_rss_desc *rss_desc =
+				(struct mlx5_flow_rss_desc *)priv->rss_desc;
 
-			MLX5_ASSERT(flow->rss.queue);
-			hrxq_idx = mlx5_hrxq_get(dev, flow->rss.key,
+			MLX5_ASSERT(rss_desc->queue_num);
+			hrxq_idx = mlx5_hrxq_get(dev, rss_desc->key,
 					     MLX5_RSS_HASH_KEY_LEN,
 					     dev_flow->hash_fields,
-					     (*flow->rss.queue),
-					     flow->rss.queue_num);
+					     rss_desc->queue,
+					     rss_desc->queue_num);
 			if (!hrxq_idx)
-				hrxq_idx = mlx5_hrxq_new(dev, flow->rss.key,
+				hrxq_idx = mlx5_hrxq_new(dev, rss_desc->key,
 						MLX5_RSS_HASH_KEY_LEN,
 						dev_flow->hash_fields,
-						(*flow->rss.queue),
-						flow->rss.queue_num,
+						rss_desc->queue,
+						rss_desc->queue_num,
 						!!(handle->layers &
 						MLX5_FLOW_LAYER_TUNNEL));
 			hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 09/10] net/mlx5: allocate rte flow from indexed pool
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (7 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 08/10] net/mlx5: optimize mlx5 flow RSS struct Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 10/10] net/mlx5: reorganize rte flow structure Suanming Mou
  2020-04-16 17:08   ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize " Raslan Darawsheh
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

This commit allocates rte flow from indexed memory pool.

Allocate rte flow memory from indexed memory pool helps save more than
MALLOC_ELEM_OVERHEAD bytes memory from rte_malloc().

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5.c      |  13 ++-
 drivers/net/mlx5/mlx5.h      |  15 ++-
 drivers/net/mlx5/mlx5_flow.c | 234 ++++++++++++++++++++++++++-----------------
 drivers/net/mlx5/mlx5_flow.h |   6 +-
 4 files changed, 160 insertions(+), 108 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 1bb464d..9ab4b1f 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -300,6 +300,15 @@ struct mlx5_dev_spawn_data {
 		.free = rte_free,
 		.type = "mlx5_flow_handle_ipool",
 	},
+	{
+		.size = sizeof(struct rte_flow),
+		.trunk_size = 4096,
+		.need_lock = 1,
+		.release_mem_en = 1,
+		.malloc = rte_malloc_socket,
+		.free = rte_free,
+		.type = "rte_flow_ipool",
+	},
 };
 
 
@@ -2885,8 +2894,8 @@ struct mlx5_flow_id_pool *
 				      mlx5_ifindex(eth_dev),
 				      eth_dev->data->mac_addrs,
 				      MLX5_MAX_MAC_ADDRESSES);
-	TAILQ_INIT(&priv->flows);
-	TAILQ_INIT(&priv->ctrl_flows);
+	priv->flows = 0;
+	priv->ctrl_flows = 0;
 	TAILQ_INIT(&priv->flow_meters);
 	TAILQ_INIT(&priv->flow_meter_profiles);
 	/* Hint libmlx5 to use PMD allocator for data plane resources */
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 164ca3a..318618e 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -56,6 +56,7 @@ enum mlx5_ipool_index {
 	MLX5_IPOOL_MCP, /* Pool for metadata resource. */
 	MLX5_IPOOL_HRXQ, /* Pool for hrxq resource. */
 	MLX5_IPOOL_MLX5_FLOW, /* Pool for mlx5 flow handle. */
+	MLX5_IPOOL_RTE_FLOW, /* Pool for rte_flow. */
 	MLX5_IPOOL_MAX,
 };
 
@@ -109,9 +110,6 @@ struct mlx5_stats_ctrl {
 	uint64_t imissed;
 };
 
-/* Flow list . */
-TAILQ_HEAD(mlx5_flows, rte_flow);
-
 /* Default PMD specific parameter value. */
 #define MLX5_ARG_UNSET (-1)
 
@@ -512,8 +510,8 @@ struct mlx5_priv {
 	unsigned int (*reta_idx)[]; /* RETA index table. */
 	unsigned int reta_idx_n; /* RETA index size. */
 	struct mlx5_drop drop_queue; /* Flow drop queues. */
-	struct mlx5_flows flows; /* RTE Flow rules. */
-	struct mlx5_flows ctrl_flows; /* Control flow rules. */
+	uint32_t flows; /* RTE Flow rules. */
+	uint32_t ctrl_flows; /* Control flow rules. */
 	void *inter_flows; /* Intermediate resources for flow creation. */
 	void *rss_desc; /* Intermediate rss description resources. */
 	int flow_idx; /* Intermediate device flow index. */
@@ -715,8 +713,7 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *dev,
 				  struct rte_flow_error *error);
 int mlx5_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow,
 		      struct rte_flow_error *error);
-void mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list,
-			  bool active);
+void mlx5_flow_list_flush(struct rte_eth_dev *dev, uint32_t *list, bool active);
 int mlx5_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error);
 int mlx5_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
 		    const struct rte_flow_action *action, void *data,
@@ -727,8 +724,8 @@ int mlx5_dev_filter_ctrl(struct rte_eth_dev *dev,
 			 enum rte_filter_type filter_type,
 			 enum rte_filter_op filter_op,
 			 void *arg);
-int mlx5_flow_start(struct rte_eth_dev *dev, struct mlx5_flows *list);
-void mlx5_flow_stop(struct rte_eth_dev *dev, struct mlx5_flows *list);
+int mlx5_flow_start(struct rte_eth_dev *dev, uint32_t *list);
+void mlx5_flow_stop(struct rte_eth_dev *dev, uint32_t *list);
 int mlx5_flow_start_default(struct rte_eth_dev *dev);
 void mlx5_flow_stop_default(struct rte_eth_dev *dev);
 void mlx5_flow_alloc_intermediate(struct rte_eth_dev *dev);
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 4f74e6b..c529aa3 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -2906,16 +2906,16 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 }
 
 /* Declare flow create/destroy prototype in advance. */
-static struct rte_flow *
-flow_list_create(struct rte_eth_dev *dev, struct mlx5_flows *list,
+static uint32_t
+flow_list_create(struct rte_eth_dev *dev, uint32_t *list,
 		 const struct rte_flow_attr *attr,
 		 const struct rte_flow_item items[],
 		 const struct rte_flow_action actions[],
 		 bool external, struct rte_flow_error *error);
 
 static void
-flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list,
-		  struct rte_flow *flow);
+flow_list_destroy(struct rte_eth_dev *dev, uint32_t *list,
+		  uint32_t flow_idx);
 
 /**
  * Add a flow of copying flow metadata registers in RX_CP_TBL.
@@ -3052,9 +3052,9 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	 * be applied, removed, deleted in ardbitrary order
 	 * by list traversing.
 	 */
-	mcp_res->flow = flow_list_create(dev, NULL, &attr, items,
+	mcp_res->rix_flow = flow_list_create(dev, NULL, &attr, items,
 					 actions, false, error);
-	if (!mcp_res->flow)
+	if (!mcp_res->rix_flow)
 		goto error;
 	mcp_res->refcnt++;
 	mcp_res->hlist_ent.key = mark_id;
@@ -3065,8 +3065,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		goto error;
 	return mcp_res;
 error:
-	if (mcp_res->flow)
-		flow_list_destroy(dev, NULL, mcp_res->flow);
+	if (mcp_res->rix_flow)
+		flow_list_destroy(dev, NULL, mcp_res->rix_flow);
 	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
 	return NULL;
 }
@@ -3096,8 +3096,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 		MLX5_ASSERT(mcp_res->appcnt);
 		flow->copy_applied = 0;
 		--mcp_res->appcnt;
-		if (!mcp_res->appcnt)
-			flow_drv_remove(dev, mcp_res->flow);
+		if (!mcp_res->appcnt) {
+			struct rte_flow *mcp_flow = mlx5_ipool_get
+					(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW],
+					mcp_res->rix_flow);
+
+			if (mcp_flow)
+				flow_drv_remove(dev, mcp_flow);
+		}
 	}
 	/*
 	 * We do not check availability of metadata registers here,
@@ -3105,8 +3111,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	 */
 	if (--mcp_res->refcnt)
 		return;
-	MLX5_ASSERT(mcp_res->flow);
-	flow_list_destroy(dev, NULL, mcp_res->flow);
+	MLX5_ASSERT(mcp_res->rix_flow);
+	flow_list_destroy(dev, NULL, mcp_res->rix_flow);
 	mlx5_hlist_remove(priv->mreg_cp_tbl, &mcp_res->hlist_ent);
 	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
 	flow->rix_mreg_copy = 0;
@@ -3138,9 +3144,15 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	if (!mcp_res)
 		return 0;
 	if (!mcp_res->appcnt) {
-		ret = flow_drv_apply(dev, mcp_res->flow, NULL);
-		if (ret)
-			return ret;
+		struct rte_flow *mcp_flow = mlx5_ipool_get
+				(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW],
+				mcp_res->rix_flow);
+
+		if (mcp_flow) {
+			ret = flow_drv_apply(dev, mcp_flow, NULL);
+			if (ret)
+				return ret;
+		}
 	}
 	++mcp_res->appcnt;
 	flow->copy_applied = 1;
@@ -3171,8 +3183,14 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	MLX5_ASSERT(mcp_res->appcnt);
 	--mcp_res->appcnt;
 	flow->copy_applied = 0;
-	if (!mcp_res->appcnt)
-		flow_drv_remove(dev, mcp_res->flow);
+	if (!mcp_res->appcnt) {
+		struct rte_flow *mcp_flow = mlx5_ipool_get
+				(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW],
+				mcp_res->rix_flow);
+
+		if (mcp_flow)
+			flow_drv_remove(dev, mcp_flow);
+	}
 }
 
 /**
@@ -3194,8 +3212,8 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 					    MLX5_DEFAULT_COPY_ID);
 	if (!mcp_res)
 		return;
-	MLX5_ASSERT(mcp_res->flow);
-	flow_list_destroy(dev, NULL, mcp_res->flow);
+	MLX5_ASSERT(mcp_res->rix_flow);
+	flow_list_destroy(dev, NULL, mcp_res->rix_flow);
 	mlx5_hlist_remove(priv->mreg_cp_tbl, &mcp_res->hlist_ent);
 	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MCP], mcp_res->idx);
 }
@@ -4218,10 +4236,10 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
  *   Perform verbose error reporting if not NULL.
  *
  * @return
- *   A flow on success, NULL otherwise and rte_errno is set.
+ *   A flow index on success, 0 otherwise and rte_errno is set.
  */
-static struct rte_flow *
-flow_list_create(struct rte_eth_dev *dev, struct mlx5_flows *list,
+static uint32_t
+flow_list_create(struct rte_eth_dev *dev, uint32_t *list,
 		 const struct rte_flow_attr *attr,
 		 const struct rte_flow_item items[],
 		 const struct rte_flow_action actions[],
@@ -4251,6 +4269,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	struct mlx5_flow_rss_desc *rss_desc = priv->rss_desc;
 	const struct rte_flow_action *p_actions_rx = actions;
 	uint32_t i;
+	uint32_t idx = 0;
 	int hairpin_flow = 0;
 	uint32_t hairpin_id = 0;
 	struct rte_flow_attr attr_tx = { .priority = 0 };
@@ -4258,19 +4277,19 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 				    error);
 
 	if (ret < 0)
-		return NULL;
+		return 0;
 	hairpin_flow = flow_check_hairpin_split(dev, attr, actions);
 	if (hairpin_flow > 0) {
 		if (hairpin_flow > MLX5_MAX_SPLIT_ACTIONS) {
 			rte_errno = EINVAL;
-			return NULL;
+			return 0;
 		}
 		flow_hairpin_split(dev, actions, actions_rx.actions,
 				   actions_hairpin_tx.actions, items_tx.items,
 				   &hairpin_id);
 		p_actions_rx = actions_rx.actions;
 	}
-	flow = rte_calloc(__func__, 1, sizeof(struct rte_flow), 0);
+	flow = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], &idx);
 	if (!flow) {
 		rte_errno = ENOMEM;
 		goto error_before_flow;
@@ -4373,19 +4392,20 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 			goto error;
 	}
 	if (list)
-		TAILQ_INSERT_TAIL(list, flow, next);
+		ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], list, idx,
+			     flow, next);
 	flow_rxq_flags_set(dev, flow);
 	/* Nested flow creation index recovery. */
 	priv->flow_idx = priv->flow_nested_idx;
 	if (priv->flow_nested_idx)
 		priv->flow_nested_idx = 0;
-	return flow;
+	return idx;
 error:
 	MLX5_ASSERT(flow);
 	ret = rte_errno; /* Save rte_errno before cleanup. */
 	flow_mreg_del_copy_action(dev, flow);
 	flow_drv_destroy(dev, flow);
-	rte_free(flow);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], idx);
 	rte_errno = ret; /* Restore rte_errno. */
 error_before_flow:
 	ret = rte_errno;
@@ -4396,7 +4416,7 @@ uint32_t mlx5_flow_adjust_priority(struct rte_eth_dev *dev, int32_t priority,
 	priv->flow_idx = priv->flow_nested_idx;
 	if (priv->flow_nested_idx)
 		priv->flow_nested_idx = 0;
-	return NULL;
+	return 0;
 }
 
 /**
@@ -4444,8 +4464,9 @@ struct rte_flow *
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct rte_flow_error error;
 
-	return flow_list_create(dev, &priv->ctrl_flows, &attr, &pattern,
-				actions, false, &error);
+	return (void *)(uintptr_t)flow_list_create(dev, &priv->ctrl_flows,
+						   &attr, &pattern,
+						   actions, false, &error);
 }
 
 /**
@@ -4474,8 +4495,8 @@ struct rte_flow *
 			"inserting a flow", dev->data->port_id);
 		return NULL;
 	}
-	return flow_list_create(dev, &priv->flows,
-				attr, items, actions, true, error);
+	return (void *)(uintptr_t)flow_list_create(dev, &priv->flows,
+				  attr, items, actions, true, error);
 }
 
 /**
@@ -4484,18 +4505,24 @@ struct rte_flow *
  * @param dev
  *   Pointer to Ethernet device.
  * @param list
- *   Pointer to a TAILQ flow list. If this parameter NULL,
- *   there is no flow removal from the list.
- * @param[in] flow
- *   Flow to destroy.
+ *   Pointer to the Indexed flow list. If this parameter NULL,
+ *   there is no flow removal from the list. Be noted that as
+ *   flow is add to the indexed list, memory of the indexed
+ *   list points to maybe changed as flow destroyed.
+ * @param[in] flow_idx
+ *   Index of flow to destroy.
  */
 static void
-flow_list_destroy(struct rte_eth_dev *dev, struct mlx5_flows *list,
-		  struct rte_flow *flow)
+flow_list_destroy(struct rte_eth_dev *dev, uint32_t *list,
+		  uint32_t flow_idx)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
+	struct rte_flow *flow = mlx5_ipool_get(priv->sh->ipool
+					       [MLX5_IPOOL_RTE_FLOW], flow_idx);
 
+	if (!flow)
+		return;
 	/*
 	 * Update RX queue flags only if port is started, otherwise it is
 	 * already clean.
@@ -4507,11 +4534,12 @@ struct rte_flow *
 				     flow->hairpin_flow_id);
 	flow_drv_destroy(dev, flow);
 	if (list)
-		TAILQ_REMOVE(list, flow, next);
+		ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], list,
+			     flow_idx, flow, next);
 	flow_mreg_del_copy_action(dev, flow);
 	if (flow->fdir) {
 		LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
-			if (priv_fdir_flow->flow == flow)
+			if (priv_fdir_flow->rix_flow == flow_idx)
 				break;
 		}
 		if (priv_fdir_flow) {
@@ -4520,7 +4548,7 @@ struct rte_flow *
 			rte_free(priv_fdir_flow);
 		}
 	}
-	rte_free(flow);
+	mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], flow_idx);
 }
 
 /**
@@ -4529,21 +4557,17 @@ struct rte_flow *
  * @param dev
  *   Pointer to Ethernet device.
  * @param list
- *   Pointer to a TAILQ flow list.
+ *   Pointer to the Indexed flow list.
  * @param active
  *   If flushing is called avtively.
  */
 void
-mlx5_flow_list_flush(struct rte_eth_dev *dev, struct mlx5_flows *list,
-		     bool active)
+mlx5_flow_list_flush(struct rte_eth_dev *dev, uint32_t *list, bool active)
 {
 	uint32_t num_flushed = 0;
 
-	while (!TAILQ_EMPTY(list)) {
-		struct rte_flow *flow;
-
-		flow = TAILQ_FIRST(list);
-		flow_list_destroy(dev, list, flow);
+	while (*list) {
+		flow_list_destroy(dev, list, *list);
 		num_flushed++;
 	}
 	if (active) {
@@ -4558,14 +4582,17 @@ struct rte_flow *
  * @param dev
  *   Pointer to Ethernet device.
  * @param list
- *   Pointer to a TAILQ flow list.
+ *   Pointer to the Indexed flow list.
  */
 void
-mlx5_flow_stop(struct rte_eth_dev *dev, struct mlx5_flows *list)
+mlx5_flow_stop(struct rte_eth_dev *dev, uint32_t *list)
 {
-	struct rte_flow *flow;
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct rte_flow *flow = NULL;
+	uint32_t idx;
 
-	TAILQ_FOREACH_REVERSE(flow, list, mlx5_flows, next) {
+	ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], *list, idx,
+		      flow, next) {
 		flow_drv_remove(dev, flow);
 		flow_mreg_stop_copy_action(dev, flow);
 	}
@@ -4579,16 +4606,18 @@ struct rte_flow *
  * @param dev
  *   Pointer to Ethernet device.
  * @param list
- *   Pointer to a TAILQ flow list.
+ *   Pointer to the Indexed flow list.
  *
  * @return
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_flow_start(struct rte_eth_dev *dev, struct mlx5_flows *list)
+mlx5_flow_start(struct rte_eth_dev *dev, uint32_t *list)
 {
-	struct rte_flow *flow;
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct rte_flow *flow = NULL;
 	struct rte_flow_error error;
+	uint32_t idx;
 	int ret = 0;
 
 	/* Make sure default copy action (reg_c[0] -> reg_b) is created. */
@@ -4596,7 +4625,8 @@ struct rte_flow *
 	if (ret < 0)
 		return -rte_errno;
 	/* Apply Flows created by application. */
-	TAILQ_FOREACH(flow, list, next) {
+	ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], *list, idx,
+		      flow, next) {
 		ret = flow_mreg_start_copy_action(dev, flow);
 		if (ret < 0)
 			goto error;
@@ -4698,9 +4728,11 @@ struct rte_flow *
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 	struct rte_flow *flow;
+	uint32_t idx;
 	int ret = 0;
 
-	TAILQ_FOREACH(flow, &priv->flows, next) {
+	ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], priv->flows, idx,
+		      flow, next) {
 		DRV_LOG(DEBUG, "port %u flow %p still referenced",
 			dev->data->port_id, (void *)flow);
 		++ret;
@@ -4749,15 +4781,15 @@ struct rte_flow *
 		.group = MLX5_HAIRPIN_TX_TABLE,
 	};
 	struct rte_flow_action actions[2];
-	struct rte_flow *flow;
+	uint32_t flow_idx;
 	struct rte_flow_error error;
 
 	actions[0].type = RTE_FLOW_ACTION_TYPE_JUMP;
 	actions[0].conf = &jump;
 	actions[1].type = RTE_FLOW_ACTION_TYPE_END;
-	flow = flow_list_create(dev, &priv->ctrl_flows,
+	flow_idx = flow_list_create(dev, &priv->ctrl_flows,
 				&attr, items, actions, false, &error);
-	if (!flow) {
+	if (!flow_idx) {
 		DRV_LOG(DEBUG,
 			"Failed to create ctrl flow: rte_errno(%d),"
 			" type(%d), message(%s)",
@@ -4834,7 +4866,7 @@ struct rte_flow *
 			.type = RTE_FLOW_ACTION_TYPE_END,
 		},
 	};
-	struct rte_flow *flow;
+	uint32_t flow_idx;
 	struct rte_flow_error error;
 	unsigned int i;
 
@@ -4843,9 +4875,9 @@ struct rte_flow *
 	}
 	for (i = 0; i != priv->reta_idx_n; ++i)
 		queue[i] = (*priv->reta_idx)[i];
-	flow = flow_list_create(dev, &priv->ctrl_flows,
+	flow_idx = flow_list_create(dev, &priv->ctrl_flows,
 				&attr, items, actions, false, &error);
-	if (!flow)
+	if (!flow_idx)
 		return -rte_errno;
 	return 0;
 }
@@ -4884,7 +4916,7 @@ struct rte_flow *
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
 
-	flow_list_destroy(dev, &priv->flows, flow);
+	flow_list_destroy(dev, &priv->flows, (uintptr_t)(void *)flow);
 	return 0;
 }
 
@@ -4940,14 +4972,25 @@ struct rte_flow *
  */
 static int
 flow_drv_query(struct rte_eth_dev *dev,
-	       struct rte_flow *flow,
+	       uint32_t flow_idx,
 	       const struct rte_flow_action *actions,
 	       void *data,
 	       struct rte_flow_error *error)
 {
+	struct mlx5_priv *priv = dev->data->dev_private;
 	const struct mlx5_flow_driver_ops *fops;
-	enum mlx5_flow_drv_type ftype = flow->drv_type;
+	struct rte_flow *flow = mlx5_ipool_get(priv->sh->ipool
+					       [MLX5_IPOOL_RTE_FLOW],
+					       flow_idx);
+	enum mlx5_flow_drv_type ftype;
 
+	if (!flow) {
+		return rte_flow_error_set(error, ENOENT,
+			  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			  NULL,
+			  "invalid flow handle");
+	}
+	ftype = flow->drv_type;
 	MLX5_ASSERT(ftype > MLX5_FLOW_TYPE_MIN && ftype < MLX5_FLOW_TYPE_MAX);
 	fops = flow_get_drv_ops(ftype);
 
@@ -4969,7 +5012,8 @@ struct rte_flow *
 {
 	int ret;
 
-	ret = flow_drv_query(dev, flow, actions, data, error);
+	ret = flow_drv_query(dev, (uintptr_t)(void *)flow, actions, data,
+			     error);
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -5205,25 +5249,25 @@ struct rte_flow *
  *   FDIR flow to lookup.
  *
  * @return
- *   Pointer of flow if found, NULL otherwise.
+ *   Index of flow if found, 0 otherwise.
  */
-static struct rte_flow *
+static uint32_t
 flow_fdir_filter_lookup(struct rte_eth_dev *dev, struct mlx5_fdir *fdir_flow)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	struct rte_flow *flow = NULL;
+	uint32_t flow_idx = 0;
 	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
 
 	MLX5_ASSERT(fdir_flow);
 	LIST_FOREACH(priv_fdir_flow, &priv->fdir_flows, next) {
 		if (!flow_fdir_cmp(priv_fdir_flow->fdir, fdir_flow)) {
-			DRV_LOG(DEBUG, "port %u found FDIR flow %p",
-				dev->data->port_id, (void *)flow);
-			flow = priv_fdir_flow->flow;
+			DRV_LOG(DEBUG, "port %u found FDIR flow %u",
+				dev->data->port_id, flow_idx);
+			flow_idx = priv_fdir_flow->rix_flow;
 			break;
 		}
 	}
-	return flow;
+	return flow_idx;
 }
 
 /**
@@ -5245,6 +5289,7 @@ struct rte_flow *
 	struct mlx5_fdir *fdir_flow;
 	struct rte_flow *flow;
 	struct mlx5_fdir_flow *priv_fdir_flow = NULL;
+	uint32_t flow_idx;
 	int ret;
 
 	fdir_flow = rte_zmalloc(__func__, sizeof(*fdir_flow), 0);
@@ -5255,8 +5300,8 @@ struct rte_flow *
 	ret = flow_fdir_filter_convert(dev, fdir_filter, fdir_flow);
 	if (ret)
 		goto error;
-	flow = flow_fdir_filter_lookup(dev, fdir_flow);
-	if (flow) {
+	flow_idx = flow_fdir_filter_lookup(dev, fdir_flow);
+	if (flow_idx) {
 		rte_errno = EEXIST;
 		goto error;
 	}
@@ -5266,14 +5311,15 @@ struct rte_flow *
 		rte_errno = ENOMEM;
 		goto error;
 	}
-	flow = flow_list_create(dev, &priv->flows, &fdir_flow->attr,
-				fdir_flow->items, fdir_flow->actions, true,
-				NULL);
+	flow_idx = flow_list_create(dev, &priv->flows, &fdir_flow->attr,
+				    fdir_flow->items, fdir_flow->actions, true,
+				    NULL);
+	flow = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW], flow_idx);
 	if (!flow)
 		goto error;
 	flow->fdir = 1;
 	priv_fdir_flow->fdir = fdir_flow;
-	priv_fdir_flow->flow = flow;
+	priv_fdir_flow->rix_flow = flow_idx;
 	LIST_INSERT_HEAD(&priv->fdir_flows, priv_fdir_flow, next);
 	DRV_LOG(DEBUG, "port %u created FDIR flow %p",
 		dev->data->port_id, (void *)flow);
@@ -5300,7 +5346,7 @@ struct rte_flow *
 			const struct rte_eth_fdir_filter *fdir_filter)
 {
 	struct mlx5_priv *priv = dev->data->dev_private;
-	struct rte_flow *flow;
+	uint32_t flow_idx;
 	struct mlx5_fdir fdir_flow = {
 		.attr.group = 0,
 	};
@@ -5318,14 +5364,12 @@ struct rte_flow *
 	if (!priv_fdir_flow)
 		return 0;
 	LIST_REMOVE(priv_fdir_flow, next);
-	flow = priv_fdir_flow->flow;
-	/* Fdir resource will be releasd after flow destroy. */
-	flow->fdir = 0;
-	flow_list_destroy(dev, &priv->flows, flow);
+	flow_idx = priv_fdir_flow->rix_flow;
+	flow_list_destroy(dev, &priv->flows, flow_idx);
 	rte_free(priv_fdir_flow->fdir);
 	rte_free(priv_fdir_flow);
-	DRV_LOG(DEBUG, "port %u deleted FDIR flow %p",
-		dev->data->port_id, (void *)flow);
+	DRV_LOG(DEBUG, "port %u deleted FDIR flow %u",
+		dev->data->port_id, flow_idx);
 	return 0;
 }
 
@@ -5367,8 +5411,7 @@ struct rte_flow *
 	while (!LIST_EMPTY(&priv->fdir_flows)) {
 		priv_fdir_flow = LIST_FIRST(&priv->fdir_flows);
 		LIST_REMOVE(priv_fdir_flow, next);
-		priv_fdir_flow->flow->fdir = 0;
-		flow_list_destroy(dev, &priv->flows, priv_fdir_flow->flow);
+		flow_list_destroy(dev, &priv->flows, priv_fdir_flow->rix_flow);
 		rte_free(priv_fdir_flow->fdir);
 		rte_free(priv_fdir_flow);
 	}
@@ -5910,19 +5953,22 @@ struct mlx5_meter_domains_infos *
 				.type = RTE_FLOW_ACTION_TYPE_END,
 			},
 		};
+		uint32_t flow_idx;
 		struct rte_flow *flow;
 		struct rte_flow_error error;
 
 		if (!config->dv_flow_en)
 			break;
 		/* Create internal flow, validation skips copy action. */
-		flow = flow_list_create(dev, NULL, &attr, items,
-					actions, false, &error);
+		flow_idx = flow_list_create(dev, NULL, &attr, items,
+					    actions, false, &error);
+		flow = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RTE_FLOW],
+				      flow_idx);
 		if (!flow)
 			continue;
 		if (dev->data->dev_started || !flow_drv_apply(dev, flow, NULL))
 			config->flow_mreg_c[n++] = idx;
-		flow_list_destroy(dev, NULL, flow);
+		flow_list_destroy(dev, NULL, flow_idx);
 	}
 	for (; n < MLX5_MREG_C_NUM; ++n)
 		config->flow_mreg_c[n] = REG_NONE;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 759b0ce..35570a9 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -461,7 +461,7 @@ struct mlx5_flow_mreg_copy_resource {
 	uint32_t refcnt; /* Reference counter. */
 	uint32_t appcnt; /* Apply/Remove counter. */
 	uint32_t idx;
-	struct rte_flow *flow; /* Built flow for copy. */
+	uint32_t rix_flow; /* Built flow for copy. */
 };
 
 /* Table data structure of the hash organization. */
@@ -757,12 +757,12 @@ struct mlx5_flow_meter_profile {
 struct mlx5_fdir_flow {
 	LIST_ENTRY(mlx5_fdir_flow) next; /* Pointer to the next element. */
 	struct mlx5_fdir *fdir; /* Pointer to fdir. */
-	struct rte_flow *flow; /* Pointer to flow. */
+	uint32_t rix_flow; /* Index to flow. */
 };
 
 /* Flow structure. */
 struct rte_flow {
-	TAILQ_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
+	ILIST_ENTRY(uint32_t)next; /**< Index to the next flow structure. */
 	enum mlx5_flow_drv_type drv_type; /**< Driver type. */
 	uint32_t counter; /**< Holds flow counter. */
 	uint32_t rix_mreg_copy;
-- 
1.8.3.1


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

* [dpdk-dev] [PATCH v2 10/10] net/mlx5: reorganize rte flow structure
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (8 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 09/10] net/mlx5: allocate rte flow from indexed pool Suanming Mou
@ 2020-04-16  8:34   ` Suanming Mou
  2020-04-16 17:08   ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize " Raslan Darawsheh
  10 siblings, 0 replies; 12+ messages in thread
From: Suanming Mou @ 2020-04-16  8:34 UTC (permalink / raw)
  To: viacheslavo, matan; +Cc: orika, wentaoc, rasland, dev

Currently, the rte flow structure is not fully aligned and has some
bits wasted. The members can be optimized and reorganized to save
memory.

1. The drv_type uses only limited bits, change the type to 2 bits what
it needs.

2. Align the hairpin_flow_id, drv_type, fdir, copy_applied to 32 bits.
As hairpin never uses the full 32 bits.

3. __rte_packed helps tight up the structure memory layout.

The optimization totally helps save 14 bytes for the structure.

Signed-off-by: Suanming Mou <suanmingm@mellanox.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@mellanox.com>
---
 drivers/net/mlx5/mlx5.c      |  3 ++-
 drivers/net/mlx5/mlx5_flow.h | 17 ++++++++++-------
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 9ab4b1f..a83791c 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -764,7 +764,8 @@ struct mlx5_flow_id_pool *
 			goto error;
 		}
 	}
-	sh->flow_id_pool = mlx5_flow_id_pool_alloc(UINT32_MAX);
+	sh->flow_id_pool = mlx5_flow_id_pool_alloc
+					((1 << HAIRPIN_FLOW_ID_BITS) - 1);
 	if (!sh->flow_id_pool) {
 		DRV_LOG(ERR, "can't create flow id pool");
 		err = ENOMEM;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 35570a9..d697eba 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -760,20 +760,23 @@ struct mlx5_fdir_flow {
 	uint32_t rix_flow; /* Index to flow. */
 };
 
+#define HAIRPIN_FLOW_ID_BITS 28
+
 /* Flow structure. */
 struct rte_flow {
 	ILIST_ENTRY(uint32_t)next; /**< Index to the next flow structure. */
-	enum mlx5_flow_drv_type drv_type; /**< Driver type. */
-	uint32_t counter; /**< Holds flow counter. */
-	uint32_t rix_mreg_copy;
-	/**< Index to metadata register copy table resource. */
-	uint16_t meter; /**< Holds flow meter id. */
 	uint32_t dev_handles;
 	/**< Device flow handles that are part of the flow. */
+	uint32_t drv_type:2; /**< Driver type. */
 	uint32_t fdir:1; /**< Identifier of associated FDIR if any. */
-	uint32_t hairpin_flow_id; /**< The flow id used for hairpin. */
+	uint32_t hairpin_flow_id:HAIRPIN_FLOW_ID_BITS;
+	/**< The flow id used for hairpin. */
 	uint32_t copy_applied:1; /**< The MARK copy Flow os applied. */
-};
+	uint32_t rix_mreg_copy;
+	/**< Index to metadata register copy table resource. */
+	uint32_t counter; /**< Holds flow counter. */
+	uint16_t meter; /**< Holds flow meter id. */
+} __rte_packed;
 
 typedef int (*mlx5_flow_validate_t)(struct rte_eth_dev *dev,
 				    const struct rte_flow_attr *attr,
-- 
1.8.3.1


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

* Re: [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure
  2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
                     ` (9 preceding siblings ...)
  2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 10/10] net/mlx5: reorganize rte flow structure Suanming Mou
@ 2020-04-16 17:08   ` Raslan Darawsheh
  10 siblings, 0 replies; 12+ messages in thread
From: Raslan Darawsheh @ 2020-04-16 17:08 UTC (permalink / raw)
  To: Suanming Mou, Slava Ovsiienko, Matan Azrad; +Cc: Ori Kam, Wentao Cui, dev

Hi,

> -----Original Message-----
> From: Suanming Mou <suanmingm@mellanox.com>
> Sent: Thursday, April 16, 2020 11:34 AM
> To: Slava Ovsiienko <viacheslavo@mellanox.com>; Matan Azrad
> <matan@mellanox.com>
> Cc: Ori Kam <orika@mellanox.com>; Wentao Cui <wentaoc@mellanox.com>;
> Raslan Darawsheh <rasland@mellanox.com>; dev@dpdk.org
> Subject: [PATCH v2 00/10] net/mlx5: optimize flow structure
> 
> This patch set is third part of the flow memory consumption optimization.
> It mainly optimizes the rte flow and mlx5 flow handle structure.
> 
> For mlx5 flow handle structure:
> 1. As one flow has only one fate action, the fate actions are reorganized
> as union.
> 2. The action flags are optimized to be the limited bits the flow needs.
> 3. The bits members are reorganized to align with bytes.
> 
> For rte flow structure:
> 1. Meter handle is converted to uint32_t type as unique meter id.
> 2. Fdir handle is converted to one bit to save the pointer to another list.
> 3. Metadata handle is converted to uint32_t type as indexed.
> 4. Remove the duplicated RSS member in rte flow.
> 5. The bit members are reorganized to align with bytes.
> 
> Some extra optimizations:
> 1. Allocate meter resource from indexed memory pool.
> 2. Allocate rte flow from indexed memory pool.
> 3. Split RSS type, level, key to common memory as they are not required
> for the flow destroy.
> 
> This patch set should be applied after the patch series as below:
> https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatch
> es.dpdk.org%2Fcover%2F68591%2F&amp;data=02%7C01%7Crasland%40mell
> anox.com%7C48b4af5f669f4b82e2ea08d7e1e10031%7Ca652971c7d2e4d9ba6
> a4d149256f461b%7C0%7C0%7C637226228837328616&amp;sdata=tsWnTFMrX
> tokGwo1usxzLbZ5HGV5OGxkCp9pMZ8Rocs%3D&amp;reserved=0
> 
> v2:
>  - Add unified routine for fate actions release.
>  - Rmove RSS totally from rte flow.
>  - Allocate rte flow totally from indexed memory pool.
> 
> Suanming Mou (9):
>   net/mlx5: reorganize fate actions as union
>   net/mlx5: optimize action flags in flow handle
>   net/mlx5: reorganize the mlx5 flow handle struct
>   net/mlx5: optimize flow meter handle type
>   net/mlx5: allocate meter from indexed pool
>   net/mlx5: convert mark copy resource to indexed
>   net/mlx5: optimize mlx5 flow RSS struct
>   net/mlx5: allocate rte flow from indexed pool
>   net/mlx5: reorganize rte flow structure
> 
> Wentao Cui (1):
>   net/mlx5: optimize flow director filter memory
> 
>  drivers/net/mlx5/mlx5.c            |  38 +++-
>  drivers/net/mlx5/mlx5.h            |  19 +-
>  drivers/net/mlx5/mlx5_flow.c       | 406 +++++++++++++++++++++++--------
> ------
>  drivers/net/mlx5/mlx5_flow.h       |  89 +++++---
>  drivers/net/mlx5/mlx5_flow_dv.c    | 214 +++++++++++--------
>  drivers/net/mlx5/mlx5_flow_meter.c |  11 +-
>  drivers/net/mlx5/mlx5_flow_verbs.c |  98 +++++----
>  7 files changed, 554 insertions(+), 321 deletions(-)
> 
> --
> 1.8.3.1

Series applied to next-net-mlx,

Kindest regards,
Raslan Darawsheh

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

end of thread, other threads:[~2020-04-16 17:08 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <https://patches.dpdk.org/cover/68470/>
2020-04-16  8:34 ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize flow structure Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 01/10] net/mlx5: reorganize fate actions as union Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 02/10] net/mlx5: optimize action flags in flow handle Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 03/10] net/mlx5: reorganize the mlx5 flow handle struct Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 04/10] net/mlx5: optimize flow meter handle type Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 05/10] net/mlx5: allocate meter from indexed pool Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 06/10] net/mlx5: convert mark copy resource to indexed Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 07/10] net/mlx5: optimize flow director filter memory Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 08/10] net/mlx5: optimize mlx5 flow RSS struct Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 09/10] net/mlx5: allocate rte flow from indexed pool Suanming Mou
2020-04-16  8:34   ` [dpdk-dev] [PATCH v2 10/10] net/mlx5: reorganize rte flow structure Suanming Mou
2020-04-16 17:08   ` [dpdk-dev] [PATCH v2 00/10] net/mlx5: optimize " Raslan Darawsheh

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).