From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30040.outbound.protection.outlook.com [40.107.3.40]) by dpdk.org (Postfix) with ESMTP id C0AEB5F13 for ; Thu, 6 Dec 2018 14:40:03 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=oWniFDNn7LuEFq1IHzPdKpLflJ6L8UNrJAExTKuDJSQ=; b=IbeAuhFjoVGoMZwoemLkRzs6+VLuKIGPeZh+HVoEQ1tlaWmzw4xxHh6eRnZ92O0K4JhY0TFjuMu7df7ll1GHIEUiCuHjVFqKxncNct9gIo/KaVIbkal6GE/ksuP8ESxpQxNpTblmchkvEYa/njGvW7DZlwIR8jVlmdV3D695i3g= Received: from DB7PR05MB4426.eurprd05.prod.outlook.com (52.134.109.15) by DB7PR05MB5033.eurprd05.prod.outlook.com (20.176.236.205) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1404.17; Thu, 6 Dec 2018 13:40:01 +0000 Received: from DB7PR05MB4426.eurprd05.prod.outlook.com ([fe80::f59c:f6f0:665b:8b16]) by DB7PR05MB4426.eurprd05.prod.outlook.com ([fe80::f59c:f6f0:665b:8b16%4]) with mapi id 15.20.1361.019; Thu, 6 Dec 2018 13:40:01 +0000 From: Shahaf Shuler To: Mordechay Haimovsky , "dev@dpdk.org" CC: Mordechay Haimovsky Thread-Topic: [PATCH] net/mlx5: support flow counters using devx Thread-Index: AQHUdDoUtuvfJO5VhE+DRCvZog3Nt6Vx4DdA Date: Thu, 6 Dec 2018 13:40:01 +0000 Message-ID: References: <1541334577-3808-1-git-send-email-motih@mellanox.com> In-Reply-To: <1541334577-3808-1-git-send-email-motih@mellanox.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=shahafs@mellanox.com; x-originating-ip: [193.47.165.251] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; DB7PR05MB5033; 6:icXM+0hYp2U51GLLBZLSEIxilC+wL7DgcFOQdh5epZJ7A8asdTijmgtz7AwjnFgFByKL/czsKcMK5HexLGHT4ex6fbR7eN/95/MDosUOwPnNlTDJqnpCr4x8Oxjxxsd3YcWMNZ9EG8M3z2ZoQmSRy5AYYc1So0KCXJSohE1hiXo6E5KR1vmr/g5GWldc72IDNT32idcUbk5g97RhHNLOJoMVBYBTadsh/e/aq2XgWPwybdGwByq97lk6dG0EbuuaeBHNektnZ5RCEF1gtZg+Agxj11jjaJDbqsFg3b1kXghVB6o0Jq5fscLx8xS9HcjT+S9JnfYcIREQM/iHR/sTnTFTcZtvfkZQJzmxXVhrBxZUU3DEW8DMAf75CaMLHrat/XYvYYKNX5IzC9lhk0SlLBhPN2nSFyCg9ik4VbLJr1/rjUuPXd6UYkXk9Jf+2HGxvrSu0qYVUhozWIDYG+ZZfw==; 5:7qpz7vxZVCIMkuYd1gFEbDbHlhemPM4bNyPyWB5PtE6ibq+ivXPJAPgBnloScWfCERGunnpbgv7Z1PI9GPhFW8zs4WJ9lAKvbFZlvF/NyWXdjD+8TlAtHAAjDiNgjqh6aApAO0lJ2FHMoLzDvArYmMpVZuTO6QX34OTX9KLKFcE=; 7:WaeW8Sl8tcojmLkxIWbcWMfP8/Fh36/VtR542wCXF1PsQlsSF/IGEXHpfOKoqfd0ZgiC/JPeDPGqmToodxEeyJB1qPKgk/4QQ2P2X07G5y8kXOIWggPupqAF801lRaZNhdva7PoZGhX/J1evUcdLhg== x-ms-exchange-antispam-srfa-diagnostics: SOS; x-ms-office365-filtering-correlation-id: aa1fe5b7-b927-49a9-6a0c-08d65b80525a x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390098)(7020095)(4652040)(8989299)(5600074)(711020)(4618075)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060)(7193020); SRVR:DB7PR05MB5033; x-ms-traffictypediagnostic: DB7PR05MB5033: x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(3231455)(999002)(944501520)(52105112)(3002001)(93006095)(93001095)(10201501046)(6055026)(148016)(149066)(150057)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123560045)(20161123564045)(20161123558120)(20161123562045)(201708071742011)(7699051)(76991095); SRVR:DB7PR05MB5033; BCL:0; PCL:0; RULEID:; SRVR:DB7PR05MB5033; x-forefront-prvs: 087894CD3C x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(979002)(376002)(136003)(396003)(39850400004)(346002)(366004)(199004)(189003)(6246003)(107886003)(476003)(55016002)(9686003)(4326008)(446003)(11346002)(486006)(74316002)(7736002)(305945005)(53946003)(14454004)(53936002)(99286004)(6506007)(76176011)(66066001)(2906002)(102836004)(26005)(3846002)(6116002)(186003)(478600001)(68736007)(25786009)(7696005)(19627235002)(256004)(14444005)(575784001)(86362001)(2501003)(71200400001)(4744004)(8936002)(71190400001)(81166006)(81156014)(316002)(105586002)(5660300001)(110136005)(6436002)(229853002)(106356001)(33656002)(97736004)(8676002)(559001)(579004)(969003)(989001)(999001)(1009001)(1019001); DIR:OUT; SFP:1101; SCL:1; SRVR:DB7PR05MB5033; H:DB7PR05MB4426.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: q1djYIBswsA0hOsNI7uVF1JhxKQqrFLHLK5Wf7JkxBFsAwavhnAFoXBvnIpho8UTdjiM5a+fifI9F7ufw88JlvfDDb8SOgWjNpyFdm+9sGSsKRoH2SmSnfrlMDTcK/sS5zxvN0Y+4+sfaLD4XTdqB1tizj1qiqBLTS+lkayhf1IqGPQZymp1mjYPMcQwaxSqNjqMjjwGX1X+R6ayFFQhDdz9bGlj08NSfGMOGn3nvqG5JeFqnasWP1co4LATzawsL0QlNkw2jR27olAu46f5DH6vDvqhX2CGial74LnPfnq2Z2ICVSio0jEXyTJbNFedX+i6f9b/bUtY8CHTy9k1QhttP38C9ue8j3EpGkIk364= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-Network-Message-Id: aa1fe5b7-b927-49a9-6a0c-08d65b80525a X-MS-Exchange-CrossTenant-originalarrivaltime: 06 Dec 2018 13:40:01.4008 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR05MB5033 Subject: Re: [dpdk-dev] [PATCH] net/mlx5: support flow counters using devx X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Dec 2018 13:40:04 -0000 Hi Moti, See some comments.=20 Sunday, November 4, 2018 2:30 PM, Mordechay Haimovsky: > Subject: [dpdk-dev] [PATCH] net/mlx5: support flow counters using devx >=20 > This commit adds counters support when creating flows via direct verbs. T= he > implementation uses devx interface in order to create query and delete th= e > counters. > This support requires MLNX_OFED_LINUX-4.5-0.1.0.1 installation. > devx support in the firmware is enabled via the "mcra /dev/mst/ > 0x3ce4.7:1 1" command. We shouldn't encourage the user to do mcra commands. The support should exi= sts on the FW w/o the need to enable it from the user.=20 I think it is already in FW.=20 >=20 > Signed-off-by: Moti Haimovsky > --- > drivers/net/mlx5/Makefile | 16 ++++ > drivers/net/mlx5/meson.build | 7 ++ > drivers/net/mlx5/mlx5.c | 22 ++++- > drivers/net/mlx5/mlx5.h | 1 + > drivers/net/mlx5/mlx5_devx_cmds.c | 134 > ++++++++++++++++++++++++++ drivers/net/mlx5/mlx5_devx_cmds.h | > 103 ++++++++++++++++++++ > drivers/net/mlx5/mlx5_flow.h | 14 ++- > drivers/net/mlx5/mlx5_flow_dv.c | 189 > +++++++++++++++++++++++++++++++++++-- > drivers/net/mlx5/mlx5_flow_verbs.c | 14 +-- > drivers/net/mlx5/mlx5_prm.h | 8 ++ > 10 files changed, 486 insertions(+), 22 deletions(-) create mode 100644 > drivers/net/mlx5/mlx5_devx_cmds.c create mode 100644 > drivers/net/mlx5/mlx5_devx_cmds.h >=20 > diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index > 7a50bcc..f8cef0a 100644 > --- a/drivers/net/mlx5/Makefile > +++ b/drivers/net/mlx5/Makefile > @@ -36,6 +36,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D > mlx5_flow_tcf.c > SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_flow_verbs.c > SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_socket.c > SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_nl.c > +SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_devx_cmds.c >=20 > ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y) > INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib +=3D $(LIB_GLUE) @@ -148,6 > +149,21 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh > func mlx5dv_create_flow_action_packet_reformat \ > $(AUTOCONF_OUTPUT) > $Q sh -- '$<' '$@' \ > + HAVE_IBV_FLOW_DEVX_COUNTERS \ > + infiniband/mlx5dv.h \ > + enum MLX5DV_FLOW_ACTION_COUNTER_DEVX \ > + $(AUTOCONF_OUTPUT) This is a validator for a new action for dv, ok > + $Q sh -- '$<' '$@' \ > + HAVE_IBV_DEVX_CONTEXT \ > + infiniband/mlx5dv.h \ > + enum MLX5DV_CONTEXT_FLAGS_DEVX \ > + $(AUTOCONF_OUTPUT) > + $Q sh -- '$<' '$@' \ > + HAVE_IBV_DEVX_OBJ \ > + infiniband/mlx5dv.h \ > + func mlx5dv_devx_obj_create \ > + $(AUTOCONF_OUTPUT) > + $Q sh -- '$<' '$@' \ Those two looks the same, and should be merge into a single case called DEV= X_SUPPORT or similar.=20 > 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..2bc2acb 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 +=3D files('mlx5_rxtx_vec.c') > @@ -100,6 +101,12 @@ 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_FLOW_DEVX_CONTEXT', 'infiniband/mlx5dv.h', > + 'MLX5DV_CONTEXT_FLAGS_DEVX' ], > + [ 'HAVE_IBV_FLOW_DEVX_OBJ', 'infiniband/mlx5dv.h', > + 'mlx5dv_devx_obj_create' ], > [ '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 62ac54f..50e46bc 100644 > --- a/drivers/net/mlx5/mlx5.c > +++ b/drivers/net/mlx5/mlx5.c > @@ -731,7 +731,7 @@ > struct mlx5_dev_config config, > const struct mlx5_switch_info *switch_info) { > - struct ibv_context *ctx; > + struct ibv_context *ctx =3D NULL; > struct ibv_device_attr_ex attr; > struct ibv_port_attr port_attr; > struct ibv_pd *pd =3D NULL; > @@ -790,10 +790,22 @@ > /* Prepare shared data between primary and secondary process. */ > mlx5_prepare_shared_data(); > errno =3D 0; > - ctx =3D mlx5_glue->open_device(ibv_dev); > - if (!ctx) { > - rte_errno =3D errno ? errno : ENODEV; > - return NULL; > +#ifdef HAVE_IBV_DEVX_CONTEXT > + ctx =3D mlx5dv_open_device(ibv_dev, > + &(struct mlx5dv_context_attr){ > + .flags =3D > MLX5DV_CONTEXT_FLAGS_DEVX, > + }); > +#endif > + if (ctx) { > + config.devx =3D 1; > + DRV_LOG(DEBUG, "DEVX is %ssupported", > + config.devx ? "" : "not "); > + } else { > + ctx =3D mlx5_glue->open_device(ibv_dev); > + if (!ctx) { > + rte_errno =3D errno ? errno : ENODEV; > + return NULL; > + } > } > #ifdef HAVE_IBV_MLX5_MOD_SWP > dv_attr.comp_mask |=3D MLX5DV_CONTEXT_MASK_SWP; diff --git > a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index > bc500b2..39dc421 100644 > --- a/drivers/net/mlx5/mlx5.h > +++ b/drivers/net/mlx5/mlx5.h > @@ -124,6 +124,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..94255e8 > --- /dev/null > +++ b/drivers/net/mlx5/mlx5_devx_cmds.c > @@ -0,0 +1,134 @@ > +// SPDX-License-Identifier: BSD-3-Clause > +/* Copyright 2018 Mellanox Technologies, Ltd */ > + > +#include > + > +#include "mlx5.h" > +#include "mlx5_devx_cmds.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 routin= e. > + * > + * @return > + * 0 on success, a negative value otherwise. > + */ > +int mlx5_devx_cmd_fc_alloc(struct ibv_context *ctx, > + struct mlx5_devx_counter_set *dcs) { #if > +defined(HAVE_IBV_FLOW_DEVX_COUNTERS) && > defined(HAVE_IBV_DEVX_OBJ) > + uint32_t in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] =3D {0}; > + uint32_t out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] =3D {0}; > + int status, syndrome; > + > + MLX5_SET(alloc_flow_counter_in, in, opcode, > + MLX5_CMD_OP_ALLOC_FLOW_COUNTER); > + dcs->obj =3D mlx5dv_devx_obj_create(ctx, > + in, sizeof(in), out, sizeof(out)); The mlx5dv_devx_obj_create should be part of mlx5_glue. You can handle the = ifdef inside the function.=20 Same for other mlx5dv_devx_* functions.=20 > + if (!dcs->obj) > + return -errno; > + status =3D MLX5_GET(query_flow_counter_out, out, status); > + syndrome =3D 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 =3D MLX5_GET(alloc_flow_counter_out, > + out, flow_counter_id); > + return 0; > +#else > + (void)ctx; > + (void)dcs; > + return -ENOTSUP; > +#endif /* HAVE_IBV_FLOW_DEVX_COUNTERS && HAVE_IBV_DEVX_OBJ */ > } > + > +/** > + * 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_fc_free(struct mlx5dv_devx_obj *obj) { #if > +defined(HAVE_IBV_FLOW_DEVX_COUNTERS) && > defined(HAVE_IBV_DEVX_OBJ) > + return mlx5dv_devx_obj_destroy(obj); > +#else > + (void)obj; > + return -ENOTSUP; > +#endif /* HAVE_IBV_FLOW_DEVX_COUNTERS && HAVE_IBV_DEVX_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_fc_query(struct mlx5_devx_counter_set *dcs, > + int clear __rte_unused, > + uint64_t *pkts, uint64_t *bytes) { #if > +defined(HAVE_IBV_FLOW_DEVX_COUNTERS) && > defined(HAVE_IBV_DEVX_OBJ) > + uint32_t out[MLX5_ST_SZ_BYTES(query_flow_counter_out) + > + MLX5_ST_SZ_BYTES(traffic_counter)] =3D {0}; > + uint32_t in[MLX5_ST_SZ_DW(query_flow_counter_in)] =3D {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 =3D mlx5dv_devx_obj_query(dcs->obj, in, sizeof(in), out, > sizeof(out)); > + if (rc) > + return rc; > + status =3D MLX5_GET(query_flow_counter_out, out, status); > + syndrome =3D MLX5_GET(query_flow_counter_out, out, syndrome); > + if (status) { > + DRV_LOG(DEBUG, "Failed to query devx counters, " > + "id %d, status %x, syndrome =3D %x", > + status, syndrome, dcs->id); > + return -1; > + } > + stats =3D MLX5_ADDR_OF(query_flow_counter_out, > + out, flow_statistics); > + *pkts =3D MLX5_GET64(traffic_counter, stats, packets); > + *bytes =3D MLX5_GET64(traffic_counter, stats, octets); > + return 0; > +#else > + (void)dcs; > + (void)pkts; > + (void)bytes; > + return -ENOTSUP; > +#endif /* HAVE_IBV_FLOW_DEVX_COUNTERS && HAVE_IBV_DEVX_OBJ */ > } > diff --git a/drivers/net/mlx5/mlx5_devx_cmds.h > b/drivers/net/mlx5/mlx5_devx_cmds.h > new file mode 100644 > index 0000000..2f42e9d > --- /dev/null > +++ b/drivers/net/mlx5/mlx5_devx_cmds.h Why the input/output parameters are not part of mlx5_prm.h?=20 > @@ -0,0 +1,103 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2018 Mellanox Technologies, Ltd */ > + > +#ifndef RTE_PMD_MLX5_DEVX_CMDS_H_ > +#define RTE_PMD_MLX5_DEVX_CMDS_H_ > + > +#include > + > +/* Verbs header. */ > +/* ISO C doesn't support unnamed structs/unions, disabling -pedantic. > +*/ #ifdef PEDANTIC #pragma GCC diagnostic ignored "-Wpedantic" > +#endif > +#include > +#ifdef PEDANTIC > +#pragma GCC diagnostic error "-Wpedantic" > +#endif > + > +#include "mlx5_autoconf.h" > + > +#ifndef HAVE_IBV_DEVX_OBJ > +struct mlx5dv_devx_obj; > +#endif > + > +struct mlx5_devx_counter_set { > + struct mlx5dv_devx_obj *obj; > + int id; /* Flow counter ID */ > +}; > + > +enum { > + MLX5_CMD_OP_ALLOC_FLOW_COUNTER =3D 0x939, > + MLX5_CMD_OP_QUERY_FLOW_COUNTER =3D 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]; > +}; > + > +/* mlx5_devx_cmds.c */ > + > +int mlx5_devx_cmd_fc_alloc(struct ibv_context *ctx, > + struct mlx5_devx_counter_set *dcx); int > +mlx5_devx_cmd_fc_free(struct mlx5dv_devx_obj *obj); int > +mlx5_devx_cmd_fc_query(struct mlx5_devx_counter_set *dcx, > + int clear, > + uint64_t *pkts, uint64_t *bytes); > + > +#endif /* RTE_PMD_MLX5_DEVX_CMDS_H_ */ > diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h > index 2a3ce44..c083e80 100644 > --- a/drivers/net/mlx5/mlx5_flow.h > +++ b/drivers/net/mlx5/mlx5_flow.h > @@ -21,6 +21,10 @@ > #pragma GCC diagnostic error "-Wpedantic" > #endif >=20 > +#include "mlx5.h" > +#include "mlx5_devx_cmds.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) @@ -269,13 +273,17 @@ > 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 devx_cnt:1; /**< Devx counter */ I don't understand why this flag is needed. The flow engine is fixed on the command line paramters.=20 If dv was chosen then it will be only the dcs counter. Otherwise (verbs) it= will the relevant verbs counter according to ifdef.=20 > 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 c11ecd4..8fa5de8 100644 > --- a/drivers/net/mlx5/mlx5_flow_dv.c > +++ b/drivers/net/mlx5/mlx5_flow_dv.c > @@ -32,6 +32,7 @@ > #include "mlx5_prm.h" > #include "mlx5_glue.h" > #include "mlx5_flow.h" > +#include "mlx5_devx_cmds.h" >=20 > #ifdef HAVE_IBV_FLOW_DV_SUPPORT >=20 > @@ -704,6 +705,88 @@ > } >=20 > /** > + * 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 > + * A pointer to the counter, 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 =3D dev->data->dev_private; > + struct mlx5_flow_counter *cnt =3D NULL; > + struct mlx5_devx_counter_set *dcs =3D NULL; > + int ret; > + > + if (!priv->config.devx) { > + ret =3D -EINVAL; > + goto error_exit; > + } > + if (shared) { > + LIST_FOREACH(cnt, &priv->flow_counters, next) { > + if (cnt->shared && cnt->id =3D=3D id) { > + cnt->ref_cnt++; > + return cnt; > + } > + } > + } > + cnt =3D rte_calloc(__func__, 1, sizeof(*cnt), 0); > + dcs =3D rte_calloc(__func__, 1, sizeof(*dcs), 0); > + if (!dcs || !cnt) { > + ret =3D -ENOMEM; > + goto error_exit; > + } > + ret =3D mlx5_devx_cmd_fc_alloc(priv->ctx, dcs); > + if (ret) > + goto error_exit; > + struct mlx5_flow_counter tmpl =3D { > + .shared =3D shared, > + .ref_cnt =3D 1, > + .devx_cnt =3D 1, > + .id =3D id, > + .dcs =3D dcs, > + }; > + *cnt =3D tmpl; > + LIST_INSERT_HEAD(&priv->flow_counters, cnt, next); > + return cnt; > +error_exit: > + rte_free(cnt); > + rte_free(dcs); > + rte_errno =3D -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 =3D=3D 0) { > + ret =3D mlx5_devx_cmd_fc_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. > * > @@ -778,6 +861,9 @@ > int tunnel =3D 0; > uint8_t next_protocol =3D 0xff; > int actions_n =3D 0; > +#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS Why this ifdef is needed ? > + struct priv *priv =3D dev->data->dev_private; #endif >=20 > if (items =3D=3D NULL) > return -1; > @@ -941,9 +1027,14 @@ > ++actions_n; > break; > case RTE_FLOW_ACTION_TYPE_COUNT: > - ret =3D mlx5_flow_validate_action_count(dev, attr, > error); > - if (ret < 0) > - return ret; > +#ifdef HAVE_IBV_FLOW_DEVX_COUNTERS Same question. > + if (!priv->config.devx) > +#endif > + return rte_flow_error_set > + (error, ENOTSUP, > + > RTE_FLOW_ERROR_TYPE_UNSPECIFIED, > + NULL, > + "count action not supported"); > action_flags |=3D MLX5_FLOW_ACTION_COUNT; > ++actions_n; > break; > @@ -1693,6 +1784,7 @@ > } > } >=20 > + Extra space.=20 > /** > * Store the requested actions in an array. > * > @@ -1719,6 +1811,7 @@ > { > const struct rte_flow_action_queue *queue; > const struct rte_flow_action_rss *rss; > + const struct rte_flow_action_count *count; > int actions_n =3D dev_flow->dv.actions_n; > struct rte_flow *flow =3D dev_flow->flow; > const struct rte_flow_action *action_ptr =3D action; @@ -1837,6 > +1930,22 @@ > /* If decap is followed by encap, handle it at encap case. */ > flow->actions |=3D MLX5_FLOW_ACTION_RAW_DECAP; > break; > + case RTE_FLOW_ACTION_TYPE_COUNT: > + count =3D action->conf; > + flow->counter =3D flow_dv_counter_new(dev, > + count->shared, count->id); > + if (!flow->counter) > + return rte_flow_error_set(error, rte_errno, > + > RTE_FLOW_ERROR_TYPE_ACTION, > + action, > + "cannot create counter" > + " object."); > + dev_flow->dv.actions[actions_n].type =3D > + > MLX5DV_FLOW_ACTION_COUNTER_DEVX; > + dev_flow->dv.actions[actions_n].obj =3D flow->counter->dcs- > >obj; > + flow->actions |=3D MLX5_FLOW_ACTION_COUNT; > + actions_n++; > + break; > default: > break; > } > @@ -2203,8 +2312,6 @@ > dv->hrxq =3D NULL; > } > } > - if (flow->counter) > - flow->counter =3D NULL; This is a bug fix right? Should be on different commit.=20 > } >=20 > /** > @@ -2223,6 +2330,10 @@ > if (!flow) > return; > flow_dv_remove(dev, flow); > + if (flow->counter) { > + flow_dv_counter_release(flow->counter); > + flow->counter =3D NULL; > + } Same.=20 > while (!LIST_EMPTY(&flow->dev_flows)) { > dev_flow =3D LIST_FIRST(&flow->dev_flows); > LIST_REMOVE(dev_flow, next); > @@ -2235,6 +2346,55 @@ > } >=20 > /** > + * 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_flow *flow, void *data, > + struct rte_flow_error *error) > +{ > + struct rte_flow_query_count *qc =3D data; > + uint64_t pkts =3D 0; > + uint64_t bytes =3D 0; > + int err; > + > + if (flow->counter) { > + err =3D mlx5_devx_cmd_fc_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 counter"); > + qc->hits_set =3D 1; > + qc->bytes_set =3D 1; > + qc->hits =3D pkts - flow->counter->hits; > + qc->bytes =3D bytes - flow->counter->bytes; > + if (qc->reset) { > + flow->counter->hits =3D pkts; > + flow->counter->bytes =3D bytes; > + } > + return 0; > + } > + return rte_flow_error_set(error, ENOTSUP, > + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, > + NULL, > + "counters are not available"); > +} > + > +/** > * Query a flow. > * > * @see rte_flow_query() > @@ -2247,8 +2407,23 @@ > void *data __rte_unused, > struct rte_flow_error *error __rte_unused) { > - rte_errno =3D ENOTSUP; > - return -rte_errno; > + int ret =3D -EINVAL; > + > + for (; actions->type !=3D RTE_FLOW_ACTION_TYPE_END; actions++) { > + switch (actions->type) { > + case RTE_FLOW_ACTION_TYPE_VOID: > + break; > + case RTE_FLOW_ACTION_TYPE_COUNT: > + ret =3D flow_dv_query_count(flow, data, error); > + break; > + default: > + return rte_flow_error_set(error, ENOTSUP, > + > RTE_FLOW_ERROR_TYPE_ACTION, > + actions, > + "action not supported"); > + } > + } > + return ret; > } >=20 >=20 > diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c > b/drivers/net/mlx5/mlx5_flow_verbs.c > index 2e506b9..ba63945 100644 > --- a/drivers/net/mlx5/mlx5_flow_verbs.c > +++ b/drivers/net/mlx5/mlx5_flow_verbs.c > @@ -117,13 +117,13 @@ > struct mlx5_flow_counter *cnt; > int ret; >=20 > - LIST_FOREACH(cnt, &priv->flow_counters, next) { > - if (!cnt->shared || cnt->shared !=3D shared) > - continue; > - if (cnt->id !=3D id) > - continue; > - cnt->ref_cnt++; > - return cnt; > + if (shared) { > + LIST_FOREACH(cnt, &priv->flow_counters, next) { > + if (cnt->shared && cnt->id =3D=3D id) { > + cnt->ref_cnt++; > + return cnt; > + } > + } This logic change, while correct, needs to be performed on a different patc= h.=20 > } > cnt =3D rte_calloc(__func__, 1, sizeof(*cnt), 0); > if (!cnt) { > diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h > index 29742b1..5ff2dd0 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) >=20 > struct mlx5_ifc_fte_match_set_misc_bits { > -- > 1.8.3.1