DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v1 0/3] support flow counters using devx
@ 2018-12-25 14:38 Mordechay Haimovsky
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic Mordechay Haimovsky
                   ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-25 14:38 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This series of commits add support for creating, allocating, querying
and destroying flow counters in mlx5 PMD using the devx interface.

Moti Haimovsky (3):
  net/mlx5: modify shared counter allocation logic
  net/mlx5: add devx functions to glue
  net/mlx5: support flow counters using devx

 drivers/net/mlx5/Makefile          |  11 ++
 drivers/net/mlx5/meson.build       |   7 ++
 drivers/net/mlx5/mlx5.c            |  17 ++-
 drivers/net/mlx5/mlx5.h            |   1 +
 drivers/net/mlx5/mlx5_devx_cmds.c  | 117 +++++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h       |  12 +-
 drivers/net/mlx5/mlx5_flow_dv.c    | 232 +++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_flow_verbs.c |  14 +--
 drivers/net/mlx5/mlx5_glue.c       | 100 ++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h       |  19 +++
 drivers/net/mlx5/mlx5_prm.h        |  86 ++++++++++++++
 11 files changed, 593 insertions(+), 23 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic
  2018-12-25 14:38 [dpdk-dev] [PATCH v1 0/3] support flow counters using devx Mordechay Haimovsky
@ 2018-12-25 14:38 ` Mordechay Haimovsky
  2018-12-27  8:12   ` Shahaf Shuler
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2 siblings, 1 reply; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-25 14:38 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This commit modifies the logic for searching an allocating a shared
counter in mlx5_flow_verbs.

modifies commit 84c406e74524 ("net/mlx5: add flow translate function")

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
 drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 81ec59d..409e1cd 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -121,13 +121,13 @@
 	struct mlx5_flow_counter *cnt;
 	int ret;
 
-	LIST_FOREACH(cnt, &priv->flow_counters, next) {
-		if (!cnt->shared || cnt->shared != shared)
-			continue;
-		if (cnt->id != id)
-			continue;
-		cnt->ref_cnt++;
-		return cnt;
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
 	}
 	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
 	if (!cnt) {
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue
  2018-12-25 14:38 [dpdk-dev] [PATCH v1 0/3] support flow counters using devx Mordechay Haimovsky
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic Mordechay Haimovsky
@ 2018-12-25 14:38 ` Mordechay Haimovsky
  2018-12-27  8:12   ` Shahaf Shuler
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2 siblings, 1 reply; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-25 14:38 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This patch adds glue functions for operations:
  - dv_open_device.
  - devx object create, destroy, query and modify.
  - devx general command
The new operations depend on HAVE_IBV_DEVX_OBJ.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
 drivers/net/mlx5/Makefile    |  5 +++
 drivers/net/mlx5/meson.build |  2 +
 drivers/net/mlx5/mlx5_glue.c | 99 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 19 +++++++++
 4 files changed, 125 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 895cdfe..58e2d15 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -148,6 +148,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_DEVX_OBJ \
+		infiniband/mlx5dv.h \
+		func mlx5dv_devx_obj_create \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 28938db..e323c3a 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -104,6 +104,8 @@ if build
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
+		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
+		'mlx5dv_devx_obj_create' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index dd10ad6..7d3d9d3 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -479,6 +479,99 @@
 #endif
 }
 
+static struct ibv_context *
+mlx5_glue_dv_open_device(struct ibv_device *device)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_open_device(device,
+				  &(struct mlx5dv_context_attr){
+					.flags = MLX5DV_CONTEXT_FLAGS_DEVX,
+				  });
+#else
+	(void)device;
+	return NULL;
+#endif
+}
+
+static struct mlx5dv_devx_obj *
+mlx5_glue_devx_obj_create(struct ibv_context *ctx,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_create(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return NULL;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_destroy(struct mlx5dv_devx_obj *obj)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_destroy(obj);
+#else
+	(void)obj;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_query(struct mlx5dv_devx_obj *obj,
+			 const void *in, size_t inlen,
+			 void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_query(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_modify(struct mlx5dv_devx_obj *obj,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_modify(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_general_cmd(struct ibv_context *ctx,
+			   const void *in, size_t inlen,
+			   void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_general_cmd(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
 	.version = MLX5_GLUE_VERSION,
@@ -535,4 +628,10 @@
 	.dv_create_flow = mlx5_glue_dv_create_flow,
 	.dv_create_flow_action_packet_reformat =
 			mlx5_glue_dv_create_flow_action_packet_reformat,
+	.dv_open_device = mlx5_glue_dv_open_device,
+	.devx_obj_create = mlx5_glue_devx_obj_create,
+	.devx_obj_destroy = mlx5_glue_devx_obj_destroy,
+	.devx_obj_query = mlx5_glue_devx_obj_query,
+	.devx_obj_modify = mlx5_glue_devx_obj_modify,
+	.devx_general_cmd = mlx5_glue_devx_general_cmd,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 2d92ba8..a6cd2cd 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -55,6 +55,10 @@
 enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
+#ifndef HAVE_IBV_DEVX_OBJ
+struct mlx5dv_devx_obj;
+#endif
+
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
 struct mlx5_glue {
 	const char *version;
@@ -164,6 +168,21 @@ struct mlx5_glue {
 		 void *data,
 		 enum mlx5dv_flow_action_packet_reformat_type reformat_type,
 		 enum mlx5dv_flow_table_type ft_type);
+	struct ibv_context *(*dv_open_device)(struct ibv_device *device);
+	struct mlx5dv_devx_obj *(*devx_obj_create)
+					(struct ibv_context *ctx,
+					 const void *in, size_t inlen,
+					 void *out, size_t outlen);
+	int (*devx_obj_destroy)(struct mlx5dv_devx_obj *obj);
+	int (*devx_obj_query)(struct mlx5dv_devx_obj *obj,
+			      const void *in, size_t inlen,
+			      void *out, size_t outlen);
+	int (*devx_obj_modify)(struct mlx5dv_devx_obj *obj,
+			       const void *in, size_t inlen,
+			       void *out, size_t outlen);
+	int (*devx_general_cmd)(struct ibv_context *context,
+				const void *in, size_t inlen,
+				void *out, size_t outlen);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx
  2018-12-25 14:38 [dpdk-dev] [PATCH v1 0/3] support flow counters using devx Mordechay Haimovsky
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic Mordechay Haimovsky
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
@ 2018-12-25 14:38 ` Mordechay Haimovsky
  2018-12-27  8:15   ` Shahaf Shuler
                     ` (4 more replies)
  2 siblings, 5 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-25 14:38 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This commit adds counters support when creating flows via direct
verbs. The implementation uses devx interface in order to create
query and delete the counters.
This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
 drivers/net/mlx5/Makefile         |   6 +
 drivers/net/mlx5/meson.build      |   5 +
 drivers/net/mlx5/mlx5.c           |  17 ++-
 drivers/net/mlx5/mlx5.h           |   1 +
 drivers/net/mlx5/mlx5_devx_cmds.c | 117 +++++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h      |  12 +-
 drivers/net/mlx5/mlx5_flow_dv.c   | 232 ++++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_glue.c      |   1 +
 drivers/net/mlx5/mlx5_prm.h       |  86 ++++++++++++++
 9 files changed, 461 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 58e2d15..bd96706 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_tcf.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_devx_cmds.c
 
 ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y)
 INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib += $(LIB_GLUE)
@@ -153,6 +154,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_devx_obj_create \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_FLOW_DEVX_COUNTERS \
+		infiniband/mlx5dv.h \
+		enum MLX5DV_FLOW_ACTION_COUNTER_DEVX \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e323c3a..9a5077d 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -46,6 +46,7 @@ if build
 		'mlx5_trigger.c',
 		'mlx5_txq.c',
 		'mlx5_vlan.c',
+		'mlx5_devx_cmds.c',
 	)
 	if dpdk_conf.has('RTE_ARCH_X86_64') or dpdk_conf.has('RTE_ARCH_ARM64')
 		sources += files('mlx5_rxtx_vec.c')
@@ -100,6 +101,10 @@ if build
 		'MLX5DV_CQ_INIT_ATTR_FLAGS_CQE_PAD' ],
 		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
 		'mlx5dv_create_flow_action_packet_reformat' ],
+		[ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h',
+		'MLX5DV_FLOW_ACTION_COUNTER_DEVX' ],
+		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
+		'MLX5DV_CONTEXT_FLAGS_DEVX' ],
 		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 9e5cab1..1e00b8b 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -727,7 +727,7 @@
 	       struct mlx5_dev_config config,
 	       const struct mlx5_switch_info *switch_info)
 {
-	struct ibv_context *ctx;
+	struct ibv_context *ctx = NULL;
 	struct ibv_device_attr_ex attr;
 	struct ibv_port_attr port_attr;
 	struct ibv_pd *pd = NULL;
@@ -786,10 +786,17 @@
 	/* Prepare shared data between primary and secondary process. */
 	mlx5_prepare_shared_data();
 	errno = 0;
-	ctx = mlx5_glue->open_device(ibv_dev);
-	if (!ctx) {
-		rte_errno = errno ? errno : ENODEV;
-		return NULL;
+	ctx = mlx5_glue->dv_open_device(ibv_dev);
+	if (ctx) {
+		config.devx = 1;
+		DRV_LOG(DEBUG, "DEVX is %ssupported",
+			config.devx ? "" : "not ");
+	} else {
+		ctx = mlx5_glue->open_device(ibv_dev);
+		if (!ctx) {
+			rte_errno = errno ? errno : ENODEV;
+			return NULL;
+		}
 	}
 #ifdef HAVE_IBV_MLX5_MOD_SWP
 	dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 75aeeb2..1fcdb71 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -129,6 +129,7 @@ struct mlx5_dev_config {
 	unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */
 	unsigned int dv_flow_en:1; /* Enable DV flow. */
 	unsigned int swp:1; /* Tx generic tunnel checksum and TSO offload. */
+	unsigned int devx:1; /* Whether devx interface is available or not. */
 	struct {
 		unsigned int enabled:1; /* Whether MPRQ is enabled. */
 		unsigned int stride_num_n; /* Number of strides. */
diff --git a/drivers/net/mlx5/mlx5_devx_cmds.c b/drivers/net/mlx5/mlx5_devx_cmds.c
new file mode 100644
index 0000000..a3f421e
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_devx_cmds.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright 2018 Mellanox Technologies, Ltd */
+
+#include <rte_flow_driver.h>
+
+#include "mlx5.h"
+#include "mlx5_glue.h"
+#include "mlx5_prm.h"
+
+/*
+ * Dummy struct to prevent compilation errors when
+ * mlx5dv_devx_obj is not defined in mlx5dv.h
+ */
+#ifndef HAVE_IBV_DEVX_OBJ
+struct mlx5dv_devx_obj {
+	void *ctx;
+};
+#endif /* HAVE_IBV_DEVX_OBJ */
+
+/**
+ * Allocate flow counters via devx interface.
+ *
+ * @param[in] ctx
+ *   ibv contexts returned from mlx5dv_open_device.
+ * @param dcs
+ *   Pointer to counters properties structure to be filled by the routine.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcs)
+{
+	uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)]   = {0};
+	uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0};
+	int status, syndrome;
+
+	MLX5_SET(alloc_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
+	dcs->obj = mlx5_glue->devx_obj_create(ctx, in,
+					      sizeof(in), out, sizeof(out));
+	if (!dcs->obj)
+		return -errno;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to create devx counters, "
+			"status %x, syndrome %x", status, syndrome);
+		return -1;
+	}
+	dcs->id = MLX5_GET(alloc_flow_counter_out,
+			   out, flow_counter_id);
+	return 0;
+}
+
+/**
+ * Free flow counters obtained via devx interface.
+ *
+ * @param[in] obj
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj)
+{
+	return mlx5_glue->devx_obj_destroy(obj);
+}
+
+/**
+ * Query flow counters values.
+ *
+ * @param[in] dcs
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ * @param[in] clear
+ *   Whether hardware should clear the counters after the query or not.
+ *  @param pkts
+ *   The number of packets that matched the flow.
+ *  @param bytes
+ *    The number of bytes that matched the flow.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs,
+				 int clear __rte_unused,
+				 uint64_t *pkts, uint64_t *bytes)
+{
+	uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
+		MLX5_ST_SZ_BYTES(traffic_counter)]   = {0};
+	uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0};
+	void *stats;
+	int status, syndrome, rc;
+
+	MLX5_SET(query_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
+	MLX5_SET(query_flow_counter_in, in, op_mod, 0);
+	MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id);
+	rc = mlx5_glue->devx_obj_query(dcs->obj,
+				       in, sizeof(in), out, sizeof(out));
+	if (rc)
+		return rc;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to query devx counters, "
+			"id %d, status %x, syndrome = %x",
+			status, syndrome, dcs->id);
+		return -1;
+	}
+	stats = MLX5_ADDR_OF(query_flow_counter_out,
+			     out, flow_statistics);
+	*pkts = MLX5_GET64(traffic_counter, stats, packets);
+	*bytes = MLX5_GET64(traffic_counter, stats, octets);
+	return 0;
+}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index 4a7c052..838c85a 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -21,6 +21,9 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include "mlx5.h"
+#include "mlx5_prm.h"
+
 /* Pattern outer Layer bits. */
 #define MLX5_FLOW_LAYER_OUTER_L2 (1u << 0)
 #define MLX5_FLOW_LAYER_OUTER_L3_IPV4 (1u << 1)
@@ -273,13 +276,16 @@ struct mlx5_flow {
 struct mlx5_flow_counter {
 	LIST_ENTRY(mlx5_flow_counter) next; /**< Pointer to the next counter. */
 	uint32_t shared:1; /**< Share counter ID with other flow rules. */
-	uint32_t ref_cnt:31; /**< Reference counter. */
+	uint32_t ref_cnt:30; /**< Reference counter. */
 	uint32_t id; /**< Counter ID. */
+	union {  /**< Holds the counters for the rule. */
 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
-	struct ibv_counter_set *cs; /**< Holds the counters for the rule. */
+		struct ibv_counter_set *cs;
 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
-	struct ibv_counters *cs; /**< Holds the counters for the rule. */
+		struct ibv_counters *cs;
 #endif
+		struct mlx5_devx_counter_set *dcs;
+	};
 	uint64_t hits; /**< Number of packets matched by the rule. */
 	uint64_t bytes; /**< Number of bytes matched by the rule. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 1f31874..14dadce 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -97,6 +97,36 @@
 }
 
 /**
+ * Validate count action.
+ *
+ * @param[in] dev
+ *   device otr.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_count(struct rte_eth_dev *dev,
+			      struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+
+	if (!priv->config.devx)
+		goto notsup_err;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+	return 0;
+#endif
+notsup_err:
+	return rte_flow_error_set
+		      (error, ENOTSUP,
+		       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+		       NULL,
+		       "count action not supported");
+}
+
+/**
  * Validate the L2 encap action.
  *
  * @param[in] action_flags
@@ -704,6 +734,87 @@
 }
 
 /**
+ * Get or create a flow counter.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] shared
+ *   Indicate if this counter is shared with other flows.
+ * @param[in] id
+ *   Counter identifier.
+ *
+ * @return
+ *   pointer to flow counter on success, NULL otherwise and rte_errno is set.
+ */
+static struct mlx5_flow_counter *
+flow_dv_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_counter *cnt = NULL;
+	struct mlx5_devx_counter_set *dcs = NULL;
+	int ret;
+
+	if (!priv->config.devx) {
+		ret = -ENOTSUP;
+		goto error_exit;
+	}
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
+	}
+	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
+	dcs = rte_calloc(__func__, 1, sizeof(*dcs), 0);
+	if (!dcs || !cnt) {
+		ret = -ENOMEM;
+		goto error_exit;
+	}
+	ret = mlx5_devx_cmd_flow_counter_alloc(priv->ctx, dcs);
+	if (ret)
+		goto error_exit;
+	struct mlx5_flow_counter tmpl = {
+		.shared = shared,
+		.ref_cnt = 1,
+		.id = id,
+		.dcs = dcs,
+	};
+	*cnt = tmpl;
+	LIST_INSERT_HEAD(&priv->flow_counters, cnt, next);
+	return cnt;
+error_exit:
+	rte_free(cnt);
+	rte_free(dcs);
+	rte_errno = -ret;
+	return NULL;
+}
+
+/**
+ * Release a flow counter.
+ *
+ * @param[in] counter
+ *   Pointer to the counter handler.
+ */
+static void
+flow_dv_counter_release(struct mlx5_flow_counter *counter)
+{
+	int ret;
+
+	if (!counter)
+		return;
+	if (--counter->ref_cnt == 0) {
+		ret = mlx5_devx_cmd_flow_counter_free(counter->dcs->obj);
+		if (ret)
+			DRV_LOG(ERR, "Failed to free devx counters, %d", ret);
+		LIST_REMOVE(counter, next);
+		rte_free(counter->dcs);
+		rte_free(counter);
+	}
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -965,7 +1076,7 @@
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
-			ret = mlx5_flow_validate_action_count(dev, attr, error);
+			ret = flow_dv_validate_action_count(dev, error);
 			if (ret < 0)
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
@@ -1902,6 +2013,9 @@
 		const struct rte_flow_action_queue *queue;
 		const struct rte_flow_action_rss *rss;
 		const struct rte_flow_action *action = actions;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+		const struct rte_flow_action_count *count = action->conf;
+#endif
 		const uint8_t *rss_key;
 
 		switch (actions->type) {
@@ -1950,6 +2064,37 @@
 			flow->rss.level = rss->level;
 			action_flags |= MLX5_FLOW_ACTION_RSS;
 			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			if (!priv->config.devx) {
+				rte_errno = ENOTSUP;
+				goto cnt_err;
+			}
+			flow->counter =
+				flow_dv_counter_new(dev,
+						    count->shared, count->id);
+			if (flow->counter == NULL)
+				goto cnt_err;
+			dev_flow->dv.actions[actions_n].type =
+					MLX5DV_FLOW_ACTION_COUNTER_DEVX;
+			dev_flow->dv.actions[actions_n].obj =
+						flow->counter->dcs->obj;
+			action_flags |= MLX5_FLOW_ACTION_COUNT;
+			++actions_n;
+			break;
+cnt_err:
+			if (rte_errno == ENOTSUP)
+				return rte_flow_error_set
+					      (error, ENOTSUP,
+					       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					       NULL,
+					       "count action not supported");
+			else
+				return rte_flow_error_set
+						(error, rte_errno,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 action,
+						 "cannot create counter"
+						  " object.");
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			if (flow_dv_create_action_l2_encap(dev, actions,
@@ -2338,8 +2483,6 @@
 			dv->hrxq = NULL;
 		}
 	}
-	if (flow->counter)
-		flow->counter = NULL;
 }
 
 /**
@@ -2358,6 +2501,10 @@
 	if (!flow)
 		return;
 	flow_dv_remove(dev, flow);
+	if (flow->counter) {
+		flow_dv_counter_release(flow->counter);
+		flow->counter = NULL;
+	}
 	while (!LIST_EMPTY(&flow->dev_flows)) {
 		dev_flow = LIST_FIRST(&flow->dev_flows);
 		LIST_REMOVE(dev_flow, next);
@@ -2370,22 +2517,91 @@
 }
 
 /**
+ * Query a dv flow  rule for its statistics via devx.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] flow
+ *   Pointer to the sub flow.
+ * @param[out] data
+ *   data retrieved by the query.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
+		    void *data, struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct rte_flow_query_count *qc = data;
+	uint64_t pkts = 0;
+	uint64_t bytes = 0;
+	int err;
+
+	if (!priv->config.devx)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "counters are not supported");
+	if (flow->counter) {
+		err = mlx5_devx_cmd_flow_counter_query
+						(flow->counter->dcs,
+						 qc->reset, &pkts, &bytes);
+		if (err)
+			return rte_flow_error_set
+				(error, err,
+				 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				 NULL,
+				 "cannot read counters");
+		qc->hits_set = 1;
+		qc->bytes_set = 1;
+		qc->hits = pkts - flow->counter->hits;
+		qc->bytes = bytes - flow->counter->bytes;
+		if (qc->reset) {
+			flow->counter->hits = pkts;
+			flow->counter->bytes = bytes;
+		}
+		return 0;
+	}
+	return rte_flow_error_set(error, EINVAL,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL,
+				  "counters are not available");
+}
+
+/**
  * Query a flow.
  *
  * @see rte_flow_query()
  * @see rte_flow_ops
  */
 static int
-flow_dv_query(struct rte_eth_dev *dev __rte_unused,
+flow_dv_query(struct rte_eth_dev *dev,
 	      struct rte_flow *flow __rte_unused,
 	      const struct rte_flow_action *actions __rte_unused,
 	      void *data __rte_unused,
 	      struct rte_flow_error *error __rte_unused)
 {
-	return rte_flow_error_set(error, ENOTSUP,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL,
-				  "flow query with DV is not supported");
+	int ret = -EINVAL;
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow_dv_query_count(dev, flow, data, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  actions,
+						  "action not supported");
+		}
+	}
+	return ret;
 }
 
 
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 7d3d9d3..4078b54 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -65,6 +65,7 @@
 	return ibv_open_device(device);
 }
 
+
 static int
 mlx5_glue_close_device(struct ibv_context *context)
 {
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 29742b1..812b4bf 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -368,6 +368,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_dw_bit_off(typ, fld) (32 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0x1f))
 #define __mlx5_dw_off(typ, fld) (__mlx5_bit_off(typ, fld) / 32)
+#define __mlx5_64_off(typ, fld) (__mlx5_bit_off(typ, fld) / 64)
 #define __mlx5_dw_mask(typ, fld) (__mlx5_mask(typ, fld) << \
 				  __mlx5_dw_bit_off(typ, fld))
 #define __mlx5_mask(typ, fld) ((u32)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
@@ -375,6 +376,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_16_bit_off(typ, fld) (16 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0xf))
 #define __mlx5_mask16(typ, fld) ((u16)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
+#define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32)
 #define MLX5_ST_SZ_DB(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8)
@@ -391,10 +393,16 @@ struct mlx5_modification_cmd {
 				 (((_v) & __mlx5_mask(typ, fld)) << \
 				   __mlx5_dw_bit_off(typ, fld))); \
 	} while (0)
+#define MLX5_GET(typ, p, fld) \
+	((rte_be_to_cpu_32(*((__be32 *)(p) +\
+	__mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
+	__mlx5_mask(typ, fld))
 #define MLX5_GET16(typ, p, fld) \
 	((rte_be_to_cpu_16(*((__be16 *)(p) + \
 	  __mlx5_16_off(typ, fld))) >> __mlx5_16_bit_off(typ, fld)) & \
 	 __mlx5_mask16(typ, fld))
+#define MLX5_GET64(typ, p, fld) rte_be_to_cpu_64(*((__be64 *)(p) + \
+						   __mlx5_64_off(typ, fld)))
 #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8)
 
 struct mlx5_ifc_fte_match_set_misc_bits {
@@ -500,6 +508,69 @@ enum {
 	MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT
 };
 
+enum {
+	MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939,
+	MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b,
+};
+
+/* Flow counters. */
+struct mlx5_ifc_alloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_alloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_traffic_counter_bits {
+	u8         packets[0x40];
+	u8         octets[0x40];
+};
+
+struct mlx5_ifc_query_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+	struct mlx5_ifc_traffic_counter_bits flow_statistics[];
+};
+
+struct mlx5_ifc_query_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x80];
+	u8         clear[0x1];
+	u8         reserved_at_c1[0xf];
+	u8         num_of_counters[0x10];
+	u8         flow_counter_id[0x20];
+};
+
 /* CQE format mask. */
 #define MLX5E_CQE_FORMAT_MASK 0xc
 
@@ -581,4 +652,19 @@ struct mlx5_mini_cqe8 {
 #endif
 }
 
+
+/* devx counyter object */
+struct mlx5_devx_counter_set {
+	struct mlx5dv_devx_obj *obj;
+	int id; /* Flow counter ID */
+};
+
+/* mlx5_devx_cmds.c */
+
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcx);
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj);
+int mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcx,
+				     int clear,
+				     uint64_t *pkts, uint64_t *bytes);
 #endif /* RTE_PMD_MLX5_PRM_H_ */
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic Mordechay Haimovsky
@ 2018-12-27  8:12   ` Shahaf Shuler
  0 siblings, 0 replies; 24+ messages in thread
From: Shahaf Shuler @ 2018-12-27  8:12 UTC (permalink / raw)
  To: Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky

Tuesday, December 25, 2018 4:39 PM, Mordechay Haimovsky:
> Subject: [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation
> logic
> 
> This commit modifies the logic for searching an allocating a shared counter in
> mlx5_flow_verbs.

Need to explain - why you change it?
I assume it is because only shared counters need to be search on the PMD database, correct?

> 
> modifies commit 84c406e74524 ("net/mlx5: add flow translate function")

If above correct, better to introduce it as fix commit w/ Cc: stable@dpdk.org

> 
> Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> ---
>  drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c
> b/drivers/net/mlx5/mlx5_flow_verbs.c
> index 81ec59d..409e1cd 100644
> --- a/drivers/net/mlx5/mlx5_flow_verbs.c
> +++ b/drivers/net/mlx5/mlx5_flow_verbs.c
> @@ -121,13 +121,13 @@
>  	struct mlx5_flow_counter *cnt;
>  	int ret;
> 
> -	LIST_FOREACH(cnt, &priv->flow_counters, next) {
> -		if (!cnt->shared || cnt->shared != shared)
> -			continue;
> -		if (cnt->id != id)
> -			continue;
> -		cnt->ref_cnt++;
> -		return cnt;
> +	if (shared) {
> +		LIST_FOREACH(cnt, &priv->flow_counters, next) {
> +			if (cnt->shared && cnt->id == id) {
> +				cnt->ref_cnt++;
> +				return cnt;
> +			}
> +		}
>  	}
>  	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
>  	if (!cnt) {
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
@ 2018-12-27  8:12   ` Shahaf Shuler
  0 siblings, 0 replies; 24+ messages in thread
From: Shahaf Shuler @ 2018-12-27  8:12 UTC (permalink / raw)
  To: Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky, Dekel Peled

Tuesday, December 25, 2018 4:39 PM, Mordechay Haimovsky:
> Subject: [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue
> 
> This patch adds glue functions for operations:
>   - dv_open_device.
>   - devx object create, destroy, query and modify.
>   - devx general command
> The new operations depend on HAVE_IBV_DEVX_OBJ.
> 
> Signed-off-by: Moti Haimovsky <motih@mellanox.com>

Acked-by: Shahaf Shuler <shahafs@mellanox.com>

Note in general you need also the bump the LIB_GLUE version, but there is a commit which do it already: https://patches.dpdk.org/patch/49277/
Please make sure you rebase on top of it. 

> ---
>  drivers/net/mlx5/Makefile    |  5 +++
>  drivers/net/mlx5/meson.build |  2 +
>  drivers/net/mlx5/mlx5_glue.c | 99
> ++++++++++++++++++++++++++++++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h | 19 +++++++++
>  4 files changed, 125 insertions(+)
> 
> diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index
> 895cdfe..58e2d15 100644
> --- a/drivers/net/mlx5/Makefile
> +++ b/drivers/net/mlx5/Makefile
> @@ -148,6 +148,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-
> config-h.sh
>  		func mlx5dv_create_flow_action_packet_reformat \
>  		$(AUTOCONF_OUTPUT)
>  	$Q sh -- '$<' '$@' \
> +		HAVE_IBV_DEVX_OBJ \
> +		infiniband/mlx5dv.h \
> +		func mlx5dv_devx_obj_create \
> +		$(AUTOCONF_OUTPUT)
> +	$Q sh -- '$<' '$@' \
>  		HAVE_ETHTOOL_LINK_MODE_25G \
>  		/usr/include/linux/ethtool.h \
>  		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \ diff --
> git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build index
> 28938db..e323c3a 100644
> --- a/drivers/net/mlx5/meson.build
> +++ b/drivers/net/mlx5/meson.build
> @@ -104,6 +104,8 @@ if build
>  		'IBV_FLOW_SPEC_MPLS' ],
>  		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING',
> 'infiniband/verbs.h',
>  		'IBV_WQ_FLAG_RX_END_PADDING' ],
> +		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
> +		'mlx5dv_devx_obj_create' ],
>  		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
>  		'SUPPORTED_40000baseKR4_Full' ],
>  		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c index
> dd10ad6..7d3d9d3 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -479,6 +479,99 @@
>  #endif
>  }
> 
> +static struct ibv_context *
> +mlx5_glue_dv_open_device(struct ibv_device *device) { #ifdef
> +HAVE_IBV_DEVX_OBJ
> +	return mlx5dv_open_device(device,
> +				  &(struct mlx5dv_context_attr){
> +					.flags =
> MLX5DV_CONTEXT_FLAGS_DEVX,
> +				  });
> +#else
> +	(void)device;
> +	return NULL;
> +#endif
> +}
> +
> +static struct mlx5dv_devx_obj *
> +mlx5_glue_devx_obj_create(struct ibv_context *ctx,
> +			  const void *in, size_t inlen,
> +			  void *out, size_t outlen)
> +{
> +#ifdef HAVE_IBV_DEVX_OBJ
> +	return mlx5dv_devx_obj_create(ctx, in, inlen, out, outlen); #else
> +	(void)ctx;
> +	(void)in;
> +	(void)inlen;
> +	(void)out;
> +	(void)outlen;
> +	return NULL;
> +#endif
> +}
> +
> +static int
> +mlx5_glue_devx_obj_destroy(struct mlx5dv_devx_obj *obj) { #ifdef
> +HAVE_IBV_DEVX_OBJ
> +	return mlx5dv_devx_obj_destroy(obj);
> +#else
> +	(void)obj;
> +	return -ENOTSUP;
> +#endif
> +}
> +
> +static int
> +mlx5_glue_devx_obj_query(struct mlx5dv_devx_obj *obj,
> +			 const void *in, size_t inlen,
> +			 void *out, size_t outlen)
> +{
> +#ifdef HAVE_IBV_DEVX_OBJ
> +	return mlx5dv_devx_obj_query(obj, in, inlen, out, outlen); #else
> +	(void)obj;
> +	(void)in;
> +	(void)inlen;
> +	(void)out;
> +	(void)outlen;
> +	return -ENOTSUP;
> +#endif
> +}
> +
> +static int
> +mlx5_glue_devx_obj_modify(struct mlx5dv_devx_obj *obj,
> +			  const void *in, size_t inlen,
> +			  void *out, size_t outlen)
> +{
> +#ifdef HAVE_IBV_DEVX_OBJ
> +	return mlx5dv_devx_obj_modify(obj, in, inlen, out, outlen); #else
> +	(void)obj;
> +	(void)in;
> +	(void)inlen;
> +	(void)out;
> +	(void)outlen;
> +	return -ENOTSUP;
> +#endif
> +}
> +
> +static int
> +mlx5_glue_devx_general_cmd(struct ibv_context *ctx,
> +			   const void *in, size_t inlen,
> +			   void *out, size_t outlen)
> +{
> +#ifdef HAVE_IBV_DEVX_OBJ
> +	return mlx5dv_devx_general_cmd(ctx, in, inlen, out, outlen); #else
> +	(void)ctx;
> +	(void)in;
> +	(void)inlen;
> +	(void)out;
> +	(void)outlen;
> +	return -ENOTSUP;
> +#endif
> +}
> +
>  alignas(RTE_CACHE_LINE_SIZE)
>  const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
>  	.version = MLX5_GLUE_VERSION,
> @@ -535,4 +628,10 @@
>  	.dv_create_flow = mlx5_glue_dv_create_flow,
>  	.dv_create_flow_action_packet_reformat =
>  			mlx5_glue_dv_create_flow_action_packet_reformat,
> +	.dv_open_device = mlx5_glue_dv_open_device,
> +	.devx_obj_create = mlx5_glue_devx_obj_create,
> +	.devx_obj_destroy = mlx5_glue_devx_obj_destroy,
> +	.devx_obj_query = mlx5_glue_devx_obj_query,
> +	.devx_obj_modify = mlx5_glue_devx_obj_modify,
> +	.devx_general_cmd = mlx5_glue_devx_general_cmd,
>  };
> diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
> index 2d92ba8..a6cd2cd 100644
> --- a/drivers/net/mlx5/mlx5_glue.h
> +++ b/drivers/net/mlx5/mlx5_glue.h
> @@ -55,6 +55,10 @@
>  enum mlx5dv_flow_table_type { flow_table_type = 0, };  #endif
> 
> +#ifndef HAVE_IBV_DEVX_OBJ
> +struct mlx5dv_devx_obj;
> +#endif
> +
>  /* LIB_GLUE_VERSION must be updated every time this structure is modified.
> */  struct mlx5_glue {
>  	const char *version;
> @@ -164,6 +168,21 @@ struct mlx5_glue {
>  		 void *data,
>  		 enum mlx5dv_flow_action_packet_reformat_type
> reformat_type,
>  		 enum mlx5dv_flow_table_type ft_type);
> +	struct ibv_context *(*dv_open_device)(struct ibv_device *device);
> +	struct mlx5dv_devx_obj *(*devx_obj_create)
> +					(struct ibv_context *ctx,
> +					 const void *in, size_t inlen,
> +					 void *out, size_t outlen);
> +	int (*devx_obj_destroy)(struct mlx5dv_devx_obj *obj);
> +	int (*devx_obj_query)(struct mlx5dv_devx_obj *obj,
> +			      const void *in, size_t inlen,
> +			      void *out, size_t outlen);
> +	int (*devx_obj_modify)(struct mlx5dv_devx_obj *obj,
> +			       const void *in, size_t inlen,
> +			       void *out, size_t outlen);
> +	int (*devx_general_cmd)(struct ibv_context *context,
> +				const void *in, size_t inlen,
> +				void *out, size_t outlen);
>  };
> 
>  const struct mlx5_glue *mlx5_glue;
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
@ 2018-12-27  8:15   ` Shahaf Shuler
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 0/3] " Mordechay Haimovsky
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 24+ messages in thread
From: Shahaf Shuler @ 2018-12-27  8:15 UTC (permalink / raw)
  To: Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky

Tuesday, December 25, 2018 4:39 PM, Mordechay Haimovsky:
> Subject: [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx
> 
> This commit adds counters support when creating flows via direct verbs. The
> implementation uses devx interface in order to create query and delete the
> counters.
> This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation.
> 
> Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> ---
>  drivers/net/mlx5/Makefile         |   6 +
>  drivers/net/mlx5/meson.build      |   5 +
>  drivers/net/mlx5/mlx5.c           |  17 ++-
>  drivers/net/mlx5/mlx5.h           |   1 +
>  drivers/net/mlx5/mlx5_devx_cmds.c | 117 +++++++++++++++++++
>  drivers/net/mlx5/mlx5_flow.h      |  12 +-
>  drivers/net/mlx5/mlx5_flow_dv.c   | 232
> ++++++++++++++++++++++++++++++++++++--
>  drivers/net/mlx5/mlx5_glue.c      |   1 +
>  drivers/net/mlx5/mlx5_prm.h       |  86 ++++++++++++++
>  9 files changed, 461 insertions(+), 16 deletions(-)  create mode 100644
> drivers/net/mlx5/mlx5_devx_cmds.c
> 
> diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index
> 58e2d15..bd96706 100644
> --- a/drivers/net/mlx5/Makefile
> +++ b/drivers/net/mlx5/Makefile
> @@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=
> mlx5_flow_tcf.c
>  SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c
>  SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
>  SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c
> +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_devx_cmds.c
> 
>  ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y)
>  INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib += $(LIB_GLUE) @@ -153,6
> +154,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
>  		func mlx5dv_devx_obj_create \
>  		$(AUTOCONF_OUTPUT)
>  	$Q sh -- '$<' '$@' \
> +		HAVE_IBV_FLOW_DEVX_COUNTERS \
> +		infiniband/mlx5dv.h \
> +		enum MLX5DV_FLOW_ACTION_COUNTER_DEVX \
> +		$(AUTOCONF_OUTPUT)
> +	$Q sh -- '$<' '$@' \
>  		HAVE_ETHTOOL_LINK_MODE_25G \
>  		/usr/include/linux/ethtool.h \
>  		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \ diff --
> git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build index
> e323c3a..9a5077d 100644
> --- a/drivers/net/mlx5/meson.build
> +++ b/drivers/net/mlx5/meson.build
> @@ -46,6 +46,7 @@ if build
>  		'mlx5_trigger.c',
>  		'mlx5_txq.c',
>  		'mlx5_vlan.c',
> +		'mlx5_devx_cmds.c',
>  	)
>  	if dpdk_conf.has('RTE_ARCH_X86_64') or
> dpdk_conf.has('RTE_ARCH_ARM64')
>  		sources += files('mlx5_rxtx_vec.c')
> @@ -100,6 +101,10 @@ if build
>  		'MLX5DV_CQ_INIT_ATTR_FLAGS_CQE_PAD' ],
>  		[ 'HAVE_IBV_FLOW_DV_SUPPORT', 'infiniband/mlx5dv.h',
>  		'mlx5dv_create_flow_action_packet_reformat' ],
> +		[ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h',
> +		'MLX5DV_FLOW_ACTION_COUNTER_DEVX' ],
> +		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
> +		'MLX5DV_CONTEXT_FLAGS_DEVX' ],

I don't understand,
On the second patch of this series you detect the HVA_IBV_DEVX_OBJ according to:
+		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
+		'mlx5dv_devx_obj_create' ],

Typo?

>  		[ 'HAVE_IBV_DEVICE_MPLS_SUPPORT', 'infiniband/verbs.h',
>  		'IBV_FLOW_SPEC_MPLS' ],
>  		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING',
> 'infiniband/verbs.h', diff --git a/drivers/net/mlx5/mlx5.c
> b/drivers/net/mlx5/mlx5.c index 9e5cab1..1e00b8b 100644
> --- a/drivers/net/mlx5/mlx5.c
> +++ b/drivers/net/mlx5/mlx5.c
> @@ -727,7 +727,7 @@
>  	       struct mlx5_dev_config config,
>  	       const struct mlx5_switch_info *switch_info)  {
> -	struct ibv_context *ctx;
> +	struct ibv_context *ctx = NULL;
>  	struct ibv_device_attr_ex attr;
>  	struct ibv_port_attr port_attr;
>  	struct ibv_pd *pd = NULL;
> @@ -786,10 +786,17 @@
>  	/* Prepare shared data between primary and secondary process. */
>  	mlx5_prepare_shared_data();
>  	errno = 0;
> -	ctx = mlx5_glue->open_device(ibv_dev);
> -	if (!ctx) {
> -		rte_errno = errno ? errno : ENODEV;
> -		return NULL;
> +	ctx = mlx5_glue->dv_open_device(ibv_dev);
> +	if (ctx) {
> +		config.devx = 1;
> +		DRV_LOG(DEBUG, "DEVX is %ssupported",
> +			config.devx ? "" : "not ");

You can just print "devx is support", config is set right above. 

> +	} else {
> +		ctx = mlx5_glue->open_device(ibv_dev);
> +		if (!ctx) {
> +			rte_errno = errno ? errno : ENODEV;
> +			return NULL;
> +		}
>  	}
>  #ifdef HAVE_IBV_MLX5_MOD_SWP
>  	dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP; diff --git
> a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 75aeeb2..1fcdb71
> 100644
> --- a/drivers/net/mlx5/mlx5.h
> +++ b/drivers/net/mlx5/mlx5.h
> @@ -129,6 +129,7 @@ struct mlx5_dev_config {
>  	unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */
>  	unsigned int dv_flow_en:1; /* Enable DV flow. */
>  	unsigned int swp:1; /* Tx generic tunnel checksum and TSO offload. */
> +	unsigned int devx:1; /* Whether devx interface is available or not. */
>  	struct {
>  		unsigned int enabled:1; /* Whether MPRQ is enabled. */
>  		unsigned int stride_num_n; /* Number of strides. */ diff --git
> a/drivers/net/mlx5/mlx5_devx_cmds.c b/drivers/net/mlx5/mlx5_devx_cmds.c
> new file mode 100644
> index 0000000..a3f421e
> --- /dev/null
> +++ b/drivers/net/mlx5/mlx5_devx_cmds.c
> @@ -0,0 +1,117 @@
> +// SPDX-License-Identifier: BSD-3-Clause
> +/* Copyright 2018 Mellanox Technologies, Ltd */
> +
> +#include <rte_flow_driver.h>
> +
> +#include "mlx5.h"
> +#include "mlx5_glue.h"
> +#include "mlx5_prm.h"
> +
> +/*
> + * Dummy struct to prevent compilation errors when
> + * mlx5dv_devx_obj is not defined in mlx5dv.h  */ #ifndef
> +HAVE_IBV_DEVX_OBJ struct mlx5dv_devx_obj {
> +	void *ctx;
> +};
> +#endif /* HAVE_IBV_DEVX_OBJ */

Since it is devx commands file, why not to ifdef the entire file and avoid such dummy declaration? 

> +
> +/**
> + * Allocate flow counters via devx interface.
> + *
> + * @param[in] ctx
> + *   ibv contexts returned from mlx5dv_open_device.
> + * @param dcs
> + *   Pointer to counters properties structure to be filled by the routine.
> + *
> + * @return
> + *   0 on success, a negative value otherwise.
> + */
> +int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
> +				     struct mlx5_devx_counter_set *dcs) {
> +	uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)]   = {0};
> +	uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0};
> +	int status, syndrome;
> +
> +	MLX5_SET(alloc_flow_counter_in, in, opcode,
> +		 MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
> +	dcs->obj = mlx5_glue->devx_obj_create(ctx, in,
> +					      sizeof(in), out, sizeof(out));
> +	if (!dcs->obj)
> +		return -errno;
> +	status = MLX5_GET(query_flow_counter_out, out, status);
> +	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
> +	if (status) {
> +		DRV_LOG(DEBUG, "Failed to create devx counters, "
> +			"status %x, syndrome %x", status, syndrome);
> +		return -1;
> +	}
> +	dcs->id = MLX5_GET(alloc_flow_counter_out,
> +			   out, flow_counter_id);
> +	return 0;
> +}
> +
> +/**
> + * Free flow counters obtained via devx interface.
> + *
> + * @param[in] obj
> + *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
> + *
> + * @return
> + *   0 on success, a negative value otherwise.
> + */
> +int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj) {
> +	return mlx5_glue->devx_obj_destroy(obj); }
> +
> +/**
> + * Query flow counters values.
> + *
> + * @param[in] dcs
> + *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
> + * @param[in] clear
> + *   Whether hardware should clear the counters after the query or not.
> + *  @param pkts
> + *   The number of packets that matched the flow.
> + *  @param bytes
> + *    The number of bytes that matched the flow.
> + *
> + * @return
> + *   0 on success, a negative value otherwise.
> + */
> +int
> +mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs,
> +				 int clear __rte_unused,
> +				 uint64_t *pkts, uint64_t *bytes)
> +{
> +	uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
> +		MLX5_ST_SZ_BYTES(traffic_counter)]   = {0};
> +	uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0};
> +	void *stats;
> +	int status, syndrome, rc;
> +
> +	MLX5_SET(query_flow_counter_in, in, opcode,
> +		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
> +	MLX5_SET(query_flow_counter_in, in, op_mod, 0);
> +	MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id);
> +	rc = mlx5_glue->devx_obj_query(dcs->obj,
> +				       in, sizeof(in), out, sizeof(out));
> +	if (rc)
> +		return rc;
> +	status = MLX5_GET(query_flow_counter_out, out, status);
> +	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
> +	if (status) {
> +		DRV_LOG(DEBUG, "Failed to query devx counters, "
> +			"id %d, status %x, syndrome = %x",
> +			status, syndrome, dcs->id);
> +		return -1;
> +	}
> +	stats = MLX5_ADDR_OF(query_flow_counter_out,
> +			     out, flow_statistics);
> +	*pkts = MLX5_GET64(traffic_counter, stats, packets);
> +	*bytes = MLX5_GET64(traffic_counter, stats, octets);
> +	return 0;
> +}
> diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
> index 4a7c052..838c85a 100644
> --- a/drivers/net/mlx5/mlx5_flow.h
> +++ b/drivers/net/mlx5/mlx5_flow.h
> @@ -21,6 +21,9 @@
>  #pragma GCC diagnostic error "-Wpedantic"
>  #endif
> 
> +#include "mlx5.h"
> +#include "mlx5_prm.h"
> +
>  /* Pattern outer Layer bits. */
>  #define MLX5_FLOW_LAYER_OUTER_L2 (1u << 0)  #define
> MLX5_FLOW_LAYER_OUTER_L3_IPV4 (1u << 1) @@ -273,13 +276,16 @@
> struct mlx5_flow {  struct mlx5_flow_counter {
>  	LIST_ENTRY(mlx5_flow_counter) next; /**< Pointer to the next counter.
> */
>  	uint32_t shared:1; /**< Share counter ID with other flow rules. */
> -	uint32_t ref_cnt:31; /**< Reference counter. */
> +	uint32_t ref_cnt:30; /**< Reference counter. */

Why you take 1 bit out of the ref_cnt?

>  	uint32_t id; /**< Counter ID. */
> +	union {  /**< Holds the counters for the rule. */
>  #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
> -	struct ibv_counter_set *cs; /**< Holds the counters for the rule. */
> +		struct ibv_counter_set *cs;
>  #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
> -	struct ibv_counters *cs; /**< Holds the counters for the rule. */
> +		struct ibv_counters *cs;
>  #endif
> +		struct mlx5_devx_counter_set *dcs;
> +	};
>  	uint64_t hits; /**< Number of packets matched by the rule. */
>  	uint64_t bytes; /**< Number of bytes matched by the rule. */  }; diff --
> git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
> index 1f31874..14dadce 100644
> --- a/drivers/net/mlx5/mlx5_flow_dv.c
> +++ b/drivers/net/mlx5/mlx5_flow_dv.c
> @@ -97,6 +97,36 @@
>  }
> 
>  /**
> + * Validate count action.
> + *
> + * @param[in] dev
> + *   device otr.
> + * @param[out] error
> + *   Pointer to error structure.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_validate_action_count(struct rte_eth_dev *dev,
> +			      struct rte_flow_error *error)
> +{
> +	struct priv *priv = dev->data->dev_private;
> +
> +	if (!priv->config.devx)
> +		goto notsup_err;
> +#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
> +	return 0;
> +#endif
> +notsup_err:
> +	return rte_flow_error_set
> +		      (error, ENOTSUP,
> +		       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +		       NULL,
> +		       "count action not supported"); }
> +
> +/**
>   * Validate the L2 encap action.
>   *
>   * @param[in] action_flags
> @@ -704,6 +734,87 @@
>  }
> 
>  /**
> + * Get or create a flow counter.
> + *
> + * @param[in] dev
> + *   Pointer to the Ethernet device structure.
> + * @param[in] shared
> + *   Indicate if this counter is shared with other flows.
> + * @param[in] id
> + *   Counter identifier.
> + *
> + * @return
> + *   pointer to flow counter on success, NULL otherwise and rte_errno is set.
> + */
> +static struct mlx5_flow_counter *
> +flow_dv_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t
> +id) {
> +	struct priv *priv = dev->data->dev_private;
> +	struct mlx5_flow_counter *cnt = NULL;
> +	struct mlx5_devx_counter_set *dcs = NULL;
> +	int ret;
> +
> +	if (!priv->config.devx) {
> +		ret = -ENOTSUP;
> +		goto error_exit;
> +	}
> +	if (shared) {
> +		LIST_FOREACH(cnt, &priv->flow_counters, next) {
> +			if (cnt->shared && cnt->id == id) {
> +				cnt->ref_cnt++;
> +				return cnt;
> +			}
> +		}
> +	}
> +	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
> +	dcs = rte_calloc(__func__, 1, sizeof(*dcs), 0);
> +	if (!dcs || !cnt) {
> +		ret = -ENOMEM;
> +		goto error_exit;
> +	}
> +	ret = mlx5_devx_cmd_flow_counter_alloc(priv->ctx, dcs);
> +	if (ret)
> +		goto error_exit;
> +	struct mlx5_flow_counter tmpl = {
> +		.shared = shared,
> +		.ref_cnt = 1,
> +		.id = id,
> +		.dcs = dcs,
> +	};
> +	*cnt = tmpl;
> +	LIST_INSERT_HEAD(&priv->flow_counters, cnt, next);
> +	return cnt;
> +error_exit:
> +	rte_free(cnt);
> +	rte_free(dcs);
> +	rte_errno = -ret;
> +	return NULL;
> +}
> +
> +/**
> + * Release a flow counter.
> + *
> + * @param[in] counter
> + *   Pointer to the counter handler.
> + */
> +static void
> +flow_dv_counter_release(struct mlx5_flow_counter *counter) {
> +	int ret;
> +
> +	if (!counter)
> +		return;
> +	if (--counter->ref_cnt == 0) {
> +		ret = mlx5_devx_cmd_flow_counter_free(counter->dcs->obj);
> +		if (ret)
> +			DRV_LOG(ERR, "Failed to free devx counters, %d", ret);
> +		LIST_REMOVE(counter, next);
> +		rte_free(counter->dcs);
> +		rte_free(counter);
> +	}
> +}
> +
> +/**
>   * Verify the @p attributes will be correctly understood by the NIC and store
>   * them in the @p flow if everything is correct.
>   *
> @@ -965,7 +1076,7 @@
>  			++actions_n;
>  			break;
>  		case RTE_FLOW_ACTION_TYPE_COUNT:
> -			ret = mlx5_flow_validate_action_count(dev, attr,
> error);
> +			ret = flow_dv_validate_action_count(dev, error);
>  			if (ret < 0)
>  				return ret;
>  			action_flags |= MLX5_FLOW_ACTION_COUNT; @@ -
> 1902,6 +2013,9 @@
>  		const struct rte_flow_action_queue *queue;
>  		const struct rte_flow_action_rss *rss;
>  		const struct rte_flow_action *action = actions;
> +#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
> +		const struct rte_flow_action_count *count = action->conf;
> #endif
>  		const uint8_t *rss_key;
> 
>  		switch (actions->type) {
> @@ -1950,6 +2064,37 @@
>  			flow->rss.level = rss->level;
>  			action_flags |= MLX5_FLOW_ACTION_RSS;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_COUNT:
> +			if (!priv->config.devx) {
> +				rte_errno = ENOTSUP;
> +				goto cnt_err;
> +			}
> +			flow->counter =
> +				flow_dv_counter_new(dev,
> +						    count->shared, count->id);
> +			if (flow->counter == NULL)
> +				goto cnt_err;
> +			dev_flow->dv.actions[actions_n].type =
> +
> 	MLX5DV_FLOW_ACTION_COUNTER_DEVX;
> +			dev_flow->dv.actions[actions_n].obj =
> +						flow->counter->dcs->obj;
> +			action_flags |= MLX5_FLOW_ACTION_COUNT;
> +			++actions_n;
> +			break;
> +cnt_err:
> +			if (rte_errno == ENOTSUP)
> +				return rte_flow_error_set
> +					      (error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +					       NULL,
> +					       "count action not supported");
> +			else
> +				return rte_flow_error_set
> +						(error, rte_errno,
> +
> RTE_FLOW_ERROR_TYPE_ACTION,
> +						 action,
> +						 "cannot create counter"
> +						  " object.");
>  		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
>  		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
>  			if (flow_dv_create_action_l2_encap(dev, actions, @@
> -2338,8 +2483,6 @@
>  			dv->hrxq = NULL;
>  		}
>  	}
> -	if (flow->counter)
> -		flow->counter = NULL;
>  }
> 
>  /**
> @@ -2358,6 +2501,10 @@
>  	if (!flow)
>  		return;
>  	flow_dv_remove(dev, flow);
> +	if (flow->counter) {
> +		flow_dv_counter_release(flow->counter);
> +		flow->counter = NULL;
> +	}
>  	while (!LIST_EMPTY(&flow->dev_flows)) {
>  		dev_flow = LIST_FIRST(&flow->dev_flows);
>  		LIST_REMOVE(dev_flow, next);
> @@ -2370,22 +2517,91 @@
>  }
> 
>  /**
> + * Query a dv flow  rule for its statistics via devx.
> + *
> + * @param[in] dev
> + *   Pointer to Ethernet device.
> + * @param[in] flow
> + *   Pointer to the sub flow.
> + * @param[out] data
> + *   data retrieved by the query.
> + * @param[out] error
> + *   Perform verbose error reporting if not NULL.
> + *
> + * @return
> + *   0 on success, a negative errno value otherwise and rte_errno is set.
> + */
> +static int
> +flow_dv_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
> +		    void *data, struct rte_flow_error *error) {
> +	struct priv *priv = dev->data->dev_private;
> +	struct rte_flow_query_count *qc = data;
> +	uint64_t pkts = 0;
> +	uint64_t bytes = 0;
> +	int err;
> +
> +	if (!priv->config.devx)
> +		return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +					  NULL,
> +					  "counters are not supported");
> +	if (flow->counter) {
> +		err = mlx5_devx_cmd_flow_counter_query
> +						(flow->counter->dcs,
> +						 qc->reset, &pkts, &bytes);
> +		if (err)
> +			return rte_flow_error_set
> +				(error, err,
> +				 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +				 NULL,
> +				 "cannot read counters");
> +		qc->hits_set = 1;
> +		qc->bytes_set = 1;
> +		qc->hits = pkts - flow->counter->hits;
> +		qc->bytes = bytes - flow->counter->bytes;
> +		if (qc->reset) {
> +			flow->counter->hits = pkts;
> +			flow->counter->bytes = bytes;
> +		}
> +		return 0;
> +	}
> +	return rte_flow_error_set(error, EINVAL,
> +				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> +				  NULL,
> +				  "counters are not available");
> +}
> +
> +/**
>   * Query a flow.
>   *
>   * @see rte_flow_query()
>   * @see rte_flow_ops
>   */
>  static int
> -flow_dv_query(struct rte_eth_dev *dev __rte_unused,
> +flow_dv_query(struct rte_eth_dev *dev,
>  	      struct rte_flow *flow __rte_unused,
>  	      const struct rte_flow_action *actions __rte_unused,
>  	      void *data __rte_unused,
>  	      struct rte_flow_error *error __rte_unused)  {
> -	return rte_flow_error_set(error, ENOTSUP,
> -				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
> -				  NULL,
> -				  "flow query with DV is not supported");
> +	int ret = -EINVAL;
> +
> +	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
> +		switch (actions->type) {
> +		case RTE_FLOW_ACTION_TYPE_VOID:
> +			break;
> +		case RTE_FLOW_ACTION_TYPE_COUNT:
> +			ret = flow_dv_query_count(dev, flow, data, error);
> +			break;
> +		default:
> +			return rte_flow_error_set(error, ENOTSUP,
> +
> RTE_FLOW_ERROR_TYPE_ACTION,
> +						  actions,
> +						  "action not supported");
> +		}
> +	}
> +	return ret;
>  }
> 
> 
> diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c index
> 7d3d9d3..4078b54 100644
> --- a/drivers/net/mlx5/mlx5_glue.c
> +++ b/drivers/net/mlx5/mlx5_glue.c
> @@ -65,6 +65,7 @@
>  	return ibv_open_device(device);
>  }
> 
> +

Remove blank line. 

>  static int
>  mlx5_glue_close_device(struct ibv_context *context)  { diff --git
> a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h index
> 29742b1..812b4bf 100644
> --- a/drivers/net/mlx5/mlx5_prm.h
> +++ b/drivers/net/mlx5/mlx5_prm.h
> @@ -368,6 +368,7 @@ struct mlx5_modification_cmd {  #define
> __mlx5_dw_bit_off(typ, fld) (32 - __mlx5_bit_sz(typ, fld) - \
>  				    (__mlx5_bit_off(typ, fld) & 0x1f))  #define
> __mlx5_dw_off(typ, fld) (__mlx5_bit_off(typ, fld) / 32)
> +#define __mlx5_64_off(typ, fld) (__mlx5_bit_off(typ, fld) / 64)
>  #define __mlx5_dw_mask(typ, fld) (__mlx5_mask(typ, fld) << \
>  				  __mlx5_dw_bit_off(typ, fld))
>  #define __mlx5_mask(typ, fld) ((u32)((1ull << __mlx5_bit_sz(typ, fld)) - 1)) @@
> -375,6 +376,7 @@ struct mlx5_modification_cmd {  #define
> __mlx5_16_bit_off(typ, fld) (16 - __mlx5_bit_sz(typ, fld) - \
>  				    (__mlx5_bit_off(typ, fld) & 0xf))  #define
> __mlx5_mask16(typ, fld) ((u16)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
> +#define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) /
> +8)
>  #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32)
> #define MLX5_ST_SZ_DB(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
> #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8) @@ -391,10
> +393,16 @@ struct mlx5_modification_cmd {
>  				 (((_v) & __mlx5_mask(typ, fld)) << \
>  				   __mlx5_dw_bit_off(typ, fld))); \
>  	} while (0)
> +#define MLX5_GET(typ, p, fld) \
> +	((rte_be_to_cpu_32(*((__be32 *)(p) +\
> +	__mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
> +	__mlx5_mask(typ, fld))
>  #define MLX5_GET16(typ, p, fld) \
>  	((rte_be_to_cpu_16(*((__be16 *)(p) + \
>  	  __mlx5_16_off(typ, fld))) >> __mlx5_16_bit_off(typ, fld)) & \
>  	 __mlx5_mask16(typ, fld))
> +#define MLX5_GET64(typ, p, fld) rte_be_to_cpu_64(*((__be64 *)(p) + \
> +						   __mlx5_64_off(typ, fld)))
>  #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8)
> 
>  struct mlx5_ifc_fte_match_set_misc_bits { @@ -500,6 +508,69 @@ enum {
>  	MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT
>  };
> 
> +enum {
> +	MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939,
> +	MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b, };
> +
> +/* Flow counters. */
> +struct mlx5_ifc_alloc_flow_counter_out_bits {
> +	u8         status[0x8];
> +	u8         reserved_at_8[0x18];
> +	u8         syndrome[0x20];
> +	u8         flow_counter_id[0x20];
> +	u8         reserved_at_60[0x20];
> +};
> +
> +struct mlx5_ifc_alloc_flow_counter_in_bits {
> +	u8         opcode[0x10];
> +	u8         reserved_at_10[0x10];
> +	u8         reserved_at_20[0x10];
> +	u8         op_mod[0x10];
> +	u8         reserved_at_40[0x40];
> +};
> +
> +struct mlx5_ifc_dealloc_flow_counter_out_bits {
> +	u8         status[0x8];
> +	u8         reserved_at_8[0x18];
> +	u8         syndrome[0x20];
> +	u8         reserved_at_40[0x40];
> +};
> +
> +struct mlx5_ifc_dealloc_flow_counter_in_bits {
> +	u8         opcode[0x10];
> +	u8         reserved_at_10[0x10];
> +	u8         reserved_at_20[0x10];
> +	u8         op_mod[0x10];
> +	u8         flow_counter_id[0x20];
> +	u8         reserved_at_60[0x20];
> +};
> +
> +struct mlx5_ifc_traffic_counter_bits {
> +	u8         packets[0x40];
> +	u8         octets[0x40];
> +};
> +
> +struct mlx5_ifc_query_flow_counter_out_bits {
> +	u8         status[0x8];
> +	u8         reserved_at_8[0x18];
> +	u8         syndrome[0x20];
> +	u8         reserved_at_40[0x40];
> +	struct mlx5_ifc_traffic_counter_bits flow_statistics[]; };
> +
> +struct mlx5_ifc_query_flow_counter_in_bits {
> +	u8         opcode[0x10];
> +	u8         reserved_at_10[0x10];
> +	u8         reserved_at_20[0x10];
> +	u8         op_mod[0x10];
> +	u8         reserved_at_40[0x80];
> +	u8         clear[0x1];
> +	u8         reserved_at_c1[0xf];
> +	u8         num_of_counters[0x10];
> +	u8         flow_counter_id[0x20];
> +};
> +
>  /* CQE format mask. */
>  #define MLX5E_CQE_FORMAT_MASK 0xc
> 
> @@ -581,4 +652,19 @@ struct mlx5_mini_cqe8 {  #endif  }
> 
> +

The below declaration does not belong to mlx5_prm.h. either in mlx5.h or new mlx5_devx.h. 
Need to ifdef accordingly. 

> +/* devx counyter object */
> +struct mlx5_devx_counter_set {
> +	struct mlx5dv_devx_obj *obj;
> +	int id; /* Flow counter ID */
> +};
> +
> +/* mlx5_devx_cmds.c */
> +
> +int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
> +				     struct mlx5_devx_counter_set *dcx); int
> +mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj); int
> +mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcx,
> +				     int clear,
> +				     uint64_t *pkts, uint64_t *bytes);
>  #endif /* RTE_PMD_MLX5_PRM_H_ */
> --
> 1.8.3.1

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

* [dpdk-dev] [PATCH v2 0/3] support flow counters using devx
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2018-12-27  8:15   ` Shahaf Shuler
@ 2018-12-27 22:20   ` Mordechay Haimovsky
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-27 22:20 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This series of commits add support for creating, allocating, querying
and destroying flow counters in mlx5 PMD using the devx interface.

Moti Haimovsky (3):
  net/mlx5: fix shared counter allocation logic
  net/mlx5: add devx functions to glue
  net/mlx5: support flow counters using devx

 drivers/net/mlx5/Makefile          |  11 ++
 drivers/net/mlx5/meson.build       |   5 +
 drivers/net/mlx5/mlx5.c            |  16 ++-
 drivers/net/mlx5/mlx5.h            |  15 +++
 drivers/net/mlx5/mlx5_devx_cmds.c  | 107 +++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h       |  10 +-
 drivers/net/mlx5/mlx5_flow_dv.c    | 232 +++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_flow_verbs.c |  14 +--
 drivers/net/mlx5/mlx5_glue.c       |  98 ++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h       |  19 +++
 drivers/net/mlx5/mlx5_prm.h        |  71 ++++++++++++
 11 files changed, 576 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2018-12-27  8:15   ` Shahaf Shuler
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 0/3] " Mordechay Haimovsky
@ 2018-12-27 22:20   ` Mordechay Haimovsky
  2018-12-29 20:12     ` Slava Ovsiienko
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  4 siblings, 1 reply; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-27 22:20 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky, stable

This commit fixes the logic for searching and allocating a shared
counter in mlx5_flow_verbs.
Now only the shared counters in the counters list are checked for
a match and not all the counters as before.

Fixes: 84c406e74524 ("net/mlx5: add flow translate function")
Cc: stable@dpdk.org

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modified commit header
---
 drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 81ec59d..409e1cd 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -121,13 +121,13 @@
 	struct mlx5_flow_counter *cnt;
 	int ret;
 
-	LIST_FOREACH(cnt, &priv->flow_counters, next) {
-		if (!cnt->shared || cnt->shared != shared)
-			continue;
-		if (cnt->id != id)
-			continue;
-		cnt->ref_cnt++;
-		return cnt;
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
 	}
 	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
 	if (!cnt) {
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 2/3] net/mlx5: add devx functions to glue
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
                     ` (2 preceding siblings ...)
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
@ 2018-12-27 22:20   ` Mordechay Haimovsky
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  4 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-27 22:20 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This patch adds glue functions for operations:
  - dv_open_device.
  - devx object create, destroy, query and modify.
  - devx general command
The new operations depend on HAVE_IBV_DEVX_OBJ.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modifications according to review inputs.
  see message Id: 1545748697-3385-3-git-send-email-motih@mellanox.com
---
 drivers/net/mlx5/Makefile    |  5 +++
 drivers/net/mlx5/meson.build |  2 +
 drivers/net/mlx5/mlx5_glue.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 19 +++++++++
 4 files changed, 124 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 1353c18..8ddad1a 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -148,6 +148,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_DEVX_OBJ \
+		infiniband/mlx5dv.h \
+		func mlx5dv_devx_obj_create \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 8ba19e8..e2fc4ea 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -104,6 +104,8 @@ if build
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
+		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
+		'mlx5dv_devx_obj_create' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index a806d92..c817d86 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -498,6 +498,98 @@
 #endif
 }
 
+static struct ibv_context *
+mlx5_glue_dv_open_device(struct ibv_device *device)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_open_device(device,
+				  &(struct mlx5dv_context_attr){
+					.flags = MLX5DV_CONTEXT_FLAGS_DEVX,
+				  });
+#else
+	(void)device;
+	return NULL;
+#endif
+}
+
+static struct mlx5dv_devx_obj *
+mlx5_glue_devx_obj_create(struct ibv_context *ctx,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_create(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return NULL;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_destroy(struct mlx5dv_devx_obj *obj)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_destroy(obj);
+#else
+	(void)obj;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_query(struct mlx5dv_devx_obj *obj,
+			 const void *in, size_t inlen,
+			 void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_query(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_modify(struct mlx5dv_devx_obj *obj,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_modify(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_general_cmd(struct ibv_context *ctx,
+			   const void *in, size_t inlen,
+			   void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_general_cmd(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
 
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
@@ -557,4 +649,10 @@
 			mlx5_glue_dv_create_flow_action_packet_reformat,
 	.dv_create_flow_action_modify_header =
 			mlx5_glue_dv_create_flow_action_modify_header,
+	.dv_open_device = mlx5_glue_dv_open_device,
+	.devx_obj_create = mlx5_glue_devx_obj_create,
+	.devx_obj_destroy = mlx5_glue_devx_obj_destroy,
+	.devx_obj_query = mlx5_glue_devx_obj_query,
+	.devx_obj_modify = mlx5_glue_devx_obj_modify,
+	.devx_general_cmd = mlx5_glue_devx_general_cmd,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 9cfe836..b118960 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -55,6 +55,10 @@
 enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
+#ifndef HAVE_IBV_DEVX_OBJ
+struct mlx5dv_devx_obj;
+#endif
+
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
 struct mlx5_glue {
 	const char *version;
@@ -169,6 +173,21 @@ struct mlx5_glue {
 					 size_t actions_sz,
 					 uint64_t actions[],
 					 enum mlx5dv_flow_table_type ft_type);
+	struct ibv_context *(*dv_open_device)(struct ibv_device *device);
+	struct mlx5dv_devx_obj *(*devx_obj_create)
+					(struct ibv_context *ctx,
+					 const void *in, size_t inlen,
+					 void *out, size_t outlen);
+	int (*devx_obj_destroy)(struct mlx5dv_devx_obj *obj);
+	int (*devx_obj_query)(struct mlx5dv_devx_obj *obj,
+			      const void *in, size_t inlen,
+			      void *out, size_t outlen);
+	int (*devx_obj_modify)(struct mlx5dv_devx_obj *obj,
+			       const void *in, size_t inlen,
+			       void *out, size_t outlen);
+	int (*devx_general_cmd)(struct ibv_context *context,
+				const void *in, size_t inlen,
+				void *out, size_t outlen);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx
  2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
                     ` (3 preceding siblings ...)
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
@ 2018-12-27 22:20   ` Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 0/3] " Mordechay Haimovsky
                       ` (3 more replies)
  4 siblings, 4 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2018-12-27 22:20 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This commit adds counters support when creating flows via direct
verbs. The implementation uses devx interface in order to create
query and delete the counters.
This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modifications according to revir,
  See message Id: 1545748697-3385-4-git-send-email-motih@mellanox.com
---
 drivers/net/mlx5/Makefile         |   6 +
 drivers/net/mlx5/meson.build      |   3 +
 drivers/net/mlx5/mlx5.c           |  16 ++-
 drivers/net/mlx5/mlx5.h           |  15 +++
 drivers/net/mlx5/mlx5_devx_cmds.c | 107 ++++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h      |  10 +-
 drivers/net/mlx5/mlx5_flow_dv.c   | 232 ++++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_prm.h       |  71 ++++++++++++
 8 files changed, 445 insertions(+), 15 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 8ddad1a..a1749e4 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_tcf.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_devx_cmds.c
 
 ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y)
 INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib += $(LIB_GLUE)
@@ -153,6 +154,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_devx_obj_create \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_FLOW_DEVX_COUNTERS \
+		infiniband/mlx5dv.h \
+		enum MLX5DV_FLOW_ACTION_COUNTER_DEVX \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e2fc4ea..e9db36c 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -46,6 +46,7 @@ if build
 		'mlx5_trigger.c',
 		'mlx5_txq.c',
 		'mlx5_vlan.c',
+		'mlx5_devx_cmds.c',
 	)
 	if dpdk_conf.has('RTE_ARCH_X86_64') or dpdk_conf.has('RTE_ARCH_ARM64')
 		sources += files('mlx5_rxtx_vec.c')
@@ -106,6 +107,8 @@ if build
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
 		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
 		'mlx5dv_devx_obj_create' ],
+		[ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h',
+		'MLX5DV_FLOW_ACTION_COUNTER_DEVX' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 9e5cab1..93c1686 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -727,7 +727,7 @@
 	       struct mlx5_dev_config config,
 	       const struct mlx5_switch_info *switch_info)
 {
-	struct ibv_context *ctx;
+	struct ibv_context *ctx = NULL;
 	struct ibv_device_attr_ex attr;
 	struct ibv_port_attr port_attr;
 	struct ibv_pd *pd = NULL;
@@ -786,10 +786,16 @@
 	/* Prepare shared data between primary and secondary process. */
 	mlx5_prepare_shared_data();
 	errno = 0;
-	ctx = mlx5_glue->open_device(ibv_dev);
-	if (!ctx) {
-		rte_errno = errno ? errno : ENODEV;
-		return NULL;
+	ctx = mlx5_glue->dv_open_device(ibv_dev);
+	if (ctx) {
+		config.devx = 1;
+		DRV_LOG(DEBUG, "DEVX is supported");
+	} else {
+		ctx = mlx5_glue->open_device(ibv_dev);
+		if (!ctx) {
+			rte_errno = errno ? errno : ENODEV;
+			return NULL;
+		}
 	}
 #ifdef HAVE_IBV_MLX5_MOD_SWP
 	dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index b2fe5cb..cf60c46 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -96,6 +96,12 @@ struct mlx5_stats_ctrl {
 	uint64_t imissed_base;
 };
 
+/* devx counter object */
+struct mlx5_devx_counter_set {
+	struct mlx5dv_devx_obj *obj;
+	int id; /* Flow counter ID */
+};
+
 /* Flow list . */
 TAILQ_HEAD(mlx5_flows, rte_flow);
 
@@ -129,6 +135,7 @@ struct mlx5_dev_config {
 	unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */
 	unsigned int dv_flow_en:1; /* Enable DV flow. */
 	unsigned int swp:1; /* Tx generic tunnel checksum and TSO offload. */
+	unsigned int devx:1; /* Whether devx interface is available or not. */
 	struct {
 		unsigned int enabled:1; /* Whether MPRQ is enabled. */
 		unsigned int stride_num_n; /* Number of strides. */
@@ -410,4 +417,12 @@ int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct ether_addr *mac,
 int mlx5_nl_switch_info(int nl, unsigned int ifindex,
 			struct mlx5_switch_info *info);
 
+/* mlx5_devx_cmds.c */
+
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcx);
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj);
+int mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcx,
+				     int clear,
+				     uint64_t *pkts, uint64_t *bytes);
 #endif /* RTE_PMD_MLX5_H_ */
diff --git a/drivers/net/mlx5/mlx5_devx_cmds.c b/drivers/net/mlx5/mlx5_devx_cmds.c
new file mode 100644
index 0000000..a9dff58
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_devx_cmds.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright 2018 Mellanox Technologies, Ltd */
+
+#include <rte_flow_driver.h>
+
+#include "mlx5.h"
+#include "mlx5_glue.h"
+#include "mlx5_prm.h"
+
+/**
+ * Allocate flow counters via devx interface.
+ *
+ * @param[in] ctx
+ *   ibv contexts returned from mlx5dv_open_device.
+ * @param dcs
+ *   Pointer to counters properties structure to be filled by the routine.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcs)
+{
+	uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)]   = {0};
+	uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0};
+	int status, syndrome;
+
+	MLX5_SET(alloc_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
+	dcs->obj = mlx5_glue->devx_obj_create(ctx, in,
+					      sizeof(in), out, sizeof(out));
+	if (!dcs->obj)
+		return -errno;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to create devx counters, "
+			"status %x, syndrome %x", status, syndrome);
+		return -1;
+	}
+	dcs->id = MLX5_GET(alloc_flow_counter_out,
+			   out, flow_counter_id);
+	return 0;
+}
+
+/**
+ * Free flow counters obtained via devx interface.
+ *
+ * @param[in] obj
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj)
+{
+	return mlx5_glue->devx_obj_destroy(obj);
+}
+
+/**
+ * Query flow counters values.
+ *
+ * @param[in] dcs
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ * @param[in] clear
+ *   Whether hardware should clear the counters after the query or not.
+ *  @param pkts
+ *   The number of packets that matched the flow.
+ *  @param bytes
+ *    The number of bytes that matched the flow.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs,
+				 int clear __rte_unused,
+				 uint64_t *pkts, uint64_t *bytes)
+{
+	uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
+		MLX5_ST_SZ_BYTES(traffic_counter)]   = {0};
+	uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0};
+	void *stats;
+	int status, syndrome, rc;
+
+	MLX5_SET(query_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
+	MLX5_SET(query_flow_counter_in, in, op_mod, 0);
+	MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id);
+	rc = mlx5_glue->devx_obj_query(dcs->obj,
+				       in, sizeof(in), out, sizeof(out));
+	if (rc)
+		return rc;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to query devx counters, "
+			"id %d, status %x, syndrome = %x",
+			status, syndrome, dcs->id);
+		return -1;
+	}
+	stats = MLX5_ADDR_OF(query_flow_counter_out,
+			     out, flow_statistics);
+	*pkts = MLX5_GET64(traffic_counter, stats, packets);
+	*bytes = MLX5_GET64(traffic_counter, stats, octets);
+	return 0;
+}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index cb1e6fd..ad9abb1 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -21,6 +21,9 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include "mlx5.h"
+#include "mlx5_prm.h"
+
 /* Pattern outer Layer bits. */
 #define MLX5_FLOW_LAYER_OUTER_L2 (1u << 0)
 #define MLX5_FLOW_LAYER_OUTER_L3_IPV4 (1u << 1)
@@ -319,11 +322,14 @@ struct mlx5_flow_counter {
 	uint32_t shared:1; /**< Share counter ID with other flow rules. */
 	uint32_t ref_cnt:31; /**< Reference counter. */
 	uint32_t id; /**< Counter ID. */
+	union {  /**< Holds the counters for the rule. */
 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
-	struct ibv_counter_set *cs; /**< Holds the counters for the rule. */
+		struct ibv_counter_set *cs;
 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
-	struct ibv_counters *cs; /**< Holds the counters for the rule. */
+		struct ibv_counters *cs;
 #endif
+		struct mlx5_devx_counter_set *dcs;
+	};
 	uint64_t hits; /**< Number of packets matched by the rule. */
 	uint64_t bytes; /**< Number of bytes matched by the rule. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 4c0b7ed..0d35282 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -569,6 +569,36 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Validate count action.
+ *
+ * @param[in] dev
+ *   device otr.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_count(struct rte_eth_dev *dev,
+			      struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+
+	if (!priv->config.devx)
+		goto notsup_err;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+	return 0;
+#endif
+notsup_err:
+	return rte_flow_error_set
+		      (error, ENOTSUP,
+		       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+		       NULL,
+		       "count action not supported");
+}
+
+/**
  * Validate the L2 encap action.
  *
  * @param[in] action_flags
@@ -1456,6 +1486,87 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Get or create a flow counter.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] shared
+ *   Indicate if this counter is shared with other flows.
+ * @param[in] id
+ *   Counter identifier.
+ *
+ * @return
+ *   pointer to flow counter on success, NULL otherwise and rte_errno is set.
+ */
+static struct mlx5_flow_counter *
+flow_dv_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_counter *cnt = NULL;
+	struct mlx5_devx_counter_set *dcs = NULL;
+	int ret;
+
+	if (!priv->config.devx) {
+		ret = -ENOTSUP;
+		goto error_exit;
+	}
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
+	}
+	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
+	dcs = rte_calloc(__func__, 1, sizeof(*dcs), 0);
+	if (!dcs || !cnt) {
+		ret = -ENOMEM;
+		goto error_exit;
+	}
+	ret = mlx5_devx_cmd_flow_counter_alloc(priv->ctx, dcs);
+	if (ret)
+		goto error_exit;
+	struct mlx5_flow_counter tmpl = {
+		.shared = shared,
+		.ref_cnt = 1,
+		.id = id,
+		.dcs = dcs,
+	};
+	*cnt = tmpl;
+	LIST_INSERT_HEAD(&priv->flow_counters, cnt, next);
+	return cnt;
+error_exit:
+	rte_free(cnt);
+	rte_free(dcs);
+	rte_errno = -ret;
+	return NULL;
+}
+
+/**
+ * Release a flow counter.
+ *
+ * @param[in] counter
+ *   Pointer to the counter handler.
+ */
+static void
+flow_dv_counter_release(struct mlx5_flow_counter *counter)
+{
+	int ret;
+
+	if (!counter)
+		return;
+	if (--counter->ref_cnt == 0) {
+		ret = mlx5_devx_cmd_flow_counter_free(counter->dcs->obj);
+		if (ret)
+			DRV_LOG(ERR, "Failed to free devx counters, %d", ret);
+		LIST_REMOVE(counter, next);
+		rte_free(counter->dcs);
+		rte_free(counter);
+	}
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -1717,7 +1828,7 @@ struct field_modify_info modify_tcp[] = {
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
-			ret = mlx5_flow_validate_action_count(dev, attr, error);
+			ret = flow_dv_validate_action_count(dev, error);
 			if (ret < 0)
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
@@ -2741,6 +2852,9 @@ struct field_modify_info modify_tcp[] = {
 		const struct rte_flow_action_queue *queue;
 		const struct rte_flow_action_rss *rss;
 		const struct rte_flow_action *action = actions;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+		const struct rte_flow_action_count *count = action->conf;
+#endif
 		const uint8_t *rss_key;
 
 		switch (actions->type) {
@@ -2789,6 +2903,37 @@ struct field_modify_info modify_tcp[] = {
 			flow->rss.level = rss->level;
 			action_flags |= MLX5_FLOW_ACTION_RSS;
 			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			if (!priv->config.devx) {
+				rte_errno = ENOTSUP;
+				goto cnt_err;
+			}
+			flow->counter =
+				flow_dv_counter_new(dev,
+						    count->shared, count->id);
+			if (flow->counter == NULL)
+				goto cnt_err;
+			dev_flow->dv.actions[actions_n].type =
+					MLX5DV_FLOW_ACTION_COUNTER_DEVX;
+			dev_flow->dv.actions[actions_n].obj =
+						flow->counter->dcs->obj;
+			action_flags |= MLX5_FLOW_ACTION_COUNT;
+			++actions_n;
+			break;
+cnt_err:
+			if (rte_errno == ENOTSUP)
+				return rte_flow_error_set
+					      (error, ENOTSUP,
+					       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					       NULL,
+					       "count action not supported");
+			else
+				return rte_flow_error_set
+						(error, rte_errno,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 action,
+						 "cannot create counter"
+						  " object.");
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			if (flow_dv_create_action_l2_encap(dev, actions,
@@ -3279,8 +3424,6 @@ struct field_modify_info modify_tcp[] = {
 			dv->hrxq = NULL;
 		}
 	}
-	if (flow->counter)
-		flow->counter = NULL;
 }
 
 /**
@@ -3299,6 +3442,10 @@ struct field_modify_info modify_tcp[] = {
 	if (!flow)
 		return;
 	flow_dv_remove(dev, flow);
+	if (flow->counter) {
+		flow_dv_counter_release(flow->counter);
+		flow->counter = NULL;
+	}
 	while (!LIST_EMPTY(&flow->dev_flows)) {
 		dev_flow = LIST_FIRST(&flow->dev_flows);
 		LIST_REMOVE(dev_flow, next);
@@ -3313,22 +3460,91 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Query a dv flow  rule for its statistics via devx.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] flow
+ *   Pointer to the sub flow.
+ * @param[out] data
+ *   data retrieved by the query.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
+		    void *data, struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct rte_flow_query_count *qc = data;
+	uint64_t pkts = 0;
+	uint64_t bytes = 0;
+	int err;
+
+	if (!priv->config.devx)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "counters are not supported");
+	if (flow->counter) {
+		err = mlx5_devx_cmd_flow_counter_query
+						(flow->counter->dcs,
+						 qc->reset, &pkts, &bytes);
+		if (err)
+			return rte_flow_error_set
+				(error, err,
+				 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				 NULL,
+				 "cannot read counters");
+		qc->hits_set = 1;
+		qc->bytes_set = 1;
+		qc->hits = pkts - flow->counter->hits;
+		qc->bytes = bytes - flow->counter->bytes;
+		if (qc->reset) {
+			flow->counter->hits = pkts;
+			flow->counter->bytes = bytes;
+		}
+		return 0;
+	}
+	return rte_flow_error_set(error, EINVAL,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL,
+				  "counters are not available");
+}
+
+/**
  * Query a flow.
  *
  * @see rte_flow_query()
  * @see rte_flow_ops
  */
 static int
-flow_dv_query(struct rte_eth_dev *dev __rte_unused,
+flow_dv_query(struct rte_eth_dev *dev,
 	      struct rte_flow *flow __rte_unused,
 	      const struct rte_flow_action *actions __rte_unused,
 	      void *data __rte_unused,
 	      struct rte_flow_error *error __rte_unused)
 {
-	return rte_flow_error_set(error, ENOTSUP,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL,
-				  "flow query with DV is not supported");
+	int ret = -EINVAL;
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow_dv_query_count(dev, flow, data, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  actions,
+						  "action not supported");
+		}
+	}
+	return ret;
 }
 
 
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 5c39036..da1219e 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -368,6 +368,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_dw_bit_off(typ, fld) (32 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0x1f))
 #define __mlx5_dw_off(typ, fld) (__mlx5_bit_off(typ, fld) / 32)
+#define __mlx5_64_off(typ, fld) (__mlx5_bit_off(typ, fld) / 64)
 #define __mlx5_dw_mask(typ, fld) (__mlx5_mask(typ, fld) << \
 				  __mlx5_dw_bit_off(typ, fld))
 #define __mlx5_mask(typ, fld) ((u32)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
@@ -375,6 +376,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_16_bit_off(typ, fld) (16 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0xf))
 #define __mlx5_mask16(typ, fld) ((u16)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
+#define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32)
 #define MLX5_ST_SZ_DB(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8)
@@ -391,10 +393,16 @@ struct mlx5_modification_cmd {
 				 (((_v) & __mlx5_mask(typ, fld)) << \
 				   __mlx5_dw_bit_off(typ, fld))); \
 	} while (0)
+#define MLX5_GET(typ, p, fld) \
+	((rte_be_to_cpu_32(*((__be32 *)(p) +\
+	__mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
+	__mlx5_mask(typ, fld))
 #define MLX5_GET16(typ, p, fld) \
 	((rte_be_to_cpu_16(*((__be16 *)(p) + \
 	  __mlx5_16_off(typ, fld))) >> __mlx5_16_bit_off(typ, fld)) & \
 	 __mlx5_mask16(typ, fld))
+#define MLX5_GET64(typ, p, fld) rte_be_to_cpu_64(*((__be64 *)(p) + \
+						   __mlx5_64_off(typ, fld)))
 #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8)
 
 struct mlx5_ifc_fte_match_set_misc_bits {
@@ -500,6 +508,69 @@ enum {
 	MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT
 };
 
+enum {
+	MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939,
+	MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b,
+};
+
+/* Flow counters. */
+struct mlx5_ifc_alloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_alloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_traffic_counter_bits {
+	u8         packets[0x40];
+	u8         octets[0x40];
+};
+
+struct mlx5_ifc_query_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+	struct mlx5_ifc_traffic_counter_bits flow_statistics[];
+};
+
+struct mlx5_ifc_query_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x80];
+	u8         clear[0x1];
+	u8         reserved_at_c1[0xf];
+	u8         num_of_counters[0x10];
+	u8         flow_counter_id[0x20];
+};
+
 /* CQE format mask. */
 #define MLX5E_CQE_FORMAT_MASK 0xc
 
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
@ 2018-12-29 20:12     ` Slava Ovsiienko
  2018-12-31  7:23       ` Shahaf Shuler
  2019-01-02  6:58       ` Mordechay Haimovsky
  0 siblings, 2 replies; 24+ messages in thread
From: Slava Ovsiienko @ 2018-12-29 20:12 UTC (permalink / raw)
  To: Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky, stable

Moti, don't you forget to update flow_verbs_counter_release() ?
Only shared counters should be removed from the list.

WBR,
Slava

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Mordechay Haimovsky
> Sent: Friday, December 28, 2018 0:20
> To: dev@dpdk.org
> Cc: Mordechay Haimovsky <motih@mellanox.com>; stable@dpdk.org
> Subject: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation
> logic
> 
> This commit fixes the logic for searching and allocating a shared counter in
> mlx5_flow_verbs.
> Now only the shared counters in the counters list are checked for a match
> and not all the counters as before.
> 
> Fixes: 84c406e74524 ("net/mlx5: add flow translate function")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> ---
> v2:
> * Modified commit header
> ---
>  drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c
> b/drivers/net/mlx5/mlx5_flow_verbs.c
> index 81ec59d..409e1cd 100644
> --- a/drivers/net/mlx5/mlx5_flow_verbs.c
> +++ b/drivers/net/mlx5/mlx5_flow_verbs.c
> @@ -121,13 +121,13 @@
>  	struct mlx5_flow_counter *cnt;
>  	int ret;
> 
> -	LIST_FOREACH(cnt, &priv->flow_counters, next) {
> -		if (!cnt->shared || cnt->shared != shared)
> -			continue;
> -		if (cnt->id != id)
> -			continue;
> -		cnt->ref_cnt++;
> -		return cnt;
> +	if (shared) {
> +		LIST_FOREACH(cnt, &priv->flow_counters, next) {
> +			if (cnt->shared && cnt->id == id) {
> +				cnt->ref_cnt++;
> +				return cnt;
> +			}
> +		}
>  	}
>  	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
>  	if (!cnt) {
> --
> 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic
  2018-12-29 20:12     ` Slava Ovsiienko
@ 2018-12-31  7:23       ` Shahaf Shuler
  2019-01-02  6:58       ` Mordechay Haimovsky
  1 sibling, 0 replies; 24+ messages in thread
From: Shahaf Shuler @ 2018-12-31  7:23 UTC (permalink / raw)
  To: Slava Ovsiienko, Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky, stable

Saturday, December 29, 2018 10:13 PM, Slava Ovsiienko:
> Subject: Re: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation
> logic
> 
> Moti, don't you forget to update flow_verbs_counter_release() ?
> Only shared counters should be removed from the list.

+1, thanks slava.

Moti, I have no more comments on this series.
Please fix above and send the next series w/ my Ack. 

> 
> WBR,
> Slava
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Mordechay Haimovsky
> > Sent: Friday, December 28, 2018 0:20
> > To: dev@dpdk.org
> > Cc: Mordechay Haimovsky <motih@mellanox.com>; stable@dpdk.org
> > Subject: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter
> > allocation logic
> >
> > This commit fixes the logic for searching and allocating a shared
> > counter in mlx5_flow_verbs.
> > Now only the shared counters in the counters list are checked for a
> > match and not all the counters as before.
> >
> > Fixes: 84c406e74524 ("net/mlx5: add flow translate function")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> > ---
> > v2:
> > * Modified commit header
> > ---
> >  drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c
> > b/drivers/net/mlx5/mlx5_flow_verbs.c
> > index 81ec59d..409e1cd 100644
> > --- a/drivers/net/mlx5/mlx5_flow_verbs.c
> > +++ b/drivers/net/mlx5/mlx5_flow_verbs.c
> > @@ -121,13 +121,13 @@
> >  	struct mlx5_flow_counter *cnt;
> >  	int ret;
> >
> > -	LIST_FOREACH(cnt, &priv->flow_counters, next) {
> > -		if (!cnt->shared || cnt->shared != shared)
> > -			continue;
> > -		if (cnt->id != id)
> > -			continue;
> > -		cnt->ref_cnt++;
> > -		return cnt;
> > +	if (shared) {
> > +		LIST_FOREACH(cnt, &priv->flow_counters, next) {
> > +			if (cnt->shared && cnt->id == id) {
> > +				cnt->ref_cnt++;
> > +				return cnt;
> > +			}
> > +		}
> >  	}
> >  	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
> >  	if (!cnt) {
> > --
> > 1.8.3.1

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

* Re: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic
  2018-12-29 20:12     ` Slava Ovsiienko
  2018-12-31  7:23       ` Shahaf Shuler
@ 2019-01-02  6:58       ` Mordechay Haimovsky
  1 sibling, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-02  6:58 UTC (permalink / raw)
  To: Slava Ovsiienko, dev; +Cc: stable

Hi,
 Every counter that is created (shared or not) is added to the counters list 
Therefore every counter destined for  removal (i.e. ref_count == 0) should also be 
Removed from this list.

What am I missing ?

Moti

> -----Original Message-----
> From: Slava Ovsiienko
> Sent: Saturday, December 29, 2018 10:13 PM
> To: Mordechay Haimovsky <motih@mellanox.com>; dev@dpdk.org
> Cc: Mordechay Haimovsky <motih@mellanox.com>; stable@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter
> allocation logic
> 
> Moti, don't you forget to update flow_verbs_counter_release() ?
> Only shared counters should be removed from the list.
> 
> WBR,
> Slava
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Mordechay Haimovsky
> > Sent: Friday, December 28, 2018 0:20
> > To: dev@dpdk.org
> > Cc: Mordechay Haimovsky <motih@mellanox.com>; stable@dpdk.org
> > Subject: [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter
> > allocation logic
> >
> > This commit fixes the logic for searching and allocating a shared
> > counter in mlx5_flow_verbs.
> > Now only the shared counters in the counters list are checked for a
> > match and not all the counters as before.
> >
> > Fixes: 84c406e74524 ("net/mlx5: add flow translate function")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> > ---
> > v2:
> > * Modified commit header
> > ---
> >  drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
> >  1 file changed, 7 insertions(+), 7 deletions(-)
> >
> > diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c
> > b/drivers/net/mlx5/mlx5_flow_verbs.c
> > index 81ec59d..409e1cd 100644
> > --- a/drivers/net/mlx5/mlx5_flow_verbs.c
> > +++ b/drivers/net/mlx5/mlx5_flow_verbs.c
> > @@ -121,13 +121,13 @@
> >  	struct mlx5_flow_counter *cnt;
> >  	int ret;
> >
> > -	LIST_FOREACH(cnt, &priv->flow_counters, next) {
> > -		if (!cnt->shared || cnt->shared != shared)
> > -			continue;
> > -		if (cnt->id != id)
> > -			continue;
> > -		cnt->ref_cnt++;
> > -		return cnt;
> > +	if (shared) {
> > +		LIST_FOREACH(cnt, &priv->flow_counters, next) {
> > +			if (cnt->shared && cnt->id == id) {
> > +				cnt->ref_cnt++;
> > +				return cnt;
> > +			}
> > +		}
> >  	}
> >  	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
> >  	if (!cnt) {
> > --
> > 1.8.3.1

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

* [dpdk-dev] [PATCH v3 0/3] support flow counters using devx
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
@ 2019-01-02  9:43     ` Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-02  9:43 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This series of commits add support for creating, allocating, querying
and destroying flow counters in mlx5 PMD using the devx interface.

Moti Haimovsky (3):
  net/mlx5: fix shared counter allocation logic
  net/mlx5: add devx functions to glue
  net/mlx5: support flow counters using devx

 drivers/net/mlx5/Makefile          |  11 ++
 drivers/net/mlx5/meson.build       |   5 +
 drivers/net/mlx5/mlx5.c            |  16 ++-
 drivers/net/mlx5/mlx5.h            |  15 +++
 drivers/net/mlx5/mlx5_devx_cmds.c  | 107 +++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h       |  10 +-
 drivers/net/mlx5/mlx5_flow_dv.c    | 232 +++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_flow_verbs.c |  14 +--
 drivers/net/mlx5/mlx5_glue.c       |  98 ++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h       |  19 +++
 drivers/net/mlx5/mlx5_prm.h        |  71 ++++++++++++
 11 files changed, 576 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 1/3] net/mlx5: fix shared counter allocation logic
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 0/3] " Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
@ 2019-01-02  9:43     ` Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  3 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-02  9:43 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky, stable

This commit fixes the logic for searching and allocating a shared
counter in mlx5_flow_verbs.
Now only the shared counters in the counters list are checked for
a match and not all the counters as before.

Fixes: 84c406e74524 ("net/mlx5: add flow translate function")
Cc: stable@dpdk.org

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modified commit header
---
 drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 81ec59d..409e1cd 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -121,13 +121,13 @@
 	struct mlx5_flow_counter *cnt;
 	int ret;
 
-	LIST_FOREACH(cnt, &priv->flow_counters, next) {
-		if (!cnt->shared || cnt->shared != shared)
-			continue;
-		if (cnt->id != id)
-			continue;
-		cnt->ref_cnt++;
-		return cnt;
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
 	}
 	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
 	if (!cnt) {
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 2/3] net/mlx5: add devx functions to glue
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 0/3] " Mordechay Haimovsky
@ 2019-01-02  9:43     ` Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  3 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-02  9:43 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This patch adds glue functions for operations:
  - dv_open_device.
  - devx object create, destroy, query and modify.
  - devx general command
The new operations depend on HAVE_IBV_DEVX_OBJ.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modifications according to review inputs.
  see message Id: 1545748697-3385-3-git-send-email-motih@mellanox.com
---
 drivers/net/mlx5/Makefile    |  5 +++
 drivers/net/mlx5/meson.build |  2 +
 drivers/net/mlx5/mlx5_glue.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 19 +++++++++
 4 files changed, 124 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 1353c18..8ddad1a 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -148,6 +148,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_DEVX_OBJ \
+		infiniband/mlx5dv.h \
+		func mlx5dv_devx_obj_create \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 8ba19e8..e2fc4ea 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -104,6 +104,8 @@ if build
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
+		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
+		'mlx5dv_devx_obj_create' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index a806d92..c817d86 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -498,6 +498,98 @@
 #endif
 }
 
+static struct ibv_context *
+mlx5_glue_dv_open_device(struct ibv_device *device)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_open_device(device,
+				  &(struct mlx5dv_context_attr){
+					.flags = MLX5DV_CONTEXT_FLAGS_DEVX,
+				  });
+#else
+	(void)device;
+	return NULL;
+#endif
+}
+
+static struct mlx5dv_devx_obj *
+mlx5_glue_devx_obj_create(struct ibv_context *ctx,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_create(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return NULL;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_destroy(struct mlx5dv_devx_obj *obj)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_destroy(obj);
+#else
+	(void)obj;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_query(struct mlx5dv_devx_obj *obj,
+			 const void *in, size_t inlen,
+			 void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_query(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_modify(struct mlx5dv_devx_obj *obj,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_modify(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_general_cmd(struct ibv_context *ctx,
+			   const void *in, size_t inlen,
+			   void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_general_cmd(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
 
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
@@ -557,4 +649,10 @@
 			mlx5_glue_dv_create_flow_action_packet_reformat,
 	.dv_create_flow_action_modify_header =
 			mlx5_glue_dv_create_flow_action_modify_header,
+	.dv_open_device = mlx5_glue_dv_open_device,
+	.devx_obj_create = mlx5_glue_devx_obj_create,
+	.devx_obj_destroy = mlx5_glue_devx_obj_destroy,
+	.devx_obj_query = mlx5_glue_devx_obj_query,
+	.devx_obj_modify = mlx5_glue_devx_obj_modify,
+	.devx_general_cmd = mlx5_glue_devx_general_cmd,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 9cfe836..b118960 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -55,6 +55,10 @@
 enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
+#ifndef HAVE_IBV_DEVX_OBJ
+struct mlx5dv_devx_obj;
+#endif
+
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
 struct mlx5_glue {
 	const char *version;
@@ -169,6 +173,21 @@ struct mlx5_glue {
 					 size_t actions_sz,
 					 uint64_t actions[],
 					 enum mlx5dv_flow_table_type ft_type);
+	struct ibv_context *(*dv_open_device)(struct ibv_device *device);
+	struct mlx5dv_devx_obj *(*devx_obj_create)
+					(struct ibv_context *ctx,
+					 const void *in, size_t inlen,
+					 void *out, size_t outlen);
+	int (*devx_obj_destroy)(struct mlx5dv_devx_obj *obj);
+	int (*devx_obj_query)(struct mlx5dv_devx_obj *obj,
+			      const void *in, size_t inlen,
+			      void *out, size_t outlen);
+	int (*devx_obj_modify)(struct mlx5dv_devx_obj *obj,
+			       const void *in, size_t inlen,
+			       void *out, size_t outlen);
+	int (*devx_general_cmd)(struct ibv_context *context,
+				const void *in, size_t inlen,
+				void *out, size_t outlen);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx
  2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
                       ` (2 preceding siblings ...)
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
@ 2019-01-02  9:43     ` Mordechay Haimovsky
  2019-01-03  8:29       ` Shahaf Shuler
                         ` (4 more replies)
  3 siblings, 5 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-02  9:43 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This commit adds counters support when creating flows via direct
verbs. The implementation uses devx interface in order to create
query and delete the counters.
This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modifications according to code review,
  See message Id: 1545748697-3385-4-git-send-email-motih@mellanox.com
v3:
* Modified calls to devx routins to be done through the glue interface.
 See message Id: 1545949196-3355-4-git-send-email-motih@mellanox.com
---
 drivers/net/mlx5/Makefile         |   6 +
 drivers/net/mlx5/meson.build      |   3 +
 drivers/net/mlx5/mlx5.c           |  16 ++-
 drivers/net/mlx5/mlx5.h           |  15 +++
 drivers/net/mlx5/mlx5_devx_cmds.c | 107 ++++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h      |  10 +-
 drivers/net/mlx5/mlx5_flow_dv.c   | 232 ++++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_prm.h       |  71 ++++++++++++
 8 files changed, 445 insertions(+), 15 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 8ddad1a..a1749e4 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_tcf.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_devx_cmds.c
 
 ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y)
 INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib += $(LIB_GLUE)
@@ -153,6 +154,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_devx_obj_create \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_FLOW_DEVX_COUNTERS \
+		infiniband/mlx5dv.h \
+		enum MLX5DV_FLOW_ACTION_COUNTER_DEVX \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e2fc4ea..e9db36c 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -46,6 +46,7 @@ if build
 		'mlx5_trigger.c',
 		'mlx5_txq.c',
 		'mlx5_vlan.c',
+		'mlx5_devx_cmds.c',
 	)
 	if dpdk_conf.has('RTE_ARCH_X86_64') or dpdk_conf.has('RTE_ARCH_ARM64')
 		sources += files('mlx5_rxtx_vec.c')
@@ -106,6 +107,8 @@ if build
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
 		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
 		'mlx5dv_devx_obj_create' ],
+		[ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h',
+		'MLX5DV_FLOW_ACTION_COUNTER_DEVX' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 4521045..c5ed402 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -727,7 +727,7 @@
 	       struct mlx5_dev_config config,
 	       const struct mlx5_switch_info *switch_info)
 {
-	struct ibv_context *ctx;
+	struct ibv_context *ctx = NULL;
 	struct ibv_device_attr_ex attr;
 	struct ibv_port_attr port_attr;
 	struct ibv_pd *pd = NULL;
@@ -786,10 +786,16 @@
 	/* Prepare shared data between primary and secondary process. */
 	mlx5_prepare_shared_data();
 	errno = 0;
-	ctx = mlx5_glue->open_device(ibv_dev);
-	if (!ctx) {
-		rte_errno = errno ? errno : ENODEV;
-		return NULL;
+	ctx = mlx5_glue->dv_open_device(ibv_dev);
+	if (ctx) {
+		config.devx = 1;
+		DRV_LOG(DEBUG, "DEVX is supported");
+	} else {
+		ctx = mlx5_glue->open_device(ibv_dev);
+		if (!ctx) {
+			rte_errno = errno ? errno : ENODEV;
+			return NULL;
+		}
 	}
 #ifdef HAVE_IBV_MLX5_MOD_SWP
 	dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index b48cd94..45f0398 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -98,6 +98,12 @@ struct mlx5_stats_ctrl {
 	uint64_t imissed_base;
 };
 
+/* devx counter object */
+struct mlx5_devx_counter_set {
+	struct mlx5dv_devx_obj *obj;
+	int id; /* Flow counter ID */
+};
+
 /* Flow list . */
 TAILQ_HEAD(mlx5_flows, rte_flow);
 
@@ -131,6 +137,7 @@ struct mlx5_dev_config {
 	unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */
 	unsigned int dv_flow_en:1; /* Enable DV flow. */
 	unsigned int swp:1; /* Tx generic tunnel checksum and TSO offload. */
+	unsigned int devx:1; /* Whether devx interface is available or not. */
 	struct {
 		unsigned int enabled:1; /* Whether MPRQ is enabled. */
 		unsigned int stride_num_n; /* Number of strides. */
@@ -412,4 +419,12 @@ int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct ether_addr *mac,
 int mlx5_nl_switch_info(int nl, unsigned int ifindex,
 			struct mlx5_switch_info *info);
 
+/* mlx5_devx_cmds.c */
+
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcx);
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj);
+int mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcx,
+				     int clear,
+				     uint64_t *pkts, uint64_t *bytes);
 #endif /* RTE_PMD_MLX5_H_ */
diff --git a/drivers/net/mlx5/mlx5_devx_cmds.c b/drivers/net/mlx5/mlx5_devx_cmds.c
new file mode 100644
index 0000000..a9dff58
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_devx_cmds.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright 2018 Mellanox Technologies, Ltd */
+
+#include <rte_flow_driver.h>
+
+#include "mlx5.h"
+#include "mlx5_glue.h"
+#include "mlx5_prm.h"
+
+/**
+ * Allocate flow counters via devx interface.
+ *
+ * @param[in] ctx
+ *   ibv contexts returned from mlx5dv_open_device.
+ * @param dcs
+ *   Pointer to counters properties structure to be filled by the routine.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcs)
+{
+	uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)]   = {0};
+	uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0};
+	int status, syndrome;
+
+	MLX5_SET(alloc_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
+	dcs->obj = mlx5_glue->devx_obj_create(ctx, in,
+					      sizeof(in), out, sizeof(out));
+	if (!dcs->obj)
+		return -errno;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to create devx counters, "
+			"status %x, syndrome %x", status, syndrome);
+		return -1;
+	}
+	dcs->id = MLX5_GET(alloc_flow_counter_out,
+			   out, flow_counter_id);
+	return 0;
+}
+
+/**
+ * Free flow counters obtained via devx interface.
+ *
+ * @param[in] obj
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj)
+{
+	return mlx5_glue->devx_obj_destroy(obj);
+}
+
+/**
+ * Query flow counters values.
+ *
+ * @param[in] dcs
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ * @param[in] clear
+ *   Whether hardware should clear the counters after the query or not.
+ *  @param pkts
+ *   The number of packets that matched the flow.
+ *  @param bytes
+ *    The number of bytes that matched the flow.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs,
+				 int clear __rte_unused,
+				 uint64_t *pkts, uint64_t *bytes)
+{
+	uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
+		MLX5_ST_SZ_BYTES(traffic_counter)]   = {0};
+	uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0};
+	void *stats;
+	int status, syndrome, rc;
+
+	MLX5_SET(query_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
+	MLX5_SET(query_flow_counter_in, in, op_mod, 0);
+	MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id);
+	rc = mlx5_glue->devx_obj_query(dcs->obj,
+				       in, sizeof(in), out, sizeof(out));
+	if (rc)
+		return rc;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to query devx counters, "
+			"id %d, status %x, syndrome = %x",
+			status, syndrome, dcs->id);
+		return -1;
+	}
+	stats = MLX5_ADDR_OF(query_flow_counter_out,
+			     out, flow_statistics);
+	*pkts = MLX5_GET64(traffic_counter, stats, packets);
+	*bytes = MLX5_GET64(traffic_counter, stats, octets);
+	return 0;
+}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index cb1e6fd..ad9abb1 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -21,6 +21,9 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include "mlx5.h"
+#include "mlx5_prm.h"
+
 /* Pattern outer Layer bits. */
 #define MLX5_FLOW_LAYER_OUTER_L2 (1u << 0)
 #define MLX5_FLOW_LAYER_OUTER_L3_IPV4 (1u << 1)
@@ -319,11 +322,14 @@ struct mlx5_flow_counter {
 	uint32_t shared:1; /**< Share counter ID with other flow rules. */
 	uint32_t ref_cnt:31; /**< Reference counter. */
 	uint32_t id; /**< Counter ID. */
+	union {  /**< Holds the counters for the rule. */
 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
-	struct ibv_counter_set *cs; /**< Holds the counters for the rule. */
+		struct ibv_counter_set *cs;
 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
-	struct ibv_counters *cs; /**< Holds the counters for the rule. */
+		struct ibv_counters *cs;
 #endif
+		struct mlx5_devx_counter_set *dcs;
+	};
 	uint64_t hits; /**< Number of packets matched by the rule. */
 	uint64_t bytes; /**< Number of bytes matched by the rule. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 4c0b7ed..0d35282 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -569,6 +569,36 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Validate count action.
+ *
+ * @param[in] dev
+ *   device otr.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_count(struct rte_eth_dev *dev,
+			      struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+
+	if (!priv->config.devx)
+		goto notsup_err;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+	return 0;
+#endif
+notsup_err:
+	return rte_flow_error_set
+		      (error, ENOTSUP,
+		       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+		       NULL,
+		       "count action not supported");
+}
+
+/**
  * Validate the L2 encap action.
  *
  * @param[in] action_flags
@@ -1456,6 +1486,87 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Get or create a flow counter.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] shared
+ *   Indicate if this counter is shared with other flows.
+ * @param[in] id
+ *   Counter identifier.
+ *
+ * @return
+ *   pointer to flow counter on success, NULL otherwise and rte_errno is set.
+ */
+static struct mlx5_flow_counter *
+flow_dv_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_counter *cnt = NULL;
+	struct mlx5_devx_counter_set *dcs = NULL;
+	int ret;
+
+	if (!priv->config.devx) {
+		ret = -ENOTSUP;
+		goto error_exit;
+	}
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
+	}
+	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
+	dcs = rte_calloc(__func__, 1, sizeof(*dcs), 0);
+	if (!dcs || !cnt) {
+		ret = -ENOMEM;
+		goto error_exit;
+	}
+	ret = mlx5_devx_cmd_flow_counter_alloc(priv->ctx, dcs);
+	if (ret)
+		goto error_exit;
+	struct mlx5_flow_counter tmpl = {
+		.shared = shared,
+		.ref_cnt = 1,
+		.id = id,
+		.dcs = dcs,
+	};
+	*cnt = tmpl;
+	LIST_INSERT_HEAD(&priv->flow_counters, cnt, next);
+	return cnt;
+error_exit:
+	rte_free(cnt);
+	rte_free(dcs);
+	rte_errno = -ret;
+	return NULL;
+}
+
+/**
+ * Release a flow counter.
+ *
+ * @param[in] counter
+ *   Pointer to the counter handler.
+ */
+static void
+flow_dv_counter_release(struct mlx5_flow_counter *counter)
+{
+	int ret;
+
+	if (!counter)
+		return;
+	if (--counter->ref_cnt == 0) {
+		ret = mlx5_devx_cmd_flow_counter_free(counter->dcs->obj);
+		if (ret)
+			DRV_LOG(ERR, "Failed to free devx counters, %d", ret);
+		LIST_REMOVE(counter, next);
+		rte_free(counter->dcs);
+		rte_free(counter);
+	}
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -1717,7 +1828,7 @@ struct field_modify_info modify_tcp[] = {
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
-			ret = mlx5_flow_validate_action_count(dev, attr, error);
+			ret = flow_dv_validate_action_count(dev, error);
 			if (ret < 0)
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
@@ -2741,6 +2852,9 @@ struct field_modify_info modify_tcp[] = {
 		const struct rte_flow_action_queue *queue;
 		const struct rte_flow_action_rss *rss;
 		const struct rte_flow_action *action = actions;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+		const struct rte_flow_action_count *count = action->conf;
+#endif
 		const uint8_t *rss_key;
 
 		switch (actions->type) {
@@ -2789,6 +2903,37 @@ struct field_modify_info modify_tcp[] = {
 			flow->rss.level = rss->level;
 			action_flags |= MLX5_FLOW_ACTION_RSS;
 			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			if (!priv->config.devx) {
+				rte_errno = ENOTSUP;
+				goto cnt_err;
+			}
+			flow->counter =
+				flow_dv_counter_new(dev,
+						    count->shared, count->id);
+			if (flow->counter == NULL)
+				goto cnt_err;
+			dev_flow->dv.actions[actions_n].type =
+					MLX5DV_FLOW_ACTION_COUNTER_DEVX;
+			dev_flow->dv.actions[actions_n].obj =
+						flow->counter->dcs->obj;
+			action_flags |= MLX5_FLOW_ACTION_COUNT;
+			++actions_n;
+			break;
+cnt_err:
+			if (rte_errno == ENOTSUP)
+				return rte_flow_error_set
+					      (error, ENOTSUP,
+					       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					       NULL,
+					       "count action not supported");
+			else
+				return rte_flow_error_set
+						(error, rte_errno,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 action,
+						 "cannot create counter"
+						  " object.");
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			if (flow_dv_create_action_l2_encap(dev, actions,
@@ -3279,8 +3424,6 @@ struct field_modify_info modify_tcp[] = {
 			dv->hrxq = NULL;
 		}
 	}
-	if (flow->counter)
-		flow->counter = NULL;
 }
 
 /**
@@ -3299,6 +3442,10 @@ struct field_modify_info modify_tcp[] = {
 	if (!flow)
 		return;
 	flow_dv_remove(dev, flow);
+	if (flow->counter) {
+		flow_dv_counter_release(flow->counter);
+		flow->counter = NULL;
+	}
 	while (!LIST_EMPTY(&flow->dev_flows)) {
 		dev_flow = LIST_FIRST(&flow->dev_flows);
 		LIST_REMOVE(dev_flow, next);
@@ -3313,22 +3460,91 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Query a dv flow  rule for its statistics via devx.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] flow
+ *   Pointer to the sub flow.
+ * @param[out] data
+ *   data retrieved by the query.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
+		    void *data, struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct rte_flow_query_count *qc = data;
+	uint64_t pkts = 0;
+	uint64_t bytes = 0;
+	int err;
+
+	if (!priv->config.devx)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "counters are not supported");
+	if (flow->counter) {
+		err = mlx5_devx_cmd_flow_counter_query
+						(flow->counter->dcs,
+						 qc->reset, &pkts, &bytes);
+		if (err)
+			return rte_flow_error_set
+				(error, err,
+				 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				 NULL,
+				 "cannot read counters");
+		qc->hits_set = 1;
+		qc->bytes_set = 1;
+		qc->hits = pkts - flow->counter->hits;
+		qc->bytes = bytes - flow->counter->bytes;
+		if (qc->reset) {
+			flow->counter->hits = pkts;
+			flow->counter->bytes = bytes;
+		}
+		return 0;
+	}
+	return rte_flow_error_set(error, EINVAL,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL,
+				  "counters are not available");
+}
+
+/**
  * Query a flow.
  *
  * @see rte_flow_query()
  * @see rte_flow_ops
  */
 static int
-flow_dv_query(struct rte_eth_dev *dev __rte_unused,
+flow_dv_query(struct rte_eth_dev *dev,
 	      struct rte_flow *flow __rte_unused,
 	      const struct rte_flow_action *actions __rte_unused,
 	      void *data __rte_unused,
 	      struct rte_flow_error *error __rte_unused)
 {
-	return rte_flow_error_set(error, ENOTSUP,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL,
-				  "flow query with DV is not supported");
+	int ret = -EINVAL;
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow_dv_query_count(dev, flow, data, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  actions,
+						  "action not supported");
+		}
+	}
+	return ret;
 }
 
 
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 5c39036..da1219e 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -368,6 +368,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_dw_bit_off(typ, fld) (32 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0x1f))
 #define __mlx5_dw_off(typ, fld) (__mlx5_bit_off(typ, fld) / 32)
+#define __mlx5_64_off(typ, fld) (__mlx5_bit_off(typ, fld) / 64)
 #define __mlx5_dw_mask(typ, fld) (__mlx5_mask(typ, fld) << \
 				  __mlx5_dw_bit_off(typ, fld))
 #define __mlx5_mask(typ, fld) ((u32)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
@@ -375,6 +376,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_16_bit_off(typ, fld) (16 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0xf))
 #define __mlx5_mask16(typ, fld) ((u16)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
+#define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32)
 #define MLX5_ST_SZ_DB(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8)
@@ -391,10 +393,16 @@ struct mlx5_modification_cmd {
 				 (((_v) & __mlx5_mask(typ, fld)) << \
 				   __mlx5_dw_bit_off(typ, fld))); \
 	} while (0)
+#define MLX5_GET(typ, p, fld) \
+	((rte_be_to_cpu_32(*((__be32 *)(p) +\
+	__mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
+	__mlx5_mask(typ, fld))
 #define MLX5_GET16(typ, p, fld) \
 	((rte_be_to_cpu_16(*((__be16 *)(p) + \
 	  __mlx5_16_off(typ, fld))) >> __mlx5_16_bit_off(typ, fld)) & \
 	 __mlx5_mask16(typ, fld))
+#define MLX5_GET64(typ, p, fld) rte_be_to_cpu_64(*((__be64 *)(p) + \
+						   __mlx5_64_off(typ, fld)))
 #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8)
 
 struct mlx5_ifc_fte_match_set_misc_bits {
@@ -500,6 +508,69 @@ enum {
 	MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT
 };
 
+enum {
+	MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939,
+	MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b,
+};
+
+/* Flow counters. */
+struct mlx5_ifc_alloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_alloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_traffic_counter_bits {
+	u8         packets[0x40];
+	u8         octets[0x40];
+};
+
+struct mlx5_ifc_query_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+	struct mlx5_ifc_traffic_counter_bits flow_statistics[];
+};
+
+struct mlx5_ifc_query_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x80];
+	u8         clear[0x1];
+	u8         reserved_at_c1[0xf];
+	u8         num_of_counters[0x10];
+	u8         flow_counter_id[0x20];
+};
+
 /* CQE format mask. */
 #define MLX5E_CQE_FORMAT_MASK 0xc
 
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
@ 2019-01-03  8:29       ` Shahaf Shuler
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 0/3] " Mordechay Haimovsky
                         ` (3 subsequent siblings)
  4 siblings, 0 replies; 24+ messages in thread
From: Shahaf Shuler @ 2019-01-03  8:29 UTC (permalink / raw)
  To: Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky

Moti,

Wednesday, January 2, 2019 11:43 AM, Mordechay Haimovsky:
> Subject: [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx
> 
> This commit adds counters support when creating flows via direct verbs. The
> implementation uses devx interface in order to create query and delete the
> counters.
> This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation.
> 
> Signed-off-by: Moti Haimovsky <motih@mellanox.com>
> ---
> v2:
> * Modifications according to code review,
>   See message Id: 1545748697-3385-4-git-send-email-motih@mellanox.com
> v3:
> * Modified calls to devx routins to be done through the glue interface.
>  See message Id: 1545949196-3355-4-git-send-email-motih@mellanox.com
> ---

[...]

> @@ -2789,6 +2903,37 @@ struct field_modify_info modify_tcp[] = {
>  			flow->rss.level = rss->level;
>  			action_flags |= MLX5_FLOW_ACTION_RSS;
>  			break;
> +		case RTE_FLOW_ACTION_TYPE_COUNT:
> +			if (!priv->config.devx) {
> +				rte_errno = ENOTSUP;
> +				goto cnt_err;
> +			}
> +			flow->counter =
> +				flow_dv_counter_new(dev,
> +						    count->shared, count->id);
> +			if (flow->counter == NULL)
> +				goto cnt_err;
> +			dev_flow->dv.actions[actions_n].type =
> +
> 	MLX5DV_FLOW_ACTION_COUNTER_DEVX;

Am having compilation issue here w/ old rdma-core where this feature is not defined. 
Please take care, and add my acked-by on the next version. 

> +			dev_flow->dv.actions[actions_n].obj =
> +						flow->counter->dcs->obj;
> +			action_flags |= MLX5_FLOW_ACTION_COUNT;
> +			++actions_n;
> +			break;
> +cnt_err:
> +			if (rte_errno == ENOTSUP)
> +				return rte_flow_error_set
> +					      (error, ENOTSUP,

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

* [dpdk-dev] [PATCH v4 0/3] support flow counters using devx
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2019-01-03  8:29       ` Shahaf Shuler
@ 2019-01-03 15:06       ` Mordechay Haimovsky
  2019-01-06  7:43         ` Shahaf Shuler
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
                         ` (2 subsequent siblings)
  4 siblings, 1 reply; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-03 15:06 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This series of commits add support for creating, allocating, querying
and destroying flow counters in mlx5 PMD using the devx interface.

Moti Haimovsky (3):
  net/mlx5: fix shared counter allocation logic
  net/mlx5: add devx functions to glue
  net/mlx5: support flow counters using devx

 drivers/net/mlx5/Makefile          |  11 ++
 drivers/net/mlx5/meson.build       |   5 +
 drivers/net/mlx5/mlx5.c            |  16 ++-
 drivers/net/mlx5/mlx5.h            |  15 +++
 drivers/net/mlx5/mlx5_devx_cmds.c  | 107 +++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h       |  10 +-
 drivers/net/mlx5/mlx5_flow_dv.c    | 234 +++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_flow_verbs.c |  14 +--
 drivers/net/mlx5/mlx5_glue.c       |  98 ++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h       |  19 +++
 drivers/net/mlx5/mlx5_prm.h        |  71 +++++++++++
 11 files changed, 578 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 1/3] net/mlx5: fix shared counter allocation logic
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
                         ` (2 preceding siblings ...)
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
@ 2019-01-03 15:06       ` Mordechay Haimovsky
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  4 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-03 15:06 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky, stable

This commit fixes the logic for searching and allocating a shared
counter in mlx5_flow_verbs.
Now only the shared counters in the counters list are checked for
a match and not all the counters as before.

Fixes: 84c406e74524 ("net/mlx5: add flow translate function")
Cc: stable@dpdk.org

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modified commit header
---
 drivers/net/mlx5/mlx5_flow_verbs.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c
index 81ec59d..409e1cd 100644
--- a/drivers/net/mlx5/mlx5_flow_verbs.c
+++ b/drivers/net/mlx5/mlx5_flow_verbs.c
@@ -121,13 +121,13 @@
 	struct mlx5_flow_counter *cnt;
 	int ret;
 
-	LIST_FOREACH(cnt, &priv->flow_counters, next) {
-		if (!cnt->shared || cnt->shared != shared)
-			continue;
-		if (cnt->id != id)
-			continue;
-		cnt->ref_cnt++;
-		return cnt;
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
 	}
 	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
 	if (!cnt) {
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 2/3] net/mlx5: add devx functions to glue
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  2019-01-03  8:29       ` Shahaf Shuler
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 0/3] " Mordechay Haimovsky
@ 2019-01-03 15:06       ` Mordechay Haimovsky
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
  4 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-03 15:06 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This patch adds glue functions for operations:
  - dv_open_device.
  - devx object create, destroy, query and modify.
  - devx general command
The new operations depend on HAVE_IBV_DEVX_OBJ.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
v2:
* Modifications according to review inputs.
  see message Id: 1545748697-3385-3-git-send-email-motih@mellanox.com
---
 drivers/net/mlx5/Makefile    |  5 +++
 drivers/net/mlx5/meson.build |  2 +
 drivers/net/mlx5/mlx5_glue.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/mlx5/mlx5_glue.h | 19 +++++++++
 4 files changed, 124 insertions(+)

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 1353c18..8ddad1a 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -148,6 +148,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_create_flow_action_packet_reformat \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_DEVX_OBJ \
+		infiniband/mlx5dv.h \
+		func mlx5dv_devx_obj_create \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index 8ba19e8..e2fc4ea 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -104,6 +104,8 @@ if build
 		'IBV_FLOW_SPEC_MPLS' ],
 		[ 'HAVE_IBV_WQ_FLAG_RX_END_PADDING', 'infiniband/verbs.h',
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
+		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
+		'mlx5dv_devx_obj_create' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index a806d92..c817d86 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -498,6 +498,98 @@
 #endif
 }
 
+static struct ibv_context *
+mlx5_glue_dv_open_device(struct ibv_device *device)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_open_device(device,
+				  &(struct mlx5dv_context_attr){
+					.flags = MLX5DV_CONTEXT_FLAGS_DEVX,
+				  });
+#else
+	(void)device;
+	return NULL;
+#endif
+}
+
+static struct mlx5dv_devx_obj *
+mlx5_glue_devx_obj_create(struct ibv_context *ctx,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_create(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return NULL;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_destroy(struct mlx5dv_devx_obj *obj)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_destroy(obj);
+#else
+	(void)obj;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_query(struct mlx5dv_devx_obj *obj,
+			 const void *in, size_t inlen,
+			 void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_query(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_obj_modify(struct mlx5dv_devx_obj *obj,
+			  const void *in, size_t inlen,
+			  void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_obj_modify(obj, in, inlen, out, outlen);
+#else
+	(void)obj;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
+
+static int
+mlx5_glue_devx_general_cmd(struct ibv_context *ctx,
+			   const void *in, size_t inlen,
+			   void *out, size_t outlen)
+{
+#ifdef HAVE_IBV_DEVX_OBJ
+	return mlx5dv_devx_general_cmd(ctx, in, inlen, out, outlen);
+#else
+	(void)ctx;
+	(void)in;
+	(void)inlen;
+	(void)out;
+	(void)outlen;
+	return -ENOTSUP;
+#endif
+}
 
 alignas(RTE_CACHE_LINE_SIZE)
 const struct mlx5_glue *mlx5_glue = &(const struct mlx5_glue){
@@ -557,4 +649,10 @@
 			mlx5_glue_dv_create_flow_action_packet_reformat,
 	.dv_create_flow_action_modify_header =
 			mlx5_glue_dv_create_flow_action_modify_header,
+	.dv_open_device = mlx5_glue_dv_open_device,
+	.devx_obj_create = mlx5_glue_devx_obj_create,
+	.devx_obj_destroy = mlx5_glue_devx_obj_destroy,
+	.devx_obj_query = mlx5_glue_devx_obj_query,
+	.devx_obj_modify = mlx5_glue_devx_obj_modify,
+	.devx_general_cmd = mlx5_glue_devx_general_cmd,
 };
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index 9cfe836..b118960 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -55,6 +55,10 @@
 enum mlx5dv_flow_table_type { flow_table_type = 0, };
 #endif
 
+#ifndef HAVE_IBV_DEVX_OBJ
+struct mlx5dv_devx_obj;
+#endif
+
 /* LIB_GLUE_VERSION must be updated every time this structure is modified. */
 struct mlx5_glue {
 	const char *version;
@@ -169,6 +173,21 @@ struct mlx5_glue {
 					 size_t actions_sz,
 					 uint64_t actions[],
 					 enum mlx5dv_flow_table_type ft_type);
+	struct ibv_context *(*dv_open_device)(struct ibv_device *device);
+	struct mlx5dv_devx_obj *(*devx_obj_create)
+					(struct ibv_context *ctx,
+					 const void *in, size_t inlen,
+					 void *out, size_t outlen);
+	int (*devx_obj_destroy)(struct mlx5dv_devx_obj *obj);
+	int (*devx_obj_query)(struct mlx5dv_devx_obj *obj,
+			      const void *in, size_t inlen,
+			      void *out, size_t outlen);
+	int (*devx_obj_modify)(struct mlx5dv_devx_obj *obj,
+			       const void *in, size_t inlen,
+			       void *out, size_t outlen);
+	int (*devx_general_cmd)(struct ibv_context *context,
+				const void *in, size_t inlen,
+				void *out, size_t outlen);
 };
 
 const struct mlx5_glue *mlx5_glue;
-- 
1.8.3.1

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

* [dpdk-dev] [PATCH v4 3/3] net/mlx5: support flow counters using devx
  2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
                         ` (3 preceding siblings ...)
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
@ 2019-01-03 15:06       ` Mordechay Haimovsky
  4 siblings, 0 replies; 24+ messages in thread
From: Mordechay Haimovsky @ 2019-01-03 15:06 UTC (permalink / raw)
  To: dev; +Cc: Mordechay Haimovsky

This commit adds counters support when creating flows via direct
verbs. The implementation uses devx interface in order to create
query and delete the counters.
This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation.

Signed-off-by: Moti Haimovsky <motih@mellanox.com>
---
---
v2:
* Modifications according to code review,
  See message Id: 1545748697-3385-4-git-send-email-motih@mellanox.com
v3:
* Modified calls to devx routins to be done through the glue interface.
 See message Id: 1545949196-3355-4-git-send-email-motih@mellanox.com
v4:
* Fixed compilation errors with old rdma-core packages
---
 drivers/net/mlx5/Makefile         |   6 +
 drivers/net/mlx5/meson.build      |   3 +
 drivers/net/mlx5/mlx5.c           |  16 ++-
 drivers/net/mlx5/mlx5.h           |  15 +++
 drivers/net/mlx5/mlx5_devx_cmds.c | 107 +++++++++++++++++
 drivers/net/mlx5/mlx5_flow.h      |  10 +-
 drivers/net/mlx5/mlx5_flow_dv.c   | 234 ++++++++++++++++++++++++++++++++++++--
 drivers/net/mlx5/mlx5_prm.h       |  71 ++++++++++++
 8 files changed, 447 insertions(+), 15 deletions(-)
 create mode 100644 drivers/net/mlx5/mlx5_devx_cmds.c

diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 8ddad1a..a1749e4 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_tcf.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c
+SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_devx_cmds.c
 
 ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y)
 INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib += $(LIB_GLUE)
@@ -153,6 +154,11 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh
 		func mlx5dv_devx_obj_create \
 		$(AUTOCONF_OUTPUT)
 	$Q sh -- '$<' '$@' \
+		HAVE_IBV_FLOW_DEVX_COUNTERS \
+		infiniband/mlx5dv.h \
+		enum MLX5DV_FLOW_ACTION_COUNTER_DEVX \
+		$(AUTOCONF_OUTPUT)
+	$Q sh -- '$<' '$@' \
 		HAVE_ETHTOOL_LINK_MODE_25G \
 		/usr/include/linux/ethtool.h \
 		enum ETHTOOL_LINK_MODE_25000baseCR_Full_BIT \
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index e2fc4ea..e9db36c 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -46,6 +46,7 @@ if build
 		'mlx5_trigger.c',
 		'mlx5_txq.c',
 		'mlx5_vlan.c',
+		'mlx5_devx_cmds.c',
 	)
 	if dpdk_conf.has('RTE_ARCH_X86_64') or dpdk_conf.has('RTE_ARCH_ARM64')
 		sources += files('mlx5_rxtx_vec.c')
@@ -106,6 +107,8 @@ if build
 		'IBV_WQ_FLAG_RX_END_PADDING' ],
 		[ 'HAVE_IBV_DEVX_OBJ', 'infiniband/mlx5dv.h',
 		'mlx5dv_devx_obj_create' ],
+		[ 'HAVE_IBV_FLOW_DEVX_COUNTERS', 'infiniband/mlx5dv.h',
+		'MLX5DV_FLOW_ACTION_COUNTER_DEVX' ],
 		[ 'HAVE_SUPPORTED_40000baseKR4_Full', 'linux/ethtool.h',
 		'SUPPORTED_40000baseKR4_Full' ],
 		[ 'HAVE_SUPPORTED_40000baseCR4_Full', 'linux/ethtool.h',
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 4521045..c5ed402 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -727,7 +727,7 @@
 	       struct mlx5_dev_config config,
 	       const struct mlx5_switch_info *switch_info)
 {
-	struct ibv_context *ctx;
+	struct ibv_context *ctx = NULL;
 	struct ibv_device_attr_ex attr;
 	struct ibv_port_attr port_attr;
 	struct ibv_pd *pd = NULL;
@@ -786,10 +786,16 @@
 	/* Prepare shared data between primary and secondary process. */
 	mlx5_prepare_shared_data();
 	errno = 0;
-	ctx = mlx5_glue->open_device(ibv_dev);
-	if (!ctx) {
-		rte_errno = errno ? errno : ENODEV;
-		return NULL;
+	ctx = mlx5_glue->dv_open_device(ibv_dev);
+	if (ctx) {
+		config.devx = 1;
+		DRV_LOG(DEBUG, "DEVX is supported");
+	} else {
+		ctx = mlx5_glue->open_device(ibv_dev);
+		if (!ctx) {
+			rte_errno = errno ? errno : ENODEV;
+			return NULL;
+		}
 	}
 #ifdef HAVE_IBV_MLX5_MOD_SWP
 	dv_attr.comp_mask |= MLX5DV_CONTEXT_MASK_SWP;
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index b48cd94..45f0398 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -98,6 +98,12 @@ struct mlx5_stats_ctrl {
 	uint64_t imissed_base;
 };
 
+/* devx counter object */
+struct mlx5_devx_counter_set {
+	struct mlx5dv_devx_obj *obj;
+	int id; /* Flow counter ID */
+};
+
 /* Flow list . */
 TAILQ_HEAD(mlx5_flows, rte_flow);
 
@@ -131,6 +137,7 @@ struct mlx5_dev_config {
 	unsigned int vf_nl_en:1; /* Enable Netlink requests in VF mode. */
 	unsigned int dv_flow_en:1; /* Enable DV flow. */
 	unsigned int swp:1; /* Tx generic tunnel checksum and TSO offload. */
+	unsigned int devx:1; /* Whether devx interface is available or not. */
 	struct {
 		unsigned int enabled:1; /* Whether MPRQ is enabled. */
 		unsigned int stride_num_n; /* Number of strides. */
@@ -412,4 +419,12 @@ int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct ether_addr *mac,
 int mlx5_nl_switch_info(int nl, unsigned int ifindex,
 			struct mlx5_switch_info *info);
 
+/* mlx5_devx_cmds.c */
+
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcx);
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj);
+int mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcx,
+				     int clear,
+				     uint64_t *pkts, uint64_t *bytes);
 #endif /* RTE_PMD_MLX5_H_ */
diff --git a/drivers/net/mlx5/mlx5_devx_cmds.c b/drivers/net/mlx5/mlx5_devx_cmds.c
new file mode 100644
index 0000000..a9dff58
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_devx_cmds.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright 2018 Mellanox Technologies, Ltd */
+
+#include <rte_flow_driver.h>
+
+#include "mlx5.h"
+#include "mlx5_glue.h"
+#include "mlx5_prm.h"
+
+/**
+ * Allocate flow counters via devx interface.
+ *
+ * @param[in] ctx
+ *   ibv contexts returned from mlx5dv_open_device.
+ * @param dcs
+ *   Pointer to counters properties structure to be filled by the routine.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_alloc(struct ibv_context *ctx,
+				     struct mlx5_devx_counter_set *dcs)
+{
+	uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)]   = {0};
+	uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0};
+	int status, syndrome;
+
+	MLX5_SET(alloc_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_ALLOC_FLOW_COUNTER);
+	dcs->obj = mlx5_glue->devx_obj_create(ctx, in,
+					      sizeof(in), out, sizeof(out));
+	if (!dcs->obj)
+		return -errno;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to create devx counters, "
+			"status %x, syndrome %x", status, syndrome);
+		return -1;
+	}
+	dcs->id = MLX5_GET(alloc_flow_counter_out,
+			   out, flow_counter_id);
+	return 0;
+}
+
+/**
+ * Free flow counters obtained via devx interface.
+ *
+ * @param[in] obj
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int mlx5_devx_cmd_flow_counter_free(struct mlx5dv_devx_obj *obj)
+{
+	return mlx5_glue->devx_obj_destroy(obj);
+}
+
+/**
+ * Query flow counters values.
+ *
+ * @param[in] dcs
+ *   devx object that was obtained from mlx5_devx_cmd_fc_alloc.
+ * @param[in] clear
+ *   Whether hardware should clear the counters after the query or not.
+ *  @param pkts
+ *   The number of packets that matched the flow.
+ *  @param bytes
+ *    The number of bytes that matched the flow.
+ *
+ * @return
+ *   0 on success, a negative value otherwise.
+ */
+int
+mlx5_devx_cmd_flow_counter_query(struct mlx5_devx_counter_set *dcs,
+				 int clear __rte_unused,
+				 uint64_t *pkts, uint64_t *bytes)
+{
+	uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) +
+		MLX5_ST_SZ_BYTES(traffic_counter)]   = {0};
+	uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {0};
+	void *stats;
+	int status, syndrome, rc;
+
+	MLX5_SET(query_flow_counter_in, in, opcode,
+		 MLX5_CMD_OP_QUERY_FLOW_COUNTER);
+	MLX5_SET(query_flow_counter_in, in, op_mod, 0);
+	MLX5_SET(query_flow_counter_in, in, flow_counter_id, dcs->id);
+	rc = mlx5_glue->devx_obj_query(dcs->obj,
+				       in, sizeof(in), out, sizeof(out));
+	if (rc)
+		return rc;
+	status = MLX5_GET(query_flow_counter_out, out, status);
+	syndrome = MLX5_GET(query_flow_counter_out, out, syndrome);
+	if (status) {
+		DRV_LOG(DEBUG, "Failed to query devx counters, "
+			"id %d, status %x, syndrome = %x",
+			status, syndrome, dcs->id);
+		return -1;
+	}
+	stats = MLX5_ADDR_OF(query_flow_counter_out,
+			     out, flow_statistics);
+	*pkts = MLX5_GET64(traffic_counter, stats, packets);
+	*bytes = MLX5_GET64(traffic_counter, stats, octets);
+	return 0;
+}
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index cb1e6fd..ad9abb1 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -21,6 +21,9 @@
 #pragma GCC diagnostic error "-Wpedantic"
 #endif
 
+#include "mlx5.h"
+#include "mlx5_prm.h"
+
 /* Pattern outer Layer bits. */
 #define MLX5_FLOW_LAYER_OUTER_L2 (1u << 0)
 #define MLX5_FLOW_LAYER_OUTER_L3_IPV4 (1u << 1)
@@ -319,11 +322,14 @@ struct mlx5_flow_counter {
 	uint32_t shared:1; /**< Share counter ID with other flow rules. */
 	uint32_t ref_cnt:31; /**< Reference counter. */
 	uint32_t id; /**< Counter ID. */
+	union {  /**< Holds the counters for the rule. */
 #if defined(HAVE_IBV_DEVICE_COUNTERS_SET_V42)
-	struct ibv_counter_set *cs; /**< Holds the counters for the rule. */
+		struct ibv_counter_set *cs;
 #elif defined(HAVE_IBV_DEVICE_COUNTERS_SET_V45)
-	struct ibv_counters *cs; /**< Holds the counters for the rule. */
+		struct ibv_counters *cs;
 #endif
+		struct mlx5_devx_counter_set *dcs;
+	};
 	uint64_t hits; /**< Number of packets matched by the rule. */
 	uint64_t bytes; /**< Number of bytes matched by the rule. */
 };
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 4c0b7ed..1e9dabd 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -35,6 +35,10 @@
 
 #ifdef HAVE_IBV_FLOW_DV_SUPPORT
 
+#ifndef HAVE_IBV_FLOW_DEVX_COUNTERS
+#define MLX5DV_FLOW_ACTION_COUNTER_DEVX 0
+#endif
+
 union flow_dv_attr {
 	struct {
 		uint32_t valid:1;
@@ -569,6 +573,36 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Validate count action.
+ *
+ * @param[in] dev
+ *   device otr.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_count(struct rte_eth_dev *dev,
+			      struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+
+	if (!priv->config.devx)
+		goto notsup_err;
+#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS
+	return 0;
+#endif
+notsup_err:
+	return rte_flow_error_set
+		      (error, ENOTSUP,
+		       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+		       NULL,
+		       "count action not supported");
+}
+
+/**
  * Validate the L2 encap action.
  *
  * @param[in] action_flags
@@ -1456,6 +1490,87 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Get or create a flow counter.
+ *
+ * @param[in] dev
+ *   Pointer to the Ethernet device structure.
+ * @param[in] shared
+ *   Indicate if this counter is shared with other flows.
+ * @param[in] id
+ *   Counter identifier.
+ *
+ * @return
+ *   pointer to flow counter on success, NULL otherwise and rte_errno is set.
+ */
+static struct mlx5_flow_counter *
+flow_dv_counter_new(struct rte_eth_dev *dev, uint32_t shared, uint32_t id)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct mlx5_flow_counter *cnt = NULL;
+	struct mlx5_devx_counter_set *dcs = NULL;
+	int ret;
+
+	if (!priv->config.devx) {
+		ret = -ENOTSUP;
+		goto error_exit;
+	}
+	if (shared) {
+		LIST_FOREACH(cnt, &priv->flow_counters, next) {
+			if (cnt->shared && cnt->id == id) {
+				cnt->ref_cnt++;
+				return cnt;
+			}
+		}
+	}
+	cnt = rte_calloc(__func__, 1, sizeof(*cnt), 0);
+	dcs = rte_calloc(__func__, 1, sizeof(*dcs), 0);
+	if (!dcs || !cnt) {
+		ret = -ENOMEM;
+		goto error_exit;
+	}
+	ret = mlx5_devx_cmd_flow_counter_alloc(priv->ctx, dcs);
+	if (ret)
+		goto error_exit;
+	struct mlx5_flow_counter tmpl = {
+		.shared = shared,
+		.ref_cnt = 1,
+		.id = id,
+		.dcs = dcs,
+	};
+	*cnt = tmpl;
+	LIST_INSERT_HEAD(&priv->flow_counters, cnt, next);
+	return cnt;
+error_exit:
+	rte_free(cnt);
+	rte_free(dcs);
+	rte_errno = -ret;
+	return NULL;
+}
+
+/**
+ * Release a flow counter.
+ *
+ * @param[in] counter
+ *   Pointer to the counter handler.
+ */
+static void
+flow_dv_counter_release(struct mlx5_flow_counter *counter)
+{
+	int ret;
+
+	if (!counter)
+		return;
+	if (--counter->ref_cnt == 0) {
+		ret = mlx5_devx_cmd_flow_counter_free(counter->dcs->obj);
+		if (ret)
+			DRV_LOG(ERR, "Failed to free devx counters, %d", ret);
+		LIST_REMOVE(counter, next);
+		rte_free(counter->dcs);
+		rte_free(counter);
+	}
+}
+
+/**
  * Verify the @p attributes will be correctly understood by the NIC and store
  * them in the @p flow if everything is correct.
  *
@@ -1717,7 +1832,7 @@ struct field_modify_info modify_tcp[] = {
 			++actions_n;
 			break;
 		case RTE_FLOW_ACTION_TYPE_COUNT:
-			ret = mlx5_flow_validate_action_count(dev, attr, error);
+			ret = flow_dv_validate_action_count(dev, error);
 			if (ret < 0)
 				return ret;
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
@@ -2741,6 +2856,7 @@ struct field_modify_info modify_tcp[] = {
 		const struct rte_flow_action_queue *queue;
 		const struct rte_flow_action_rss *rss;
 		const struct rte_flow_action *action = actions;
+		const struct rte_flow_action_count *count = action->conf;
 		const uint8_t *rss_key;
 
 		switch (actions->type) {
@@ -2789,6 +2905,37 @@ struct field_modify_info modify_tcp[] = {
 			flow->rss.level = rss->level;
 			action_flags |= MLX5_FLOW_ACTION_RSS;
 			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			if (!priv->config.devx) {
+				rte_errno = ENOTSUP;
+				goto cnt_err;
+			}
+			flow->counter =
+				flow_dv_counter_new(dev,
+						    count->shared, count->id);
+			if (flow->counter == NULL)
+				goto cnt_err;
+			dev_flow->dv.actions[actions_n].type =
+					MLX5DV_FLOW_ACTION_COUNTER_DEVX;
+			dev_flow->dv.actions[actions_n].obj =
+						flow->counter->dcs->obj;
+			action_flags |= MLX5_FLOW_ACTION_COUNT;
+			++actions_n;
+			break;
+cnt_err:
+			if (rte_errno == ENOTSUP)
+				return rte_flow_error_set
+					      (error, ENOTSUP,
+					       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					       NULL,
+					       "count action not supported");
+			else
+				return rte_flow_error_set
+						(error, rte_errno,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 action,
+						 "cannot create counter"
+						  " object.");
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			if (flow_dv_create_action_l2_encap(dev, actions,
@@ -3279,8 +3426,6 @@ struct field_modify_info modify_tcp[] = {
 			dv->hrxq = NULL;
 		}
 	}
-	if (flow->counter)
-		flow->counter = NULL;
 }
 
 /**
@@ -3299,6 +3444,10 @@ struct field_modify_info modify_tcp[] = {
 	if (!flow)
 		return;
 	flow_dv_remove(dev, flow);
+	if (flow->counter) {
+		flow_dv_counter_release(flow->counter);
+		flow->counter = NULL;
+	}
 	while (!LIST_EMPTY(&flow->dev_flows)) {
 		dev_flow = LIST_FIRST(&flow->dev_flows);
 		LIST_REMOVE(dev_flow, next);
@@ -3313,22 +3462,91 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Query a dv flow  rule for its statistics via devx.
+ *
+ * @param[in] dev
+ *   Pointer to Ethernet device.
+ * @param[in] flow
+ *   Pointer to the sub flow.
+ * @param[out] data
+ *   data retrieved by the query.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_query_count(struct rte_eth_dev *dev, struct rte_flow *flow,
+		    void *data, struct rte_flow_error *error)
+{
+	struct priv *priv = dev->data->dev_private;
+	struct rte_flow_query_count *qc = data;
+	uint64_t pkts = 0;
+	uint64_t bytes = 0;
+	int err;
+
+	if (!priv->config.devx)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+					  NULL,
+					  "counters are not supported");
+	if (flow->counter) {
+		err = mlx5_devx_cmd_flow_counter_query
+						(flow->counter->dcs,
+						 qc->reset, &pkts, &bytes);
+		if (err)
+			return rte_flow_error_set
+				(error, err,
+				 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				 NULL,
+				 "cannot read counters");
+		qc->hits_set = 1;
+		qc->bytes_set = 1;
+		qc->hits = pkts - flow->counter->hits;
+		qc->bytes = bytes - flow->counter->bytes;
+		if (qc->reset) {
+			flow->counter->hits = pkts;
+			flow->counter->bytes = bytes;
+		}
+		return 0;
+	}
+	return rte_flow_error_set(error, EINVAL,
+				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+				  NULL,
+				  "counters are not available");
+}
+
+/**
  * Query a flow.
  *
  * @see rte_flow_query()
  * @see rte_flow_ops
  */
 static int
-flow_dv_query(struct rte_eth_dev *dev __rte_unused,
+flow_dv_query(struct rte_eth_dev *dev,
 	      struct rte_flow *flow __rte_unused,
 	      const struct rte_flow_action *actions __rte_unused,
 	      void *data __rte_unused,
 	      struct rte_flow_error *error __rte_unused)
 {
-	return rte_flow_error_set(error, ENOTSUP,
-				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				  NULL,
-				  "flow query with DV is not supported");
+	int ret = -EINVAL;
+
+	for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
+		switch (actions->type) {
+		case RTE_FLOW_ACTION_TYPE_VOID:
+			break;
+		case RTE_FLOW_ACTION_TYPE_COUNT:
+			ret = flow_dv_query_count(dev, flow, data, error);
+			break;
+		default:
+			return rte_flow_error_set(error, ENOTSUP,
+						  RTE_FLOW_ERROR_TYPE_ACTION,
+						  actions,
+						  "action not supported");
+		}
+	}
+	return ret;
 }
 
 
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 5c39036..da1219e 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -368,6 +368,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_dw_bit_off(typ, fld) (32 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0x1f))
 #define __mlx5_dw_off(typ, fld) (__mlx5_bit_off(typ, fld) / 32)
+#define __mlx5_64_off(typ, fld) (__mlx5_bit_off(typ, fld) / 64)
 #define __mlx5_dw_mask(typ, fld) (__mlx5_mask(typ, fld) << \
 				  __mlx5_dw_bit_off(typ, fld))
 #define __mlx5_mask(typ, fld) ((u32)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
@@ -375,6 +376,7 @@ struct mlx5_modification_cmd {
 #define __mlx5_16_bit_off(typ, fld) (16 - __mlx5_bit_sz(typ, fld) - \
 				    (__mlx5_bit_off(typ, fld) & 0xf))
 #define __mlx5_mask16(typ, fld) ((u16)((1ull << __mlx5_bit_sz(typ, fld)) - 1))
+#define MLX5_ST_SZ_BYTES(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_ST_SZ_DW(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 32)
 #define MLX5_ST_SZ_DB(typ) (sizeof(struct mlx5_ifc_##typ##_bits) / 8)
 #define MLX5_BYTE_OFF(typ, fld) (__mlx5_bit_off(typ, fld) / 8)
@@ -391,10 +393,16 @@ struct mlx5_modification_cmd {
 				 (((_v) & __mlx5_mask(typ, fld)) << \
 				   __mlx5_dw_bit_off(typ, fld))); \
 	} while (0)
+#define MLX5_GET(typ, p, fld) \
+	((rte_be_to_cpu_32(*((__be32 *)(p) +\
+	__mlx5_dw_off(typ, fld))) >> __mlx5_dw_bit_off(typ, fld)) & \
+	__mlx5_mask(typ, fld))
 #define MLX5_GET16(typ, p, fld) \
 	((rte_be_to_cpu_16(*((__be16 *)(p) + \
 	  __mlx5_16_off(typ, fld))) >> __mlx5_16_bit_off(typ, fld)) & \
 	 __mlx5_mask16(typ, fld))
+#define MLX5_GET64(typ, p, fld) rte_be_to_cpu_64(*((__be64 *)(p) + \
+						   __mlx5_64_off(typ, fld)))
 #define MLX5_FLD_SZ_BYTES(typ, fld) (__mlx5_bit_sz(typ, fld) / 8)
 
 struct mlx5_ifc_fte_match_set_misc_bits {
@@ -500,6 +508,69 @@ enum {
 	MLX5_MATCH_CRITERIA_ENABLE_MISC2_BIT
 };
 
+enum {
+	MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939,
+	MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b,
+};
+
+/* Flow counters. */
+struct mlx5_ifc_alloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_alloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+};
+
+struct mlx5_ifc_dealloc_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         flow_counter_id[0x20];
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_traffic_counter_bits {
+	u8         packets[0x40];
+	u8         octets[0x40];
+};
+
+struct mlx5_ifc_query_flow_counter_out_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+	u8         syndrome[0x20];
+	u8         reserved_at_40[0x40];
+	struct mlx5_ifc_traffic_counter_bits flow_statistics[];
+};
+
+struct mlx5_ifc_query_flow_counter_in_bits {
+	u8         opcode[0x10];
+	u8         reserved_at_10[0x10];
+	u8         reserved_at_20[0x10];
+	u8         op_mod[0x10];
+	u8         reserved_at_40[0x80];
+	u8         clear[0x1];
+	u8         reserved_at_c1[0xf];
+	u8         num_of_counters[0x10];
+	u8         flow_counter_id[0x20];
+};
+
 /* CQE format mask. */
 #define MLX5E_CQE_FORMAT_MASK 0xc
 
-- 
1.8.3.1

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

* Re: [dpdk-dev] [PATCH v4 0/3] support flow counters using devx
  2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 0/3] " Mordechay Haimovsky
@ 2019-01-06  7:43         ` Shahaf Shuler
  0 siblings, 0 replies; 24+ messages in thread
From: Shahaf Shuler @ 2019-01-06  7:43 UTC (permalink / raw)
  To: Mordechay Haimovsky, dev; +Cc: Mordechay Haimovsky

Thursday, January 3, 2019 5:07 PM, Mordechay Haimovsky:
> Subject: [dpdk-dev] [PATCH v4 0/3] support flow counters using devx
> 
> This series of commits add support for creating, allocating, querying and
> destroying flow counters in mlx5 PMD using the devx interface.
> 
> Moti Haimovsky (3):
>   net/mlx5: fix shared counter allocation logic
>   net/mlx5: add devx functions to glue
>   net/mlx5: support flow counters using devx
> 
>  drivers/net/mlx5/Makefile          |  11 ++
>  drivers/net/mlx5/meson.build       |   5 +
>  drivers/net/mlx5/mlx5.c            |  16 ++-
>  drivers/net/mlx5/mlx5.h            |  15 +++
>  drivers/net/mlx5/mlx5_devx_cmds.c  | 107 +++++++++++++++++
>  drivers/net/mlx5/mlx5_flow.h       |  10 +-
>  drivers/net/mlx5/mlx5_flow_dv.c    | 234
> +++++++++++++++++++++++++++++++++++--
>  drivers/net/mlx5/mlx5_flow_verbs.c |  14 +--
>  drivers/net/mlx5/mlx5_glue.c       |  98 ++++++++++++++++
>  drivers/net/mlx5/mlx5_glue.h       |  19 +++
>  drivers/net/mlx5/mlx5_prm.h        |  71 +++++++++++
>  11 files changed, 578 insertions(+), 22 deletions(-)  create mode 100644
> drivers/net/mlx5/mlx5_devx_cmds.c

Series applied to next-net-mlx, thanks.

Moti - please notice your author name and singed-of name are not aligned. 
I fixed it for this series, please update your gitconfig for them to match on the next patches. 

> 
> --
> 1.8.3.1

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

end of thread, other threads:[~2019-01-06  7:43 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-25 14:38 [dpdk-dev] [PATCH v1 0/3] support flow counters using devx Mordechay Haimovsky
2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 1/3] net/mlx5: modify shared counter allocation logic Mordechay Haimovsky
2018-12-27  8:12   ` Shahaf Shuler
2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
2018-12-27  8:12   ` Shahaf Shuler
2018-12-25 14:38 ` [dpdk-dev] [PATCH v1 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
2018-12-27  8:15   ` Shahaf Shuler
2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 0/3] " Mordechay Haimovsky
2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
2018-12-29 20:12     ` Slava Ovsiienko
2018-12-31  7:23       ` Shahaf Shuler
2019-01-02  6:58       ` Mordechay Haimovsky
2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
2018-12-27 22:20   ` [dpdk-dev] [PATCH v2 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 0/3] " Mordechay Haimovsky
2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
2019-01-02  9:43     ` [dpdk-dev] [PATCH v3 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky
2019-01-03  8:29       ` Shahaf Shuler
2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 0/3] " Mordechay Haimovsky
2019-01-06  7:43         ` Shahaf Shuler
2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 2/3] net/mlx5: add devx functions to glue Mordechay Haimovsky
2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 1/3] net/mlx5: fix shared counter allocation logic Mordechay Haimovsky
2019-01-03 15:06       ` [dpdk-dev] [PATCH v4 3/3] net/mlx5: support flow counters using devx Mordechay Haimovsky

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