get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/64975/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 64975,
    "url": "http://patches.dpdk.org/api/patches/64975/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1579539790-3882-37-git-send-email-matan@mellanox.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1579539790-3882-37-git-send-email-matan@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1579539790-3882-37-git-send-email-matan@mellanox.com",
    "date": "2020-01-20T17:03:08",
    "name": "[v1,36/38] mlx5: share Netlink commands",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "03ecb742279804e6d9954e40714041f49d43a26a",
    "submitter": {
        "id": 796,
        "url": "http://patches.dpdk.org/api/people/796/?format=api",
        "name": "Matan Azrad",
        "email": "matan@mellanox.com"
    },
    "delegate": {
        "id": 2642,
        "url": "http://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1579539790-3882-37-git-send-email-matan@mellanox.com/mbox/",
    "series": [
        {
            "id": 8223,
            "url": "http://patches.dpdk.org/api/series/8223/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=8223",
            "date": "2020-01-20T17:02:37",
            "name": "Introduce mlx5 vDPA driver",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/8223/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/64975/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/64975/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 2C702A0526;\n\tMon, 20 Jan 2020 18:10:35 +0100 (CET)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 3E52F1C118;\n\tMon, 20 Jan 2020 18:04:20 +0100 (CET)",
            "from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129])\n by dpdk.org (Postfix) with ESMTP id E09FD1BFB5\n for <dev@dpdk.org>; Mon, 20 Jan 2020 18:03:14 +0100 (CET)",
            "from Internal Mail-Server by MTLPINE1 (envelope-from\n asafp@mellanox.com)\n with ESMTPS (AES256-SHA encrypted); 20 Jan 2020 19:03:14 +0200",
            "from pegasus07.mtr.labs.mlnx (pegasus07.mtr.labs.mlnx\n [10.210.16.112])\n by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 00KH3BGt024424;\n Mon, 20 Jan 2020 19:03:14 +0200"
        ],
        "From": "Matan Azrad <matan@mellanox.com>",
        "To": "dev@dpdk.org",
        "Cc": "Maxime Coquelin <maxime.coquelin@redhat.com>,\n Thomas Monjalon <thomas@monjalon.net>",
        "Date": "Mon, 20 Jan 2020 17:03:08 +0000",
        "Message-Id": "<1579539790-3882-37-git-send-email-matan@mellanox.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1579539790-3882-1-git-send-email-matan@mellanox.com>",
        "References": "<1579539790-3882-1-git-send-email-matan@mellanox.com>",
        "Subject": "[dpdk-dev] [PATCH v1 36/38] mlx5: share Netlink commands",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Move Netlink mechanism and its dependecies from net/mlx5 to common/mlx5\nin order to be ready to use by other mlx5 drivers.\n\nThe dependencies are BITFIELD defines, the ppc64 compilation workaround\nfor bool type and the function mlx5_translate_port_name.\n\nUpdate build mechanism accordingly.\n\nSigned-off-by: Matan Azrad <matan@mellanox.com>\n---\n drivers/common/mlx5/Makefile                    |    3 +-\n drivers/common/mlx5/meson.build                 |    1 +\n drivers/common/mlx5/mlx5_common.c               |   55 +\n drivers/common/mlx5/mlx5_common.h               |   58 +\n drivers/common/mlx5/mlx5_nl.c                   | 1337 ++++++++++++++++++++++\n drivers/common/mlx5/mlx5_nl.h                   |   57 +\n drivers/common/mlx5/rte_common_mlx5_version.map |   18 +-\n drivers/net/mlx5/Makefile                       |    1 -\n drivers/net/mlx5/meson.build                    |    1 -\n drivers/net/mlx5/mlx5.h                         |    2 +-\n drivers/net/mlx5/mlx5_defs.h                    |    8 -\n drivers/net/mlx5/mlx5_ethdev.c                  |   55 -\n drivers/net/mlx5/mlx5_nl.c                      | 1338 -----------------------\n drivers/net/mlx5/mlx5_nl.h                      |   72 --\n drivers/net/mlx5/mlx5_vlan.c                    |    2 +-\n 15 files changed, 1529 insertions(+), 1479 deletions(-)\n create mode 100644 drivers/common/mlx5/mlx5_nl.c\n create mode 100644 drivers/common/mlx5/mlx5_nl.h\n delete mode 100644 drivers/net/mlx5/mlx5_nl.c\n delete mode 100644 drivers/net/mlx5/mlx5_nl.h",
    "diff": "diff --git a/drivers/common/mlx5/Makefile b/drivers/common/mlx5/Makefile\nindex aeacce3..60bec3f 100644\n--- a/drivers/common/mlx5/Makefile\n+++ b/drivers/common/mlx5/Makefile\n@@ -16,6 +16,7 @@ SRCS-y += mlx5_glue.c\n endif\n SRCS-y += mlx5_devx_cmds.c\n SRCS-y += mlx5_common.c\n+SRCS-y += mlx5_nl.c\n ifeq ($(CONFIG_RTE_IBVERBS_LINK_DLOPEN),y)\n INSTALL-y-lib += $(LIB_GLUE)\n endif\n@@ -42,7 +43,7 @@ else\n LDLIBS += -libverbs -lmlx5\n endif\n \n-LDLIBS += -lrte_eal -lrte_pci -lrte_kvargs\n+LDLIBS += -lrte_eal -lrte_pci -lrte_kvargs -lrte_net\n \n # A few warnings cannot be avoided in external headers.\n CFLAGS += -Wno-error=cast-qual -DNDEBUG -UPEDANTIC\ndiff --git a/drivers/common/mlx5/meson.build b/drivers/common/mlx5/meson.build\nindex 8291a92..46c7c3bb 100644\n--- a/drivers/common/mlx5/meson.build\n+++ b/drivers/common/mlx5/meson.build\n@@ -42,6 +42,7 @@ if build\n \tsources = files(\n \t\t'mlx5_devx_cmds.c',\n \t\t'mlx5_common.c',\n+\t\t'mlx5_nl.c',\n \t)\n \tif not pmd_dlopen\n \t\tsources += files('mlx5_glue.c')\ndiff --git a/drivers/common/mlx5/mlx5_common.c b/drivers/common/mlx5/mlx5_common.c\nindex f756b6b..7ca6136 100644\n--- a/drivers/common/mlx5/mlx5_common.c\n+++ b/drivers/common/mlx5/mlx5_common.c\n@@ -107,6 +107,61 @@\n \treturn ret;\n }\n \n+/**\n+ * Extract port name, as a number, from sysfs or netlink information.\n+ *\n+ * @param[in] port_name_in\n+ *   String representing the port name.\n+ * @param[out] port_info_out\n+ *   Port information, including port name as a number and port name\n+ *   type if recognized\n+ *\n+ * @return\n+ *   port_name field set according to recognized name format.\n+ */\n+void\n+mlx5_translate_port_name(const char *port_name_in,\n+\t\t\t struct mlx5_switch_info *port_info_out)\n+{\n+\tchar pf_c1, pf_c2, vf_c1, vf_c2;\n+\tchar *end;\n+\tint sc_items;\n+\n+\t/*\n+\t * Check for port-name as a string of the form pf0vf0\n+\t * (support kernel ver >= 5.0 or OFED ver >= 4.6).\n+\t */\n+\tsc_items = sscanf(port_name_in, \"%c%c%d%c%c%d\",\n+\t\t\t  &pf_c1, &pf_c2, &port_info_out->pf_num,\n+\t\t\t  &vf_c1, &vf_c2, &port_info_out->port_name);\n+\tif (sc_items == 6 &&\n+\t    pf_c1 == 'p' && pf_c2 == 'f' &&\n+\t    vf_c1 == 'v' && vf_c2 == 'f') {\n+\t\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF;\n+\t\treturn;\n+\t}\n+\t/*\n+\t * Check for port-name as a string of the form p0\n+\t * (support kernel ver >= 5.0, or OFED ver >= 4.6).\n+\t */\n+\tsc_items = sscanf(port_name_in, \"%c%d\",\n+\t\t\t  &pf_c1, &port_info_out->port_name);\n+\tif (sc_items == 2 && pf_c1 == 'p') {\n+\t\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK;\n+\t\treturn;\n+\t}\n+\t/* Check for port-name as a number (support kernel ver < 5.0 */\n+\terrno = 0;\n+\tport_info_out->port_name = strtol(port_name_in, &end, 0);\n+\tif (!errno &&\n+\t    (size_t)(end - port_name_in) == strlen(port_name_in)) {\n+\t\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY;\n+\t\treturn;\n+\t}\n+\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN;\n+\treturn;\n+}\n+\n #ifdef RTE_IBVERBS_LINK_DLOPEN\n \n /**\ndiff --git a/drivers/common/mlx5/mlx5_common.h b/drivers/common/mlx5/mlx5_common.h\nindex aeaa7b9..ac65105 100644\n--- a/drivers/common/mlx5/mlx5_common.h\n+++ b/drivers/common/mlx5/mlx5_common.h\n@@ -18,6 +18,35 @@\n \n \n /*\n+ * Compilation workaround for PPC64 when AltiVec is fully enabled, e.g. std=c11.\n+ * Otherwise there would be a type conflict between stdbool and altivec.\n+ */\n+#if defined(__PPC64__) && !defined(__APPLE_ALTIVEC__)\n+#undef bool\n+/* redefine as in stdbool.h */\n+#define bool _Bool\n+#endif\n+\n+/* Bit-field manipulation. */\n+#define BITFIELD_DECLARE(bf, type, size) \\\n+\ttype bf[(((size_t)(size) / (sizeof(type) * CHAR_BIT)) + \\\n+\t\t !!((size_t)(size) % (sizeof(type) * CHAR_BIT)))]\n+#define BITFIELD_DEFINE(bf, type, size) \\\n+\tBITFIELD_DECLARE((bf), type, (size)) = { 0 }\n+#define BITFIELD_SET(bf, b) \\\n+\t(assert((size_t)(b) < (sizeof(bf) * CHAR_BIT)), \\\n+\t (void)((bf)[((b) / (sizeof((bf)[0]) * CHAR_BIT))] |= \\\n+\t\t((size_t)1 << ((b) % (sizeof((bf)[0]) * CHAR_BIT)))))\n+#define BITFIELD_RESET(bf, b) \\\n+\t(assert((size_t)(b) < (sizeof(bf) * CHAR_BIT)), \\\n+\t (void)((bf)[((b) / (sizeof((bf)[0]) * CHAR_BIT))] &= \\\n+\t\t~((size_t)1 << ((b) % (sizeof((bf)[0]) * CHAR_BIT)))))\n+#define BITFIELD_ISSET(bf, b) \\\n+\t(assert((size_t)(b) < (sizeof(bf) * CHAR_BIT)), \\\n+\t !!(((bf)[((b) / (sizeof((bf)[0]) * CHAR_BIT))] & \\\n+\t     ((size_t)1 << ((b) % (sizeof((bf)[0]) * CHAR_BIT))))))\n+\n+/*\n  * Helper macros to work around __VA_ARGS__ limitations in a C99 compliant\n  * manner.\n  */\n@@ -112,6 +141,33 @@ enum {\n \tPCI_DEVICE_ID_MELLANOX_CONNECTX6DXVF = 0x101e,\n };\n \n+/* Maximum number of simultaneous unicast MAC addresses. */\n+#define MLX5_MAX_UC_MAC_ADDRESSES 128\n+/* Maximum number of simultaneous Multicast MAC addresses. */\n+#define MLX5_MAX_MC_MAC_ADDRESSES 128\n+/* Maximum number of simultaneous MAC addresses. */\n+#define MLX5_MAX_MAC_ADDRESSES \\\n+\t(MLX5_MAX_UC_MAC_ADDRESSES + MLX5_MAX_MC_MAC_ADDRESSES)\n+\n+/* Recognized Infiniband device physical port name types. */\n+enum mlx5_nl_phys_port_name_type {\n+\tMLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */\n+\tMLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */\n+\tMLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */\n+\tMLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */\n+\tMLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */\n+};\n+\n+/** Switch information returned by mlx5_nl_switch_info(). */\n+struct mlx5_switch_info {\n+\tuint32_t master:1; /**< Master device. */\n+\tuint32_t representor:1; /**< Representor device. */\n+\tenum mlx5_nl_phys_port_name_type name_type; /** < Port name type. */\n+\tint32_t pf_num; /**< PF number (valid for pfxvfx format only). */\n+\tint32_t port_name; /**< Representor port name. */\n+\tuint64_t switch_id; /**< Switch identifier. */\n+};\n+\n /* CQE status. */\n enum mlx5_cqe_status {\n \tMLX5_CQE_STATUS_SW_OWN = -1,\n@@ -152,5 +208,7 @@ enum mlx5_cqe_status {\n \n int mlx5_dev_to_pci_addr(const char *dev_path, struct rte_pci_addr *pci_addr);\n int mlx5_vdpa_mode_selected(struct rte_devargs *devargs);\n+void mlx5_translate_port_name(const char *port_name_in,\n+\t\t\t      struct mlx5_switch_info *port_info_out);\n \n #endif /* RTE_PMD_MLX5_COMMON_H_ */\ndiff --git a/drivers/common/mlx5/mlx5_nl.c b/drivers/common/mlx5/mlx5_nl.c\nnew file mode 100644\nindex 0000000..b4fc053\n--- /dev/null\n+++ b/drivers/common/mlx5/mlx5_nl.c\n@@ -0,0 +1,1337 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2018 6WIND S.A.\n+ * Copyright 2018 Mellanox Technologies, Ltd\n+ */\n+\n+#include <errno.h>\n+#include <linux/if_link.h>\n+#include <linux/rtnetlink.h>\n+#include <net/if.h>\n+#include <rdma/rdma_netlink.h>\n+#include <stdbool.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <stdalign.h>\n+#include <string.h>\n+#include <sys/socket.h>\n+#include <unistd.h>\n+#include <stdbool.h>\n+\n+#include <rte_errno.h>\n+#include <rte_atomic.h>\n+\n+#include \"mlx5_nl.h\"\n+#include \"mlx5_common_utils.h\"\n+\n+/* Size of the buffer to receive kernel messages */\n+#define MLX5_NL_BUF_SIZE (32 * 1024)\n+/* Send buffer size for the Netlink socket */\n+#define MLX5_SEND_BUF_SIZE 32768\n+/* Receive buffer size for the Netlink socket */\n+#define MLX5_RECV_BUF_SIZE 32768\n+\n+/** Parameters of VLAN devices created by driver. */\n+#define MLX5_VMWA_VLAN_DEVICE_PFX \"evmlx\"\n+/*\n+ * Define NDA_RTA as defined in iproute2 sources.\n+ *\n+ * see in iproute2 sources file include/libnetlink.h\n+ */\n+#ifndef MLX5_NDA_RTA\n+#define MLX5_NDA_RTA(r) \\\n+\t((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))\n+#endif\n+/*\n+ * Define NLMSG_TAIL as defined in iproute2 sources.\n+ *\n+ * see in iproute2 sources file include/libnetlink.h\n+ */\n+#ifndef NLMSG_TAIL\n+#define NLMSG_TAIL(nmsg) \\\n+\t((struct rtattr *)(((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))\n+#endif\n+/*\n+ * The following definitions are normally found in rdma/rdma_netlink.h,\n+ * however they are so recent that most systems do not expose them yet.\n+ */\n+#ifndef HAVE_RDMA_NL_NLDEV\n+#define RDMA_NL_NLDEV 5\n+#endif\n+#ifndef HAVE_RDMA_NLDEV_CMD_GET\n+#define RDMA_NLDEV_CMD_GET 1\n+#endif\n+#ifndef HAVE_RDMA_NLDEV_CMD_PORT_GET\n+#define RDMA_NLDEV_CMD_PORT_GET 5\n+#endif\n+#ifndef HAVE_RDMA_NLDEV_ATTR_DEV_INDEX\n+#define RDMA_NLDEV_ATTR_DEV_INDEX 1\n+#endif\n+#ifndef HAVE_RDMA_NLDEV_ATTR_DEV_NAME\n+#define RDMA_NLDEV_ATTR_DEV_NAME 2\n+#endif\n+#ifndef HAVE_RDMA_NLDEV_ATTR_PORT_INDEX\n+#define RDMA_NLDEV_ATTR_PORT_INDEX 3\n+#endif\n+#ifndef HAVE_RDMA_NLDEV_ATTR_NDEV_INDEX\n+#define RDMA_NLDEV_ATTR_NDEV_INDEX 50\n+#endif\n+\n+/* These are normally found in linux/if_link.h. */\n+#ifndef HAVE_IFLA_NUM_VF\n+#define IFLA_NUM_VF 21\n+#endif\n+#ifndef HAVE_IFLA_EXT_MASK\n+#define IFLA_EXT_MASK 29\n+#endif\n+#ifndef HAVE_IFLA_PHYS_SWITCH_ID\n+#define IFLA_PHYS_SWITCH_ID 36\n+#endif\n+#ifndef HAVE_IFLA_PHYS_PORT_NAME\n+#define IFLA_PHYS_PORT_NAME 38\n+#endif\n+\n+/* Add/remove MAC address through Netlink */\n+struct mlx5_nl_mac_addr {\n+\tstruct rte_ether_addr (*mac)[];\n+\t/**< MAC address handled by the device. */\n+\tint mac_n; /**< Number of addresses in the array. */\n+};\n+\n+#define MLX5_NL_CMD_GET_IB_NAME (1 << 0)\n+#define MLX5_NL_CMD_GET_IB_INDEX (1 << 1)\n+#define MLX5_NL_CMD_GET_NET_INDEX (1 << 2)\n+#define MLX5_NL_CMD_GET_PORT_INDEX (1 << 3)\n+\n+/** Data structure used by mlx5_nl_cmdget_cb(). */\n+struct mlx5_nl_ifindex_data {\n+\tconst char *name; /**< IB device name (in). */\n+\tuint32_t flags; /**< found attribute flags (out). */\n+\tuint32_t ibindex; /**< IB device index (out). */\n+\tuint32_t ifindex; /**< Network interface index (out). */\n+\tuint32_t portnum; /**< IB device max port number (out). */\n+};\n+\n+rte_atomic32_t atomic_sn = RTE_ATOMIC32_INIT(0);\n+\n+/* Generate Netlink sequence number. */\n+#define MLX5_NL_SN_GENERATE ((uint32_t)rte_atomic32_add_return(&atomic_sn, 1))\n+\n+/**\n+ * Opens a Netlink socket.\n+ *\n+ * @param protocol\n+ *   Netlink protocol (e.g. NETLINK_ROUTE, NETLINK_RDMA).\n+ *\n+ * @return\n+ *   A file descriptor on success, a negative errno value otherwise and\n+ *   rte_errno is set.\n+ */\n+int\n+mlx5_nl_init(int protocol)\n+{\n+\tint fd;\n+\tint sndbuf_size = MLX5_SEND_BUF_SIZE;\n+\tint rcvbuf_size = MLX5_RECV_BUF_SIZE;\n+\tstruct sockaddr_nl local = {\n+\t\t.nl_family = AF_NETLINK,\n+\t};\n+\tint ret;\n+\n+\tfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);\n+\tif (fd == -1) {\n+\t\trte_errno = errno;\n+\t\treturn -rte_errno;\n+\t}\n+\tret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, sizeof(int));\n+\tif (ret == -1) {\n+\t\trte_errno = errno;\n+\t\tgoto error;\n+\t}\n+\tret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(int));\n+\tif (ret == -1) {\n+\t\trte_errno = errno;\n+\t\tgoto error;\n+\t}\n+\tret = bind(fd, (struct sockaddr *)&local, sizeof(local));\n+\tif (ret == -1) {\n+\t\trte_errno = errno;\n+\t\tgoto error;\n+\t}\n+\treturn fd;\n+error:\n+\tclose(fd);\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Send a request message to the kernel on the Netlink socket.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] nh\n+ *   The Netlink message send to the kernel.\n+ * @param[in] ssn\n+ *   Sequence number.\n+ * @param[in] req\n+ *   Pointer to the request structure.\n+ * @param[in] len\n+ *   Length of the request in bytes.\n+ *\n+ * @return\n+ *   The number of sent bytes on success, a negative errno value otherwise and\n+ *   rte_errno is set.\n+ */\n+static int\n+mlx5_nl_request(int nlsk_fd, struct nlmsghdr *nh, uint32_t sn, void *req,\n+\t\tint len)\n+{\n+\tstruct sockaddr_nl sa = {\n+\t\t.nl_family = AF_NETLINK,\n+\t};\n+\tstruct iovec iov[2] = {\n+\t\t{ .iov_base = nh, .iov_len = sizeof(*nh), },\n+\t\t{ .iov_base = req, .iov_len = len, },\n+\t};\n+\tstruct msghdr msg = {\n+\t\t.msg_name = &sa,\n+\t\t.msg_namelen = sizeof(sa),\n+\t\t.msg_iov = iov,\n+\t\t.msg_iovlen = 2,\n+\t};\n+\tint send_bytes;\n+\n+\tnh->nlmsg_pid = 0; /* communication with the kernel uses pid 0 */\n+\tnh->nlmsg_seq = sn;\n+\tsend_bytes = sendmsg(nlsk_fd, &msg, 0);\n+\tif (send_bytes < 0) {\n+\t\trte_errno = errno;\n+\t\treturn -rte_errno;\n+\t}\n+\treturn send_bytes;\n+}\n+\n+/**\n+ * Send a message to the kernel on the Netlink socket.\n+ *\n+ * @param[in] nlsk_fd\n+ *   The Netlink socket file descriptor used for communication.\n+ * @param[in] nh\n+ *   The Netlink message send to the kernel.\n+ * @param[in] sn\n+ *   Sequence number.\n+ *\n+ * @return\n+ *   The number of sent bytes on success, a negative errno value otherwise and\n+ *   rte_errno is set.\n+ */\n+static int\n+mlx5_nl_send(int nlsk_fd, struct nlmsghdr *nh, uint32_t sn)\n+{\n+\tstruct sockaddr_nl sa = {\n+\t\t.nl_family = AF_NETLINK,\n+\t};\n+\tstruct iovec iov = {\n+\t\t.iov_base = nh,\n+\t\t.iov_len = nh->nlmsg_len,\n+\t};\n+\tstruct msghdr msg = {\n+\t\t.msg_name = &sa,\n+\t\t.msg_namelen = sizeof(sa),\n+\t\t.msg_iov = &iov,\n+\t\t.msg_iovlen = 1,\n+\t};\n+\tint send_bytes;\n+\n+\tnh->nlmsg_pid = 0; /* communication with the kernel uses pid 0 */\n+\tnh->nlmsg_seq = sn;\n+\tsend_bytes = sendmsg(nlsk_fd, &msg, 0);\n+\tif (send_bytes < 0) {\n+\t\trte_errno = errno;\n+\t\treturn -rte_errno;\n+\t}\n+\treturn send_bytes;\n+}\n+\n+/**\n+ * Receive a message from the kernel on the Netlink socket, following\n+ * mlx5_nl_send().\n+ *\n+ * @param[in] nlsk_fd\n+ *   The Netlink socket file descriptor used for communication.\n+ * @param[in] sn\n+ *   Sequence number.\n+ * @param[in] cb\n+ *   The callback function to call for each Netlink message received.\n+ * @param[in, out] arg\n+ *   Custom arguments for the callback.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),\n+\t     void *arg)\n+{\n+\tstruct sockaddr_nl sa;\n+\tchar buf[MLX5_RECV_BUF_SIZE];\n+\tstruct iovec iov = {\n+\t\t.iov_base = buf,\n+\t\t.iov_len = sizeof(buf),\n+\t};\n+\tstruct msghdr msg = {\n+\t\t.msg_name = &sa,\n+\t\t.msg_namelen = sizeof(sa),\n+\t\t.msg_iov = &iov,\n+\t\t/* One message at a time */\n+\t\t.msg_iovlen = 1,\n+\t};\n+\tint multipart = 0;\n+\tint ret = 0;\n+\n+\tdo {\n+\t\tstruct nlmsghdr *nh;\n+\t\tint recv_bytes = 0;\n+\n+\t\tdo {\n+\t\t\trecv_bytes = recvmsg(nlsk_fd, &msg, 0);\n+\t\t\tif (recv_bytes == -1) {\n+\t\t\t\trte_errno = errno;\n+\t\t\t\treturn -rte_errno;\n+\t\t\t}\n+\t\t\tnh = (struct nlmsghdr *)buf;\n+\t\t} while (nh->nlmsg_seq != sn);\n+\t\tfor (;\n+\t\t     NLMSG_OK(nh, (unsigned int)recv_bytes);\n+\t\t     nh = NLMSG_NEXT(nh, recv_bytes)) {\n+\t\t\tif (nh->nlmsg_type == NLMSG_ERROR) {\n+\t\t\t\tstruct nlmsgerr *err_data = NLMSG_DATA(nh);\n+\n+\t\t\t\tif (err_data->error < 0) {\n+\t\t\t\t\trte_errno = -err_data->error;\n+\t\t\t\t\treturn -rte_errno;\n+\t\t\t\t}\n+\t\t\t\t/* Ack message. */\n+\t\t\t\treturn 0;\n+\t\t\t}\n+\t\t\t/* Multi-part msgs and their trailing DONE message. */\n+\t\t\tif (nh->nlmsg_flags & NLM_F_MULTI) {\n+\t\t\t\tif (nh->nlmsg_type == NLMSG_DONE)\n+\t\t\t\t\treturn 0;\n+\t\t\t\tmultipart = 1;\n+\t\t\t}\n+\t\t\tif (cb) {\n+\t\t\t\tret = cb(nh, arg);\n+\t\t\t\tif (ret < 0)\n+\t\t\t\t\treturn ret;\n+\t\t\t}\n+\t\t}\n+\t} while (multipart);\n+\treturn ret;\n+}\n+\n+/**\n+ * Parse Netlink message to retrieve the bridge MAC address.\n+ *\n+ * @param nh\n+ *   Pointer to Netlink Message Header.\n+ * @param arg\n+ *   PMD data register with this callback.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_mac_addr_cb(struct nlmsghdr *nh, void *arg)\n+{\n+\tstruct mlx5_nl_mac_addr *data = arg;\n+\tstruct ndmsg *r = NLMSG_DATA(nh);\n+\tstruct rtattr *attribute;\n+\tint len;\n+\n+\tlen = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*r));\n+\tfor (attribute = MLX5_NDA_RTA(r);\n+\t     RTA_OK(attribute, len);\n+\t     attribute = RTA_NEXT(attribute, len)) {\n+\t\tif (attribute->rta_type == NDA_LLADDR) {\n+\t\t\tif (data->mac_n == MLX5_MAX_MAC_ADDRESSES) {\n+\t\t\t\tDRV_LOG(WARNING,\n+\t\t\t\t\t\"not enough room to finalize the\"\n+\t\t\t\t\t\" request\");\n+\t\t\t\trte_errno = ENOMEM;\n+\t\t\t\treturn -rte_errno;\n+\t\t\t}\n+#ifndef NDEBUG\n+\t\t\tchar m[18];\n+\n+\t\t\trte_ether_format_addr(m, 18, RTA_DATA(attribute));\n+\t\t\tDRV_LOG(DEBUG, \"bridge MAC address %s\", m);\n+#endif\n+\t\t\tmemcpy(&(*data->mac)[data->mac_n++],\n+\t\t\t       RTA_DATA(attribute), RTE_ETHER_ADDR_LEN);\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+/**\n+ * Get bridge MAC addresses.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param mac[out]\n+ *   Pointer to the array table of MAC addresses to fill.\n+ *   Its size should be of MLX5_MAX_MAC_ADDRESSES.\n+ * @param mac_n[out]\n+ *   Number of entries filled in MAC array.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_mac_addr_list(int nlsk_fd, unsigned int iface_idx,\n+\t\t      struct rte_ether_addr (*mac)[], int *mac_n)\n+{\n+\tstruct {\n+\t\tstruct nlmsghdr\thdr;\n+\t\tstruct ifinfomsg ifm;\n+\t} req = {\n+\t\t.hdr = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n+\t\t\t.nlmsg_type = RTM_GETNEIGH,\n+\t\t\t.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,\n+\t\t},\n+\t\t.ifm = {\n+\t\t\t.ifi_family = PF_BRIDGE,\n+\t\t\t.ifi_index = iface_idx,\n+\t\t},\n+\t};\n+\tstruct mlx5_nl_mac_addr data = {\n+\t\t.mac = mac,\n+\t\t.mac_n = 0,\n+\t};\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tif (nlsk_fd == -1)\n+\t\treturn 0;\n+\tret = mlx5_nl_request(nlsk_fd, &req.hdr, sn, &req.ifm,\n+\t\t\t      sizeof(struct ifinfomsg));\n+\tif (ret < 0)\n+\t\tgoto error;\n+\tret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_mac_addr_cb, &data);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\t*mac_n = data.mac_n;\n+\treturn 0;\n+error:\n+\tDRV_LOG(DEBUG, \"Interface %u cannot retrieve MAC address list %s\",\n+\t\tiface_idx, strerror(rte_errno));\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Modify the MAC address neighbour table with Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param mac\n+ *   MAC address to consider.\n+ * @param add\n+ *   1 to add the MAC address, 0 to remove the MAC address.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,\n+\t\t\tstruct rte_ether_addr *mac, int add)\n+{\n+\tstruct {\n+\t\tstruct nlmsghdr hdr;\n+\t\tstruct ndmsg ndm;\n+\t\tstruct rtattr rta;\n+\t\tuint8_t buffer[RTE_ETHER_ADDR_LEN];\n+\t} req = {\n+\t\t.hdr = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |\n+\t\t\t\tNLM_F_EXCL | NLM_F_ACK,\n+\t\t\t.nlmsg_type = add ? RTM_NEWNEIGH : RTM_DELNEIGH,\n+\t\t},\n+\t\t.ndm = {\n+\t\t\t.ndm_family = PF_BRIDGE,\n+\t\t\t.ndm_state = NUD_NOARP | NUD_PERMANENT,\n+\t\t\t.ndm_ifindex = iface_idx,\n+\t\t\t.ndm_flags = NTF_SELF,\n+\t\t},\n+\t\t.rta = {\n+\t\t\t.rta_type = NDA_LLADDR,\n+\t\t\t.rta_len = RTA_LENGTH(RTE_ETHER_ADDR_LEN),\n+\t\t},\n+\t};\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tif (nlsk_fd == -1)\n+\t\treturn 0;\n+\tmemcpy(RTA_DATA(&req.rta), mac, RTE_ETHER_ADDR_LEN);\n+\treq.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +\n+\t\tRTA_ALIGN(req.rta.rta_len);\n+\tret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\treturn 0;\n+error:\n+\tDRV_LOG(DEBUG,\n+\t\t\"Interface %u cannot %s MAC address\"\n+\t\t\" %02X:%02X:%02X:%02X:%02X:%02X %s\",\n+\t\tiface_idx,\n+\t\tadd ? \"add\" : \"remove\",\n+\t\tmac->addr_bytes[0], mac->addr_bytes[1],\n+\t\tmac->addr_bytes[2], mac->addr_bytes[3],\n+\t\tmac->addr_bytes[4], mac->addr_bytes[5],\n+\t\tstrerror(rte_errno));\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Modify the VF MAC address neighbour table with Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param mac\n+ *    MAC address to consider.\n+ * @param vf_index\n+ *    VF index.\n+ *\n+ * @return\n+ *    0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,\n+\t\t\t   struct rte_ether_addr *mac, int vf_index)\n+{\n+\tint ret;\n+\tstruct {\n+\t\tstruct nlmsghdr hdr;\n+\t\tstruct ifinfomsg ifm;\n+\t\tstruct rtattr vf_list_rta;\n+\t\tstruct rtattr vf_info_rta;\n+\t\tstruct rtattr vf_mac_rta;\n+\t\tstruct ifla_vf_mac ivm;\n+\t} req = {\n+\t\t.hdr = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,\n+\t\t\t.nlmsg_type = RTM_BASE,\n+\t\t},\n+\t\t.ifm = {\n+\t\t\t.ifi_index = iface_idx,\n+\t\t},\n+\t\t.vf_list_rta = {\n+\t\t\t.rta_type = IFLA_VFINFO_LIST,\n+\t\t\t.rta_len = RTA_ALIGN(RTA_LENGTH(0)),\n+\t\t},\n+\t\t.vf_info_rta = {\n+\t\t\t.rta_type = IFLA_VF_INFO,\n+\t\t\t.rta_len = RTA_ALIGN(RTA_LENGTH(0)),\n+\t\t},\n+\t\t.vf_mac_rta = {\n+\t\t\t.rta_type = IFLA_VF_MAC,\n+\t\t},\n+\t};\n+\tstruct ifla_vf_mac ivm = {\n+\t\t.vf = vf_index,\n+\t};\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\n+\tmemcpy(&ivm.mac, mac, RTE_ETHER_ADDR_LEN);\n+\tmemcpy(RTA_DATA(&req.vf_mac_rta), &ivm, sizeof(ivm));\n+\n+\treq.vf_mac_rta.rta_len = RTA_LENGTH(sizeof(ivm));\n+\treq.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +\n+\t\tRTA_ALIGN(req.vf_list_rta.rta_len) +\n+\t\tRTA_ALIGN(req.vf_info_rta.rta_len) +\n+\t\tRTA_ALIGN(req.vf_mac_rta.rta_len);\n+\treq.vf_list_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),\n+\t\t\t\t\t       &req.vf_list_rta);\n+\treq.vf_info_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),\n+\t\t\t\t\t       &req.vf_info_rta);\n+\n+\tif (nlsk_fd < 0)\n+\t\treturn -1;\n+\tret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n+\tif (ret < 0)\n+\t\tgoto error;\n+\treturn 0;\n+error:\n+\tDRV_LOG(ERR,\n+\t\t\"representor %u cannot set VF MAC address \"\n+\t\t\"%02X:%02X:%02X:%02X:%02X:%02X : %s\",\n+\t\tvf_index,\n+\t\tmac->addr_bytes[0], mac->addr_bytes[1],\n+\t\tmac->addr_bytes[2], mac->addr_bytes[3],\n+\t\tmac->addr_bytes[4], mac->addr_bytes[5],\n+\t\tstrerror(rte_errno));\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Add a MAC address.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param mac_own\n+ *   BITFIELD_DECLARE array to store the mac.\n+ * @param mac\n+ *   MAC address to register.\n+ * @param index\n+ *   MAC address index.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_mac_addr_add(int nlsk_fd, unsigned int iface_idx,\n+\t\t     uint64_t *mac_own, struct rte_ether_addr *mac,\n+\t\t     uint32_t index)\n+{\n+\tint ret;\n+\n+\tret = mlx5_nl_mac_addr_modify(nlsk_fd, iface_idx, mac, 1);\n+\tif (!ret)\n+\t\tBITFIELD_SET(mac_own, index);\n+\tif (ret == -EEXIST)\n+\t\treturn 0;\n+\treturn ret;\n+}\n+\n+/**\n+ * Remove a MAC address.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param mac_own\n+ *   BITFIELD_DECLARE array to store the mac.\n+ * @param mac\n+ *   MAC address to remove.\n+ * @param index\n+ *   MAC address index.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_mac_addr_remove(int nlsk_fd, unsigned int iface_idx, uint64_t *mac_own,\n+\t\t\tstruct rte_ether_addr *mac, uint32_t index)\n+{\n+\tBITFIELD_RESET(mac_own, index);\n+\treturn mlx5_nl_mac_addr_modify(nlsk_fd, iface_idx, mac, 0);\n+}\n+\n+/**\n+ * Synchronize Netlink bridge table to the internal table.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param mac_addrs\n+ *   Mac addresses array to sync.\n+ * @param n\n+ *   @p mac_addrs array size.\n+ */\n+void\n+mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,\n+\t\t      struct rte_ether_addr *mac_addrs, int n)\n+{\n+\tstruct rte_ether_addr macs[n];\n+\tint macs_n = 0;\n+\tint i;\n+\tint ret;\n+\n+\tret = mlx5_nl_mac_addr_list(nlsk_fd, iface_idx, &macs, &macs_n);\n+\tif (ret)\n+\t\treturn;\n+\tfor (i = 0; i != macs_n; ++i) {\n+\t\tint j;\n+\n+\t\t/* Verify the address is not in the array yet. */\n+\t\tfor (j = 0; j != n; ++j)\n+\t\t\tif (rte_is_same_ether_addr(&macs[i], &mac_addrs[j]))\n+\t\t\t\tbreak;\n+\t\tif (j != n)\n+\t\t\tcontinue;\n+\t\t/* Find the first entry available. */\n+\t\tfor (j = 0; j != n; ++j) {\n+\t\t\tif (rte_is_zero_ether_addr(&mac_addrs[j])) {\n+\t\t\t\tmac_addrs[j] = macs[i];\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n+/**\n+ * Flush all added MAC addresses.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param[in] mac_addrs\n+ *   Mac addresses array to flush.\n+ * @param n\n+ *   @p mac_addrs array size.\n+ * @param mac_own\n+ *   BITFIELD_DECLARE array to store the mac.\n+ */\n+void\n+mlx5_nl_mac_addr_flush(int nlsk_fd, unsigned int iface_idx,\n+\t\t       struct rte_ether_addr *mac_addrs, int n,\n+\t\t       uint64_t *mac_own)\n+{\n+\tint i;\n+\n+\tfor (i = n - 1; i >= 0; --i) {\n+\t\tstruct rte_ether_addr *m = &mac_addrs[i];\n+\n+\t\tif (BITFIELD_ISSET(mac_own, i))\n+\t\t\tmlx5_nl_mac_addr_remove(nlsk_fd, iface_idx, mac_own, m,\n+\t\t\t\t\t\ti);\n+\t}\n+}\n+\n+/**\n+ * Enable promiscuous / all multicast mode through Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param flags\n+ *   IFF_PROMISC for promiscuous, IFF_ALLMULTI for allmulti.\n+ * @param enable\n+ *   Nonzero to enable, disable otherwise.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_device_flags(int nlsk_fd, unsigned int iface_idx, uint32_t flags,\n+\t\t     int enable)\n+{\n+\tstruct {\n+\t\tstruct nlmsghdr hdr;\n+\t\tstruct ifinfomsg ifi;\n+\t} req = {\n+\t\t.hdr = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n+\t\t\t.nlmsg_type = RTM_NEWLINK,\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST,\n+\t\t},\n+\t\t.ifi = {\n+\t\t\t.ifi_flags = enable ? flags : 0,\n+\t\t\t.ifi_change = flags,\n+\t\t\t.ifi_index = iface_idx,\n+\t\t},\n+\t};\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tassert(!(flags & ~(IFF_PROMISC | IFF_ALLMULTI)));\n+\tif (nlsk_fd < 0)\n+\t\treturn 0;\n+\tret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);\n+\tif (ret < 0)\n+\t\treturn ret;\n+\treturn 0;\n+}\n+\n+/**\n+ * Enable promiscuous mode through Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param enable\n+ *   Nonzero to enable, disable otherwise.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable)\n+{\n+\tint ret = mlx5_nl_device_flags(nlsk_fd, iface_idx, IFF_PROMISC, enable);\n+\n+\tif (ret)\n+\t\tDRV_LOG(DEBUG,\n+\t\t\t\"Interface %u cannot %s promisc mode: Netlink error %s\",\n+\t\t\tiface_idx, enable ? \"enable\" : \"disable\",\n+\t\t\tstrerror(rte_errno));\n+\treturn ret;\n+}\n+\n+/**\n+ * Enable all multicast mode through Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] iface_idx\n+ *   Net device interface index.\n+ * @param enable\n+ *   Nonzero to enable, disable otherwise.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable)\n+{\n+\tint ret = mlx5_nl_device_flags(nlsk_fd, iface_idx, IFF_ALLMULTI,\n+\t\t\t\t       enable);\n+\n+\tif (ret)\n+\t\tDRV_LOG(DEBUG,\n+\t\t\t\"Interface %u cannot %s allmulti : Netlink error %s\",\n+\t\t\tiface_idx, enable ? \"enable\" : \"disable\",\n+\t\t\tstrerror(rte_errno));\n+\treturn ret;\n+}\n+\n+/**\n+ * Process network interface information from Netlink message.\n+ *\n+ * @param nh\n+ *   Pointer to Netlink message header.\n+ * @param arg\n+ *   Opaque data pointer for this callback.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_cmdget_cb(struct nlmsghdr *nh, void *arg)\n+{\n+\tstruct mlx5_nl_ifindex_data *data = arg;\n+\tstruct mlx5_nl_ifindex_data local = {\n+\t\t.flags = 0,\n+\t};\n+\tsize_t off = NLMSG_HDRLEN;\n+\n+\tif (nh->nlmsg_type !=\n+\t    RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET) &&\n+\t    nh->nlmsg_type !=\n+\t    RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_PORT_GET))\n+\t\tgoto error;\n+\twhile (off < nh->nlmsg_len) {\n+\t\tstruct nlattr *na = (void *)((uintptr_t)nh + off);\n+\t\tvoid *payload = (void *)((uintptr_t)na + NLA_HDRLEN);\n+\n+\t\tif (na->nla_len > nh->nlmsg_len - off)\n+\t\t\tgoto error;\n+\t\tswitch (na->nla_type) {\n+\t\tcase RDMA_NLDEV_ATTR_DEV_INDEX:\n+\t\t\tlocal.ibindex = *(uint32_t *)payload;\n+\t\t\tlocal.flags |= MLX5_NL_CMD_GET_IB_INDEX;\n+\t\t\tbreak;\n+\t\tcase RDMA_NLDEV_ATTR_DEV_NAME:\n+\t\t\tif (!strcmp(payload, data->name))\n+\t\t\t\tlocal.flags |= MLX5_NL_CMD_GET_IB_NAME;\n+\t\t\tbreak;\n+\t\tcase RDMA_NLDEV_ATTR_NDEV_INDEX:\n+\t\t\tlocal.ifindex = *(uint32_t *)payload;\n+\t\t\tlocal.flags |= MLX5_NL_CMD_GET_NET_INDEX;\n+\t\t\tbreak;\n+\t\tcase RDMA_NLDEV_ATTR_PORT_INDEX:\n+\t\t\tlocal.portnum = *(uint32_t *)payload;\n+\t\t\tlocal.flags |= MLX5_NL_CMD_GET_PORT_INDEX;\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\t\toff += NLA_ALIGN(na->nla_len);\n+\t}\n+\t/*\n+\t * It is possible to have multiple messages for all\n+\t * Infiniband devices in the system with appropriate name.\n+\t * So we should gather parameters locally and copy to\n+\t * query context only in case of coinciding device name.\n+\t */\n+\tif (local.flags & MLX5_NL_CMD_GET_IB_NAME) {\n+\t\tdata->flags = local.flags;\n+\t\tdata->ibindex = local.ibindex;\n+\t\tdata->ifindex = local.ifindex;\n+\t\tdata->portnum = local.portnum;\n+\t}\n+\treturn 0;\n+error:\n+\trte_errno = EINVAL;\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Get index of network interface associated with some IB device.\n+ *\n+ * This is the only somewhat safe method to avoid resorting to heuristics\n+ * when faced with port representors. Unfortunately it requires at least\n+ * Linux 4.17.\n+ *\n+ * @param nl\n+ *   Netlink socket of the RDMA kind (NETLINK_RDMA).\n+ * @param[in] name\n+ *   IB device name.\n+ * @param[in] pindex\n+ *   IB device port index, starting from 1\n+ * @return\n+ *   A valid (nonzero) interface index on success, 0 otherwise and rte_errno\n+ *   is set.\n+ */\n+unsigned int\n+mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex)\n+{\n+\tstruct mlx5_nl_ifindex_data data = {\n+\t\t.name = name,\n+\t\t.flags = 0,\n+\t\t.ibindex = 0, /* Determined during first pass. */\n+\t\t.ifindex = 0, /* Determined during second pass. */\n+\t};\n+\tunion {\n+\t\tstruct nlmsghdr nh;\n+\t\tuint8_t buf[NLMSG_HDRLEN +\n+\t\t\t    NLA_HDRLEN + NLA_ALIGN(sizeof(data.ibindex)) +\n+\t\t\t    NLA_HDRLEN + NLA_ALIGN(sizeof(pindex))];\n+\t} req = {\n+\t\t.nh = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH(0),\n+\t\t\t.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,\n+\t\t\t\t\t\t       RDMA_NLDEV_CMD_GET),\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,\n+\t\t},\n+\t};\n+\tstruct nlattr *na;\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tret = mlx5_nl_send(nl, &req.nh, sn);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tif (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||\n+\t    !(data.flags & MLX5_NL_CMD_GET_IB_INDEX))\n+\t\tgoto error;\n+\tdata.flags = 0;\n+\tsn = MLX5_NL_SN_GENERATE;\n+\treq.nh.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,\n+\t\t\t\t\t     RDMA_NLDEV_CMD_PORT_GET);\n+\treq.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n+\treq.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.buf) - NLMSG_HDRLEN);\n+\tna = (void *)((uintptr_t)req.buf + NLMSG_HDRLEN);\n+\tna->nla_len = NLA_HDRLEN + sizeof(data.ibindex);\n+\tna->nla_type = RDMA_NLDEV_ATTR_DEV_INDEX;\n+\tmemcpy((void *)((uintptr_t)na + NLA_HDRLEN),\n+\t       &data.ibindex, sizeof(data.ibindex));\n+\tna = (void *)((uintptr_t)na + NLA_ALIGN(na->nla_len));\n+\tna->nla_len = NLA_HDRLEN + sizeof(pindex);\n+\tna->nla_type = RDMA_NLDEV_ATTR_PORT_INDEX;\n+\tmemcpy((void *)((uintptr_t)na + NLA_HDRLEN),\n+\t       &pindex, sizeof(pindex));\n+\tret = mlx5_nl_send(nl, &req.nh, sn);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tif (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||\n+\t    !(data.flags & MLX5_NL_CMD_GET_IB_INDEX) ||\n+\t    !(data.flags & MLX5_NL_CMD_GET_NET_INDEX) ||\n+\t    !data.ifindex)\n+\t\tgoto error;\n+\treturn data.ifindex;\n+error:\n+\trte_errno = ENODEV;\n+\treturn 0;\n+}\n+\n+/**\n+ * Get the number of physical ports of given IB device.\n+ *\n+ * @param nl\n+ *   Netlink socket of the RDMA kind (NETLINK_RDMA).\n+ * @param[in] name\n+ *   IB device name.\n+ *\n+ * @return\n+ *   A valid (nonzero) number of ports on success, 0 otherwise\n+ *   and rte_errno is set.\n+ */\n+unsigned int\n+mlx5_nl_portnum(int nl, const char *name)\n+{\n+\tstruct mlx5_nl_ifindex_data data = {\n+\t\t.flags = 0,\n+\t\t.name = name,\n+\t\t.ifindex = 0,\n+\t\t.portnum = 0,\n+\t};\n+\tstruct nlmsghdr req = {\n+\t\t.nlmsg_len = NLMSG_LENGTH(0),\n+\t\t.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,\n+\t\t\t\t\t       RDMA_NLDEV_CMD_GET),\n+\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,\n+\t};\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tret = mlx5_nl_send(nl, &req, sn);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tif (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||\n+\t    !(data.flags & MLX5_NL_CMD_GET_IB_INDEX) ||\n+\t    !(data.flags & MLX5_NL_CMD_GET_PORT_INDEX)) {\n+\t\trte_errno = ENODEV;\n+\t\treturn 0;\n+\t}\n+\tif (!data.portnum)\n+\t\trte_errno = EINVAL;\n+\treturn data.portnum;\n+}\n+\n+/**\n+ * Analyze gathered port parameters via Netlink to recognize master\n+ * and representor devices for E-Switch configuration.\n+ *\n+ * @param[in] num_vf_set\n+ *   flag of presence of number of VFs port attribute.\n+ * @param[inout] switch_info\n+ *   Port information, including port name as a number and port name\n+ *   type if recognized\n+ *\n+ * @return\n+ *   master and representor flags are set in switch_info according to\n+ *   recognized parameters (if any).\n+ */\n+static void\n+mlx5_nl_check_switch_info(bool num_vf_set,\n+\t\t\t  struct mlx5_switch_info *switch_info)\n+{\n+\tswitch (switch_info->name_type) {\n+\tcase MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:\n+\t\t/*\n+\t\t * Name is not recognized, assume the master,\n+\t\t * check the number of VFs key presence.\n+\t\t */\n+\t\tswitch_info->master = num_vf_set;\n+\t\tbreak;\n+\tcase MLX5_PHYS_PORT_NAME_TYPE_NOTSET:\n+\t\t/*\n+\t\t * Name is not set, this assumes the legacy naming\n+\t\t * schema for master, just check if there is a\n+\t\t * number of VFs key.\n+\t\t */\n+\t\tswitch_info->master = num_vf_set;\n+\t\tbreak;\n+\tcase MLX5_PHYS_PORT_NAME_TYPE_UPLINK:\n+\t\t/* New uplink naming schema recognized. */\n+\t\tswitch_info->master = 1;\n+\t\tbreak;\n+\tcase MLX5_PHYS_PORT_NAME_TYPE_LEGACY:\n+\t\t/* Legacy representors naming schema. */\n+\t\tswitch_info->representor = !num_vf_set;\n+\t\tbreak;\n+\tcase MLX5_PHYS_PORT_NAME_TYPE_PFVF:\n+\t\t/* New representors naming schema. */\n+\t\tswitch_info->representor = 1;\n+\t\tbreak;\n+\t}\n+}\n+\n+/**\n+ * Process switch information from Netlink message.\n+ *\n+ * @param nh\n+ *   Pointer to Netlink message header.\n+ * @param arg\n+ *   Opaque data pointer for this callback.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg)\n+{\n+\tstruct mlx5_switch_info info = {\n+\t\t.master = 0,\n+\t\t.representor = 0,\n+\t\t.name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET,\n+\t\t.port_name = 0,\n+\t\t.switch_id = 0,\n+\t};\n+\tsize_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));\n+\tbool switch_id_set = false;\n+\tbool num_vf_set = false;\n+\n+\tif (nh->nlmsg_type != RTM_NEWLINK)\n+\t\tgoto error;\n+\twhile (off < nh->nlmsg_len) {\n+\t\tstruct rtattr *ra = (void *)((uintptr_t)nh + off);\n+\t\tvoid *payload = RTA_DATA(ra);\n+\t\tunsigned int i;\n+\n+\t\tif (ra->rta_len > nh->nlmsg_len - off)\n+\t\t\tgoto error;\n+\t\tswitch (ra->rta_type) {\n+\t\tcase IFLA_NUM_VF:\n+\t\t\tnum_vf_set = true;\n+\t\t\tbreak;\n+\t\tcase IFLA_PHYS_PORT_NAME:\n+\t\t\tmlx5_translate_port_name((char *)payload, &info);\n+\t\t\tbreak;\n+\t\tcase IFLA_PHYS_SWITCH_ID:\n+\t\t\tinfo.switch_id = 0;\n+\t\t\tfor (i = 0; i < RTA_PAYLOAD(ra); ++i) {\n+\t\t\t\tinfo.switch_id <<= 8;\n+\t\t\t\tinfo.switch_id |= ((uint8_t *)payload)[i];\n+\t\t\t}\n+\t\t\tswitch_id_set = true;\n+\t\t\tbreak;\n+\t\t}\n+\t\toff += RTA_ALIGN(ra->rta_len);\n+\t}\n+\tif (switch_id_set) {\n+\t\t/* We have some E-Switch configuration. */\n+\t\tmlx5_nl_check_switch_info(num_vf_set, &info);\n+\t}\n+\tassert(!(info.master && info.representor));\n+\tmemcpy(arg, &info, sizeof(info));\n+\treturn 0;\n+error:\n+\trte_errno = EINVAL;\n+\treturn -rte_errno;\n+}\n+\n+/**\n+ * Get switch information associated with network interface.\n+ *\n+ * @param nl\n+ *   Netlink socket of the ROUTE kind (NETLINK_ROUTE).\n+ * @param ifindex\n+ *   Network interface index.\n+ * @param[out] info\n+ *   Switch information object, populated in case of success.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_switch_info(int nl, unsigned int ifindex,\n+\t\t    struct mlx5_switch_info *info)\n+{\n+\tstruct {\n+\t\tstruct nlmsghdr nh;\n+\t\tstruct ifinfomsg info;\n+\t\tstruct rtattr rta;\n+\t\tuint32_t extmask;\n+\t} req = {\n+\t\t.nh = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH\n+\t\t\t\t\t(sizeof(req.info) +\n+\t\t\t\t\t RTA_LENGTH(sizeof(uint32_t))),\n+\t\t\t.nlmsg_type = RTM_GETLINK,\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,\n+\t\t},\n+\t\t.info = {\n+\t\t\t.ifi_family = AF_UNSPEC,\n+\t\t\t.ifi_index = ifindex,\n+\t\t},\n+\t\t.rta = {\n+\t\t\t.rta_type = IFLA_EXT_MASK,\n+\t\t\t.rta_len = RTA_LENGTH(sizeof(int32_t)),\n+\t\t},\n+\t\t.extmask = RTE_LE32(1),\n+\t};\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tret = mlx5_nl_send(nl, &req.nh, sn);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(nl, sn, mlx5_nl_switch_info_cb, info);\n+\tif (info->master && info->representor) {\n+\t\tDRV_LOG(ERR, \"ifindex %u device is recognized as master\"\n+\t\t\t     \" and as representor\", ifindex);\n+\t\trte_errno = ENODEV;\n+\t\tret = -rte_errno;\n+\t}\n+\treturn ret;\n+}\n+\n+/*\n+ * Delete VLAN network device by ifindex.\n+ *\n+ * @param[in] tcf\n+ *   Context object initialized by mlx5_nl_vlan_vmwa_init().\n+ * @param[in] ifindex\n+ *   Interface index of network device to delete.\n+ */\n+void\n+mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,\n+\t\t      uint32_t ifindex)\n+{\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\tstruct {\n+\t\tstruct nlmsghdr nh;\n+\t\tstruct ifinfomsg info;\n+\t} req = {\n+\t\t.nh = {\n+\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n+\t\t\t.nlmsg_type = RTM_DELLINK,\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,\n+\t\t},\n+\t\t.info = {\n+\t\t\t.ifi_family = AF_UNSPEC,\n+\t\t\t.ifi_index = ifindex,\n+\t\t},\n+\t};\n+\n+\tif (ifindex) {\n+\t\tret = mlx5_nl_send(vmwa->nl_socket, &req.nh, sn);\n+\t\tif (ret >= 0)\n+\t\t\tret = mlx5_nl_recv(vmwa->nl_socket, sn, NULL, NULL);\n+\t\tif (ret < 0)\n+\t\t\tDRV_LOG(WARNING, \"netlink: error deleting VLAN WA\"\n+\t\t\t\t\" ifindex %u, %d\", ifindex, ret);\n+\t}\n+}\n+\n+/* Set of subroutines to build Netlink message. */\n+static struct nlattr *\n+nl_msg_tail(struct nlmsghdr *nlh)\n+{\n+\treturn (struct nlattr *)\n+\t\t(((uint8_t *)nlh) + NLMSG_ALIGN(nlh->nlmsg_len));\n+}\n+\n+static void\n+nl_attr_put(struct nlmsghdr *nlh, int type, const void *data, int alen)\n+{\n+\tstruct nlattr *nla = nl_msg_tail(nlh);\n+\n+\tnla->nla_type = type;\n+\tnla->nla_len = NLMSG_ALIGN(sizeof(struct nlattr) + alen);\n+\tnlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + nla->nla_len;\n+\n+\tif (alen)\n+\t\tmemcpy((uint8_t *)nla + sizeof(struct nlattr), data, alen);\n+}\n+\n+static struct nlattr *\n+nl_attr_nest_start(struct nlmsghdr *nlh, int type)\n+{\n+\tstruct nlattr *nest = (struct nlattr *)nl_msg_tail(nlh);\n+\n+\tnl_attr_put(nlh, type, NULL, 0);\n+\treturn nest;\n+}\n+\n+static void\n+nl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *nest)\n+{\n+\tnest->nla_len = (uint8_t *)nl_msg_tail(nlh) - (uint8_t *)nest;\n+}\n+\n+/*\n+ * Create network VLAN device with specified VLAN tag.\n+ *\n+ * @param[in] tcf\n+ *   Context object initialized by mlx5_nl_vlan_vmwa_init().\n+ * @param[in] ifindex\n+ *   Base network interface index.\n+ * @param[in] tag\n+ *   VLAN tag for VLAN network device to create.\n+ */\n+uint32_t\n+mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,\n+\t\t\t uint32_t ifindex, uint16_t tag)\n+{\n+\tstruct nlmsghdr *nlh;\n+\tstruct ifinfomsg *ifm;\n+\tchar name[sizeof(MLX5_VMWA_VLAN_DEVICE_PFX) + 32];\n+\n+\talignas(RTE_CACHE_LINE_SIZE)\n+\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct ifinfomsg)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 8 +\n+\t\t    NLMSG_ALIGN(sizeof(uint32_t)) +\n+\t\t    NLMSG_ALIGN(sizeof(name)) +\n+\t\t    NLMSG_ALIGN(sizeof(\"vlan\")) +\n+\t\t    NLMSG_ALIGN(sizeof(uint32_t)) +\n+\t\t    NLMSG_ALIGN(sizeof(uint16_t)) + 16];\n+\tstruct nlattr *na_info;\n+\tstruct nlattr *na_vlan;\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\n+\tmemset(buf, 0, sizeof(buf));\n+\tnlh = (struct nlmsghdr *)buf;\n+\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n+\tnlh->nlmsg_type = RTM_NEWLINK;\n+\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |\n+\t\t\t   NLM_F_EXCL | NLM_F_ACK;\n+\tifm = (struct ifinfomsg *)nl_msg_tail(nlh);\n+\tnlh->nlmsg_len += sizeof(struct ifinfomsg);\n+\tifm->ifi_family = AF_UNSPEC;\n+\tifm->ifi_type = 0;\n+\tifm->ifi_index = 0;\n+\tifm->ifi_flags = IFF_UP;\n+\tifm->ifi_change = 0xffffffff;\n+\tnl_attr_put(nlh, IFLA_LINK, &ifindex, sizeof(ifindex));\n+\tret = snprintf(name, sizeof(name), \"%s.%u.%u\",\n+\t\t       MLX5_VMWA_VLAN_DEVICE_PFX, ifindex, tag);\n+\tnl_attr_put(nlh, IFLA_IFNAME, name, ret + 1);\n+\tna_info = nl_attr_nest_start(nlh, IFLA_LINKINFO);\n+\tnl_attr_put(nlh, IFLA_INFO_KIND, \"vlan\", sizeof(\"vlan\"));\n+\tna_vlan = nl_attr_nest_start(nlh, IFLA_INFO_DATA);\n+\tnl_attr_put(nlh, IFLA_VLAN_ID, &tag, sizeof(tag));\n+\tnl_attr_nest_end(nlh, na_vlan);\n+\tnl_attr_nest_end(nlh, na_info);\n+\tassert(sizeof(buf) >= nlh->nlmsg_len);\n+\tret = mlx5_nl_send(vmwa->nl_socket, nlh, sn);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(vmwa->nl_socket, sn, NULL, NULL);\n+\tif (ret < 0) {\n+\t\tDRV_LOG(WARNING, \"netlink: VLAN %s create failure (%d)\", name,\n+\t\t\tret);\n+\t}\n+\t// Try to get ifindex of created or pre-existing device.\n+\tret = if_nametoindex(name);\n+\tif (!ret) {\n+\t\tDRV_LOG(WARNING, \"VLAN %s failed to get index (%d)\", name,\n+\t\t\terrno);\n+\t\treturn 0;\n+\t}\n+\treturn ret;\n+}\ndiff --git a/drivers/common/mlx5/mlx5_nl.h b/drivers/common/mlx5/mlx5_nl.h\nnew file mode 100644\nindex 0000000..8e66a98\n--- /dev/null\n+++ b/drivers/common/mlx5/mlx5_nl.h\n@@ -0,0 +1,57 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright 2019 Mellanox Technologies, Ltd\n+ */\n+\n+#ifndef RTE_PMD_MLX5_NL_H_\n+#define RTE_PMD_MLX5_NL_H_\n+\n+#include <linux/netlink.h>\n+\n+#include <rte_ether.h>\n+\n+#include \"mlx5_common.h\"\n+\n+\n+/* VLAN netdev for VLAN workaround. */\n+struct mlx5_nl_vlan_dev {\n+\tuint32_t refcnt;\n+\tuint32_t ifindex; /**< Own interface index. */\n+};\n+\n+/*\n+ * Array of VLAN devices created on the base of VF\n+ * used for workaround in virtual environments.\n+ */\n+struct mlx5_nl_vlan_vmwa_context {\n+\tint nl_socket;\n+\tuint32_t vf_ifindex;\n+\tstruct mlx5_nl_vlan_dev vlan_dev[4096];\n+};\n+\n+\n+int mlx5_nl_init(int protocol);\n+int mlx5_nl_mac_addr_add(int nlsk_fd, unsigned int iface_idx, uint64_t *mac_own,\n+\t\t\t struct rte_ether_addr *mac, uint32_t index);\n+int mlx5_nl_mac_addr_remove(int nlsk_fd, unsigned int iface_idx,\n+\t\t\t    uint64_t *mac_own, struct rte_ether_addr *mac,\n+\t\t\t    uint32_t index);\n+void mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,\n+\t\t\t   struct rte_ether_addr *mac_addrs, int n);\n+void mlx5_nl_mac_addr_flush(int nlsk_fd, unsigned int iface_idx,\n+\t\t\t    struct rte_ether_addr *mac_addrs, int n,\n+\t\t\t    uint64_t *mac_own);\n+int mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable);\n+int mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable);\n+unsigned int mlx5_nl_portnum(int nl, const char *name);\n+unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);\n+int mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,\n+\t\t\t       struct rte_ether_addr *mac, int vf_index);\n+int mlx5_nl_switch_info(int nl, unsigned int ifindex,\n+\t\t\tstruct mlx5_switch_info *info);\n+\n+void mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,\n+\t\t\t      uint32_t ifindex);\n+uint32_t mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,\n+\t\t\t\t  uint32_t ifindex, uint16_t tag);\n+\n+#endif /* RTE_PMD_MLX5_NL_H_ */\ndiff --git a/drivers/common/mlx5/rte_common_mlx5_version.map b/drivers/common/mlx5/rte_common_mlx5_version.map\nindex 16b9b34..318a024 100644\n--- a/drivers/common/mlx5/rte_common_mlx5_version.map\n+++ b/drivers/common/mlx5/rte_common_mlx5_version.map\n@@ -24,5 +24,21 @@ DPDK_20.02 {\n \tmlx5_devx_get_out_command_status;\n \n \tmlx5_dev_to_pci_addr;\n-\tmlx5_vdpa_mode_selected;\n+\n+\tmlx5_nl_allmulti;\n+\tmlx5_nl_ifindex;\n+\tmlx5_nl_init;\n+\tmlx5_nl_mac_addr_add;\n+\tmlx5_nl_mac_addr_flush;\n+\tmlx5_nl_mac_addr_remove;\n+\tmlx5_nl_mac_addr_sync;\n+\tmlx5_nl_portnum;\n+\tmlx5_nl_promisc;\n+\tmlx5_nl_switch_info;\n+\tmlx5_nl_vf_mac_addr_modify;\n+\tmlx5_nl_vlan_vmwa_create;\n+\tmlx5_nl_vlan_vmwa_delete;\n+\n+\tmlx5_translate_port_name;\n+        mlx5_vdpa_mode_selected;\n };\ndiff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile\nindex dc6b3c8..d26afbb 100644\n--- a/drivers/net/mlx5/Makefile\n+++ b/drivers/net/mlx5/Makefile\n@@ -30,7 +30,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_meter.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_dv.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_flow_verbs.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mp.c\n-SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_nl.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_utils.c\n SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_socket.c\n \ndiff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build\nindex e10ef3a..d45be00 100644\n--- a/drivers/net/mlx5/meson.build\n+++ b/drivers/net/mlx5/meson.build\n@@ -19,7 +19,6 @@ sources = files(\n \t'mlx5_flow_verbs.c',\n \t'mlx5_mac.c',\n \t'mlx5_mr.c',\n-\t'mlx5_nl.c',\n \t'mlx5_rss.c',\n \t'mlx5_rxmode.c',\n \t'mlx5_rxq.c',\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex 5d25d8b..48f31c2 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -35,11 +35,11 @@\n #include <mlx5_glue.h>\n #include <mlx5_devx_cmds.h>\n #include <mlx5_prm.h>\n+#include <mlx5_nl.h>\n \n #include \"mlx5_defs.h\"\n #include \"mlx5_utils.h\"\n #include \"mlx5_mr.h\"\n-#include \"mlx5_nl.h\"\n #include \"mlx5_autoconf.h\"\n \n /* Request types for IPC. */\ndiff --git a/drivers/net/mlx5/mlx5_defs.h b/drivers/net/mlx5/mlx5_defs.h\nindex dc9b965..9b392ed 100644\n--- a/drivers/net/mlx5/mlx5_defs.h\n+++ b/drivers/net/mlx5/mlx5_defs.h\n@@ -14,14 +14,6 @@\n /* Reported driver name. */\n #define MLX5_DRIVER_NAME \"net_mlx5\"\n \n-/* Maximum number of simultaneous unicast MAC addresses. */\n-#define MLX5_MAX_UC_MAC_ADDRESSES 128\n-/* Maximum number of simultaneous Multicast MAC addresses. */\n-#define MLX5_MAX_MC_MAC_ADDRESSES 128\n-/* Maximum number of simultaneous MAC addresses. */\n-#define MLX5_MAX_MAC_ADDRESSES \\\n-\t(MLX5_MAX_UC_MAC_ADDRESSES + MLX5_MAX_MC_MAC_ADDRESSES)\n-\n /* Maximum number of simultaneous VLAN filters. */\n #define MLX5_MAX_VLAN_IDS 128\n \ndiff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c\nindex 5484104..b765636 100644\n--- a/drivers/net/mlx5/mlx5_ethdev.c\n+++ b/drivers/net/mlx5/mlx5_ethdev.c\n@@ -1940,61 +1940,6 @@ struct mlx5_priv *\n }\n \n /**\n- * Extract port name, as a number, from sysfs or netlink information.\n- *\n- * @param[in] port_name_in\n- *   String representing the port name.\n- * @param[out] port_info_out\n- *   Port information, including port name as a number and port name\n- *   type if recognized\n- *\n- * @return\n- *   port_name field set according to recognized name format.\n- */\n-void\n-mlx5_translate_port_name(const char *port_name_in,\n-\t\t\t struct mlx5_switch_info *port_info_out)\n-{\n-\tchar pf_c1, pf_c2, vf_c1, vf_c2;\n-\tchar *end;\n-\tint sc_items;\n-\n-\t/*\n-\t * Check for port-name as a string of the form pf0vf0\n-\t * (support kernel ver >= 5.0 or OFED ver >= 4.6).\n-\t */\n-\tsc_items = sscanf(port_name_in, \"%c%c%d%c%c%d\",\n-\t\t\t  &pf_c1, &pf_c2, &port_info_out->pf_num,\n-\t\t\t  &vf_c1, &vf_c2, &port_info_out->port_name);\n-\tif (sc_items == 6 &&\n-\t    pf_c1 == 'p' && pf_c2 == 'f' &&\n-\t    vf_c1 == 'v' && vf_c2 == 'f') {\n-\t\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF;\n-\t\treturn;\n-\t}\n-\t/*\n-\t * Check for port-name as a string of the form p0\n-\t * (support kernel ver >= 5.0, or OFED ver >= 4.6).\n-\t */\n-\tsc_items = sscanf(port_name_in, \"%c%d\",\n-\t\t\t  &pf_c1, &port_info_out->port_name);\n-\tif (sc_items == 2 && pf_c1 == 'p') {\n-\t\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK;\n-\t\treturn;\n-\t}\n-\t/* Check for port-name as a number (support kernel ver < 5.0 */\n-\terrno = 0;\n-\tport_info_out->port_name = strtol(port_name_in, &end, 0);\n-\tif (!errno &&\n-\t    (size_t)(end - port_name_in) == strlen(port_name_in)) {\n-\t\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY;\n-\t\treturn;\n-\t}\n-\tport_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN;\n-\treturn;\n-}\n-\n-/**\n  * DPDK callback to retrieve plug-in module EEPROM information (type and size).\n  *\n  * @param dev\ndiff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c\ndeleted file mode 100644\nindex 6b8ca00..0000000\n--- a/drivers/net/mlx5/mlx5_nl.c\n+++ /dev/null\n@@ -1,1338 +0,0 @@\n-/* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright 2018 6WIND S.A.\n- * Copyright 2018 Mellanox Technologies, Ltd\n- */\n-\n-#include <errno.h>\n-#include <linux/if_link.h>\n-#include <linux/rtnetlink.h>\n-#include <net/if.h>\n-#include <rdma/rdma_netlink.h>\n-#include <stdbool.h>\n-#include <stdint.h>\n-#include <stdlib.h>\n-#include <stdalign.h>\n-#include <string.h>\n-#include <sys/socket.h>\n-#include <unistd.h>\n-\n-#include <rte_errno.h>\n-#include <rte_atomic.h>\n-#include <rte_ether.h>\n-\n-#include \"mlx5.h\"\n-#include \"mlx5_nl.h\"\n-#include \"mlx5_utils.h\"\n-\n-/* Size of the buffer to receive kernel messages */\n-#define MLX5_NL_BUF_SIZE (32 * 1024)\n-/* Send buffer size for the Netlink socket */\n-#define MLX5_SEND_BUF_SIZE 32768\n-/* Receive buffer size for the Netlink socket */\n-#define MLX5_RECV_BUF_SIZE 32768\n-\n-/** Parameters of VLAN devices created by driver. */\n-#define MLX5_VMWA_VLAN_DEVICE_PFX \"evmlx\"\n-/*\n- * Define NDA_RTA as defined in iproute2 sources.\n- *\n- * see in iproute2 sources file include/libnetlink.h\n- */\n-#ifndef MLX5_NDA_RTA\n-#define MLX5_NDA_RTA(r) \\\n-\t((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))\n-#endif\n-/*\n- * Define NLMSG_TAIL as defined in iproute2 sources.\n- *\n- * see in iproute2 sources file include/libnetlink.h\n- */\n-#ifndef NLMSG_TAIL\n-#define NLMSG_TAIL(nmsg) \\\n-\t((struct rtattr *)(((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))\n-#endif\n-/*\n- * The following definitions are normally found in rdma/rdma_netlink.h,\n- * however they are so recent that most systems do not expose them yet.\n- */\n-#ifndef HAVE_RDMA_NL_NLDEV\n-#define RDMA_NL_NLDEV 5\n-#endif\n-#ifndef HAVE_RDMA_NLDEV_CMD_GET\n-#define RDMA_NLDEV_CMD_GET 1\n-#endif\n-#ifndef HAVE_RDMA_NLDEV_CMD_PORT_GET\n-#define RDMA_NLDEV_CMD_PORT_GET 5\n-#endif\n-#ifndef HAVE_RDMA_NLDEV_ATTR_DEV_INDEX\n-#define RDMA_NLDEV_ATTR_DEV_INDEX 1\n-#endif\n-#ifndef HAVE_RDMA_NLDEV_ATTR_DEV_NAME\n-#define RDMA_NLDEV_ATTR_DEV_NAME 2\n-#endif\n-#ifndef HAVE_RDMA_NLDEV_ATTR_PORT_INDEX\n-#define RDMA_NLDEV_ATTR_PORT_INDEX 3\n-#endif\n-#ifndef HAVE_RDMA_NLDEV_ATTR_NDEV_INDEX\n-#define RDMA_NLDEV_ATTR_NDEV_INDEX 50\n-#endif\n-\n-/* These are normally found in linux/if_link.h. */\n-#ifndef HAVE_IFLA_NUM_VF\n-#define IFLA_NUM_VF 21\n-#endif\n-#ifndef HAVE_IFLA_EXT_MASK\n-#define IFLA_EXT_MASK 29\n-#endif\n-#ifndef HAVE_IFLA_PHYS_SWITCH_ID\n-#define IFLA_PHYS_SWITCH_ID 36\n-#endif\n-#ifndef HAVE_IFLA_PHYS_PORT_NAME\n-#define IFLA_PHYS_PORT_NAME 38\n-#endif\n-\n-/* Add/remove MAC address through Netlink */\n-struct mlx5_nl_mac_addr {\n-\tstruct rte_ether_addr (*mac)[];\n-\t/**< MAC address handled by the device. */\n-\tint mac_n; /**< Number of addresses in the array. */\n-};\n-\n-#define MLX5_NL_CMD_GET_IB_NAME (1 << 0)\n-#define MLX5_NL_CMD_GET_IB_INDEX (1 << 1)\n-#define MLX5_NL_CMD_GET_NET_INDEX (1 << 2)\n-#define MLX5_NL_CMD_GET_PORT_INDEX (1 << 3)\n-\n-/** Data structure used by mlx5_nl_cmdget_cb(). */\n-struct mlx5_nl_ifindex_data {\n-\tconst char *name; /**< IB device name (in). */\n-\tuint32_t flags; /**< found attribute flags (out). */\n-\tuint32_t ibindex; /**< IB device index (out). */\n-\tuint32_t ifindex; /**< Network interface index (out). */\n-\tuint32_t portnum; /**< IB device max port number (out). */\n-};\n-\n-rte_atomic32_t atomic_sn = RTE_ATOMIC32_INIT(0);\n-\n-/* Generate Netlink sequence number. */\n-#define MLX5_NL_SN_GENERATE ((uint32_t)rte_atomic32_add_return(&atomic_sn, 1))\n-\n-/**\n- * Opens a Netlink socket.\n- *\n- * @param protocol\n- *   Netlink protocol (e.g. NETLINK_ROUTE, NETLINK_RDMA).\n- *\n- * @return\n- *   A file descriptor on success, a negative errno value otherwise and\n- *   rte_errno is set.\n- */\n-int\n-mlx5_nl_init(int protocol)\n-{\n-\tint fd;\n-\tint sndbuf_size = MLX5_SEND_BUF_SIZE;\n-\tint rcvbuf_size = MLX5_RECV_BUF_SIZE;\n-\tstruct sockaddr_nl local = {\n-\t\t.nl_family = AF_NETLINK,\n-\t};\n-\tint ret;\n-\n-\tfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol);\n-\tif (fd == -1) {\n-\t\trte_errno = errno;\n-\t\treturn -rte_errno;\n-\t}\n-\tret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, sizeof(int));\n-\tif (ret == -1) {\n-\t\trte_errno = errno;\n-\t\tgoto error;\n-\t}\n-\tret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf_size, sizeof(int));\n-\tif (ret == -1) {\n-\t\trte_errno = errno;\n-\t\tgoto error;\n-\t}\n-\tret = bind(fd, (struct sockaddr *)&local, sizeof(local));\n-\tif (ret == -1) {\n-\t\trte_errno = errno;\n-\t\tgoto error;\n-\t}\n-\treturn fd;\n-error:\n-\tclose(fd);\n-\treturn -rte_errno;\n-}\n-\n-/**\n- * Send a request message to the kernel on the Netlink socket.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] nh\n- *   The Netlink message send to the kernel.\n- * @param[in] ssn\n- *   Sequence number.\n- * @param[in] req\n- *   Pointer to the request structure.\n- * @param[in] len\n- *   Length of the request in bytes.\n- *\n- * @return\n- *   The number of sent bytes on success, a negative errno value otherwise and\n- *   rte_errno is set.\n- */\n-static int\n-mlx5_nl_request(int nlsk_fd, struct nlmsghdr *nh, uint32_t sn, void *req,\n-\t\tint len)\n-{\n-\tstruct sockaddr_nl sa = {\n-\t\t.nl_family = AF_NETLINK,\n-\t};\n-\tstruct iovec iov[2] = {\n-\t\t{ .iov_base = nh, .iov_len = sizeof(*nh), },\n-\t\t{ .iov_base = req, .iov_len = len, },\n-\t};\n-\tstruct msghdr msg = {\n-\t\t.msg_name = &sa,\n-\t\t.msg_namelen = sizeof(sa),\n-\t\t.msg_iov = iov,\n-\t\t.msg_iovlen = 2,\n-\t};\n-\tint send_bytes;\n-\n-\tnh->nlmsg_pid = 0; /* communication with the kernel uses pid 0 */\n-\tnh->nlmsg_seq = sn;\n-\tsend_bytes = sendmsg(nlsk_fd, &msg, 0);\n-\tif (send_bytes < 0) {\n-\t\trte_errno = errno;\n-\t\treturn -rte_errno;\n-\t}\n-\treturn send_bytes;\n-}\n-\n-/**\n- * Send a message to the kernel on the Netlink socket.\n- *\n- * @param[in] nlsk_fd\n- *   The Netlink socket file descriptor used for communication.\n- * @param[in] nh\n- *   The Netlink message send to the kernel.\n- * @param[in] sn\n- *   Sequence number.\n- *\n- * @return\n- *   The number of sent bytes on success, a negative errno value otherwise and\n- *   rte_errno is set.\n- */\n-static int\n-mlx5_nl_send(int nlsk_fd, struct nlmsghdr *nh, uint32_t sn)\n-{\n-\tstruct sockaddr_nl sa = {\n-\t\t.nl_family = AF_NETLINK,\n-\t};\n-\tstruct iovec iov = {\n-\t\t.iov_base = nh,\n-\t\t.iov_len = nh->nlmsg_len,\n-\t};\n-\tstruct msghdr msg = {\n-\t\t.msg_name = &sa,\n-\t\t.msg_namelen = sizeof(sa),\n-\t\t.msg_iov = &iov,\n-\t\t.msg_iovlen = 1,\n-\t};\n-\tint send_bytes;\n-\n-\tnh->nlmsg_pid = 0; /* communication with the kernel uses pid 0 */\n-\tnh->nlmsg_seq = sn;\n-\tsend_bytes = sendmsg(nlsk_fd, &msg, 0);\n-\tif (send_bytes < 0) {\n-\t\trte_errno = errno;\n-\t\treturn -rte_errno;\n-\t}\n-\treturn send_bytes;\n-}\n-\n-/**\n- * Receive a message from the kernel on the Netlink socket, following\n- * mlx5_nl_send().\n- *\n- * @param[in] nlsk_fd\n- *   The Netlink socket file descriptor used for communication.\n- * @param[in] sn\n- *   Sequence number.\n- * @param[in] cb\n- *   The callback function to call for each Netlink message received.\n- * @param[in, out] arg\n- *   Custom arguments for the callback.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_recv(int nlsk_fd, uint32_t sn, int (*cb)(struct nlmsghdr *, void *arg),\n-\t     void *arg)\n-{\n-\tstruct sockaddr_nl sa;\n-\tchar buf[MLX5_RECV_BUF_SIZE];\n-\tstruct iovec iov = {\n-\t\t.iov_base = buf,\n-\t\t.iov_len = sizeof(buf),\n-\t};\n-\tstruct msghdr msg = {\n-\t\t.msg_name = &sa,\n-\t\t.msg_namelen = sizeof(sa),\n-\t\t.msg_iov = &iov,\n-\t\t/* One message at a time */\n-\t\t.msg_iovlen = 1,\n-\t};\n-\tint multipart = 0;\n-\tint ret = 0;\n-\n-\tdo {\n-\t\tstruct nlmsghdr *nh;\n-\t\tint recv_bytes = 0;\n-\n-\t\tdo {\n-\t\t\trecv_bytes = recvmsg(nlsk_fd, &msg, 0);\n-\t\t\tif (recv_bytes == -1) {\n-\t\t\t\trte_errno = errno;\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-\t\t\tnh = (struct nlmsghdr *)buf;\n-\t\t} while (nh->nlmsg_seq != sn);\n-\t\tfor (;\n-\t\t     NLMSG_OK(nh, (unsigned int)recv_bytes);\n-\t\t     nh = NLMSG_NEXT(nh, recv_bytes)) {\n-\t\t\tif (nh->nlmsg_type == NLMSG_ERROR) {\n-\t\t\t\tstruct nlmsgerr *err_data = NLMSG_DATA(nh);\n-\n-\t\t\t\tif (err_data->error < 0) {\n-\t\t\t\t\trte_errno = -err_data->error;\n-\t\t\t\t\treturn -rte_errno;\n-\t\t\t\t}\n-\t\t\t\t/* Ack message. */\n-\t\t\t\treturn 0;\n-\t\t\t}\n-\t\t\t/* Multi-part msgs and their trailing DONE message. */\n-\t\t\tif (nh->nlmsg_flags & NLM_F_MULTI) {\n-\t\t\t\tif (nh->nlmsg_type == NLMSG_DONE)\n-\t\t\t\t\treturn 0;\n-\t\t\t\tmultipart = 1;\n-\t\t\t}\n-\t\t\tif (cb) {\n-\t\t\t\tret = cb(nh, arg);\n-\t\t\t\tif (ret < 0)\n-\t\t\t\t\treturn ret;\n-\t\t\t}\n-\t\t}\n-\t} while (multipart);\n-\treturn ret;\n-}\n-\n-/**\n- * Parse Netlink message to retrieve the bridge MAC address.\n- *\n- * @param nh\n- *   Pointer to Netlink Message Header.\n- * @param arg\n- *   PMD data register with this callback.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_mac_addr_cb(struct nlmsghdr *nh, void *arg)\n-{\n-\tstruct mlx5_nl_mac_addr *data = arg;\n-\tstruct ndmsg *r = NLMSG_DATA(nh);\n-\tstruct rtattr *attribute;\n-\tint len;\n-\n-\tlen = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*r));\n-\tfor (attribute = MLX5_NDA_RTA(r);\n-\t     RTA_OK(attribute, len);\n-\t     attribute = RTA_NEXT(attribute, len)) {\n-\t\tif (attribute->rta_type == NDA_LLADDR) {\n-\t\t\tif (data->mac_n == MLX5_MAX_MAC_ADDRESSES) {\n-\t\t\t\tDRV_LOG(WARNING,\n-\t\t\t\t\t\"not enough room to finalize the\"\n-\t\t\t\t\t\" request\");\n-\t\t\t\trte_errno = ENOMEM;\n-\t\t\t\treturn -rte_errno;\n-\t\t\t}\n-#ifndef NDEBUG\n-\t\t\tchar m[18];\n-\n-\t\t\trte_ether_format_addr(m, 18, RTA_DATA(attribute));\n-\t\t\tDRV_LOG(DEBUG, \"bridge MAC address %s\", m);\n-#endif\n-\t\t\tmemcpy(&(*data->mac)[data->mac_n++],\n-\t\t\t       RTA_DATA(attribute), RTE_ETHER_ADDR_LEN);\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-/**\n- * Get bridge MAC addresses.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param mac[out]\n- *   Pointer to the array table of MAC addresses to fill.\n- *   Its size should be of MLX5_MAX_MAC_ADDRESSES.\n- * @param mac_n[out]\n- *   Number of entries filled in MAC array.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_mac_addr_list(int nlsk_fd, unsigned int iface_idx,\n-\t\t      struct rte_ether_addr (*mac)[], int *mac_n)\n-{\n-\tstruct {\n-\t\tstruct nlmsghdr\thdr;\n-\t\tstruct ifinfomsg ifm;\n-\t} req = {\n-\t\t.hdr = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n-\t\t\t.nlmsg_type = RTM_GETNEIGH,\n-\t\t\t.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,\n-\t\t},\n-\t\t.ifm = {\n-\t\t\t.ifi_family = PF_BRIDGE,\n-\t\t\t.ifi_index = iface_idx,\n-\t\t},\n-\t};\n-\tstruct mlx5_nl_mac_addr data = {\n-\t\t.mac = mac,\n-\t\t.mac_n = 0,\n-\t};\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tif (nlsk_fd == -1)\n-\t\treturn 0;\n-\tret = mlx5_nl_request(nlsk_fd, &req.hdr, sn, &req.ifm,\n-\t\t\t      sizeof(struct ifinfomsg));\n-\tif (ret < 0)\n-\t\tgoto error;\n-\tret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_mac_addr_cb, &data);\n-\tif (ret < 0)\n-\t\tgoto error;\n-\t*mac_n = data.mac_n;\n-\treturn 0;\n-error:\n-\tDRV_LOG(DEBUG, \"Interface %u cannot retrieve MAC address list %s\",\n-\t\tiface_idx, strerror(rte_errno));\n-\treturn -rte_errno;\n-}\n-\n-/**\n- * Modify the MAC address neighbour table with Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param mac\n- *   MAC address to consider.\n- * @param add\n- *   1 to add the MAC address, 0 to remove the MAC address.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,\n-\t\t\tstruct rte_ether_addr *mac, int add)\n-{\n-\tstruct {\n-\t\tstruct nlmsghdr hdr;\n-\t\tstruct ndmsg ndm;\n-\t\tstruct rtattr rta;\n-\t\tuint8_t buffer[RTE_ETHER_ADDR_LEN];\n-\t} req = {\n-\t\t.hdr = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)),\n-\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |\n-\t\t\t\tNLM_F_EXCL | NLM_F_ACK,\n-\t\t\t.nlmsg_type = add ? RTM_NEWNEIGH : RTM_DELNEIGH,\n-\t\t},\n-\t\t.ndm = {\n-\t\t\t.ndm_family = PF_BRIDGE,\n-\t\t\t.ndm_state = NUD_NOARP | NUD_PERMANENT,\n-\t\t\t.ndm_ifindex = iface_idx,\n-\t\t\t.ndm_flags = NTF_SELF,\n-\t\t},\n-\t\t.rta = {\n-\t\t\t.rta_type = NDA_LLADDR,\n-\t\t\t.rta_len = RTA_LENGTH(RTE_ETHER_ADDR_LEN),\n-\t\t},\n-\t};\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tif (nlsk_fd == -1)\n-\t\treturn 0;\n-\tmemcpy(RTA_DATA(&req.rta), mac, RTE_ETHER_ADDR_LEN);\n-\treq.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +\n-\t\tRTA_ALIGN(req.rta.rta_len);\n-\tret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);\n-\tif (ret < 0)\n-\t\tgoto error;\n-\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n-\tif (ret < 0)\n-\t\tgoto error;\n-\treturn 0;\n-error:\n-\tDRV_LOG(DEBUG,\n-\t\t\"Interface %u cannot %s MAC address\"\n-\t\t\" %02X:%02X:%02X:%02X:%02X:%02X %s\",\n-\t\tiface_idx,\n-\t\tadd ? \"add\" : \"remove\",\n-\t\tmac->addr_bytes[0], mac->addr_bytes[1],\n-\t\tmac->addr_bytes[2], mac->addr_bytes[3],\n-\t\tmac->addr_bytes[4], mac->addr_bytes[5],\n-\t\tstrerror(rte_errno));\n-\treturn -rte_errno;\n-}\n-\n-/**\n- * Modify the VF MAC address neighbour table with Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param mac\n- *    MAC address to consider.\n- * @param vf_index\n- *    VF index.\n- *\n- * @return\n- *    0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,\n-\t\t\t   struct rte_ether_addr *mac, int vf_index)\n-{\n-\tint ret;\n-\tstruct {\n-\t\tstruct nlmsghdr hdr;\n-\t\tstruct ifinfomsg ifm;\n-\t\tstruct rtattr vf_list_rta;\n-\t\tstruct rtattr vf_info_rta;\n-\t\tstruct rtattr vf_mac_rta;\n-\t\tstruct ifla_vf_mac ivm;\n-\t} req = {\n-\t\t.hdr = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n-\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,\n-\t\t\t.nlmsg_type = RTM_BASE,\n-\t\t},\n-\t\t.ifm = {\n-\t\t\t.ifi_index = iface_idx,\n-\t\t},\n-\t\t.vf_list_rta = {\n-\t\t\t.rta_type = IFLA_VFINFO_LIST,\n-\t\t\t.rta_len = RTA_ALIGN(RTA_LENGTH(0)),\n-\t\t},\n-\t\t.vf_info_rta = {\n-\t\t\t.rta_type = IFLA_VF_INFO,\n-\t\t\t.rta_len = RTA_ALIGN(RTA_LENGTH(0)),\n-\t\t},\n-\t\t.vf_mac_rta = {\n-\t\t\t.rta_type = IFLA_VF_MAC,\n-\t\t},\n-\t};\n-\tstruct ifla_vf_mac ivm = {\n-\t\t.vf = vf_index,\n-\t};\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\n-\tmemcpy(&ivm.mac, mac, RTE_ETHER_ADDR_LEN);\n-\tmemcpy(RTA_DATA(&req.vf_mac_rta), &ivm, sizeof(ivm));\n-\n-\treq.vf_mac_rta.rta_len = RTA_LENGTH(sizeof(ivm));\n-\treq.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +\n-\t\tRTA_ALIGN(req.vf_list_rta.rta_len) +\n-\t\tRTA_ALIGN(req.vf_info_rta.rta_len) +\n-\t\tRTA_ALIGN(req.vf_mac_rta.rta_len);\n-\treq.vf_list_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),\n-\t\t\t\t\t       &req.vf_list_rta);\n-\treq.vf_info_rta.rta_len = RTE_PTR_DIFF(NLMSG_TAIL(&req.hdr),\n-\t\t\t\t\t       &req.vf_info_rta);\n-\n-\tif (nlsk_fd < 0)\n-\t\treturn -1;\n-\tret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);\n-\tif (ret < 0)\n-\t\tgoto error;\n-\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n-\tif (ret < 0)\n-\t\tgoto error;\n-\treturn 0;\n-error:\n-\tDRV_LOG(ERR,\n-\t\t\"representor %u cannot set VF MAC address \"\n-\t\t\"%02X:%02X:%02X:%02X:%02X:%02X : %s\",\n-\t\tvf_index,\n-\t\tmac->addr_bytes[0], mac->addr_bytes[1],\n-\t\tmac->addr_bytes[2], mac->addr_bytes[3],\n-\t\tmac->addr_bytes[4], mac->addr_bytes[5],\n-\t\tstrerror(rte_errno));\n-\treturn -rte_errno;\n-}\n-\n-/**\n- * Add a MAC address.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param mac_own\n- *   BITFIELD_DECLARE array to store the mac.\n- * @param mac\n- *   MAC address to register.\n- * @param index\n- *   MAC address index.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_mac_addr_add(int nlsk_fd, unsigned int iface_idx,\n-\t\t     uint64_t *mac_own, struct rte_ether_addr *mac,\n-\t\t     uint32_t index)\n-{\n-\tint ret;\n-\n-\tret = mlx5_nl_mac_addr_modify(nlsk_fd, iface_idx, mac, 1);\n-\tif (!ret)\n-\t\tBITFIELD_SET(mac_own, index);\n-\tif (ret == -EEXIST)\n-\t\treturn 0;\n-\treturn ret;\n-}\n-\n-/**\n- * Remove a MAC address.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param mac_own\n- *   BITFIELD_DECLARE array to store the mac.\n- * @param mac\n- *   MAC address to remove.\n- * @param index\n- *   MAC address index.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_mac_addr_remove(int nlsk_fd, unsigned int iface_idx, uint64_t *mac_own,\n-\t\t\tstruct rte_ether_addr *mac, uint32_t index)\n-{\n-\tBITFIELD_RESET(mac_own, index);\n-\treturn mlx5_nl_mac_addr_modify(nlsk_fd, iface_idx, mac, 0);\n-}\n-\n-/**\n- * Synchronize Netlink bridge table to the internal table.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param mac_addrs\n- *   Mac addresses array to sync.\n- * @param n\n- *   @p mac_addrs array size.\n- */\n-void\n-mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,\n-\t\t      struct rte_ether_addr *mac_addrs, int n)\n-{\n-\tstruct rte_ether_addr macs[n];\n-\tint macs_n = 0;\n-\tint i;\n-\tint ret;\n-\n-\tret = mlx5_nl_mac_addr_list(nlsk_fd, iface_idx, &macs, &macs_n);\n-\tif (ret)\n-\t\treturn;\n-\tfor (i = 0; i != macs_n; ++i) {\n-\t\tint j;\n-\n-\t\t/* Verify the address is not in the array yet. */\n-\t\tfor (j = 0; j != n; ++j)\n-\t\t\tif (rte_is_same_ether_addr(&macs[i], &mac_addrs[j]))\n-\t\t\t\tbreak;\n-\t\tif (j != n)\n-\t\t\tcontinue;\n-\t\t/* Find the first entry available. */\n-\t\tfor (j = 0; j != n; ++j) {\n-\t\t\tif (rte_is_zero_ether_addr(&mac_addrs[j])) {\n-\t\t\t\tmac_addrs[j] = macs[i];\n-\t\t\t\tbreak;\n-\t\t\t}\n-\t\t}\n-\t}\n-}\n-\n-/**\n- * Flush all added MAC addresses.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param[in] mac_addrs\n- *   Mac addresses array to flush.\n- * @param n\n- *   @p mac_addrs array size.\n- * @param mac_own\n- *   BITFIELD_DECLARE array to store the mac.\n- */\n-void\n-mlx5_nl_mac_addr_flush(int nlsk_fd, unsigned int iface_idx,\n-\t\t       struct rte_ether_addr *mac_addrs, int n,\n-\t\t       uint64_t *mac_own)\n-{\n-\tint i;\n-\n-\tfor (i = n - 1; i >= 0; --i) {\n-\t\tstruct rte_ether_addr *m = &mac_addrs[i];\n-\n-\t\tif (BITFIELD_ISSET(mac_own, i))\n-\t\t\tmlx5_nl_mac_addr_remove(nlsk_fd, iface_idx, mac_own, m,\n-\t\t\t\t\t\ti);\n-\t}\n-}\n-\n-/**\n- * Enable promiscuous / all multicast mode through Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param flags\n- *   IFF_PROMISC for promiscuous, IFF_ALLMULTI for allmulti.\n- * @param enable\n- *   Nonzero to enable, disable otherwise.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_device_flags(int nlsk_fd, unsigned int iface_idx, uint32_t flags,\n-\t\t     int enable)\n-{\n-\tstruct {\n-\t\tstruct nlmsghdr hdr;\n-\t\tstruct ifinfomsg ifi;\n-\t} req = {\n-\t\t.hdr = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n-\t\t\t.nlmsg_type = RTM_NEWLINK,\n-\t\t\t.nlmsg_flags = NLM_F_REQUEST,\n-\t\t},\n-\t\t.ifi = {\n-\t\t\t.ifi_flags = enable ? flags : 0,\n-\t\t\t.ifi_change = flags,\n-\t\t\t.ifi_index = iface_idx,\n-\t\t},\n-\t};\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tassert(!(flags & ~(IFF_PROMISC | IFF_ALLMULTI)));\n-\tif (nlsk_fd < 0)\n-\t\treturn 0;\n-\tret = mlx5_nl_send(nlsk_fd, &req.hdr, sn);\n-\tif (ret < 0)\n-\t\treturn ret;\n-\treturn 0;\n-}\n-\n-/**\n- * Enable promiscuous mode through Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param enable\n- *   Nonzero to enable, disable otherwise.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable)\n-{\n-\tint ret = mlx5_nl_device_flags(nlsk_fd, iface_idx, IFF_PROMISC, enable);\n-\n-\tif (ret)\n-\t\tDRV_LOG(DEBUG,\n-\t\t\t\"Interface %u cannot %s promisc mode: Netlink error %s\",\n-\t\t\tiface_idx, enable ? \"enable\" : \"disable\",\n-\t\t\tstrerror(rte_errno));\n-\treturn ret;\n-}\n-\n-/**\n- * Enable all multicast mode through Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] iface_idx\n- *   Net device interface index.\n- * @param enable\n- *   Nonzero to enable, disable otherwise.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable)\n-{\n-\tint ret = mlx5_nl_device_flags(nlsk_fd, iface_idx, IFF_ALLMULTI,\n-\t\t\t\t       enable);\n-\n-\tif (ret)\n-\t\tDRV_LOG(DEBUG,\n-\t\t\t\"Interface %u cannot %s allmulti : Netlink error %s\",\n-\t\t\tiface_idx, enable ? \"enable\" : \"disable\",\n-\t\t\tstrerror(rte_errno));\n-\treturn ret;\n-}\n-\n-/**\n- * Process network interface information from Netlink message.\n- *\n- * @param nh\n- *   Pointer to Netlink message header.\n- * @param arg\n- *   Opaque data pointer for this callback.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_cmdget_cb(struct nlmsghdr *nh, void *arg)\n-{\n-\tstruct mlx5_nl_ifindex_data *data = arg;\n-\tstruct mlx5_nl_ifindex_data local = {\n-\t\t.flags = 0,\n-\t};\n-\tsize_t off = NLMSG_HDRLEN;\n-\n-\tif (nh->nlmsg_type !=\n-\t    RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_GET) &&\n-\t    nh->nlmsg_type !=\n-\t    RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, RDMA_NLDEV_CMD_PORT_GET))\n-\t\tgoto error;\n-\twhile (off < nh->nlmsg_len) {\n-\t\tstruct nlattr *na = (void *)((uintptr_t)nh + off);\n-\t\tvoid *payload = (void *)((uintptr_t)na + NLA_HDRLEN);\n-\n-\t\tif (na->nla_len > nh->nlmsg_len - off)\n-\t\t\tgoto error;\n-\t\tswitch (na->nla_type) {\n-\t\tcase RDMA_NLDEV_ATTR_DEV_INDEX:\n-\t\t\tlocal.ibindex = *(uint32_t *)payload;\n-\t\t\tlocal.flags |= MLX5_NL_CMD_GET_IB_INDEX;\n-\t\t\tbreak;\n-\t\tcase RDMA_NLDEV_ATTR_DEV_NAME:\n-\t\t\tif (!strcmp(payload, data->name))\n-\t\t\t\tlocal.flags |= MLX5_NL_CMD_GET_IB_NAME;\n-\t\t\tbreak;\n-\t\tcase RDMA_NLDEV_ATTR_NDEV_INDEX:\n-\t\t\tlocal.ifindex = *(uint32_t *)payload;\n-\t\t\tlocal.flags |= MLX5_NL_CMD_GET_NET_INDEX;\n-\t\t\tbreak;\n-\t\tcase RDMA_NLDEV_ATTR_PORT_INDEX:\n-\t\t\tlocal.portnum = *(uint32_t *)payload;\n-\t\t\tlocal.flags |= MLX5_NL_CMD_GET_PORT_INDEX;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tbreak;\n-\t\t}\n-\t\toff += NLA_ALIGN(na->nla_len);\n-\t}\n-\t/*\n-\t * It is possible to have multiple messages for all\n-\t * Infiniband devices in the system with appropriate name.\n-\t * So we should gather parameters locally and copy to\n-\t * query context only in case of coinciding device name.\n-\t */\n-\tif (local.flags & MLX5_NL_CMD_GET_IB_NAME) {\n-\t\tdata->flags = local.flags;\n-\t\tdata->ibindex = local.ibindex;\n-\t\tdata->ifindex = local.ifindex;\n-\t\tdata->portnum = local.portnum;\n-\t}\n-\treturn 0;\n-error:\n-\trte_errno = EINVAL;\n-\treturn -rte_errno;\n-}\n-\n-/**\n- * Get index of network interface associated with some IB device.\n- *\n- * This is the only somewhat safe method to avoid resorting to heuristics\n- * when faced with port representors. Unfortunately it requires at least\n- * Linux 4.17.\n- *\n- * @param nl\n- *   Netlink socket of the RDMA kind (NETLINK_RDMA).\n- * @param[in] name\n- *   IB device name.\n- * @param[in] pindex\n- *   IB device port index, starting from 1\n- * @return\n- *   A valid (nonzero) interface index on success, 0 otherwise and rte_errno\n- *   is set.\n- */\n-unsigned int\n-mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex)\n-{\n-\tstruct mlx5_nl_ifindex_data data = {\n-\t\t.name = name,\n-\t\t.flags = 0,\n-\t\t.ibindex = 0, /* Determined during first pass. */\n-\t\t.ifindex = 0, /* Determined during second pass. */\n-\t};\n-\tunion {\n-\t\tstruct nlmsghdr nh;\n-\t\tuint8_t buf[NLMSG_HDRLEN +\n-\t\t\t    NLA_HDRLEN + NLA_ALIGN(sizeof(data.ibindex)) +\n-\t\t\t    NLA_HDRLEN + NLA_ALIGN(sizeof(pindex))];\n-\t} req = {\n-\t\t.nh = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH(0),\n-\t\t\t.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,\n-\t\t\t\t\t\t       RDMA_NLDEV_CMD_GET),\n-\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,\n-\t\t},\n-\t};\n-\tstruct nlattr *na;\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tret = mlx5_nl_send(nl, &req.nh, sn);\n-\tif (ret < 0)\n-\t\treturn 0;\n-\tret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);\n-\tif (ret < 0)\n-\t\treturn 0;\n-\tif (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||\n-\t    !(data.flags & MLX5_NL_CMD_GET_IB_INDEX))\n-\t\tgoto error;\n-\tdata.flags = 0;\n-\tsn = MLX5_NL_SN_GENERATE;\n-\treq.nh.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,\n-\t\t\t\t\t     RDMA_NLDEV_CMD_PORT_GET);\n-\treq.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n-\treq.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.buf) - NLMSG_HDRLEN);\n-\tna = (void *)((uintptr_t)req.buf + NLMSG_HDRLEN);\n-\tna->nla_len = NLA_HDRLEN + sizeof(data.ibindex);\n-\tna->nla_type = RDMA_NLDEV_ATTR_DEV_INDEX;\n-\tmemcpy((void *)((uintptr_t)na + NLA_HDRLEN),\n-\t       &data.ibindex, sizeof(data.ibindex));\n-\tna = (void *)((uintptr_t)na + NLA_ALIGN(na->nla_len));\n-\tna->nla_len = NLA_HDRLEN + sizeof(pindex);\n-\tna->nla_type = RDMA_NLDEV_ATTR_PORT_INDEX;\n-\tmemcpy((void *)((uintptr_t)na + NLA_HDRLEN),\n-\t       &pindex, sizeof(pindex));\n-\tret = mlx5_nl_send(nl, &req.nh, sn);\n-\tif (ret < 0)\n-\t\treturn 0;\n-\tret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);\n-\tif (ret < 0)\n-\t\treturn 0;\n-\tif (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||\n-\t    !(data.flags & MLX5_NL_CMD_GET_IB_INDEX) ||\n-\t    !(data.flags & MLX5_NL_CMD_GET_NET_INDEX) ||\n-\t    !data.ifindex)\n-\t\tgoto error;\n-\treturn data.ifindex;\n-error:\n-\trte_errno = ENODEV;\n-\treturn 0;\n-}\n-\n-/**\n- * Get the number of physical ports of given IB device.\n- *\n- * @param nl\n- *   Netlink socket of the RDMA kind (NETLINK_RDMA).\n- * @param[in] name\n- *   IB device name.\n- *\n- * @return\n- *   A valid (nonzero) number of ports on success, 0 otherwise\n- *   and rte_errno is set.\n- */\n-unsigned int\n-mlx5_nl_portnum(int nl, const char *name)\n-{\n-\tstruct mlx5_nl_ifindex_data data = {\n-\t\t.flags = 0,\n-\t\t.name = name,\n-\t\t.ifindex = 0,\n-\t\t.portnum = 0,\n-\t};\n-\tstruct nlmsghdr req = {\n-\t\t.nlmsg_len = NLMSG_LENGTH(0),\n-\t\t.nlmsg_type = RDMA_NL_GET_TYPE(RDMA_NL_NLDEV,\n-\t\t\t\t\t       RDMA_NLDEV_CMD_GET),\n-\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,\n-\t};\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tret = mlx5_nl_send(nl, &req, sn);\n-\tif (ret < 0)\n-\t\treturn 0;\n-\tret = mlx5_nl_recv(nl, sn, mlx5_nl_cmdget_cb, &data);\n-\tif (ret < 0)\n-\t\treturn 0;\n-\tif (!(data.flags & MLX5_NL_CMD_GET_IB_NAME) ||\n-\t    !(data.flags & MLX5_NL_CMD_GET_IB_INDEX) ||\n-\t    !(data.flags & MLX5_NL_CMD_GET_PORT_INDEX)) {\n-\t\trte_errno = ENODEV;\n-\t\treturn 0;\n-\t}\n-\tif (!data.portnum)\n-\t\trte_errno = EINVAL;\n-\treturn data.portnum;\n-}\n-\n-/**\n- * Analyze gathered port parameters via Netlink to recognize master\n- * and representor devices for E-Switch configuration.\n- *\n- * @param[in] num_vf_set\n- *   flag of presence of number of VFs port attribute.\n- * @param[inout] switch_info\n- *   Port information, including port name as a number and port name\n- *   type if recognized\n- *\n- * @return\n- *   master and representor flags are set in switch_info according to\n- *   recognized parameters (if any).\n- */\n-static void\n-mlx5_nl_check_switch_info(bool num_vf_set,\n-\t\t\t  struct mlx5_switch_info *switch_info)\n-{\n-\tswitch (switch_info->name_type) {\n-\tcase MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN:\n-\t\t/*\n-\t\t * Name is not recognized, assume the master,\n-\t\t * check the number of VFs key presence.\n-\t\t */\n-\t\tswitch_info->master = num_vf_set;\n-\t\tbreak;\n-\tcase MLX5_PHYS_PORT_NAME_TYPE_NOTSET:\n-\t\t/*\n-\t\t * Name is not set, this assumes the legacy naming\n-\t\t * schema for master, just check if there is a\n-\t\t * number of VFs key.\n-\t\t */\n-\t\tswitch_info->master = num_vf_set;\n-\t\tbreak;\n-\tcase MLX5_PHYS_PORT_NAME_TYPE_UPLINK:\n-\t\t/* New uplink naming schema recognized. */\n-\t\tswitch_info->master = 1;\n-\t\tbreak;\n-\tcase MLX5_PHYS_PORT_NAME_TYPE_LEGACY:\n-\t\t/* Legacy representors naming schema. */\n-\t\tswitch_info->representor = !num_vf_set;\n-\t\tbreak;\n-\tcase MLX5_PHYS_PORT_NAME_TYPE_PFVF:\n-\t\t/* New representors naming schema. */\n-\t\tswitch_info->representor = 1;\n-\t\tbreak;\n-\t}\n-}\n-\n-/**\n- * Process switch information from Netlink message.\n- *\n- * @param nh\n- *   Pointer to Netlink message header.\n- * @param arg\n- *   Opaque data pointer for this callback.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg)\n-{\n-\tstruct mlx5_switch_info info = {\n-\t\t.master = 0,\n-\t\t.representor = 0,\n-\t\t.name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET,\n-\t\t.port_name = 0,\n-\t\t.switch_id = 0,\n-\t};\n-\tsize_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));\n-\tbool switch_id_set = false;\n-\tbool num_vf_set = false;\n-\n-\tif (nh->nlmsg_type != RTM_NEWLINK)\n-\t\tgoto error;\n-\twhile (off < nh->nlmsg_len) {\n-\t\tstruct rtattr *ra = (void *)((uintptr_t)nh + off);\n-\t\tvoid *payload = RTA_DATA(ra);\n-\t\tunsigned int i;\n-\n-\t\tif (ra->rta_len > nh->nlmsg_len - off)\n-\t\t\tgoto error;\n-\t\tswitch (ra->rta_type) {\n-\t\tcase IFLA_NUM_VF:\n-\t\t\tnum_vf_set = true;\n-\t\t\tbreak;\n-\t\tcase IFLA_PHYS_PORT_NAME:\n-\t\t\tmlx5_translate_port_name((char *)payload, &info);\n-\t\t\tbreak;\n-\t\tcase IFLA_PHYS_SWITCH_ID:\n-\t\t\tinfo.switch_id = 0;\n-\t\t\tfor (i = 0; i < RTA_PAYLOAD(ra); ++i) {\n-\t\t\t\tinfo.switch_id <<= 8;\n-\t\t\t\tinfo.switch_id |= ((uint8_t *)payload)[i];\n-\t\t\t}\n-\t\t\tswitch_id_set = true;\n-\t\t\tbreak;\n-\t\t}\n-\t\toff += RTA_ALIGN(ra->rta_len);\n-\t}\n-\tif (switch_id_set) {\n-\t\t/* We have some E-Switch configuration. */\n-\t\tmlx5_nl_check_switch_info(num_vf_set, &info);\n-\t}\n-\tassert(!(info.master && info.representor));\n-\tmemcpy(arg, &info, sizeof(info));\n-\treturn 0;\n-error:\n-\trte_errno = EINVAL;\n-\treturn -rte_errno;\n-}\n-\n-/**\n- * Get switch information associated with network interface.\n- *\n- * @param nl\n- *   Netlink socket of the ROUTE kind (NETLINK_ROUTE).\n- * @param ifindex\n- *   Network interface index.\n- * @param[out] info\n- *   Switch information object, populated in case of success.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_switch_info(int nl, unsigned int ifindex,\n-\t\t    struct mlx5_switch_info *info)\n-{\n-\tstruct {\n-\t\tstruct nlmsghdr nh;\n-\t\tstruct ifinfomsg info;\n-\t\tstruct rtattr rta;\n-\t\tuint32_t extmask;\n-\t} req = {\n-\t\t.nh = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH\n-\t\t\t\t\t(sizeof(req.info) +\n-\t\t\t\t\t RTA_LENGTH(sizeof(uint32_t))),\n-\t\t\t.nlmsg_type = RTM_GETLINK,\n-\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,\n-\t\t},\n-\t\t.info = {\n-\t\t\t.ifi_family = AF_UNSPEC,\n-\t\t\t.ifi_index = ifindex,\n-\t\t},\n-\t\t.rta = {\n-\t\t\t.rta_type = IFLA_EXT_MASK,\n-\t\t\t.rta_len = RTA_LENGTH(sizeof(int32_t)),\n-\t\t},\n-\t\t.extmask = RTE_LE32(1),\n-\t};\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tret = mlx5_nl_send(nl, &req.nh, sn);\n-\tif (ret >= 0)\n-\t\tret = mlx5_nl_recv(nl, sn, mlx5_nl_switch_info_cb, info);\n-\tif (info->master && info->representor) {\n-\t\tDRV_LOG(ERR, \"ifindex %u device is recognized as master\"\n-\t\t\t     \" and as representor\", ifindex);\n-\t\trte_errno = ENODEV;\n-\t\tret = -rte_errno;\n-\t}\n-\treturn ret;\n-}\n-\n-/*\n- * Delete VLAN network device by ifindex.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_nl_vlan_vmwa_init().\n- * @param[in] ifindex\n- *   Interface index of network device to delete.\n- */\n-void\n-mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,\n-\t\t      uint32_t ifindex)\n-{\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\tstruct {\n-\t\tstruct nlmsghdr nh;\n-\t\tstruct ifinfomsg info;\n-\t} req = {\n-\t\t.nh = {\n-\t\t\t.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),\n-\t\t\t.nlmsg_type = RTM_DELLINK,\n-\t\t\t.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,\n-\t\t},\n-\t\t.info = {\n-\t\t\t.ifi_family = AF_UNSPEC,\n-\t\t\t.ifi_index = ifindex,\n-\t\t},\n-\t};\n-\n-\tif (ifindex) {\n-\t\tret = mlx5_nl_send(vmwa->nl_socket, &req.nh, sn);\n-\t\tif (ret >= 0)\n-\t\t\tret = mlx5_nl_recv(vmwa->nl_socket, sn, NULL, NULL);\n-\t\tif (ret < 0)\n-\t\t\tDRV_LOG(WARNING, \"netlink: error deleting VLAN WA\"\n-\t\t\t\t\" ifindex %u, %d\", ifindex, ret);\n-\t}\n-}\n-\n-/* Set of subroutines to build Netlink message. */\n-static struct nlattr *\n-nl_msg_tail(struct nlmsghdr *nlh)\n-{\n-\treturn (struct nlattr *)\n-\t\t(((uint8_t *)nlh) + NLMSG_ALIGN(nlh->nlmsg_len));\n-}\n-\n-static void\n-nl_attr_put(struct nlmsghdr *nlh, int type, const void *data, int alen)\n-{\n-\tstruct nlattr *nla = nl_msg_tail(nlh);\n-\n-\tnla->nla_type = type;\n-\tnla->nla_len = NLMSG_ALIGN(sizeof(struct nlattr) + alen);\n-\tnlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + nla->nla_len;\n-\n-\tif (alen)\n-\t\tmemcpy((uint8_t *)nla + sizeof(struct nlattr), data, alen);\n-}\n-\n-static struct nlattr *\n-nl_attr_nest_start(struct nlmsghdr *nlh, int type)\n-{\n-\tstruct nlattr *nest = (struct nlattr *)nl_msg_tail(nlh);\n-\n-\tnl_attr_put(nlh, type, NULL, 0);\n-\treturn nest;\n-}\n-\n-static void\n-nl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *nest)\n-{\n-\tnest->nla_len = (uint8_t *)nl_msg_tail(nlh) - (uint8_t *)nest;\n-}\n-\n-/*\n- * Create network VLAN device with specified VLAN tag.\n- *\n- * @param[in] tcf\n- *   Context object initialized by mlx5_nl_vlan_vmwa_init().\n- * @param[in] ifindex\n- *   Base network interface index.\n- * @param[in] tag\n- *   VLAN tag for VLAN network device to create.\n- */\n-uint32_t\n-mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,\n-\t\t\t uint32_t ifindex, uint16_t tag)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct ifinfomsg *ifm;\n-\tchar name[sizeof(MLX5_VMWA_VLAN_DEVICE_PFX) + 32];\n-\n-\talignas(RTE_CACHE_LINE_SIZE)\n-\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct ifinfomsg)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 8 +\n-\t\t    NLMSG_ALIGN(sizeof(uint32_t)) +\n-\t\t    NLMSG_ALIGN(sizeof(name)) +\n-\t\t    NLMSG_ALIGN(sizeof(\"vlan\")) +\n-\t\t    NLMSG_ALIGN(sizeof(uint32_t)) +\n-\t\t    NLMSG_ALIGN(sizeof(uint16_t)) + 16];\n-\tstruct nlattr *na_info;\n-\tstruct nlattr *na_vlan;\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = (struct nlmsghdr *)buf;\n-\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n-\tnlh->nlmsg_type = RTM_NEWLINK;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE |\n-\t\t\t   NLM_F_EXCL | NLM_F_ACK;\n-\tifm = (struct ifinfomsg *)nl_msg_tail(nlh);\n-\tnlh->nlmsg_len += sizeof(struct ifinfomsg);\n-\tifm->ifi_family = AF_UNSPEC;\n-\tifm->ifi_type = 0;\n-\tifm->ifi_index = 0;\n-\tifm->ifi_flags = IFF_UP;\n-\tifm->ifi_change = 0xffffffff;\n-\tnl_attr_put(nlh, IFLA_LINK, &ifindex, sizeof(ifindex));\n-\tret = snprintf(name, sizeof(name), \"%s.%u.%u\",\n-\t\t       MLX5_VMWA_VLAN_DEVICE_PFX, ifindex, tag);\n-\tnl_attr_put(nlh, IFLA_IFNAME, name, ret + 1);\n-\tna_info = nl_attr_nest_start(nlh, IFLA_LINKINFO);\n-\tnl_attr_put(nlh, IFLA_INFO_KIND, \"vlan\", sizeof(\"vlan\"));\n-\tna_vlan = nl_attr_nest_start(nlh, IFLA_INFO_DATA);\n-\tnl_attr_put(nlh, IFLA_VLAN_ID, &tag, sizeof(tag));\n-\tnl_attr_nest_end(nlh, na_vlan);\n-\tnl_attr_nest_end(nlh, na_info);\n-\tassert(sizeof(buf) >= nlh->nlmsg_len);\n-\tret = mlx5_nl_send(vmwa->nl_socket, nlh, sn);\n-\tif (ret >= 0)\n-\t\tret = mlx5_nl_recv(vmwa->nl_socket, sn, NULL, NULL);\n-\tif (ret < 0) {\n-\t\tDRV_LOG(WARNING, \"netlink: VLAN %s create failure (%d)\", name,\n-\t\t\tret);\n-\t}\n-\t// Try to get ifindex of created or pre-existing device.\n-\tret = if_nametoindex(name);\n-\tif (!ret) {\n-\t\tDRV_LOG(WARNING, \"VLAN %s failed to get index (%d)\", name,\n-\t\t\terrno);\n-\t\treturn 0;\n-\t}\n-\treturn ret;\n-}\ndiff --git a/drivers/net/mlx5/mlx5_nl.h b/drivers/net/mlx5/mlx5_nl.h\ndeleted file mode 100644\nindex 9be87c0..0000000\n--- a/drivers/net/mlx5/mlx5_nl.h\n+++ /dev/null\n@@ -1,72 +0,0 @@\n-/* SPDX-License-Identifier: BSD-3-Clause\n- * Copyright 2019 Mellanox Technologies, Ltd\n- */\n-\n-#ifndef RTE_PMD_MLX5_NL_H_\n-#define RTE_PMD_MLX5_NL_H_\n-\n-#include <linux/netlink.h>\n-\n-\n-/* Recognized Infiniband device physical port name types. */\n-enum mlx5_nl_phys_port_name_type {\n-\tMLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */\n-\tMLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */\n-\tMLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */\n-\tMLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */\n-\tMLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */\n-};\n-\n-/** Switch information returned by mlx5_nl_switch_info(). */\n-struct mlx5_switch_info {\n-\tuint32_t master:1; /**< Master device. */\n-\tuint32_t representor:1; /**< Representor device. */\n-\tenum mlx5_nl_phys_port_name_type name_type; /** < Port name type. */\n-\tint32_t pf_num; /**< PF number (valid for pfxvfx format only). */\n-\tint32_t port_name; /**< Representor port name. */\n-\tuint64_t switch_id; /**< Switch identifier. */\n-};\n-\n-/* VLAN netdev for VLAN workaround. */\n-struct mlx5_nl_vlan_dev {\n-\tuint32_t refcnt;\n-\tuint32_t ifindex; /**< Own interface index. */\n-};\n-\n-/*\n- * Array of VLAN devices created on the base of VF\n- * used for workaround in virtual environments.\n- */\n-struct mlx5_nl_vlan_vmwa_context {\n-\tint nl_socket;\n-\tuint32_t vf_ifindex;\n-\tstruct mlx5_nl_vlan_dev vlan_dev[4096];\n-};\n-\n-\n-int mlx5_nl_init(int protocol);\n-int mlx5_nl_mac_addr_add(int nlsk_fd, unsigned int iface_idx, uint64_t *mac_own,\n-\t\t\t struct rte_ether_addr *mac, uint32_t index);\n-int mlx5_nl_mac_addr_remove(int nlsk_fd, unsigned int iface_idx,\n-\t\t\t    uint64_t *mac_own, struct rte_ether_addr *mac,\n-\t\t\t    uint32_t index);\n-void mlx5_nl_mac_addr_sync(int nlsk_fd, unsigned int iface_idx,\n-\t\t\t   struct rte_ether_addr *mac_addrs, int n);\n-void mlx5_nl_mac_addr_flush(int nlsk_fd, unsigned int iface_idx,\n-\t\t\t    struct rte_ether_addr *mac_addrs, int n,\n-\t\t\t    uint64_t *mac_own);\n-int mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable);\n-int mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable);\n-unsigned int mlx5_nl_portnum(int nl, const char *name);\n-unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);\n-int mlx5_nl_vf_mac_addr_modify(int nlsk_fd, unsigned int iface_idx,\n-\t\t\t       struct rte_ether_addr *mac, int vf_index);\n-int mlx5_nl_switch_info(int nl, unsigned int ifindex,\n-\t\t\tstruct mlx5_switch_info *info);\n-\n-void mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,\n-\t\t\t      uint32_t ifindex);\n-uint32_t mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,\n-\t\t\t\t  uint32_t ifindex, uint16_t tag);\n-\n-#endif /* RTE_PMD_MLX5_NL_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c\nindex fc1a91c..8e63b67 100644\n--- a/drivers/net/mlx5/mlx5_vlan.c\n+++ b/drivers/net/mlx5/mlx5_vlan.c\n@@ -33,11 +33,11 @@\n \n #include <mlx5_glue.h>\n #include <mlx5_devx_cmds.h>\n+#include <mlx5_nl.h>\n \n #include \"mlx5.h\"\n #include \"mlx5_autoconf.h\"\n #include \"mlx5_rxtx.h\"\n-#include \"mlx5_nl.h\"\n #include \"mlx5_utils.h\"\n \n /**\n",
    "prefixes": [
        "v1",
        "36/38"
    ]
}