get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 70706,
    "url": "http://patchwork.dpdk.org/api/patches/70706/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20200601055047.5108-3-ophirmu@mellanox.com/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20200601055047.5108-3-ophirmu@mellanox.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200601055047.5108-3-ophirmu@mellanox.com",
    "date": "2020-06-01T05:50:46",
    "name": "[v2,2/3] common/mlx5: move netlink files under Linux directory",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "8b428f93db1d0de03c2c218fef37fd6cc109a3b1",
    "submitter": {
        "id": 793,
        "url": "http://patchwork.dpdk.org/api/people/793/?format=api",
        "name": "Ophir Munk",
        "email": "ophirmu@mellanox.com"
    },
    "delegate": {
        "id": 3268,
        "url": "http://patchwork.dpdk.org/api/users/3268/?format=api",
        "username": "rasland",
        "first_name": "Raslan",
        "last_name": "Darawsheh",
        "email": "rasland@nvidia.com"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20200601055047.5108-3-ophirmu@mellanox.com/mbox/",
    "series": [
        {
            "id": 10278,
            "url": "http://patchwork.dpdk.org/api/series/10278/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=10278",
            "date": "2020-06-01T05:50:44",
            "name": "Linux specific files moved & split",
            "version": 2,
            "mbox": "http://patchwork.dpdk.org/series/10278/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/70706/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/70706/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 833BCA04EF;\n\tMon,  1 Jun 2020 07:51:31 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 8230A1D530;\n\tMon,  1 Jun 2020 07:51:01 +0200 (CEST)",
            "from EUR05-DB8-obe.outbound.protection.outlook.com\n (mail-db8eur05on2083.outbound.protection.outlook.com [40.107.20.83])\n by dpdk.org (Postfix) with ESMTP id 483531D453\n for <dev@dpdk.org>; Mon,  1 Jun 2020 07:50:58 +0200 (CEST)",
            "from AM0PR05MB4209.eurprd05.prod.outlook.com (2603:10a6:208:61::22)\n by AM0PR05MB5953.eurprd05.prod.outlook.com (2603:10a6:208:12f::14)\n with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3045.21; Mon, 1 Jun\n 2020 05:50:55 +0000",
            "from AM0PR05MB4209.eurprd05.prod.outlook.com\n ([fe80::1068:89a9:41d3:b14a]) by AM0PR05MB4209.eurprd05.prod.outlook.com\n ([fe80::1068:89a9:41d3:b14a%3]) with mapi id 15.20.3045.024; Mon, 1 Jun 2020\n 05:50:55 +0000",
            "from mellanox.com (37.142.13.130) by\n AM0PR06CA0110.eurprd06.prod.outlook.com (2603:10a6:208:ab::15) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.3045.17 via Frontend Transport; Mon, 1 Jun 2020 05:50:54 +0000"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;\n b=nptT8eWzU6D/HQoMW0mImiIZj2CQisibEmavA5Ys2+PZz4Z1Dt6y1tqC5fEyhnHQplJvDvkEXTBn8ept4axA2DUp+NBPpsxHRaAzwuSCZM6rGTUb3OcnE/blatWG/hitAY0S52Pe0E+5nKDgvfNl1qL2FGlalyZy6yyVJ9nJYaEJcwURcP9SpQiSgG83eRRG/T8jOZhpV3x3HeALLYeOAj4oDT8PNo75k+BC/W1lTuBhjIblquKiGbfGidCU/EruSuhAmQSDW0362PLgDH+x5KIn/LKoUnXUuym5l5Dyi71sOx0/KazLOJhMUE5mKhNVmv3HQoqEa4uXyiAwpV5wTg==",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector9901;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=/Jqip5PDkbXhDAXoMM4TCEmpuueGdeB5cpFd7WuVo28=;\n b=KGTX/OJYBpuoh5n6lgUFkG6klBPdR2eBmzY3sV7Ae1mI1n1nZkKURgcX7ryTCXZGFPz0yyn4BhnTfxzOvThpnDolA6JUIu9C3lHZQ06LzmLhNPAELhDpvnLmCELe+01wWdxP6DXBtM5hIZVuyX7qg086wZ5xjXeBUWSXNvBQeZ4uvJYhyWqwyd5tygVs7Rzg5T0+q9IGCj+5SY4Z66wKAWW1EyKrldVu/SHI+PWYtbuZtDcms4MT7snUwlQiftj1Cbjby7d5oN7iAOxuMxMEwtL5mdx/McLtaxPDqEL4a+5LOrZgE7+g4IcwDkxJB/CQqOW4xDRt5iMfyomtYUZeuQ==",
        "ARC-Authentication-Results": "i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=mellanox.com; dmarc=pass action=none header.from=mellanox.com;\n dkim=pass header.d=mellanox.com; arc=none",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=/Jqip5PDkbXhDAXoMM4TCEmpuueGdeB5cpFd7WuVo28=;\n b=ahPrb58l4Z9jMz43uquOySbLHp08aLTOvjD7RZVlNQaZlA8CwcH44Zv5LT8y8EUANsILa4OlMDtwguKQdctu4CKhcIyrwmUnk/H1q1kCF/wrz7x0eafs0hVplu0SBBUuoB1UxhENvCZJbELTrcXvvhDJ/Zv2+HDdB7vEJwjPzF0=",
        "Authentication-Results": "dpdk.org; dkim=none (message not signed)\n header.d=none;dpdk.org; dmarc=none action=none header.from=mellanox.com;",
        "From": "Ophir Munk <ophirmu@mellanox.com>",
        "To": "dev@dpdk.org,\n\tMatan Azrad <matan@mellanox.com>",
        "Cc": "Ophir Munk <ophirmu@mellanox.com>",
        "Date": "Mon,  1 Jun 2020 05:50:46 +0000",
        "Message-Id": "<20200601055047.5108-3-ophirmu@mellanox.com>",
        "X-Mailer": [
            "git-send-email 2.8.4",
            "git-send-email 2.8.4"
        ],
        "In-Reply-To": "<20200601055047.5108-1-ophirmu@mellanox.com>",
        "References": "<20200527161425.22944-1-ophirmu@mellanox.com>\n <20200601055047.5108-1-ophirmu@mellanox.com>",
        "Content-Type": "text/plain",
        "X-ClientProxiedBy": "AM0PR06CA0110.eurprd06.prod.outlook.com\n (2603:10a6:208:ab::15) To AM0PR05MB4209.eurprd05.prod.outlook.com\n (2603:10a6:208:61::22)",
        "MIME-Version": "1.0",
        "X-MS-Exchange-MessageSentRepresentingType": "1",
        "X-Originating-IP": "[37.142.13.130]",
        "X-MS-PublicTrafficType": "Email",
        "X-MS-Office365-Filtering-HT": "Tenant",
        "X-MS-Office365-Filtering-Correlation-Id": "52c7a066-0d47-4d96-b279-08d805efbfc2",
        "X-MS-TrafficTypeDiagnostic": "AM0PR05MB5953:",
        "X-MS-Exchange-Transport-Forked": "True",
        "X-Microsoft-Antispam-PRVS": "\n <AM0PR05MB59531C4E1D29B30D66D596D9D18A0@AM0PR05MB5953.eurprd05.prod.outlook.com>",
        "X-MS-Oob-TLC-OOBClassifiers": "OLM:327;",
        "X-Forefront-PRVS": "0421BF7135",
        "X-MS-Exchange-SenderADCheck": "1",
        "X-Microsoft-Antispam": "BCL:0;",
        "X-Microsoft-Antispam-Message-Info": "\n 496tFxTAnOckqiejOFi0Pj67LTcl3YqRt9nlqkgWI1SYkAbZhxEoBRMRVDS+cU1FuRrBGRYgudW6geVsMLIrDPlbrPNCr7cwq/D1nly6/zmyjQ3w097ksdZRJXmGHDiHWXiCXkeeWbg4FZUNNNuDIvcP3HoPBF6DeRQd9FXYE7UkIjdhtXR2S9yXyE7w8G3W5pSoP0zLT4S+TnrXtlLVHQDVV2o/CFmI48Gi/Snr3rkqz8ErrLR8tSEZKH7CpGMKmqvgK9ATj70iQ6B7wI+Ul8oKqLFsyRoiFMNmpn8oe1CvTFyiFWP4WdFFy7VtLGEOW2Eri209FMhRvRqYisO9TA==",
        "X-Forefront-Antispam-Report": "CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;\n IPV:NLI; SFV:NSPM; H:AM0PR05MB4209.eurprd05.prod.outlook.com; PTR:; CAT:NONE;\n SFTY:;\n SFS:(4636009)(396003)(376002)(346002)(136003)(366004)(39860400002)(6666004)(36756003)(6862004)(66556008)(66476007)(37006003)(7696005)(52116002)(8886007)(1076003)(66946007)(107886003)(83380400001)(8936002)(86362001)(30864003)(2616005)(5660300002)(316002)(26005)(8676002)(16526019)(478600001)(186003)(956004)(4326008)(6636002)(55016002)(2906002)(579004)(559001);\n DIR:OUT; SFP:1101;",
        "X-MS-Exchange-AntiSpam-MessageData": "\n hgmrALRIVomcCVXds7AY6xVW+R5nK2u8siTfZZy6zZyzLXqxFmmlw4vzbAmRehUUjb7pSIfnRv7yn+MSExWcQ8vX7QRig/+fkX9/NsBhWt7QCVKRzsnuvLkZzPi7w76rTnJsPJrM5w5QDfqektsTOSrJT1teSoXtJ91z5gmrQxqV4mqXYgkzOi72qzWE1Wq4PPHwPjSR2MrMKUoXa04L7Ct8McKjVULD2vC4PAzaR6TpIHQQ1Ai3j0gpfG1gNCIhZH3UzZWj7oqjjAK+jcEkofoXuSmVAt24paLBHNKmFQmrM2eyUrTnkf+AI01pZfWvHVnFgoa21r38MkqOFCNzNbRAT3ierPcy6OqaX8Lv6SId5Gv7ur6YHOkb35mrTecIY9mUmYaqRzL+Y+/mHYFHOmvNkegkjngyBVA40cvpPyo6diJpvDxayM2qcasI/h/OwLJr3IdDQtF401u7weq3NStAfMJU3fXvDzYS182hX2Ce9DfeeExdj5zRw6uQw+5a",
        "X-OriginatorOrg": "Mellanox.com",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n 52c7a066-0d47-4d96-b279-08d805efbfc2",
        "X-MS-Exchange-CrossTenant-OriginalArrivalTime": "01 Jun 2020 05:50:55.0282 (UTC)",
        "X-MS-Exchange-CrossTenant-FromEntityHeader": "Hosted",
        "X-MS-Exchange-CrossTenant-Id": "a652971c-7d2e-4d9b-a6a4-d149256f461b",
        "X-MS-Exchange-CrossTenant-MailboxType": "HOSTED",
        "X-MS-Exchange-CrossTenant-UserPrincipalName": "\n mXZUGicM0+VNitmLlIY+hDYc2EoWUssSlj1n2AlQIRiuH5l9WYzTGB0x7flzIiRR0CXnh/MrhiuBGWiP5Li9wA==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "AM0PR05MB5953",
        "Subject": "[dpdk-dev] [PATCH v2 2/3] common/mlx5: move netlink files under\n\tLinux directory",
        "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": "File mlx5_nl.c is using Netlink APIs which are Linux specifics.\nMove it (including file mlx5_nl.h) to common/mlx5/linux directory.\n\nSigned-off-by: Ophir Munk <ophirmu@mellanox.com>\n---\n drivers/common/mlx5/Makefile          |    2 +-\n drivers/common/mlx5/linux/meson.build |    1 +\n drivers/common/mlx5/linux/mlx5_nl.c   | 1724 +++++++++++++++++++++++++++++++++\n drivers/common/mlx5/linux/mlx5_nl.h   |   79 ++\n drivers/common/mlx5/meson.build       |    1 -\n drivers/common/mlx5/mlx5_nl.c         | 1721 --------------------------------\n drivers/common/mlx5/mlx5_nl.h         |   79 --\n 7 files changed, 1805 insertions(+), 1802 deletions(-)\n create mode 100644 drivers/common/mlx5/linux/mlx5_nl.c\n create mode 100644 drivers/common/mlx5/linux/mlx5_nl.h\n delete mode 100644 drivers/common/mlx5/mlx5_nl.c\n delete mode 100644 drivers/common/mlx5/mlx5_nl.h",
    "diff": "diff --git a/drivers/common/mlx5/Makefile b/drivers/common/mlx5/Makefile\nindex 19b1466..40bf2a5 100644\n--- a/drivers/common/mlx5/Makefile\n+++ b/drivers/common/mlx5/Makefile\n@@ -16,7 +16,7 @@ SRCS-y += linux/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+SRCS-y += linux/mlx5_nl.c\n SRCS-y += mlx5_common_mp.c\n SRCS-y += mlx5_common_mr.c\n ifeq ($(CONFIG_RTE_IBVERBS_LINK_DLOPEN),y)\ndiff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build\nindex a123fd6..04f7e03 100644\n--- a/drivers/common/mlx5/linux/meson.build\n+++ b/drivers/common/mlx5/linux/meson.build\n@@ -45,6 +45,7 @@ if static_ibverbs\n \text_deps += declare_dependency(link_args:ibv_ldflags.split())\n endif\n \n+sources += files('mlx5_nl.c')\n if not dlopen_ibverbs\n \tsources += files('mlx5_glue.c')\n endif\ndiff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c\nnew file mode 100644\nindex 0000000..2943704\n--- /dev/null\n+++ b/drivers/common/mlx5/linux/mlx5_nl.c\n@@ -0,0 +1,1724 @@\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 <linux/genetlink.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+\n+#include \"mlx5_nl.h\"\n+#include \"mlx5_common_utils.h\"\n+#ifdef HAVE_DEVLINK\n+#include <linux/devlink.h>\n+#endif\n+\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+/*\n+ * Some Devlink defines may be missed in old kernel versions,\n+ * adjust used defines.\n+ */\n+#ifndef DEVLINK_GENL_NAME\n+#define DEVLINK_GENL_NAME \"devlink\"\n+#endif\n+#ifndef DEVLINK_GENL_VERSION\n+#define DEVLINK_GENL_VERSION 1\n+#endif\n+#ifndef DEVLINK_ATTR_BUS_NAME\n+#define DEVLINK_ATTR_BUS_NAME 1\n+#endif\n+#ifndef DEVLINK_ATTR_DEV_NAME\n+#define DEVLINK_ATTR_DEV_NAME 2\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM\n+#define DEVLINK_ATTR_PARAM 80\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM_NAME\n+#define DEVLINK_ATTR_PARAM_NAME 81\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM_TYPE\n+#define DEVLINK_ATTR_PARAM_TYPE 83\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM_VALUES_LIST\n+#define DEVLINK_ATTR_PARAM_VALUES_LIST 84\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM_VALUE\n+#define DEVLINK_ATTR_PARAM_VALUE 85\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM_VALUE_DATA\n+#define DEVLINK_ATTR_PARAM_VALUE_DATA 86\n+#endif\n+#ifndef DEVLINK_ATTR_PARAM_VALUE_CMODE\n+#define DEVLINK_ATTR_PARAM_VALUE_CMODE 87\n+#endif\n+#ifndef DEVLINK_PARAM_CMODE_DRIVERINIT\n+#define DEVLINK_PARAM_CMODE_DRIVERINIT 1\n+#endif\n+#ifndef DEVLINK_CMD_RELOAD\n+#define DEVLINK_CMD_RELOAD 37\n+#endif\n+#ifndef DEVLINK_CMD_PARAM_GET\n+#define DEVLINK_CMD_PARAM_GET 38\n+#endif\n+#ifndef DEVLINK_CMD_PARAM_SET\n+#define DEVLINK_CMD_PARAM_SET 39\n+#endif\n+#ifndef NLA_FLAG\n+#define NLA_FLAG 6\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+\tvoid *buf = malloc(MLX5_RECV_BUF_SIZE);\n+\tstruct iovec iov = {\n+\t\t.iov_base = buf,\n+\t\t.iov_len = MLX5_RECV_BUF_SIZE,\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+\tif (!buf) {\n+\t\trte_errno = ENOMEM;\n+\t\treturn -rte_errno;\n+\t}\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\tret = -rte_errno;\n+\t\t\t\tgoto exit;\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\tret = -rte_errno;\n+\t\t\t\t\tgoto exit;\n+\t\t\t\t}\n+\t\t\t\t/* Ack message. */\n+\t\t\t\tret = 0;\n+\t\t\t\tgoto exit;\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\tret =  0;\n+\t\t\t\t\tgoto exit;\n+\t\t\t\t}\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\tgoto exit;\n+\t\t\t}\n+\t\t}\n+\t} while (multipart);\n+exit:\n+\tfree(buf);\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+#ifdef RTE_LIBRTE_MLX5_DEBUG\n+\t\t\tchar m[RTE_ETHER_ADDR_FMT_SIZE];\n+\n+\t\t\trte_ether_format_addr(m, RTE_ETHER_ADDR_FMT_SIZE,\n+\t\t\t\t\t      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+#ifdef RTE_LIBRTE_MLX5_DEBUG\n+\t{\n+\t\tchar m[RTE_ETHER_ADDR_FMT_SIZE];\n+\n+\t\trte_ether_format_addr(m, RTE_ETHER_ADDR_FMT_SIZE, mac);\n+\t\tDRV_LOG(DEBUG,\n+\t\t\t\"Interface %u cannot %s MAC address %s %s\",\n+\t\t\tiface_idx,\n+\t\t\tadd ? \"add\" : \"remove\", m, strerror(rte_errno));\n+\t}\n+#endif\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\tMLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);\n+\t\tif (index >= MLX5_MAX_MAC_ADDRESSES)\n+\t\t\treturn -EINVAL;\n+\n+\t\tBITFIELD_SET(mac_own, index);\n+\t}\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+\tMLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);\n+\tif (index >= MLX5_MAX_MAC_ADDRESSES)\n+\t\treturn -EINVAL;\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+\tif (n <= 0 || n >= MLX5_MAX_MAC_ADDRESSES)\n+\t\treturn;\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+\tMLX5_ASSERT(!(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+\tMLX5_ASSERT(!(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(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+\t__rte_cache_aligned\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+\tMLX5_ASSERT(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+}\n+\n+/**\n+ * Parse Netlink message to retrieve the general family ID.\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_family_id_cb(struct nlmsghdr *nh, void *arg)\n+{\n+\n+\tstruct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);\n+\tstruct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +\n+\t\t\t\t\tNLMSG_ALIGN(sizeof(struct genlmsghdr)));\n+\n+\tfor (; nla->nla_len && nla < tail;\n+\t     nla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len))) {\n+\t\tif (nla->nla_type == CTRL_ATTR_FAMILY_ID) {\n+\t\t\t*(uint16_t *)arg = *(uint16_t *)(nla + 1);\n+\t\t\treturn 0;\n+\t\t}\n+\t}\n+\treturn -EINVAL;\n+}\n+\n+#define MLX5_NL_MAX_ATTR_SIZE 100\n+/**\n+ * Get generic netlink family ID.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] name\n+ *   The family name.\n+ *\n+ * @return\n+ *   ID >= 0 on success and @p enable is updated, a negative errno value\n+ *   otherwise and rte_errno is set.\n+ */\n+static int\n+mlx5_nl_generic_family_id_get(int nlsk_fd, const char *name)\n+{\n+\tstruct nlmsghdr *nlh;\n+\tstruct genlmsghdr *genl;\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint name_size = strlen(name) + 1;\n+\tint ret;\n+\tuint16_t id = -1;\n+\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) +\n+\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE)];\n+\n+\tmemset(buf, 0, sizeof(buf));\n+\tnlh = (struct nlmsghdr *)buf;\n+\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n+\tnlh->nlmsg_type = GENL_ID_CTRL;\n+\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n+\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n+\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n+\tgenl->cmd = CTRL_CMD_GETFAMILY;\n+\tgenl->version = 1;\n+\tnl_attr_put(nlh, CTRL_ATTR_FAMILY_NAME, name, name_size);\n+\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_family_id_cb, &id);\n+\tif (ret < 0) {\n+\t\tDRV_LOG(DEBUG, \"Failed to get Netlink %s family ID: %d.\", name,\n+\t\t\tret);\n+\t\treturn ret;\n+\t}\n+\tDRV_LOG(DEBUG, \"Netlink \\\"%s\\\" family ID is %u.\", name, id);\n+\treturn (int)id;\n+}\n+\n+/**\n+ * Get Devlink family ID.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ *\n+ * @return\n+ *   ID >= 0 on success and @p enable is updated, a negative errno value\n+ *   otherwise and rte_errno is set.\n+ */\n+\n+int\n+mlx5_nl_devlink_family_id_get(int nlsk_fd)\n+{\n+\treturn mlx5_nl_generic_family_id_get(nlsk_fd, DEVLINK_GENL_NAME);\n+}\n+\n+/**\n+ * Parse Netlink message to retrieve the ROCE enable status.\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_roce_cb(struct nlmsghdr *nh, void *arg)\n+{\n+\n+\tint ret = -EINVAL;\n+\tint *enable = arg;\n+\tstruct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);\n+\tstruct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +\n+\t\t\t\t\tNLMSG_ALIGN(sizeof(struct genlmsghdr)));\n+\n+\twhile (nla->nla_len && nla < tail) {\n+\t\tswitch (nla->nla_type) {\n+\t\t/* Expected nested attributes case. */\n+\t\tcase DEVLINK_ATTR_PARAM:\n+\t\tcase DEVLINK_ATTR_PARAM_VALUES_LIST:\n+\t\tcase DEVLINK_ATTR_PARAM_VALUE:\n+\t\t\tret = 0;\n+\t\t\tnla += 1;\n+\t\t\tbreak;\n+\t\tcase DEVLINK_ATTR_PARAM_VALUE_DATA:\n+\t\t\t*enable = 1;\n+\t\t\treturn 0;\n+\t\tdefault:\n+\t\t\tnla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len));\n+\t\t}\n+\t}\n+\t*enable = 0;\n+\treturn ret;\n+}\n+\n+/**\n+ * Get ROCE enable status through Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] family_id\n+ *   the Devlink family ID.\n+ * @param pci_addr\n+ *   The device PCI address.\n+ * @param[out] enable\n+ *   Where to store the enable status.\n+ *\n+ * @return\n+ *   0 on success and @p enable is updated, a negative errno value otherwise\n+ *   and rte_errno is set.\n+ */\n+int\n+mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr,\n+\t\t\tint *enable)\n+{\n+\tstruct nlmsghdr *nlh;\n+\tstruct genlmsghdr *genl;\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\tint cur_en = 0;\n+\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 4 +\n+\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 4];\n+\n+\tmemset(buf, 0, sizeof(buf));\n+\tnlh = (struct nlmsghdr *)buf;\n+\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n+\tnlh->nlmsg_type = family_id;\n+\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n+\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n+\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n+\tgenl->cmd = DEVLINK_CMD_PARAM_GET;\n+\tgenl->version = DEVLINK_GENL_VERSION;\n+\tnl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, \"pci\", 4);\n+\tnl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);\n+\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, \"enable_roce\", 12);\n+\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_roce_cb, &cur_en);\n+\tif (ret < 0) {\n+\t\tDRV_LOG(DEBUG, \"Failed to get ROCE enable on device %s: %d.\",\n+\t\t\tpci_addr, ret);\n+\t\treturn ret;\n+\t}\n+\t*enable = cur_en;\n+\tDRV_LOG(DEBUG, \"ROCE is %sabled for device \\\"%s\\\".\",\n+\t\tcur_en ? \"en\" : \"dis\", pci_addr);\n+\treturn ret;\n+}\n+\n+/**\n+ * Reload mlx5 device kernel driver through Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] family_id\n+ *   the Devlink family ID.\n+ * @param pci_addr\n+ *   The device PCI address.\n+ * @param[out] enable\n+ *   The enable status to set.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_driver_reload(int nlsk_fd, int family_id, const char *pci_addr)\n+{\n+\tstruct nlmsghdr *nlh;\n+\tstruct genlmsghdr *genl;\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 2 +\n+\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 2];\n+\n+\tmemset(buf, 0, sizeof(buf));\n+\tnlh = (struct nlmsghdr *)buf;\n+\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n+\tnlh->nlmsg_type = family_id;\n+\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n+\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n+\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n+\tgenl->cmd = DEVLINK_CMD_RELOAD;\n+\tgenl->version = DEVLINK_GENL_VERSION;\n+\tnl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, \"pci\", 4);\n+\tnl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);\n+\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n+\tif (ret < 0) {\n+\t\tDRV_LOG(DEBUG, \"Failed to reload %s device by Netlink - %d\",\n+\t\t\tpci_addr, ret);\n+\t\treturn ret;\n+\t}\n+\tDRV_LOG(DEBUG, \"Device \\\"%s\\\" was reloaded by Netlink successfully.\",\n+\t\tpci_addr);\n+\treturn 0;\n+}\n+\n+/**\n+ * Set ROCE enable status through Netlink.\n+ *\n+ * @param[in] nlsk_fd\n+ *   Netlink socket file descriptor.\n+ * @param[in] family_id\n+ *   the Devlink family ID.\n+ * @param pci_addr\n+ *   The device PCI address.\n+ * @param[out] enable\n+ *   The enable status to set.\n+ *\n+ * @return\n+ *   0 on success, a negative errno value otherwise and rte_errno is set.\n+ */\n+int\n+mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,\n+\t\t\tint enable)\n+{\n+\tstruct nlmsghdr *nlh;\n+\tstruct genlmsghdr *genl;\n+\tuint32_t sn = MLX5_NL_SN_GENERATE;\n+\tint ret;\n+\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n+\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 6 +\n+\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 6];\n+\tuint8_t cmode = DEVLINK_PARAM_CMODE_DRIVERINIT;\n+\tuint8_t ptype = NLA_FLAG;\n+;\n+\n+\tmemset(buf, 0, sizeof(buf));\n+\tnlh = (struct nlmsghdr *)buf;\n+\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n+\tnlh->nlmsg_type = family_id;\n+\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n+\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n+\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n+\tgenl->cmd = DEVLINK_CMD_PARAM_SET;\n+\tgenl->version = DEVLINK_GENL_VERSION;\n+\tnl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, \"pci\", 4);\n+\tnl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);\n+\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, \"enable_roce\", 12);\n+\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_CMODE, &cmode, sizeof(cmode));\n+\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_TYPE, &ptype, sizeof(ptype));\n+\tif (enable)\n+\t\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, NULL, 0);\n+\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n+\tif (ret < 0) {\n+\t\tDRV_LOG(DEBUG, \"Failed to %sable ROCE for device %s by Netlink:\"\n+\t\t\t\" %d.\", enable ? \"en\" : \"dis\", pci_addr, ret);\n+\t\treturn ret;\n+\t}\n+\tDRV_LOG(DEBUG, \"Device %s ROCE was %sabled by Netlink successfully.\",\n+\t\tpci_addr, enable ? \"en\" : \"dis\");\n+\t/* Now, need to reload the driver. */\n+\treturn mlx5_nl_driver_reload(nlsk_fd, family_id, pci_addr);\n+}\ndiff --git a/drivers/common/mlx5/linux/mlx5_nl.h b/drivers/common/mlx5/linux/mlx5_nl.h\nnew file mode 100644\nindex 0000000..53021e1\n--- /dev/null\n+++ b/drivers/common/mlx5/linux/mlx5_nl.h\n@@ -0,0 +1,79 @@\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+__rte_internal\n+int mlx5_nl_init(int protocol);\n+__rte_internal\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+__rte_internal\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+__rte_internal\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+__rte_internal\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+__rte_internal\n+int mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable);\n+__rte_internal\n+int mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable);\n+__rte_internal\n+unsigned int mlx5_nl_portnum(int nl, const char *name);\n+__rte_internal\n+unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);\n+__rte_internal\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+__rte_internal\n+int mlx5_nl_switch_info(int nl, unsigned int ifindex,\n+\t\t\tstruct mlx5_switch_info *info);\n+\n+__rte_internal\n+void mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,\n+\t\t\t      uint32_t ifindex);\n+__rte_internal\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+__rte_internal\n+int mlx5_nl_devlink_family_id_get(int nlsk_fd);\n+__rte_internal\n+int mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr,\n+\t\t\t    int *enable);\n+__rte_internal\n+int mlx5_nl_driver_reload(int nlsk_fd, int family_id, const char *pci_addr);\n+__rte_internal\n+int mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,\n+\t\t\t    int enable);\n+\n+#endif /* RTE_PMD_MLX5_NL_H_ */\ndiff --git a/drivers/common/mlx5/meson.build b/drivers/common/mlx5/meson.build\nindex 9806865..0a8980f 100644\n--- a/drivers/common/mlx5/meson.build\n+++ b/drivers/common/mlx5/meson.build\n@@ -13,7 +13,6 @@ deps += ['hash', 'pci', 'net', 'eal', 'kvargs']\n sources += files(\n \t'mlx5_devx_cmds.c',\n \t'mlx5_common.c',\n-\t'mlx5_nl.c',\n \t'mlx5_common_mp.c',\n \t'mlx5_common_mr.c',\n )\ndiff --git a/drivers/common/mlx5/mlx5_nl.c b/drivers/common/mlx5/mlx5_nl.c\ndeleted file mode 100644\nindex 1a1033a..0000000\n--- a/drivers/common/mlx5/mlx5_nl.c\n+++ /dev/null\n@@ -1,1721 +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 <linux/genetlink.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-\n-#include \"mlx5_nl.h\"\n-#include \"mlx5_common_utils.h\"\n-#ifdef HAVE_DEVLINK\n-#include <linux/devlink.h>\n-#endif\n-\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-/*\n- * Some Devlink defines may be missed in old kernel versions,\n- * adjust used defines.\n- */\n-#ifndef DEVLINK_GENL_NAME\n-#define DEVLINK_GENL_NAME \"devlink\"\n-#endif\n-#ifndef DEVLINK_GENL_VERSION\n-#define DEVLINK_GENL_VERSION 1\n-#endif\n-#ifndef DEVLINK_ATTR_BUS_NAME\n-#define DEVLINK_ATTR_BUS_NAME 1\n-#endif\n-#ifndef DEVLINK_ATTR_DEV_NAME\n-#define DEVLINK_ATTR_DEV_NAME 2\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM\n-#define DEVLINK_ATTR_PARAM 80\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM_NAME\n-#define DEVLINK_ATTR_PARAM_NAME 81\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM_TYPE\n-#define DEVLINK_ATTR_PARAM_TYPE 83\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM_VALUES_LIST\n-#define DEVLINK_ATTR_PARAM_VALUES_LIST 84\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM_VALUE\n-#define DEVLINK_ATTR_PARAM_VALUE 85\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM_VALUE_DATA\n-#define DEVLINK_ATTR_PARAM_VALUE_DATA 86\n-#endif\n-#ifndef DEVLINK_ATTR_PARAM_VALUE_CMODE\n-#define DEVLINK_ATTR_PARAM_VALUE_CMODE 87\n-#endif\n-#ifndef DEVLINK_PARAM_CMODE_DRIVERINIT\n-#define DEVLINK_PARAM_CMODE_DRIVERINIT 1\n-#endif\n-#ifndef DEVLINK_CMD_RELOAD\n-#define DEVLINK_CMD_RELOAD 37\n-#endif\n-#ifndef DEVLINK_CMD_PARAM_GET\n-#define DEVLINK_CMD_PARAM_GET 38\n-#endif\n-#ifndef DEVLINK_CMD_PARAM_SET\n-#define DEVLINK_CMD_PARAM_SET 39\n-#endif\n-#ifndef NLA_FLAG\n-#define NLA_FLAG 6\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-\tvoid *buf = malloc(MLX5_RECV_BUF_SIZE);\n-\tstruct iovec iov = {\n-\t\t.iov_base = buf,\n-\t\t.iov_len = MLX5_RECV_BUF_SIZE,\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-\tif (!buf) {\n-\t\trte_errno = ENOMEM;\n-\t\treturn -rte_errno;\n-\t}\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\tret = -rte_errno;\n-\t\t\t\tgoto exit;\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\tret = -rte_errno;\n-\t\t\t\t\tgoto exit;\n-\t\t\t\t}\n-\t\t\t\t/* Ack message. */\n-\t\t\t\tret = 0;\n-\t\t\t\tgoto exit;\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\tret =  0;\n-\t\t\t\t\tgoto exit;\n-\t\t\t\t}\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\tgoto exit;\n-\t\t\t}\n-\t\t}\n-\t} while (multipart);\n-exit:\n-\tfree(buf);\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-#ifdef RTE_LIBRTE_MLX5_DEBUG\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\tMLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);\n-\t\tif (index >= MLX5_MAX_MAC_ADDRESSES)\n-\t\t\treturn -EINVAL;\n-\n-\t\tBITFIELD_SET(mac_own, index);\n-\t}\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-\tMLX5_ASSERT(index < MLX5_MAX_MAC_ADDRESSES);\n-\tif (index >= MLX5_MAX_MAC_ADDRESSES)\n-\t\treturn -EINVAL;\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-\tif (n <= 0 || n >= MLX5_MAX_MAC_ADDRESSES)\n-\t\treturn;\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-\tMLX5_ASSERT(!(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-\tMLX5_ASSERT(!(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(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-\t__rte_cache_aligned\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-\tMLX5_ASSERT(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-}\n-\n-/**\n- * Parse Netlink message to retrieve the general family ID.\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_family_id_cb(struct nlmsghdr *nh, void *arg)\n-{\n-\n-\tstruct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);\n-\tstruct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +\n-\t\t\t\t\tNLMSG_ALIGN(sizeof(struct genlmsghdr)));\n-\n-\tfor (; nla->nla_len && nla < tail;\n-\t     nla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len))) {\n-\t\tif (nla->nla_type == CTRL_ATTR_FAMILY_ID) {\n-\t\t\t*(uint16_t *)arg = *(uint16_t *)(nla + 1);\n-\t\t\treturn 0;\n-\t\t}\n-\t}\n-\treturn -EINVAL;\n-}\n-\n-#define MLX5_NL_MAX_ATTR_SIZE 100\n-/**\n- * Get generic netlink family ID.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] name\n- *   The family name.\n- *\n- * @return\n- *   ID >= 0 on success and @p enable is updated, a negative errno value\n- *   otherwise and rte_errno is set.\n- */\n-static int\n-mlx5_nl_generic_family_id_get(int nlsk_fd, const char *name)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct genlmsghdr *genl;\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint name_size = strlen(name) + 1;\n-\tint ret;\n-\tuint16_t id = -1;\n-\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) +\n-\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE)];\n-\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = (struct nlmsghdr *)buf;\n-\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n-\tnlh->nlmsg_type = GENL_ID_CTRL;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n-\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n-\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n-\tgenl->cmd = CTRL_CMD_GETFAMILY;\n-\tgenl->version = 1;\n-\tnl_attr_put(nlh, CTRL_ATTR_FAMILY_NAME, name, name_size);\n-\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n-\tif (ret >= 0)\n-\t\tret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_family_id_cb, &id);\n-\tif (ret < 0) {\n-\t\tDRV_LOG(DEBUG, \"Failed to get Netlink %s family ID: %d.\", name,\n-\t\t\tret);\n-\t\treturn ret;\n-\t}\n-\tDRV_LOG(DEBUG, \"Netlink \\\"%s\\\" family ID is %u.\", name, id);\n-\treturn (int)id;\n-}\n-\n-/**\n- * Get Devlink family ID.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- *\n- * @return\n- *   ID >= 0 on success and @p enable is updated, a negative errno value\n- *   otherwise and rte_errno is set.\n- */\n-\n-int\n-mlx5_nl_devlink_family_id_get(int nlsk_fd)\n-{\n-\treturn mlx5_nl_generic_family_id_get(nlsk_fd, DEVLINK_GENL_NAME);\n-}\n-\n-/**\n- * Parse Netlink message to retrieve the ROCE enable status.\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_roce_cb(struct nlmsghdr *nh, void *arg)\n-{\n-\n-\tint ret = -EINVAL;\n-\tint *enable = arg;\n-\tstruct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);\n-\tstruct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +\n-\t\t\t\t\tNLMSG_ALIGN(sizeof(struct genlmsghdr)));\n-\n-\twhile (nla->nla_len && nla < tail) {\n-\t\tswitch (nla->nla_type) {\n-\t\t/* Expected nested attributes case. */\n-\t\tcase DEVLINK_ATTR_PARAM:\n-\t\tcase DEVLINK_ATTR_PARAM_VALUES_LIST:\n-\t\tcase DEVLINK_ATTR_PARAM_VALUE:\n-\t\t\tret = 0;\n-\t\t\tnla += 1;\n-\t\t\tbreak;\n-\t\tcase DEVLINK_ATTR_PARAM_VALUE_DATA:\n-\t\t\t*enable = 1;\n-\t\t\treturn 0;\n-\t\tdefault:\n-\t\t\tnla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len));\n-\t\t}\n-\t}\n-\t*enable = 0;\n-\treturn ret;\n-}\n-\n-/**\n- * Get ROCE enable status through Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] family_id\n- *   the Devlink family ID.\n- * @param pci_addr\n- *   The device PCI address.\n- * @param[out] enable\n- *   Where to store the enable status.\n- *\n- * @return\n- *   0 on success and @p enable is updated, a negative errno value otherwise\n- *   and rte_errno is set.\n- */\n-int\n-mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr,\n-\t\t\tint *enable)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct genlmsghdr *genl;\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\tint cur_en = 0;\n-\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 4 +\n-\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 4];\n-\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = (struct nlmsghdr *)buf;\n-\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n-\tnlh->nlmsg_type = family_id;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n-\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n-\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n-\tgenl->cmd = DEVLINK_CMD_PARAM_GET;\n-\tgenl->version = DEVLINK_GENL_VERSION;\n-\tnl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, \"pci\", 4);\n-\tnl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);\n-\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, \"enable_roce\", 12);\n-\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n-\tif (ret >= 0)\n-\t\tret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_roce_cb, &cur_en);\n-\tif (ret < 0) {\n-\t\tDRV_LOG(DEBUG, \"Failed to get ROCE enable on device %s: %d.\",\n-\t\t\tpci_addr, ret);\n-\t\treturn ret;\n-\t}\n-\t*enable = cur_en;\n-\tDRV_LOG(DEBUG, \"ROCE is %sabled for device \\\"%s\\\".\",\n-\t\tcur_en ? \"en\" : \"dis\", pci_addr);\n-\treturn ret;\n-}\n-\n-/**\n- * Reload mlx5 device kernel driver through Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] family_id\n- *   the Devlink family ID.\n- * @param pci_addr\n- *   The device PCI address.\n- * @param[out] enable\n- *   The enable status to set.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_driver_reload(int nlsk_fd, int family_id, const char *pci_addr)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct genlmsghdr *genl;\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 2 +\n-\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 2];\n-\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = (struct nlmsghdr *)buf;\n-\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n-\tnlh->nlmsg_type = family_id;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n-\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n-\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n-\tgenl->cmd = DEVLINK_CMD_RELOAD;\n-\tgenl->version = DEVLINK_GENL_VERSION;\n-\tnl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, \"pci\", 4);\n-\tnl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);\n-\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n-\tif (ret >= 0)\n-\t\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n-\tif (ret < 0) {\n-\t\tDRV_LOG(DEBUG, \"Failed to reload %s device by Netlink - %d\",\n-\t\t\tpci_addr, ret);\n-\t\treturn ret;\n-\t}\n-\tDRV_LOG(DEBUG, \"Device \\\"%s\\\" was reloaded by Netlink successfully.\",\n-\t\tpci_addr);\n-\treturn 0;\n-}\n-\n-/**\n- * Set ROCE enable status through Netlink.\n- *\n- * @param[in] nlsk_fd\n- *   Netlink socket file descriptor.\n- * @param[in] family_id\n- *   the Devlink family ID.\n- * @param pci_addr\n- *   The device PCI address.\n- * @param[out] enable\n- *   The enable status to set.\n- *\n- * @return\n- *   0 on success, a negative errno value otherwise and rte_errno is set.\n- */\n-int\n-mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,\n-\t\t\tint enable)\n-{\n-\tstruct nlmsghdr *nlh;\n-\tstruct genlmsghdr *genl;\n-\tuint32_t sn = MLX5_NL_SN_GENERATE;\n-\tint ret;\n-\tuint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +\n-\t\t    NLMSG_ALIGN(sizeof(struct nlattr)) * 6 +\n-\t\t    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 6];\n-\tuint8_t cmode = DEVLINK_PARAM_CMODE_DRIVERINIT;\n-\tuint8_t ptype = NLA_FLAG;\n-;\n-\n-\tmemset(buf, 0, sizeof(buf));\n-\tnlh = (struct nlmsghdr *)buf;\n-\tnlh->nlmsg_len = sizeof(struct nlmsghdr);\n-\tnlh->nlmsg_type = family_id;\n-\tnlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;\n-\tgenl = (struct genlmsghdr *)nl_msg_tail(nlh);\n-\tnlh->nlmsg_len += sizeof(struct genlmsghdr);\n-\tgenl->cmd = DEVLINK_CMD_PARAM_SET;\n-\tgenl->version = DEVLINK_GENL_VERSION;\n-\tnl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, \"pci\", 4);\n-\tnl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);\n-\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, \"enable_roce\", 12);\n-\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_CMODE, &cmode, sizeof(cmode));\n-\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_TYPE, &ptype, sizeof(ptype));\n-\tif (enable)\n-\t\tnl_attr_put(nlh, DEVLINK_ATTR_PARAM_VALUE_DATA, NULL, 0);\n-\tret = mlx5_nl_send(nlsk_fd, nlh, sn);\n-\tif (ret >= 0)\n-\t\tret = mlx5_nl_recv(nlsk_fd, sn, NULL, NULL);\n-\tif (ret < 0) {\n-\t\tDRV_LOG(DEBUG, \"Failed to %sable ROCE for device %s by Netlink:\"\n-\t\t\t\" %d.\", enable ? \"en\" : \"dis\", pci_addr, ret);\n-\t\treturn ret;\n-\t}\n-\tDRV_LOG(DEBUG, \"Device %s ROCE was %sabled by Netlink successfully.\",\n-\t\tpci_addr, enable ? \"en\" : \"dis\");\n-\t/* Now, need to reload the driver. */\n-\treturn mlx5_nl_driver_reload(nlsk_fd, family_id, pci_addr);\n-}\ndiff --git a/drivers/common/mlx5/mlx5_nl.h b/drivers/common/mlx5/mlx5_nl.h\ndeleted file mode 100644\nindex 53021e1..0000000\n--- a/drivers/common/mlx5/mlx5_nl.h\n+++ /dev/null\n@@ -1,79 +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-#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-__rte_internal\n-int mlx5_nl_init(int protocol);\n-__rte_internal\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-__rte_internal\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-__rte_internal\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-__rte_internal\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-__rte_internal\n-int mlx5_nl_promisc(int nlsk_fd, unsigned int iface_idx, int enable);\n-__rte_internal\n-int mlx5_nl_allmulti(int nlsk_fd, unsigned int iface_idx, int enable);\n-__rte_internal\n-unsigned int mlx5_nl_portnum(int nl, const char *name);\n-__rte_internal\n-unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);\n-__rte_internal\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-__rte_internal\n-int mlx5_nl_switch_info(int nl, unsigned int ifindex,\n-\t\t\tstruct mlx5_switch_info *info);\n-\n-__rte_internal\n-void mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,\n-\t\t\t      uint32_t ifindex);\n-__rte_internal\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-__rte_internal\n-int mlx5_nl_devlink_family_id_get(int nlsk_fd);\n-__rte_internal\n-int mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr,\n-\t\t\t    int *enable);\n-__rte_internal\n-int mlx5_nl_driver_reload(int nlsk_fd, int family_id, const char *pci_addr);\n-__rte_internal\n-int mlx5_nl_enable_roce_set(int nlsk_fd, int family_id, const char *pci_addr,\n-\t\t\t    int enable);\n-\n-#endif /* RTE_PMD_MLX5_NL_H_ */\n",
    "prefixes": [
        "v2",
        "2/3"
    ]
}