All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] net/mlx5: support count flow action
@ 2017-08-21 12:35 Ori Kam
  2017-08-24  6:54 ` Nélio Laranjeiro
  2017-10-10 14:22 ` [PATCH v2] net/mlx5: flow counter support Nelio Laranjeiro
  0 siblings, 2 replies; 7+ messages in thread
From: Ori Kam @ 2017-08-21 12:35 UTC (permalink / raw)
  To: adrien.mazaruil, nelio.laranjeiro; +Cc: dev

Support count flow action.

This patch is basic design only, do to missing features on the verbs
driver. As soon as the features will be implemented on the verbs driver this
will be updated and rebased on top of dpdk.org/ml/archives/dev/2017-August/072351.html
(The verbs driver should be ready starting September)

This RFC should be applied on top of
dpdk.org/ml/archives/dev/2017-August/072351.html

Signed-off-by: Ori Kam <orika@mellanox.com>
---
 drivers/net/mlx5/mlx5.h      |   4 ++
 drivers/net/mlx5/mlx5_flow.c | 163 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 166 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index e89aba8..434e848 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -294,6 +294,10 @@ struct rte_flow *mlx5_flow_create(struct rte_eth_dev *,
 int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *,
 		      struct rte_flow_error *);
 int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *);
+int mlx5_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
+		enum rte_flow_action_type type,
+		void *res,
+		struct rte_flow_error *error);
 int mlx5_flow_isolate(struct rte_eth_dev *, int, struct rte_flow_error *);
 int priv_flow_start(struct priv *);
 void priv_flow_stop(struct priv *);
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 7dd3ebb..9f1ecfb 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -98,7 +98,9 @@ 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. */
+	uint32_t count:1; /**< Count action. */
 	uint64_t hash_fields; /**< Fields that participate in the hash. */
+	struct ibv_counter_set *counter; /**< Pointer to the counter struct. */
 	struct rxq *rxqs[]; /**< Pointer to the queues array. */
 };
 
@@ -150,6 +152,7 @@ struct mlx5_flow_items {
 	RTE_FLOW_ACTION_TYPE_QUEUE,
 	RTE_FLOW_ACTION_TYPE_MARK,
 	RTE_FLOW_ACTION_TYPE_FLAG,
+	RTE_FLOW_ACTION_TYPE_COUNT,
 	RTE_FLOW_ACTION_TYPE_END,
 };
 
@@ -291,6 +294,7 @@ 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 count:1; /**< Count is present in the flow. */
 	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[]. */
@@ -567,6 +571,8 @@ struct mlx5_flow_action {
 			action->mark_id = mark->id;
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
 			action->mark = 1;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_COUNT) {
+			action->count = 1;
 		} else {
 			goto exit_action_not_supported;
 		}
@@ -575,7 +581,13 @@ struct mlx5_flow_action {
 		flow->offset += sizeof(struct ibv_exp_flow_spec_action_tag);
 	if (!flow->ibv_attr && action->drop)
 		flow->offset += sizeof(struct ibv_exp_flow_spec_action_drop);
-	if (!action->queue && !action->drop) {
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+	if (action->count && !flow->ibv_attr)
+		flow->offset += sizeof(struct ibv_exp_flow_spec_action_count);
+#else
+	goto exit_action_not_supported;
+#endif
+	if (!action->queue && !action->drop  && !action->count) {
 		rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "no valid action");
 		return -rte_errno;
@@ -611,6 +623,7 @@ struct mlx5_flow_action {
 		.queue = 0,
 		.drop = 0,
 		.mark = 0,
+		.count = 0,
 		.mark_id = MLX5_FLOW_MARK_DEFAULT,
 		.queues_n = 0,
 	};
@@ -1142,6 +1155,44 @@ struct mlx5_flow_action {
 	return NULL;
 }
 
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+/**
+ * Connect the counter and add the action to the flow.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param flow
+ *   Pointer to flow structure.
+ * @param counter_id
+ * 	 Counter id.
+ *
+ * @return
+ *   Pointer to counter set.
+ */
+static struct ibv_counter_set *
+priv_flow_create_counter(struct priv *priv, struct mlx5_flow *flow, uint16_t counter_id)
+{
+
+	struct ibv_exp_flow_spec_action_count *count;
+	unsigned int size = sizeof(struct ibv_exp_flow_spec_action_count);
+	struct ibv_counter_set *counter;
+
+	counter = ibv_create_counter_set(priv->ctx,0);
+	if (!counter) {
+		return NULL;
+	}
+
+	count = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
+	*count = (struct ibv_exp_flow_spec_action_tag){
+		.type = IBV_EXP_FLOW_SPEC_ACTION_COUNT,
+		.size = size,
+		.counter_set = counter,
+	};
+	++flow->ibv_attr->num_of_specs;
+	return counter;
+}
+#endif
+
 /**
  * Convert a flow.
  *
@@ -1172,9 +1223,11 @@ struct mlx5_flow_action {
 		.queue = 0,
 		.drop = 0,
 		.mark = 0,
+		.count = 0,
 		.mark_id = MLX5_FLOW_MARK_DEFAULT,
 		.queues_n = 0,
 	};
+	struct ibv_counter_set *counter = NULL;
 	int err;
 
 	err = priv_flow_validate(priv, attr, items, actions, error, &flow,
@@ -1205,12 +1258,23 @@ struct mlx5_flow_action {
 		mlx5_flow_create_flag_mark(&flow, action.mark_id);
 		flow.offset += sizeof(struct ibv_exp_flow_spec_action_tag);
 	}
+	if (action.count) {
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+		counter = priv_flow_create_counter(priv,&flow,0);
+		if(!counter)
+			goto exit;
+		flow.offset += sizeof(struct ibv_exp_flow_spec_action_count);
+#else
+		goto exit;
+#endif
+	}
 	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);
+	rte_flow->counter = counter;
 	if (!rte_flow)
 		goto exit;
 	return rte_flow;
@@ -1258,6 +1322,12 @@ struct rte_flow *
 		  struct rte_flow *flow)
 {
 	TAILQ_REMOVE(&priv->flows, flow, next);
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+	if (flow->counter) {
+		claim_zero(ibv_destroy_counter_set(flow->counter));
+		flow->counter = NULL;
+	}
+#endif
 	if (flow->ibv_flow)
 		claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
 	if (flow->drop)
@@ -1602,3 +1672,94 @@ struct rte_flow *
 	priv_unlock(priv);
 	return 0;
 }
+
+/**
+ * Internal function to read the counter
+ * value
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param counter_set
+ *   Pointer to counter_set structure
+ * @param res
+ *   Pointer to rte_flow_query_count struct
+ *   used to return the values
+ * @param error
+ *   returns the error.
+ *
+ * @return
+ *   0 success, -1 otherwise.
+ */
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+static int
+priv_flow_query_counter(struct priv *priv,
+		struct ibv_counter_set *counter_set,
+		struct rte_flow_query_count *res,
+		struct rte_flow_error *error)
+{
+	int res_value = 0;
+	uint64_t counters[2];
+	struct ibv_counter_set_description description;
+	struct ibv_query_counter_set_attr attr = { .counter_set = counter_set, };
+	res_value = ibv_query_counter_set(attr,counters);
+	if(res_value < 0) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+								NULL, "Error while querying counter set");
+	}
+	res->hits_set = 1;
+	res->hits = counters[0];
+	res->bytes_set = 1;
+	res->bytes = counters[1];
+	res_value = ibv_query_counter_set(attr,res->hits);
+	return res_value;
+}
+#endif
+
+/**
+ * Query an existing flow rule.
+ *
+ * @see rte_flow_query()
+ * @see rte_flow_ops
+ */
+int
+mlx5_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		enum rte_flow_action_type type,
+		void *res,
+		struct rte_flow_error *error)
+{
+
+	int res_value = 0;
+	switch (type){
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			if (!flow->counter) {
+				rte_flow_error_set(error, EINVAL,
+								   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+								   NULL,
+								   "No counter is set for this flow");
+				return -1;
+			}
+#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
+			res_value = priv_flow_query_counter(mlx5_get_priv(dev), flow->counter,
+					(struct rte_flow_query_count*)res,
+					error);
+#else
+			rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
+									NULL, "Flow count unsupported");
+			(void)dev;
+			(void)flow;
+			(void)type;
+			(void)res;
+			(void)error;
+			return -1;
+#endif
+			break;
+		default:
+			rte_flow_error_set(error, EINVAL,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "Type not supported");
+			res_value = -1;
+	}
+	return res_value;
+}
-- 
1.8.3.1

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

* Re: [RFC] net/mlx5: support count flow action
  2017-08-21 12:35 [RFC] net/mlx5: support count flow action Ori Kam
@ 2017-08-24  6:54 ` Nélio Laranjeiro
  2017-08-24 14:04   ` Ori Kam
  2017-10-10 14:22 ` [PATCH v2] net/mlx5: flow counter support Nelio Laranjeiro
  1 sibling, 1 reply; 7+ messages in thread
From: Nélio Laranjeiro @ 2017-08-24  6:54 UTC (permalink / raw)
  To: Ori Kam; +Cc: adrien.mazaruil, dev

Hi Ori,

Please keep the coding style of the file, and pass checkpatch before
submitting a patch on the mailing list.  It helps the review by having a
correct patch respecting the coding style of the file.
I won't spot out here all the coding style issues, if you need some help, feel
free to ask.

On Mon, Aug 21, 2017 at 03:35:41PM +0300, Ori Kam wrote:
> Support count flow action.

Why copy/pasting the title in the commit message?

> This patch is basic design only, do to missing features on the verbs
> driver. As soon as the features will be implemented on the verbs driver this
> will be updated and rebased on top of dpdk.org/ml/archives/dev/2017-August/072351.html
> (The verbs driver should be ready starting September)
>
> This RFC should be applied on top of
> dpdk.org/ml/archives/dev/2017-August/072351.html

Last two comments should be after '---' line.

> Signed-off-by: Ori Kam <orika@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5.h      |   4 ++
>  drivers/net/mlx5/mlx5_flow.c | 163 ++++++++++++++++++++++++++++++++++++++++++-

There are missing changes in the Makefile to have the
HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT and the include of the
mlx5_autoconf.h in mlx5_flow.c.

>  2 files changed, 166 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
> index e89aba8..434e848 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
>[...] 
> +/**
> + * Query an existing flow rule.
> + *
> + * @see rte_flow_query()
> + * @see rte_flow_ops
> + */
> +int
> +mlx5_flow_query(struct rte_eth_dev *dev,
> +		struct rte_flow *flow,
> +		enum rte_flow_action_type type,
> +		void *res,
> +		struct rte_flow_error *error)
> +{
> +
> +	int res_value = 0;
> +	switch (type){
> +		case RTE_FLOW_ACTION_TYPE_COUNT:
> +			if (!flow->counter) {
> +				rte_flow_error_set(error, EINVAL,
> +								   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +								   NULL,
> +								   "No counter is set for this flow");
> +				return -1;

Wrong returned value, read the rte_flow_query API allowed values.

> +			}
> +#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
> +			res_value = priv_flow_query_counter(mlx5_get_priv(dev), flow->counter,
> +					(struct rte_flow_query_count*)res,
> +					error);
> +#else
> +			rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
> +									NULL, "Flow count unsupported");
> +			(void)dev;
> +			(void)flow;
> +			(void)type;
> +			(void)res;
> +			(void)error;
> +			return -1;

Same here.

> +#endif

I'll suggest to have a dedicated function here to handle this situation, like
a mlx5_flow_query_counters() and call it from this case.  It will clearly ease
the readability and maintenance.

Thanks,

-- 
Nélio Laranjeiro
6WIND

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

* Re: [RFC] net/mlx5: support count flow action
  2017-08-24  6:54 ` Nélio Laranjeiro
@ 2017-08-24 14:04   ` Ori Kam
  2017-08-24 15:08     ` Nélio Laranjeiro
  0 siblings, 1 reply; 7+ messages in thread
From: Ori Kam @ 2017-08-24 14:04 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: adrien.mazaruil, dev

Hi Nelio,

Please see my comments in line.

Ori

> -----Original Message-----
> From: Nélio Laranjeiro [mailto:nelio.laranjeiro@6wind.com]
> Sent: Thursday, August 24, 2017 9:54 AM
> To: Ori Kam <orika@mellanox.com>
> Cc: adrien.mazaruil@6wind.com; dev@dpdk.org
> Subject: Re: [RFC] net/mlx5: support count flow action
> 
> Hi Ori,
> 
> Please keep the coding style of the file, and pass checkpatch before
> submitting a patch on the mailing list.  It helps the review by having a correct
> patch respecting the coding style of the file.
> I won't spot out here all the coding style issues, if you need some help, feel
> free to ask.
> 
Sorry won't happen again.

> On Mon, Aug 21, 2017 at 03:35:41PM +0300, Ori Kam wrote:
> > Support count flow action.
> 
> Why copy/pasting the title in the commit message?
> 
I was under the impression that main function of the RFC should also be in the message body.

> > This patch is basic design only, do to missing features on the verbs
> > driver. As soon as the features will be implemented on the verbs
> > driver this will be updated and rebased on top of
> > dpdk.org/ml/archives/dev/2017-August/072351.html
> > (The verbs driver should be ready starting September)
> >
> > This RFC should be applied on top of
> > dpdk.org/ml/archives/dev/2017-August/072351.html
> 
> Last two comments should be after '---' line.
> 
Those two lines are part of the commit message, any way I will move them.

> > Signed-off-by: Ori Kam <orika@mellanox.com>
> > ---
> >  drivers/net/mlx5/mlx5.h      |   4 ++
> >  drivers/net/mlx5/mlx5_flow.c | 163
> > ++++++++++++++++++++++++++++++++++++++++++-
> 
> There are missing changes in the Makefile to have the
> HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT and the include of the
> mlx5_autoconf.h in mlx5_flow.c.
> 
I haven't added them since this feature is not supported yet, and 
I don't want anybody trying to activate them.
When the feature will be supported on the verbs then I will update
those files. 

> >  2 files changed, 166 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index
> > e89aba8..434e848 100644
> > --- a/drivers/net/mlx5/mlx5.h
> > +++ b/drivers/net/mlx5/mlx5.h
> >[...]
> > +/**
> > + * Query an existing flow rule.
> > + *
> > + * @see rte_flow_query()
> > + * @see rte_flow_ops
> > + */
> > +int
> > +mlx5_flow_query(struct rte_eth_dev *dev,
> > +		struct rte_flow *flow,
> > +		enum rte_flow_action_type type,
> > +		void *res,
> > +		struct rte_flow_error *error)
> > +{
> > +
> > +	int res_value = 0;
> > +	switch (type){
> > +		case RTE_FLOW_ACTION_TYPE_COUNT:
> > +			if (!flow->counter) {
> > +				rte_flow_error_set(error, EINVAL,
> > +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> > +								   NULL,
> > +								   "No counter
> is set for this flow");
> > +				return -1;
> 
> Wrong returned value, read the rte_flow_query API allowed values.
> 
Will be fixed
> > +			}
> > +#ifdef HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT
> > +			res_value =
> priv_flow_query_counter(mlx5_get_priv(dev), flow->counter,
> > +					(struct rte_flow_query_count*)res,
> > +					error);
> > +#else
> > +			rte_flow_error_set(error, ENOTSUP,
> RTE_FLOW_ERROR_TYPE_ACTION,
> > +									NULL,
> "Flow count unsupported");
> > +			(void)dev;
> > +			(void)flow;
> > +			(void)type;
> > +			(void)res;
> > +			(void)error;
> > +			return -1;
> 
> Same here.
> 
Will be fixed.

> > +#endif
> 
> I'll suggest to have a dedicated function here to handle this situation, like a
> mlx5_flow_query_counters() and call it from this case.  It will clearly ease the
> readability and maintenance.
> 
Will be update according to your suggestion.

> Thanks,
> 
> --
> Nélio Laranjeiro
> 6WIND
Thanks,
Ori Kam

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

* Re: [RFC] net/mlx5: support count flow action
  2017-08-24 14:04   ` Ori Kam
@ 2017-08-24 15:08     ` Nélio Laranjeiro
  0 siblings, 0 replies; 7+ messages in thread
From: Nélio Laranjeiro @ 2017-08-24 15:08 UTC (permalink / raw)
  To: Ori Kam; +Cc: adrien.mazaruil, dev

Hi Ori,

On Thu, Aug 24, 2017 at 02:04:32PM +0000, Ori Kam wrote:
> Hi Nelio,
> 
> Please see my comments in line.
> 
> Ori
> 
> > -----Original Message-----
> > From: Nélio Laranjeiro [mailto:nelio.laranjeiro@6wind.com]
> > Sent: Thursday, August 24, 2017 9:54 AM
> > To: Ori Kam <orika@mellanox.com>
> > Cc: adrien.mazaruil@6wind.com; dev@dpdk.org
> > Subject: Re: [RFC] net/mlx5: support count flow action
> > 
> > Hi Ori,
> > 
> > Please keep the coding style of the file, and pass checkpatch before
> > submitting a patch on the mailing list.  It helps the review by having a correct
> > patch respecting the coding style of the file.
> > I won't spot out here all the coding style issues, if you need some help, feel
> > free to ask.
> > 
> Sorry won't happen again.

No problem, first contribution is always complicate.

> > On Mon, Aug 21, 2017 at 03:35:41PM +0300, Ori Kam wrote:
> > > Support count flow action.
> > 
> > Why copy/pasting the title in the commit message?
> > 
> I was under the impression that main function of the RFC should also be in the message body.

No, it is not necessary, the commit message should bring useful information by
still being short and precise.

>[...]
> > > ---
> > >  drivers/net/mlx5/mlx5.h      |   4 ++
> > >  drivers/net/mlx5/mlx5_flow.c | 163
> > > ++++++++++++++++++++++++++++++++++++++++++-
> > 
> > There are missing changes in the Makefile to have the
> > HAVE_VERBS_IBV_EXP_FLOW_SPEC_ACTION_COUNT and the include of the
> > mlx5_autoconf.h in mlx5_flow.c.
> > 
> I haven't added them since this feature is not supported yet, and 
> I don't want anybody trying to activate them.
> When the feature will be supported on the verbs then I will update
> those files. 

Ok, so a new version should be sent soon :)

>[...]
> > 
> Will be update according to your suggestion.
 
Thanks,

-- 
Nélio Laranjeiro
6WIND

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

* [PATCH v2] net/mlx5: flow counter support
  2017-08-21 12:35 [RFC] net/mlx5: support count flow action Ori Kam
  2017-08-24  6:54 ` Nélio Laranjeiro
@ 2017-10-10 14:22 ` Nelio Laranjeiro
  2017-10-10 16:10   ` Yongseok Koh
  1 sibling, 1 reply; 7+ messages in thread
From: Nelio Laranjeiro @ 2017-10-10 14:22 UTC (permalink / raw)
  To: dev; +Cc: Ori Kam, adrien.mazarguil, yskoh, ferruh.yigit

From: Ori Kam <orika@mellanox.com>

Example for setting rule for counting packets with dest
ip = 192.168.3.1 in testpmd:

testpmd: flow create 0 ingress pattern eth / ipv4 dst is 192.168.3.1
/ end actions queue index 0 / count / end

Reading the number of packets and bytes for the rule:

testpmd: flow query 0 0 count

Note: This feature is only supported starting Mellanox OFED 4.2

Signed-off-by: Ori Kam <orika@mellanox.com>
Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>

---

Changes in V2:

 * finalise implementation after all remarks

---
---
 drivers/net/mlx5/Makefile    |   5 ++
 drivers/net/mlx5/mlx5.c      |  12 +++
 drivers/net/mlx5/mlx5.h      |   4 +
 drivers/net/mlx5/mlx5_flow.c | 193 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 214 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index e7aca04..2e90692 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -144,6 +144,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT \
 		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
+		HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT \
+		infiniband/verbs.h \
+		enum IBV_FLOW_SPEC_ACTION_COUNT \
+		$(AUTOCONF_OUTPUT)
 
 # Create mlx5_autoconf.h or update it in case it differs from the new one.
 
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index c0f7b1b..29221dc 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -548,6 +548,9 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 	int idx;
 	int i;
 	struct mlx5dv_context attrs_out;
+#ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+	struct ibv_counter_set_description cs_desc;
+#endif
 
 	(void)pci_drv;
 	assert(pci_drv == &mlx5_driver);
@@ -667,6 +670,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		struct ibv_device_attr_ex device_attr_ex;
 		struct ether_addr mac;
 		uint16_t num_vfs = 0;
+		struct ibv_device_attr_ex device_attr;
 		struct mlx5_args args = {
 			.cqe_comp = MLX5_ARG_UNSET,
 			.txq_inline = MLX5_ARG_UNSET,
@@ -721,6 +725,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			goto port_error;
 		}
 
+		ibv_query_device_ex(ctx, NULL, &device_attr);
 		/* Check port status. */
 		err = ibv_query_port(ctx, port, &port_attr);
 		if (err) {
@@ -798,6 +803,13 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 		DEBUG("L2 tunnel checksum offloads are %ssupported",
 		      (priv->hw_csum_l2tun ? "" : "not "));
 
+#ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+		priv->counter_set_supported = !!(device_attr.max_counter_sets);
+		ibv_describe_counter_set(ctx, 0, &cs_desc);
+		DEBUG("counter type = %d, num of cs = %ld, attributes = %d",
+		      cs_desc.counter_type, cs_desc.num_of_cs,
+		      cs_desc.attributes);
+#endif
 		priv->ind_table_max_size =
 			device_attr_ex.rss_caps.max_rwq_indirection_table_size;
 		/* Remove this check once DPDK supports larger/variable
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 643bab6..9ade624 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -117,6 +117,7 @@ struct priv {
 	unsigned int isolated:1; /* Whether isolated mode is enabled. */
 	unsigned int tx_vec_en:1; /* Whether Tx vector is enabled. */
 	unsigned int rx_vec_en:1; /* Whether Rx vector is enabled. */
+	unsigned int counter_set_supported:1; /* Counter set is supported. */
 	/* Whether Tx offloads for tunneled packets are supported. */
 	unsigned int max_tso_payload_sz; /* Maximum TCP payload for TSO. */
 	unsigned int txq_inline; /* Maximum packet size for inlining. */
@@ -276,6 +277,9 @@ int mlx5_flow_destroy(struct rte_eth_dev *, struct rte_flow *,
 		      struct rte_flow_error *);
 void priv_flow_flush(struct priv *, struct mlx5_flows *);
 int mlx5_flow_flush(struct rte_eth_dev *, struct rte_flow_error *);
+int mlx5_flow_query(struct rte_eth_dev *, struct rte_flow *,
+		    enum rte_flow_action_type, void *,
+		    struct rte_flow_error *);
 int mlx5_flow_isolate(struct rte_eth_dev *, int, struct rte_flow_error *);
 int priv_flow_start(struct priv *, struct mlx5_flows *);
 void priv_flow_stop(struct priv *, struct mlx5_flows *);
diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c
index 3321b3e..2b6380f 100644
--- a/drivers/net/mlx5/mlx5_flow.c
+++ b/drivers/net/mlx5/mlx5_flow.c
@@ -59,6 +59,25 @@
 #define MLX5_IPV4 4
 #define MLX5_IPV6 6
 
+#ifndef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+struct ibv_counter_set_init_attr {
+	int dummy;
+};
+struct ibv_flow_spec_counter_action {
+	int dummy;
+};
+struct ibv_counter_set {
+	int dummy;
+};
+
+static inline int
+ibv_destroy_counter_set(struct ibv_counter_set *cs)
+{
+	(void)cs;
+	return -ENOTSUP;
+}
+#endif
+
 /* Dev ops structure defined in mlx5.c */
 extern const struct eth_dev_ops mlx5_dev_ops;
 extern const struct eth_dev_ops mlx5_dev_ops_isolate;
@@ -107,6 +126,9 @@ mlx5_flow_create_copy(struct mlx5_flow_parse *parser, void *src,
 static int
 mlx5_flow_create_flag_mark(struct mlx5_flow_parse *parser, uint32_t mark_id);
 
+static int
+mlx5_flow_create_count(struct priv *priv, struct mlx5_flow_parse *parser);
+
 /* Hash RX queue types. */
 enum hash_rxq_type {
 	HASH_RXQ_TCPV4,
@@ -190,6 +212,12 @@ const struct hash_rxq_init hash_rxq_init[] = {
 /* Number of entries in hash_rxq_init[]. */
 const unsigned int hash_rxq_init_n = RTE_DIM(hash_rxq_init);
 
+/** Structure for holding counter stats. */
+struct mlx5_flow_counter_stats {
+	uint64_t hits; /**< Number of packets matched by the rule. */
+	uint64_t bytes; /**< Number of bytes matched by the rule. */
+};
+
 /** Structure for Drop queue. */
 struct mlx5_hrxq_drop {
 	struct ibv_rwq_ind_table *ind_table; /**< Indirection table. */
@@ -220,6 +248,8 @@ struct rte_flow {
 	uint16_t (*queues)[]; /**< Queues indexes to use. */
 	struct rte_eth_rss_conf rss_conf; /**< RSS configuration */
 	uint8_t rss_key[40]; /**< copy of the RSS key. */
+	struct ibv_counter_set *cs; /**< Holds the counters for the rule. */
+	struct mlx5_flow_counter_stats counter_stats;/**<The counter stats. */
 	union {
 		struct mlx5_flow frxq[RTE_DIM(hash_rxq_init)];
 		/**< Flow with Rx queue. */
@@ -275,6 +305,9 @@ static const enum rte_flow_action_type valid_actions[] = {
 	RTE_FLOW_ACTION_TYPE_QUEUE,
 	RTE_FLOW_ACTION_TYPE_MARK,
 	RTE_FLOW_ACTION_TYPE_FLAG,
+#ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+	RTE_FLOW_ACTION_TYPE_COUNT,
+#endif
 	RTE_FLOW_ACTION_TYPE_END,
 };
 
@@ -403,12 +436,14 @@ struct mlx5_flow_parse {
 	/**< Whether resources should remain after a validate. */
 	uint32_t drop:1; /**< Target is a drop queue. */
 	uint32_t mark:1; /**< Mark is present in the flow. */
+	uint32_t count:1; /**< Count is present in the flow. */
 	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[]. */
 	struct rte_eth_rss_conf rss_conf; /**< RSS configuration */
 	uint8_t rss_key[40]; /**< copy of the RSS key. */
 	enum hash_rxq_type layer; /**< Last pattern layer detected. */
+	struct ibv_counter_set *cs; /**< Holds the counter set for the rule */
 	union {
 		struct {
 			struct ibv_flow_attr *ibv_attr;
@@ -430,7 +465,11 @@ static const struct rte_flow_ops mlx5_flow_ops = {
 	.create = mlx5_flow_create,
 	.destroy = mlx5_flow_destroy,
 	.flush = mlx5_flow_flush,
+#ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+	.query = mlx5_flow_query,
+#else
 	.query = NULL,
+#endif
 	.isolate = mlx5_flow_isolate,
 };
 
@@ -740,6 +779,9 @@ priv_flow_convert_actions(struct priv *priv,
 			parser->mark_id = mark->id;
 		} else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
 			parser->mark = 1;
+		} else if (actions->type == RTE_FLOW_ACTION_TYPE_COUNT &&
+			   priv->counter_set_supported) {
+			parser->count = 1;
 		} else {
 			goto exit_action_not_supported;
 		}
@@ -837,6 +879,16 @@ priv_flow_convert_items_validate(struct priv *priv,
 			parser->queue[i].offset +=
 				sizeof(struct ibv_flow_spec_action_tag);
 	}
+	if (parser->count) {
+		unsigned int size = sizeof(struct ibv_flow_spec_counter_action);
+
+		if (parser->drop) {
+			parser->drop_q.offset += size;
+		} else {
+			for (i = 0; i != hash_rxq_init_n; ++i)
+				parser->queue[i].offset += size;
+		}
+	}
 	return 0;
 exit_item_not_supported:
 	rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
@@ -1111,6 +1163,11 @@ priv_flow_convert(struct priv *priv,
 	}
 	if (parser->mark)
 		mlx5_flow_create_flag_mark(parser, parser->mark_id);
+	if (parser->count && parser->create) {
+		mlx5_flow_create_count(priv, parser);
+		if (!parser->cs)
+			goto exit_count_error;
+	}
 	/*
 	 * Last step. Complete missing specification to reach the RSS
 	 * configuration.
@@ -1142,6 +1199,10 @@ priv_flow_convert(struct priv *priv,
 	rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
 			   NULL, "cannot allocate verbs spec attributes.");
 	return ret;
+exit_count_error:
+	rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			   NULL, "cannot create counter.");
+	return rte_errno;
 }
 
 /**
@@ -1539,6 +1600,40 @@ mlx5_flow_create_flag_mark(struct mlx5_flow_parse *parser, uint32_t mark_id)
 }
 
 /**
+ * Convert count action to Verbs specification.
+ *
+ * @param priv
+ *   Pointer to private structure.
+ * @param parser
+ *   Pointer to MLX5 flow parser structure.
+ *
+ * @return
+ *   0 on success, errno value on failure.
+ */
+static int
+mlx5_flow_create_count(struct priv *priv __rte_unused,
+		       struct mlx5_flow_parse *parser __rte_unused)
+{
+#ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+	unsigned int size = sizeof(struct ibv_flow_spec_counter_action);
+	struct ibv_counter_set_init_attr init_attr = {0};
+	struct ibv_flow_spec_counter_action counter = {
+		.type = IBV_FLOW_SPEC_ACTION_COUNT,
+		.size = size,
+		.counter_set_handle = 0,
+	};
+
+	init_attr.counter_set_id = 0;
+	parser->cs = ibv_create_counter_set(priv->ctx, &init_attr);
+	if (!parser->cs)
+		return EINVAL;
+	counter.counter_set_handle = parser->cs->handle;
+	mlx5_flow_create_copy(parser, &counter, size);
+#endif
+	return 0;
+}
+
+/**
  * Complete flow rule creation with a drop queue.
  *
  * @param priv
@@ -1580,6 +1675,8 @@ priv_flow_create_action_queue_drop(struct priv *priv,
 	parser->drop_q.ibv_attr = NULL;
 	flow->drxq.ibv_flow = ibv_create_flow(priv->flow_drop_queue->qp,
 					      flow->drxq.ibv_attr);
+	if (parser->count)
+		flow->cs = parser->cs;
 	if (!flow->drxq.ibv_flow) {
 		rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "flow rule creation failure");
@@ -1597,6 +1694,11 @@ priv_flow_create_action_queue_drop(struct priv *priv,
 		rte_free(flow->drxq.ibv_attr);
 		flow->drxq.ibv_attr = NULL;
 	}
+	if (flow->cs) {
+		claim_zero(ibv_destroy_counter_set(flow->cs));
+		flow->cs = NULL;
+		parser->cs = NULL;
+	}
 	return err;
 }
 
@@ -1687,6 +1789,8 @@ priv_flow_create_action_queue(struct priv *priv,
 	err = priv_flow_create_action_queue_rss(priv, parser, flow, error);
 	if (err)
 		goto error;
+	if (parser->count)
+		flow->cs = parser->cs;
 	if (!priv->dev->data->dev_started)
 		return 0;
 	for (i = 0; i != hash_rxq_init_n; ++i) {
@@ -1727,6 +1831,11 @@ priv_flow_create_action_queue(struct priv *priv,
 		if (flow->frxq[i].ibv_attr)
 			rte_free(flow->frxq[i].ibv_attr);
 	}
+	if (flow->cs) {
+		claim_zero(ibv_destroy_counter_set(flow->cs));
+		flow->cs = NULL;
+		parser->cs = NULL;
+	}
 	return err;
 }
 
@@ -1870,6 +1979,10 @@ priv_flow_destroy(struct priv *priv,
 {
 	unsigned int i;
 
+	if (flow->cs) {
+		claim_zero(ibv_destroy_counter_set(flow->cs));
+		flow->cs = NULL;
+	}
 	if (flow->drop || !flow->mark)
 		goto free;
 	for (i = 0; i != flow->queues_n; ++i) {
@@ -2340,6 +2453,86 @@ mlx5_flow_flush(struct rte_eth_dev *dev,
 	return 0;
 }
 
+#ifdef HAVE_IBV_DEVICE_COUNTERS_SET_SUPPORT
+/**
+ * Query flow counter.
+ *
+ * @param cs
+ *   the counter set.
+ * @param counter_value
+ *   returned data from the counter.
+ *
+ * @return
+ *   0 on success, a errno value otherwise and rte_errno is set.
+ */
+static int
+priv_flow_query_count(struct ibv_counter_set *cs,
+		      struct mlx5_flow_counter_stats *counter_stats,
+		      struct rte_flow_query_count *query_count,
+		      struct rte_flow_error *error)
+{
+	uint64_t counters[2];
+	struct ibv_query_counter_set_attr query_cs_attr = {
+		.cs = cs,
+		.query_flags = IBV_COUNTER_SET_FORCE_UPDATE,
+	};
+	struct ibv_counter_set_data query_out = {
+		.out = counters,
+		.outlen = 2 * sizeof(uint64_t),
+	};
+	int res = ibv_query_counter_set(&query_cs_attr, &query_out);
+
+	if (res) {
+		rte_flow_error_set(error, -res,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "cannot read counter");
+		return -res;
+	}
+	query_count->hits_set = 1;
+	query_count->bytes_set = 1;
+	query_count->hits = counters[0] - counter_stats->hits;
+	query_count->bytes = counters[1] - counter_stats->bytes;
+	if (query_count->reset) {
+		counter_stats->hits = counters[0];
+		counter_stats->bytes = counters[1];
+	}
+	return 0;
+}
+
+/**
+ * Query a flows.
+ *
+ * @see rte_flow_query()
+ * @see rte_flow_ops
+ */
+int
+mlx5_flow_query(struct rte_eth_dev *dev,
+		struct rte_flow *flow,
+		enum rte_flow_action_type action __rte_unused,
+		void *data,
+		struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	int res = EINVAL;
+
+	priv_lock(priv);
+	if (flow->cs) {
+		res = priv_flow_query_count(flow->cs,
+					&flow->counter_stats,
+					(struct rte_flow_query_count *)data,
+					error);
+	} else {
+		rte_flow_error_set(error, res,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				   NULL,
+				   "no counter found for flow");
+	}
+	priv_unlock(priv);
+	return -res;
+}
+#endif
+
 /**
  * Isolated mode.
  *
-- 
2.1.4

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

* Re: [PATCH v2] net/mlx5: flow counter support
  2017-10-10 14:22 ` [PATCH v2] net/mlx5: flow counter support Nelio Laranjeiro
@ 2017-10-10 16:10   ` Yongseok Koh
  2017-10-11  1:32     ` Ferruh Yigit
  0 siblings, 1 reply; 7+ messages in thread
From: Yongseok Koh @ 2017-10-10 16:10 UTC (permalink / raw)
  To: Nélio Laranjeiro; +Cc: dev, Ori Kam, Adrien Mazarguil, ferruh.yigit

> On Oct 10, 2017, at 7:22 AM, Nelio Laranjeiro <nelio.laranjeiro@6wind.com> wrote:
> 
> From: Ori Kam <orika@mellanox.com>
> 
> Example for setting rule for counting packets with dest
> ip = 192.168.3.1 in testpmd:
> 
> testpmd: flow create 0 ingress pattern eth / ipv4 dst is 192.168.3.1
> / end actions queue index 0 / count / end
> 
> Reading the number of packets and bytes for the rule:
> 
> testpmd: flow query 0 0 count
> 
> Note: This feature is only supported starting Mellanox OFED 4.2
> 
> Signed-off-by: Ori Kam <orika@mellanox.com>
> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
> 
> ---
Acked-by: Yongseok Koh <yskoh@mellanox.com>
 
Thanks

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

* Re: [PATCH v2] net/mlx5: flow counter support
  2017-10-10 16:10   ` Yongseok Koh
@ 2017-10-11  1:32     ` Ferruh Yigit
  0 siblings, 0 replies; 7+ messages in thread
From: Ferruh Yigit @ 2017-10-11  1:32 UTC (permalink / raw)
  To: Yongseok Koh, Nélio Laranjeiro; +Cc: dev, Ori Kam, Adrien Mazarguil

On 10/10/2017 5:10 PM, Yongseok Koh wrote:
>> On Oct 10, 2017, at 7:22 AM, Nelio Laranjeiro <nelio.laranjeiro@6wind.com> wrote:
>>
>> From: Ori Kam <orika@mellanox.com>
>>
>> Example for setting rule for counting packets with dest
>> ip = 192.168.3.1 in testpmd:
>>
>> testpmd: flow create 0 ingress pattern eth / ipv4 dst is 192.168.3.1
>> / end actions queue index 0 / count / end
>>
>> Reading the number of packets and bytes for the rule:
>>
>> testpmd: flow query 0 0 count
>>
>> Note: This feature is only supported starting Mellanox OFED 4.2
>>
>> Signed-off-by: Ori Kam <orika@mellanox.com>
>> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>

> Acked-by: Yongseok Koh <yskoh@mellanox.com>

Applied to dpdk-next-net/master, thanks.

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

end of thread, other threads:[~2017-10-11  1:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-21 12:35 [RFC] net/mlx5: support count flow action Ori Kam
2017-08-24  6:54 ` Nélio Laranjeiro
2017-08-24 14:04   ` Ori Kam
2017-08-24 15:08     ` Nélio Laranjeiro
2017-10-10 14:22 ` [PATCH v2] net/mlx5: flow counter support Nelio Laranjeiro
2017-10-10 16:10   ` Yongseok Koh
2017-10-11  1:32     ` Ferruh Yigit

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.