All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] net/mlx5: enhance flow API
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-03 23:36   ` Ferruh Yigit
  2017-03-04 12:42   ` Ferruh Yigit
  2017-03-01 12:49 ` [PATCH v2 1/9] net/mlx5: fix drop queue creation error Nelio Laranjeiro
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

Changes in v2:

 - Send series to dev@dpdk.org

This series brings:

 - fixes:
   - handle error on Queue Pair creation.
   - Move a free to the right function.
   - Uses a single RSS drop queue for dropping flows.
 - Enhance IPv6 filtering by adding extra fields.
 - support rss hash result in combination of mark id.
 - support flag action.
 - support RSS action.


Nelio Laranjeiro (9):
  net/mlx5: fix drop queue creation error
  net/mlx5: fix resources free in the right function
  net/mlx5: support ether type support in flow item
  net/mlx5: add RSS hash result with mark id
  net/mlx5: extend IPv6 flow item
  net/mlx5: support flag flow action
  net/mlx5: prepare support for RSS action rule
  net/mlx5: support RSS action flow rule
  net/mlx5: use an RSS drop queue

 drivers/net/mlx5/mlx5.h      |   1 +
 drivers/net/mlx5/mlx5_flow.c | 439 ++++++++++++++++++++++++++++++++++++-------
 drivers/net/mlx5/mlx5_prm.h  |   7 +-
 drivers/net/mlx5/mlx5_rxtx.c |  20 +-
 4 files changed, 386 insertions(+), 81 deletions(-)

-- 
2.1.4

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

* [PATCH v2 1/9] net/mlx5: fix drop queue creation error
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
  2017-03-01 12:49 ` [PATCH v2 0/9] net/mlx5: enhance flow API Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 2/9] net/mlx5: fix resources free in the right function Nelio Laranjeiro
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil, stable

Creating a drop queue in mlx5 ends by creating a non polled queue, but if
the associated work queue could not be created the error was not handled
ending in a undefined situation.

Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions")

CC: stable@dpdk.org
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 23c1b5e..6765a77 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -902,6 +902,12 @@ priv_flow_create_action_queue(struct priv *priv,
 						 .pd = priv->pd,
 						 .cq = rte_flow->cq,
 						 });
+		if (!rte_flow->wq) {
+			rte_flow_error_set(error, ENOMEM,
+					   RTE_FLOW_ERROR_TYPE_HANDLE,
+					   NULL, "cannot allocate WQ");
+			goto error;
+		}
 	} else {
 		rxq = container_of((*priv->rxqs)[action->queue_id],
 				   struct rxq_ctrl, rxq);
-- 
2.1.4

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

* [PATCH v2 2/9] net/mlx5: fix resources free in the right function
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
  2017-03-01 12:49 ` [PATCH v2 0/9] net/mlx5: enhance flow API Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 1/9] net/mlx5: fix drop queue creation error Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 3/9] net/mlx5: support ether type support in flow item Nelio Laranjeiro
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil, stable

ibv_attr should be freed in the function which allocates the memory.

Fixes: 2097d0d1e2cc ("net/mlx5: support basic flow items and actions")

CC: stable@dpdk.org
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 6765a77..0712926 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -974,7 +974,6 @@ priv_flow_create_action_queue(struct priv *priv,
 		ibv_exp_destroy_wq(rte_flow->wq);
 	if (!rte_flow->rxq && rte_flow->cq)
 		ibv_destroy_cq(rte_flow->cq);
-	rte_free(rte_flow->ibv_attr);
 	rte_free(rte_flow);
 	return NULL;
 }
@@ -1068,6 +1067,8 @@ priv_flow_create(struct priv *priv,
 	}
 	rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr,
 						 &action, error);
+	if (!rte_flow)
+		goto exit;
 	return rte_flow;
 exit:
 	rte_free(flow.ibv_attr);
-- 
2.1.4

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

* [PATCH v2 3/9] net/mlx5: support ether type support in flow item
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (2 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 2/9] net/mlx5: fix resources free in the right function Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 4/9] net/mlx5: add RSS hash result with mark id Nelio Laranjeiro
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 0712926..d3c0661 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -163,6 +163,7 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
 		.mask = &(const struct rte_flow_item_eth){
 			.dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
 			.src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+			.type = -1,
 		},
 		.default_mask = &rte_flow_item_eth_mask,
 		.mask_sz = sizeof(struct rte_flow_item_eth),
@@ -552,13 +553,16 @@ mlx5_flow_create_eth(const struct rte_flow_item *item,
 		mask = default_mask;
 	memcpy(eth->val.dst_mac, spec->dst.addr_bytes, ETHER_ADDR_LEN);
 	memcpy(eth->val.src_mac, spec->src.addr_bytes, ETHER_ADDR_LEN);
+	eth->val.ether_type = spec->type;
 	memcpy(eth->mask.dst_mac, mask->dst.addr_bytes, ETHER_ADDR_LEN);
 	memcpy(eth->mask.src_mac, mask->src.addr_bytes, ETHER_ADDR_LEN);
+	eth->mask.ether_type = mask->type;
 	/* Remove unwanted bits from values. */
 	for (i = 0; i < ETHER_ADDR_LEN; ++i) {
 		eth->val.dst_mac[i] &= eth->mask.dst_mac[i];
 		eth->val.src_mac[i] &= eth->mask.src_mac[i];
 	}
+	eth->val.ether_type &= eth->mask.ether_type;
 	return 0;
 }
 
-- 
2.1.4

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

* [PATCH v2 4/9] net/mlx5: add RSS hash result with mark id
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (3 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 3/9] net/mlx5: support ether type support in flow item Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 5/9] net/mlx5: extend IPv6 flow item Nelio Laranjeiro
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

RSS hash and mark ID can now coexists.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_rxtx.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 8f16f2f..122847d 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -1545,7 +1545,6 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 			      htonl(MLX5_FLOW_MARK_DEFAULT)))) {
 				pkt->hash.fdir.hi =
 					mlx5_flow_mark_get(cqe->sop_drop_qpn);
-				pkt->ol_flags &= ~PKT_RX_RSS_HASH;
 				pkt->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
 			}
 			if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip |
-- 
2.1.4

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

* [PATCH v2 5/9] net/mlx5: extend IPv6 flow item
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (4 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 4/9] net/mlx5: add RSS hash result with mark id Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 6/9] net/mlx5: support flag flow action Nelio Laranjeiro
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

This commit adds:
 - Vtc flow,
 - Protocol,
 - Hop limits

Needs MLNX_OFED-4.0-0.0.7.0 or higher.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index d3c0661..a885f6e 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -217,12 +217,15 @@ static const struct mlx5_flow_items mlx5_flow_items[] = {
 					0xff, 0xff, 0xff, 0xff,
 					0xff, 0xff, 0xff, 0xff,
 				},
+				.vtc_flow = -1,
+				.proto = -1,
+				.hop_limits = -1,
 			},
 		},
 		.default_mask = &rte_flow_item_ipv6_mask,
 		.mask_sz = sizeof(struct rte_flow_item_ipv6),
 		.convert = mlx5_flow_create_ipv6,
-		.dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6),
+		.dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6_ext),
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
 		.items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN),
@@ -668,15 +671,14 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item,
 	const struct rte_flow_item_ipv6 *spec = item->spec;
 	const struct rte_flow_item_ipv6 *mask = item->mask;
 	struct mlx5_flow *flow = (struct mlx5_flow *)data;
-	struct ibv_exp_flow_spec_ipv6 *ipv6;
-	unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6);
-	unsigned int i;
+	struct ibv_exp_flow_spec_ipv6_ext *ipv6;
+	unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6_ext);
 
 	++flow->ibv_attr->num_of_specs;
 	flow->ibv_attr->priority = 1;
 	ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
-	*ipv6 = (struct ibv_exp_flow_spec_ipv6) {
-		.type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6,
+	*ipv6 = (struct ibv_exp_flow_spec_ipv6_ext) {
+		.type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6_EXT,
 		.size = ipv6_size,
 	};
 	if (!spec)
@@ -691,11 +693,12 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item,
 	       RTE_DIM(ipv6->mask.src_ip));
 	memcpy(ipv6->mask.dst_ip, mask->hdr.dst_addr,
 	       RTE_DIM(ipv6->mask.dst_ip));
-	/* Remove unwanted bits from values. */
-	for (i = 0; i < RTE_DIM(ipv6->val.src_ip); ++i) {
-		ipv6->val.src_ip[i] &= ipv6->mask.src_ip[i];
-		ipv6->val.dst_ip[i] &= ipv6->mask.dst_ip[i];
-	}
+	ipv6->mask.flow_label = mask->hdr.vtc_flow;
+	ipv6->mask.next_hdr = mask->hdr.proto;
+	ipv6->mask.hop_limit = mask->hdr.hop_limits;
+	ipv6->val.flow_label &= ipv6->mask.flow_label;
+	ipv6->val.next_hdr &= ipv6->mask.next_hdr;
+	ipv6->val.hop_limit &= ipv6->mask.hop_limit;
 	return 0;
 }
 
-- 
2.1.4

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

* [PATCH v2 6/9] net/mlx5: support flag flow action
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (5 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 5/9] net/mlx5: extend IPv6 flow item Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 7/9] net/mlx5: prepare support for RSS action rule Nelio Laranjeiro
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

This action is not terminal in this PMD, it must be followed by a queue
action.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c |  5 +++++
 drivers/net/mlx5/mlx5_prm.h  |  7 ++++---
 drivers/net/mlx5/mlx5_rxtx.c | 19 +++++++++++--------
 3 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index a885f6e..39a96ea 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -146,6 +146,7 @@ static const enum rte_flow_action_type valid_actions[] = {
 	RTE_FLOW_ACTION_TYPE_DROP,
 	RTE_FLOW_ACTION_TYPE_QUEUE,
 	RTE_FLOW_ACTION_TYPE_MARK,
+	RTE_FLOW_ACTION_TYPE_FLAG,
 	RTE_FLOW_ACTION_TYPE_END,
 };
 
@@ -476,6 +477,8 @@ priv_flow_validate(struct priv *priv,
 				return -rte_errno;
 			}
 			action.mark = 1;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
+			action.mark = 1;
 		} else {
 			goto exit_action_not_supported;
 		}
@@ -1061,6 +1064,8 @@ priv_flow_create(struct priv *priv,
 			if (mark)
 				action.mark_id = mark->id;
 			action.mark = !action.drop;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
+			action.mark = 1;
 		} else {
 			rte_flow_error_set(error, ENOTSUP,
 					   RTE_FLOW_ERROR_TYPE_ACTION,
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 33fc386..0a77f5b 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -233,9 +233,11 @@ mlx5_flow_mark_set(uint32_t val)
 
 	/*
 	 * Add one to the user value to differentiate un-marked flows from
-	 * marked flows.
+	 * marked flows, if the ID is equal to MLX5_FLOW_MARK_DEFAULT it
+	 * remains untouched.
 	 */
-	++val;
+	if (val != MLX5_FLOW_MARK_DEFAULT)
+		++val;
 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
 	/*
 	 * Mark is 24 bits (minus reserved values) but is stored on a 32 bit
@@ -247,7 +249,6 @@ mlx5_flow_mark_set(uint32_t val)
 #else
 	ret = val;
 #endif
-	assert(ret <= MLX5_FLOW_MARK_MAX);
 	return ret;
 }
 
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 122847d..58dd7c8 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -1538,14 +1538,17 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 				pkt->hash.rss = rss_hash_res;
 				pkt->ol_flags = PKT_RX_RSS_HASH;
 			}
-			if (rxq->mark &&
-			    ((cqe->sop_drop_qpn !=
-			      htonl(MLX5_FLOW_MARK_INVALID)) &&
-			     (cqe->sop_drop_qpn !=
-			      htonl(MLX5_FLOW_MARK_DEFAULT)))) {
-				pkt->hash.fdir.hi =
-					mlx5_flow_mark_get(cqe->sop_drop_qpn);
-				pkt->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
+			if (rxq->mark && (cqe->sop_drop_qpn !=
+					  htonl(MLX5_FLOW_MARK_INVALID))) {
+				pkt->ol_flags |= PKT_RX_FDIR;
+				if (cqe->sop_drop_qpn !=
+				    htonl(MLX5_FLOW_MARK_DEFAULT)) {
+					uint32_t mark = cqe->sop_drop_qpn;
+
+					pkt->ol_flags |= PKT_RX_FDIR_ID;
+					pkt->hash.fdir.hi =
+						mlx5_flow_mark_get(mark);
+				}
 			}
 			if (rxq->csum | rxq->csum_l2tun | rxq->vlan_strip |
 			    rxq->crc_present) {
-- 
2.1.4

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

* [PATCH v2 7/9] net/mlx5: prepare support for RSS action rule
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (6 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 6/9] net/mlx5: support flag flow action Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 8/9] net/mlx5: support RSS action flow rule Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 9/9] net/mlx5: use an RSS drop queue Nelio Laranjeiro
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

In mlx5 PMD handling a single queue of several destination queues ends in
creating the same Verbs attribute, the main difference resides in the
indirection table and the RSS hash key.

This helps to prepare the supports to the RSS queues by first handling the
queue action has being an RSS queue with a single queue.  No RSS hash key
will be provided to the Verbs flow.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 249 +++++++++++++++++++++++++++++++++----------
 1 file changed, 190 insertions(+), 59 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 39a96ea..a188aa3 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -95,8 +95,10 @@ struct rte_flow {
 	struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */
 	struct ibv_exp_wq *wq; /**< Verbs work queue. */
 	struct ibv_cq *cq; /**< Verbs completion queue. */
-	struct rxq *rxq; /**< Pointer to the queue, NULL if drop queue. */
+	struct rxq *(*rxqs)[]; /**< Pointer to the queues array. */
+	uint16_t rxqs_n; /**< Number of queues in this flow, 0 if drop queue. */
 	uint32_t mark:1; /**< Set if the flow is marked. */
+	uint32_t drop:1; /**< Drop queue. */
 };
 
 /** Static initializer for items. */
@@ -279,8 +281,9 @@ struct mlx5_flow_action {
 	uint32_t queue:1; /**< Target is a receive queue. */
 	uint32_t drop:1; /**< Target is a drop queue. */
 	uint32_t mark:1; /**< Mark is present in the flow. */
-	uint32_t queue_id; /**< Identifier of the queue. */
 	uint32_t mark_id; /**< Mark identifier. */
+	uint16_t queues[RTE_MAX_QUEUES_PER_PORT]; /**< Queues indexes to use. */
+	uint16_t queues_n; /**< Number of entries in queue[]. */
 };
 
 /**
@@ -861,12 +864,128 @@ mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id)
 }
 
 /**
+ * Complete flow rule creation with a drop queue.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param flow
+ *   MLX5 flow attributes (filled by mlx5_flow_validate()).
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *
+ * @return
+ *   A flow if the rule could be created.
+ */
+static struct rte_flow *
+priv_flow_create_action_queue_drop(struct priv *priv,
+				   struct mlx5_flow *flow,
+				   struct rte_flow_error *error)
+{
+	struct rte_flow *rte_flow;
+
+	assert(priv->pd);
+	assert(priv->ctx);
+	rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);
+	if (!rte_flow) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "cannot allocate flow memory");
+		return NULL;
+	}
+	rte_flow->cq =
+		ibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,
+				  &(struct ibv_exp_cq_init_attr){
+					  .comp_mask = 0,
+				  });
+	if (!rte_flow->cq) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "cannot allocate CQ");
+		goto error;
+	}
+	rte_flow->wq = ibv_exp_create_wq(priv->ctx,
+					 &(struct ibv_exp_wq_init_attr){
+					 .wq_type = IBV_EXP_WQT_RQ,
+					 .max_recv_wr = 1,
+					 .max_recv_sge = 1,
+					 .pd = priv->pd,
+					 .cq = rte_flow->cq,
+					 });
+	if (!rte_flow->wq) {
+		rte_flow_error_set(error, ENOMEM,
+				   RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "cannot allocate WQ");
+		goto error;
+	}
+	rte_flow->drop = 1;
+	rte_flow->ibv_attr = flow->ibv_attr;
+	rte_flow->ind_table = ibv_exp_create_rwq_ind_table(
+		priv->ctx,
+		&(struct ibv_exp_rwq_ind_table_init_attr){
+			.pd = priv->pd,
+			.log_ind_tbl_size = 0,
+			.ind_tbl = &rte_flow->wq,
+			.comp_mask = 0,
+		});
+	if (!rte_flow->ind_table) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "cannot allocate indirection table");
+		goto error;
+	}
+	rte_flow->qp = ibv_exp_create_qp(
+		priv->ctx,
+		&(struct ibv_exp_qp_init_attr){
+			.qp_type = IBV_QPT_RAW_PACKET,
+			.comp_mask =
+				IBV_EXP_QP_INIT_ATTR_PD |
+				IBV_EXP_QP_INIT_ATTR_PORT |
+				IBV_EXP_QP_INIT_ATTR_RX_HASH,
+			.pd = priv->pd,
+			.rx_hash_conf = &(struct ibv_exp_rx_hash_conf){
+				.rx_hash_function =
+					IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
+				.rx_hash_key_len = rss_hash_default_key_len,
+				.rx_hash_key = rss_hash_default_key,
+				.rx_hash_fields_mask = 0,
+				.rwq_ind_tbl = rte_flow->ind_table,
+			},
+			.port_num = priv->port,
+		});
+	if (!rte_flow->qp) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "cannot allocate QP");
+		goto error;
+	}
+	if (!priv->started)
+		return rte_flow;
+	rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp,
+						 rte_flow->ibv_attr);
+	if (!rte_flow->ibv_flow) {
+		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
+				   NULL, "flow rule creation failure");
+		goto error;
+	}
+	return rte_flow;
+error:
+	assert(rte_flow);
+	if (rte_flow->qp)
+		ibv_destroy_qp(rte_flow->qp);
+	if (rte_flow->ind_table)
+		ibv_exp_destroy_rwq_ind_table(rte_flow->ind_table);
+	if (rte_flow->wq)
+		ibv_exp_destroy_wq(rte_flow->wq);
+	if (rte_flow->cq)
+		ibv_destroy_cq(rte_flow->cq);
+	rte_free(rte_flow);
+	return NULL;
+}
+
+/**
  * Complete flow rule creation.
  *
  * @param priv
  *   Pointer to private structure.
- * @param ibv_attr
- *   Verbs flow attributes.
+ * @param flow
+ *   MLX5 flow attributes (filled by mlx5_flow_validate()).
  * @param action
  *   Target action structure.
  * @param[out] error
@@ -877,62 +996,46 @@ mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id)
  */
 static struct rte_flow *
 priv_flow_create_action_queue(struct priv *priv,
-			      struct ibv_exp_flow_attr *ibv_attr,
+			      struct mlx5_flow *flow,
 			      struct mlx5_flow_action *action,
 			      struct rte_flow_error *error)
 {
-	struct rxq_ctrl *rxq;
 	struct rte_flow *rte_flow;
+	unsigned int i;
+	struct ibv_exp_wq *wq[action->queues_n];
 
 	assert(priv->pd);
 	assert(priv->ctx);
-	rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);
+	assert(!action->drop);
+	rte_flow = rte_calloc(__func__, 1,
+			      sizeof(*rte_flow) + sizeof(struct rxq *) *
+			      action->queues_n, 0);
 	if (!rte_flow) {
 		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "cannot allocate flow memory");
 		return NULL;
 	}
-	if (action->drop) {
-		rte_flow->cq =
-			ibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,
-					  &(struct ibv_exp_cq_init_attr){
-						  .comp_mask = 0,
-					  });
-		if (!rte_flow->cq) {
-			rte_flow_error_set(error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_HANDLE,
-					   NULL, "cannot allocate CQ");
-			goto error;
-		}
-		rte_flow->wq = ibv_exp_create_wq(priv->ctx,
-						 &(struct ibv_exp_wq_init_attr){
-						 .wq_type = IBV_EXP_WQT_RQ,
-						 .max_recv_wr = 1,
-						 .max_recv_sge = 1,
-						 .pd = priv->pd,
-						 .cq = rte_flow->cq,
-						 });
-		if (!rte_flow->wq) {
-			rte_flow_error_set(error, ENOMEM,
-					   RTE_FLOW_ERROR_TYPE_HANDLE,
-					   NULL, "cannot allocate WQ");
-			goto error;
-		}
-	} else {
-		rxq = container_of((*priv->rxqs)[action->queue_id],
+	rte_flow->rxqs = (struct rxq *(*)[])((uintptr_t)rte_flow +
+					     sizeof(struct rxq *) *
+					     action->queues_n);
+	for (i = 0; i < action->queues_n; ++i) {
+		struct rxq_ctrl *rxq;
+
+		rxq = container_of((*priv->rxqs)[action->queues[i]],
 				   struct rxq_ctrl, rxq);
-		rte_flow->rxq = &rxq->rxq;
+		wq[i] = rxq->wq;
+		(*rte_flow->rxqs)[i] = &rxq->rxq;
+		++rte_flow->rxqs_n;
 		rxq->rxq.mark |= action->mark;
-		rte_flow->wq = rxq->wq;
 	}
 	rte_flow->mark = action->mark;
-	rte_flow->ibv_attr = ibv_attr;
+	rte_flow->ibv_attr = flow->ibv_attr;
 	rte_flow->ind_table = ibv_exp_create_rwq_ind_table(
 		priv->ctx,
 		&(struct ibv_exp_rwq_ind_table_init_attr){
 			.pd = priv->pd,
 			.log_ind_tbl_size = 0,
-			.ind_tbl = &rte_flow->wq,
+			.ind_tbl = wq,
 			.comp_mask = 0,
 		});
 	if (!rte_flow->ind_table) {
@@ -980,10 +1083,6 @@ priv_flow_create_action_queue(struct priv *priv,
 		ibv_destroy_qp(rte_flow->qp);
 	if (rte_flow->ind_table)
 		ibv_exp_destroy_rwq_ind_table(rte_flow->ind_table);
-	if (!rte_flow->rxq && rte_flow->wq)
-		ibv_exp_destroy_wq(rte_flow->wq);
-	if (!rte_flow->rxq && rte_flow->cq)
-		ibv_destroy_cq(rte_flow->cq);
 	rte_free(rte_flow);
 	return NULL;
 }
@@ -1050,7 +1149,7 @@ priv_flow_create(struct priv *priv,
 			continue;
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
 			action.queue = 1;
-			action.queue_id =
+			action.queues[action.queues_n++] =
 				((const struct rte_flow_action_queue *)
 				 actions->conf)->index;
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
@@ -1077,8 +1176,12 @@ priv_flow_create(struct priv *priv,
 		mlx5_flow_create_flag_mark(&flow, action.mark_id);
 		flow.offset += sizeof(struct ibv_exp_flow_spec_action_tag);
 	}
-	rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr,
-						 &action, error);
+	if (action.drop)
+		rte_flow =
+			priv_flow_create_action_queue_drop(priv, &flow, error);
+	else
+		rte_flow = priv_flow_create_action_queue(priv, &flow, &action,
+							 error);
 	if (!rte_flow)
 		goto exit;
 	return rte_flow;
@@ -1133,21 +1236,41 @@ priv_flow_destroy(struct priv *priv,
 		claim_zero(ibv_destroy_qp(flow->qp));
 	if (flow->ind_table)
 		claim_zero(ibv_exp_destroy_rwq_ind_table(flow->ind_table));
-	if (!flow->rxq && flow->wq)
+	if (flow->drop && flow->wq)
 		claim_zero(ibv_exp_destroy_wq(flow->wq));
-	if (!flow->rxq && flow->cq)
+	if (flow->drop && flow->cq)
 		claim_zero(ibv_destroy_cq(flow->cq));
 	if (flow->mark) {
 		struct rte_flow *tmp;
+		struct rxq *rxq;
 		uint32_t mark_n = 0;
-
-		for (tmp = LIST_FIRST(&priv->flows);
-		     tmp;
-		     tmp = LIST_NEXT(tmp, next)) {
-			if ((flow->rxq == tmp->rxq) && tmp->mark)
-				++mark_n;
+		uint32_t queue_n;
+
+		/*
+		 * To remove the mark from the queue, the queue must not be
+		 * present in any other marked flow (RSS or not).
+		 */
+		for (queue_n = 0; queue_n < flow->rxqs_n; ++queue_n) {
+			rxq = (*flow->rxqs)[queue_n];
+			for (tmp = LIST_FIRST(&priv->flows);
+			     tmp;
+			     tmp = LIST_NEXT(tmp, next)) {
+				uint32_t tqueue_n;
+
+				if (tmp->drop)
+					continue;
+				for (tqueue_n = 0;
+				     tqueue_n < tmp->rxqs_n;
+				     ++tqueue_n) {
+					struct rxq *trxq;
+
+					trxq = (*tmp->rxqs)[tqueue_n];
+					if (rxq == trxq)
+						++mark_n;
+				}
+			}
+			rxq->mark = !!mark_n;
 		}
-		flow->rxq->mark = !!mark_n;
 	}
 	rte_free(flow->ibv_attr);
 	DEBUG("Flow destroyed %p", (void *)flow);
@@ -1228,8 +1351,12 @@ priv_flow_stop(struct priv *priv)
 	     flow = LIST_NEXT(flow, next)) {
 		claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
 		flow->ibv_flow = NULL;
-		if (flow->mark)
-			flow->rxq->mark = 0;
+		if (flow->mark) {
+			unsigned int n;
+
+			for (n = 0; n < flow->rxqs_n; ++n)
+				(*flow->rxqs)[n]->mark = 0;
+		}
 		DEBUG("Flow %p removed", (void *)flow);
 	}
 }
@@ -1259,8 +1386,12 @@ priv_flow_start(struct priv *priv)
 			return rte_errno;
 		}
 		DEBUG("Flow %p applied", (void *)flow);
-		if (flow->rxq)
-			flow->rxq->mark |= flow->mark;
+		if (flow->mark) {
+			unsigned int n;
+
+			for (n = 0; n < flow->rxqs_n; ++n)
+				(*flow->rxqs)[n]->mark = 1;
+		}
 	}
 	return 0;
 }
-- 
2.1.4

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

* [PATCH v2 8/9] net/mlx5: support RSS action flow rule
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (7 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 7/9] net/mlx5: prepare support for RSS action rule Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  2017-03-01 12:49 ` [PATCH v2 9/9] net/mlx5: use an RSS drop queue Nelio Laranjeiro
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

Implement a basic flow RSS action.  This commits don't handle the default
RSS queues already created by the control plane, this last part being huge.

Any new request RSS flow request will be added using an higher priority
than the default one to be sure this rule will be the one used.

Default ones (those created by dev_start()) remains but has they have a
lower priority they will not receive any new packet.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5_flow.c | 87 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 82 insertions(+), 5 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index a188aa3..99d0377 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -99,6 +99,7 @@ struct rte_flow {
 	uint16_t rxqs_n; /**< Number of queues in this flow, 0 if drop queue. */
 	uint32_t mark:1; /**< Set if the flow is marked. */
 	uint32_t drop:1; /**< Drop queue. */
+	uint64_t hash_fields; /**< Fields that participate in the hash. */
 };
 
 /** Static initializer for items. */
@@ -275,6 +276,7 @@ struct mlx5_flow {
 	struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */
 	unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */
 	uint32_t inner; /**< Set once VXLAN is encountered. */
+	uint64_t hash_fields; /**< Fields that participate in the hash. */
 };
 
 struct mlx5_flow_action {
@@ -456,10 +458,56 @@ priv_flow_validate(struct priv *priv,
 			const struct rte_flow_action_queue *queue =
 				(const struct rte_flow_action_queue *)
 				actions->conf;
+			uint16_t n;
+			uint16_t found = 0;
 
 			if (!queue || (queue->index > (priv->rxqs_n - 1)))
 				goto exit_action_not_supported;
+			for (n = 0; n < action.queues_n; ++n) {
+				if (action.queues[n] == queue->index) {
+					found = 1;
+					break;
+				}
+			}
+			if (action.queues_n && !found) {
+				rte_flow_error_set(error, ENOTSUP,
+					   RTE_FLOW_ERROR_TYPE_ACTION,
+					   actions,
+					   "queue action not in RSS queues");
+				return -rte_errno;
+			}
+			action.queue = 1;
+			action.queues_n = 1;
+			action.queues[0] = queue->index;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) {
+			const struct rte_flow_action_rss *rss =
+				(const struct rte_flow_action_rss *)
+				actions->conf;
+			uint16_t n;
+
+			if (action.queues_n == 1) {
+				uint16_t found = 0;
+
+				assert(action.queues_n);
+				for (n = 0; n < rss->num; ++n) {
+					if (action.queues[0] == rss->queue[n]) {
+						found = 1;
+						break;
+					}
+				}
+				if (!found) {
+					rte_flow_error_set(error, ENOTSUP,
+						   RTE_FLOW_ERROR_TYPE_ACTION,
+						   actions,
+						   "queue action not in RSS"
+						   " queues");
+					return -rte_errno;
+				}
+			}
 			action.queue = 1;
+			for (n = 0; n < rss->num; ++n)
+				action.queues[n] = rss->queue[n];
+			action.queues_n = rss->num;
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) {
 			const struct rte_flow_action_mark *mark =
 				(const struct rte_flow_action_mark *)
@@ -551,6 +599,7 @@ mlx5_flow_create_eth(const struct rte_flow_item *item,
 
 	++flow->ibv_attr->num_of_specs;
 	flow->ibv_attr->priority = 2;
+	flow->hash_fields = 0;
 	eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
 	*eth = (struct ibv_exp_flow_spec_eth) {
 		.type = flow->inner | IBV_EXP_FLOW_SPEC_ETH,
@@ -630,6 +679,8 @@ mlx5_flow_create_ipv4(const struct rte_flow_item *item,
 
 	++flow->ibv_attr->num_of_specs;
 	flow->ibv_attr->priority = 1;
+	flow->hash_fields = (IBV_EXP_RX_HASH_SRC_IPV4 |
+			     IBV_EXP_RX_HASH_DST_IPV4);
 	ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
 	*ipv4 = (struct ibv_exp_flow_spec_ipv4_ext) {
 		.type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4_EXT,
@@ -682,6 +733,8 @@ mlx5_flow_create_ipv6(const struct rte_flow_item *item,
 
 	++flow->ibv_attr->num_of_specs;
 	flow->ibv_attr->priority = 1;
+	flow->hash_fields = (IBV_EXP_RX_HASH_SRC_IPV6 |
+			     IBV_EXP_RX_HASH_DST_IPV6);
 	ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
 	*ipv6 = (struct ibv_exp_flow_spec_ipv6_ext) {
 		.type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6_EXT,
@@ -731,6 +784,8 @@ mlx5_flow_create_udp(const struct rte_flow_item *item,
 
 	++flow->ibv_attr->num_of_specs;
 	flow->ibv_attr->priority = 0;
+	flow->hash_fields |= (IBV_EXP_RX_HASH_SRC_PORT_UDP |
+			      IBV_EXP_RX_HASH_DST_PORT_UDP);
 	udp = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
 	*udp = (struct ibv_exp_flow_spec_tcp_udp) {
 		.type = flow->inner | IBV_EXP_FLOW_SPEC_UDP,
@@ -773,6 +828,8 @@ mlx5_flow_create_tcp(const struct rte_flow_item *item,
 
 	++flow->ibv_attr->num_of_specs;
 	flow->ibv_attr->priority = 0;
+	flow->hash_fields |= (IBV_EXP_RX_HASH_SRC_PORT_TCP |
+			      IBV_EXP_RX_HASH_DST_PORT_TCP);
 	tcp = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
 	*tcp = (struct ibv_exp_flow_spec_tcp_udp) {
 		.type = flow->inner | IBV_EXP_FLOW_SPEC_TCP,
@@ -1002,7 +1059,9 @@ priv_flow_create_action_queue(struct priv *priv,
 {
 	struct rte_flow *rte_flow;
 	unsigned int i;
-	struct ibv_exp_wq *wq[action->queues_n];
+	unsigned int j;
+	const unsigned int wqs_n = 1 << log2above(action->queues_n);
+	struct ibv_exp_wq *wqs[wqs_n];
 
 	assert(priv->pd);
 	assert(priv->ctx);
@@ -1023,19 +1082,26 @@ priv_flow_create_action_queue(struct priv *priv,
 
 		rxq = container_of((*priv->rxqs)[action->queues[i]],
 				   struct rxq_ctrl, rxq);
-		wq[i] = rxq->wq;
+		wqs[i] = rxq->wq;
 		(*rte_flow->rxqs)[i] = &rxq->rxq;
 		++rte_flow->rxqs_n;
 		rxq->rxq.mark |= action->mark;
 	}
+	/* finalise indirection table. */
+	for (j = 0; i < wqs_n; ++i, ++j) {
+		wqs[i] = wqs[j];
+		if (j == action->queues_n)
+			j = 0;
+	}
 	rte_flow->mark = action->mark;
 	rte_flow->ibv_attr = flow->ibv_attr;
+	rte_flow->hash_fields = flow->hash_fields;
 	rte_flow->ind_table = ibv_exp_create_rwq_ind_table(
 		priv->ctx,
 		&(struct ibv_exp_rwq_ind_table_init_attr){
 			.pd = priv->pd,
-			.log_ind_tbl_size = 0,
-			.ind_tbl = wq,
+			.log_ind_tbl_size = log2above(action->queues_n),
+			.ind_tbl = wqs,
 			.comp_mask = 0,
 		});
 	if (!rte_flow->ind_table) {
@@ -1057,7 +1123,7 @@ priv_flow_create_action_queue(struct priv *priv,
 					IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
 				.rx_hash_key_len = rss_hash_default_key_len,
 				.rx_hash_key = rss_hash_default_key,
-				.rx_hash_fields_mask = 0,
+				.rx_hash_fields_mask = rte_flow->hash_fields,
 				.rwq_ind_tbl = rte_flow->ind_table,
 			},
 			.port_num = priv->port,
@@ -1136,6 +1202,7 @@ priv_flow_create(struct priv *priv,
 		.reserved = 0,
 	};
 	flow.inner = 0;
+	flow.hash_fields = 0;
 	claim_zero(priv_flow_validate(priv, attr, items, actions,
 				      error, &flow));
 	action = (struct mlx5_flow_action){
@@ -1152,6 +1219,16 @@ priv_flow_create(struct priv *priv,
 			action.queues[action.queues_n++] =
 				((const struct rte_flow_action_queue *)
 				 actions->conf)->index;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_RSS) {
+			const struct rte_flow_action_rss *rss =
+				(const struct rte_flow_action_rss *)
+				 actions->conf;
+			uint16_t n;
+
+			action.queue = 1;
+			action.queues_n = rss->num;
+			for (n = 0; n < rss->num; ++n)
+				action.queues[n] = rss->queue[n];
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
 			action.drop = 1;
 			action.mark = 0;
-- 
2.1.4

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

* [PATCH v2 9/9] net/mlx5: use an RSS drop queue
       [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
                   ` (8 preceding siblings ...)
  2017-03-01 12:49 ` [PATCH v2 8/9] net/mlx5: support RSS action flow rule Nelio Laranjeiro
@ 2017-03-01 12:49 ` Nelio Laranjeiro
  9 siblings, 0 replies; 12+ messages in thread
From: Nelio Laranjeiro @ 2017-03-01 12:49 UTC (permalink / raw)
  To: dev; +Cc: Adrien Mazarguil

Having a drop queue per drop flow consumes a lot of memory and reduce the
speed capabilities of the NIC to handle such cases.
To avoid this and reduce memory consumption, an RSS drop queue is created
for all drop flows.

Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
---
 drivers/net/mlx5/mlx5.h      |   1 +
 drivers/net/mlx5/mlx5_flow.c | 218 +++++++++++++++++++++++++++++--------------
 2 files changed, 147 insertions(+), 72 deletions(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 7ba2886..870e01f 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -152,6 +152,7 @@ struct priv {
 	unsigned int reta_idx_n; /* RETA index size. */
 	struct fdir_filter_list *fdir_filter_list; /* Flow director rules. */
 	struct fdir_queue *fdir_drop_queue; /* Flow director drop queue. */
+	struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */
 	LIST_HEAD(mlx5_flows, rte_flow) flows; /* RTE Flow rules. */
 	uint32_t link_speed_capa; /* Link speed capabilities. */
 	struct mlx5_xstats_ctrl xstats_ctrl; /* Extended stats control. */
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 99d0377..e789c4c 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -52,6 +52,9 @@
 #include "mlx5.h"
 #include "mlx5_prm.h"
 
+/* Number of Work Queue necessary for the DROP queue. */
+#define MLX5_DROP_WQ_N 4
+
 static int
 mlx5_flow_create_eth(const struct rte_flow_item *item,
 		     const void *default_mask,
@@ -279,6 +282,14 @@ struct mlx5_flow {
 	uint64_t hash_fields; /**< Fields that participate in the hash. */
 };
 
+/** Structure for Drop queue. */
+struct rte_flow_drop {
+	struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */
+	struct ibv_qp *qp; /**< Verbs queue pair. */
+	struct ibv_exp_wq *wqs[MLX5_DROP_WQ_N]; /**< Verbs work queue. */
+	struct ibv_cq *cq; /**< Verbs completion queue. */
+};
+
 struct mlx5_flow_action {
 	uint32_t queue:1; /**< Target is a receive queue. */
 	uint32_t drop:1; /**< Target is a drop queue. */
@@ -948,70 +959,9 @@ priv_flow_create_action_queue_drop(struct priv *priv,
 				   NULL, "cannot allocate flow memory");
 		return NULL;
 	}
-	rte_flow->cq =
-		ibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,
-				  &(struct ibv_exp_cq_init_attr){
-					  .comp_mask = 0,
-				  });
-	if (!rte_flow->cq) {
-		rte_flow_error_set(error, ENOMEM,
-				   RTE_FLOW_ERROR_TYPE_HANDLE,
-				   NULL, "cannot allocate CQ");
-		goto error;
-	}
-	rte_flow->wq = ibv_exp_create_wq(priv->ctx,
-					 &(struct ibv_exp_wq_init_attr){
-					 .wq_type = IBV_EXP_WQT_RQ,
-					 .max_recv_wr = 1,
-					 .max_recv_sge = 1,
-					 .pd = priv->pd,
-					 .cq = rte_flow->cq,
-					 });
-	if (!rte_flow->wq) {
-		rte_flow_error_set(error, ENOMEM,
-				   RTE_FLOW_ERROR_TYPE_HANDLE,
-				   NULL, "cannot allocate WQ");
-		goto error;
-	}
 	rte_flow->drop = 1;
 	rte_flow->ibv_attr = flow->ibv_attr;
-	rte_flow->ind_table = ibv_exp_create_rwq_ind_table(
-		priv->ctx,
-		&(struct ibv_exp_rwq_ind_table_init_attr){
-			.pd = priv->pd,
-			.log_ind_tbl_size = 0,
-			.ind_tbl = &rte_flow->wq,
-			.comp_mask = 0,
-		});
-	if (!rte_flow->ind_table) {
-		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
-				   NULL, "cannot allocate indirection table");
-		goto error;
-	}
-	rte_flow->qp = ibv_exp_create_qp(
-		priv->ctx,
-		&(struct ibv_exp_qp_init_attr){
-			.qp_type = IBV_QPT_RAW_PACKET,
-			.comp_mask =
-				IBV_EXP_QP_INIT_ATTR_PD |
-				IBV_EXP_QP_INIT_ATTR_PORT |
-				IBV_EXP_QP_INIT_ATTR_RX_HASH,
-			.pd = priv->pd,
-			.rx_hash_conf = &(struct ibv_exp_rx_hash_conf){
-				.rx_hash_function =
-					IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
-				.rx_hash_key_len = rss_hash_default_key_len,
-				.rx_hash_key = rss_hash_default_key,
-				.rx_hash_fields_mask = 0,
-				.rwq_ind_tbl = rte_flow->ind_table,
-			},
-			.port_num = priv->port,
-		});
-	if (!rte_flow->qp) {
-		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
-				   NULL, "cannot allocate QP");
-		goto error;
-	}
+	rte_flow->qp = priv->flow_drop_queue->qp;
 	if (!priv->started)
 		return rte_flow;
 	rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp,
@@ -1024,14 +974,6 @@ priv_flow_create_action_queue_drop(struct priv *priv,
 	return rte_flow;
 error:
 	assert(rte_flow);
-	if (rte_flow->qp)
-		ibv_destroy_qp(rte_flow->qp);
-	if (rte_flow->ind_table)
-		ibv_exp_destroy_rwq_ind_table(rte_flow->ind_table);
-	if (rte_flow->wq)
-		ibv_exp_destroy_wq(rte_flow->wq);
-	if (rte_flow->cq)
-		ibv_destroy_cq(rte_flow->cq);
 	rte_free(rte_flow);
 	return NULL;
 }
@@ -1309,6 +1251,8 @@ priv_flow_destroy(struct priv *priv,
 	LIST_REMOVE(flow, next);
 	if (flow->ibv_flow)
 		claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
+	if (flow->drop)
+		goto free;
 	if (flow->qp)
 		claim_zero(ibv_destroy_qp(flow->qp));
 	if (flow->ind_table)
@@ -1349,6 +1293,7 @@ priv_flow_destroy(struct priv *priv,
 			rxq->mark = !!mark_n;
 		}
 	}
+free:
 	rte_free(flow->ibv_attr);
 	DEBUG("Flow destroyed %p", (void *)flow);
 	rte_free(flow);
@@ -1411,6 +1356,125 @@ mlx5_flow_flush(struct rte_eth_dev *dev,
 }
 
 /**
+ * Create drop queue.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ *
+ * @return
+ *   0 on success.
+ */
+static int
+priv_flow_create_drop_queue(struct priv *priv)
+{
+	struct rte_flow_drop *fdq = NULL;
+	unsigned int i;
+
+	assert(priv->pd);
+	assert(priv->ctx);
+	fdq = rte_calloc(__func__, 1, sizeof(*fdq), 0);
+	if (!fdq) {
+		WARN("cannot allocate memory for drop queue");
+		goto error;
+	}
+	fdq->cq = ibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,
+			&(struct ibv_exp_cq_init_attr){
+			.comp_mask = 0,
+			});
+	if (!fdq->cq) {
+		WARN("cannot allocate CQ for drop queue");
+		goto error;
+	}
+	for (i = 0; i != MLX5_DROP_WQ_N; ++i) {
+		fdq->wqs[i] = ibv_exp_create_wq(priv->ctx,
+				&(struct ibv_exp_wq_init_attr){
+				.wq_type = IBV_EXP_WQT_RQ,
+				.max_recv_wr = 1,
+				.max_recv_sge = 1,
+				.pd = priv->pd,
+				.cq = fdq->cq,
+				});
+		if (!fdq->wqs[i]) {
+			WARN("cannot allocate WQ for drop queue");
+			goto error;
+		}
+	}
+	fdq->ind_table = ibv_exp_create_rwq_ind_table(priv->ctx,
+			&(struct ibv_exp_rwq_ind_table_init_attr){
+			.pd = priv->pd,
+			.log_ind_tbl_size = 0,
+			.ind_tbl = fdq->wqs,
+			.comp_mask = 0,
+			});
+	if (!fdq->ind_table) {
+		WARN("cannot allocate indirection table for drop queue");
+		goto error;
+	}
+	fdq->qp = ibv_exp_create_qp(priv->ctx,
+		&(struct ibv_exp_qp_init_attr){
+			.qp_type = IBV_QPT_RAW_PACKET,
+			.comp_mask =
+				IBV_EXP_QP_INIT_ATTR_PD |
+				IBV_EXP_QP_INIT_ATTR_PORT |
+				IBV_EXP_QP_INIT_ATTR_RX_HASH,
+			.pd = priv->pd,
+			.rx_hash_conf = &(struct ibv_exp_rx_hash_conf){
+				.rx_hash_function =
+					IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
+				.rx_hash_key_len = rss_hash_default_key_len,
+				.rx_hash_key = rss_hash_default_key,
+				.rx_hash_fields_mask = 0,
+				.rwq_ind_tbl = fdq->ind_table,
+				},
+			.port_num = priv->port,
+			});
+	if (!fdq->qp) {
+		WARN("cannot allocate QP for drop queue");
+		goto error;
+	}
+	priv->flow_drop_queue = fdq;
+	return 0;
+error:
+	if (fdq->qp)
+		claim_zero(ibv_destroy_qp(fdq->qp));
+	if (fdq->ind_table)
+		claim_zero(ibv_exp_destroy_rwq_ind_table(fdq->ind_table));
+	for (i = 0; i != MLX5_DROP_WQ_N; ++i) {
+		if (fdq->wqs[i])
+			claim_zero(ibv_exp_destroy_wq(fdq->wqs[i]));
+	}
+	if (fdq->cq)
+		claim_zero(ibv_destroy_cq(fdq->cq));
+	if (fdq)
+		rte_free(fdq);
+	priv->flow_drop_queue = NULL;
+	return -1;
+}
+
+/**
+ * Delete drop queue.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ */
+static void
+priv_flow_delete_drop_queue(struct priv *priv)
+{
+	struct rte_flow_drop *fdq = priv->flow_drop_queue;
+	unsigned int i;
+
+	claim_zero(ibv_destroy_qp(fdq->qp));
+	claim_zero(ibv_exp_destroy_rwq_ind_table(fdq->ind_table));
+	for (i = 0; i != MLX5_DROP_WQ_N; ++i) {
+		assert(fdq->wqs[i]);
+		claim_zero(ibv_exp_destroy_wq(fdq->wqs[i]));
+	}
+	claim_zero(ibv_destroy_cq(fdq->cq));
+	rte_free(fdq);
+	priv->flow_drop_queue = NULL;
+}
+
+/**
  * Remove all flows.
  *
  * Called by dev_stop() to remove all flows.
@@ -1436,6 +1500,7 @@ priv_flow_stop(struct priv *priv)
 		}
 		DEBUG("Flow %p removed", (void *)flow);
 	}
+	priv_flow_delete_drop_queue(priv);
 }
 
 /**
@@ -1450,13 +1515,22 @@ priv_flow_stop(struct priv *priv)
 int
 priv_flow_start(struct priv *priv)
 {
+	int ret;
 	struct rte_flow *flow;
 
+	ret = priv_flow_create_drop_queue(priv);
+	if (ret)
+		return -1;
 	for (flow = LIST_FIRST(&priv->flows);
 	     flow;
 	     flow = LIST_NEXT(flow, next)) {
-		flow->ibv_flow = ibv_exp_create_flow(flow->qp,
-						     flow->ibv_attr);
+		struct ibv_qp *qp;
+
+		if (flow->drop)
+			qp = priv->flow_drop_queue->qp;
+		else
+			qp = flow->qp;
+		flow->ibv_flow = ibv_exp_create_flow(qp, flow->ibv_attr);
 		if (!flow->ibv_flow) {
 			DEBUG("Flow %p cannot be applied", (void *)flow);
 			rte_errno = EINVAL;
-- 
2.1.4

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

* Re: [PATCH v2 0/9] net/mlx5: enhance flow API
  2017-03-01 12:49 ` [PATCH v2 0/9] net/mlx5: enhance flow API Nelio Laranjeiro
@ 2017-03-03 23:36   ` Ferruh Yigit
  2017-03-04 12:42   ` Ferruh Yigit
  1 sibling, 0 replies; 12+ messages in thread
From: Ferruh Yigit @ 2017-03-03 23:36 UTC (permalink / raw)
  To: Nelio Laranjeiro, dev; +Cc: Adrien Mazarguil

On 3/1/2017 12:49 PM, Nelio Laranjeiro wrote:
> Changes in v2:
> 
>  - Send series to dev@dpdk.org
> 
> This series brings:
> 
>  - fixes:
>    - handle error on Queue Pair creation.
>    - Move a free to the right function.
>    - Uses a single RSS drop queue for dropping flows.
>  - Enhance IPv6 filtering by adding extra fields.
>  - support rss hash result in combination of mark id.
>  - support flag action.
>  - support RSS action.
> 
> 
> Nelio Laranjeiro (9):
>   net/mlx5: fix drop queue creation error
>   net/mlx5: fix resources free in the right function
>   net/mlx5: support ether type support in flow item
>   net/mlx5: add RSS hash result with mark id
>   net/mlx5: extend IPv6 flow item
>   net/mlx5: support flag flow action
>   net/mlx5: prepare support for RSS action rule
>   net/mlx5: support RSS action flow rule
>   net/mlx5: use an RSS drop queue

It looks like patchset has a dependency to [1], please note them next
time to help review.

Thanks,
ferruh

[1]
http://dpdk.org/dev/patchwork/patch/20937/

> 
>  drivers/net/mlx5/mlx5.h      |   1 +
>  drivers/net/mlx5/mlx5_flow.c | 439 ++++++++++++++++++++++++++++++++++++-------
>  drivers/net/mlx5/mlx5_prm.h  |   7 +-
>  drivers/net/mlx5/mlx5_rxtx.c |  20 +-
>  4 files changed, 386 insertions(+), 81 deletions(-)
> 

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

* Re: [PATCH v2 0/9] net/mlx5: enhance flow API
  2017-03-01 12:49 ` [PATCH v2 0/9] net/mlx5: enhance flow API Nelio Laranjeiro
  2017-03-03 23:36   ` Ferruh Yigit
@ 2017-03-04 12:42   ` Ferruh Yigit
  1 sibling, 0 replies; 12+ messages in thread
From: Ferruh Yigit @ 2017-03-04 12:42 UTC (permalink / raw)
  To: Nelio Laranjeiro, dev; +Cc: Adrien Mazarguil

On 3/1/2017 12:49 PM, Nelio Laranjeiro wrote:
> Changes in v2:
> 
>  - Send series to dev@dpdk.org
> 
> This series brings:
> 
>  - fixes:
>    - handle error on Queue Pair creation.
>    - Move a free to the right function.
>    - Uses a single RSS drop queue for dropping flows.
>  - Enhance IPv6 filtering by adding extra fields.
>  - support rss hash result in combination of mark id.
>  - support flag action.
>  - support RSS action.
> 
> 
> Nelio Laranjeiro (9):
>   net/mlx5: fix drop queue creation error
>   net/mlx5: fix resources free in the right function
>   net/mlx5: support ether type support in flow item
>   net/mlx5: add RSS hash result with mark id
>   net/mlx5: extend IPv6 flow item
>   net/mlx5: support flag flow action
>   net/mlx5: prepare support for RSS action rule
>   net/mlx5: support RSS action flow rule
>   net/mlx5: use an RSS drop queue

Series applied to dpdk-next-net/master, thanks.

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

end of thread, other threads:[~2017-03-04 12:42 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1488364873.git.nelio.laranjeiro@6wind.com>
2017-03-01 12:49 ` [PATCH v2 0/9] net/mlx5: enhance flow API Nelio Laranjeiro
2017-03-03 23:36   ` Ferruh Yigit
2017-03-04 12:42   ` Ferruh Yigit
2017-03-01 12:49 ` [PATCH v2 1/9] net/mlx5: fix drop queue creation error Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 2/9] net/mlx5: fix resources free in the right function Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 3/9] net/mlx5: support ether type support in flow item Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 4/9] net/mlx5: add RSS hash result with mark id Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 5/9] net/mlx5: extend IPv6 flow item Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 6/9] net/mlx5: support flag flow action Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 7/9] net/mlx5: prepare support for RSS action rule Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 8/9] net/mlx5: support RSS action flow rule Nelio Laranjeiro
2017-03-01 12:49 ` [PATCH v2 9/9] net/mlx5: use an RSS drop queue Nelio Laranjeiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.