get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 42734,
    "url": "http://patches.dpdk.org/api/patches/42734/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20180710155743.14448-7-adrien.mazarguil@6wind.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20180710155743.14448-7-adrien.mazarguil@6wind.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180710155743.14448-7-adrien.mazarguil@6wind.com",
    "date": "2018-07-10T16:04:52",
    "name": "[v5,06/10] net/mlx5: add port representor awareness",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "0587d280395aba7fc42345127d9dbee282b0d10f",
    "submitter": {
        "id": 165,
        "url": "http://patches.dpdk.org/api/people/165/?format=api",
        "name": "Adrien Mazarguil",
        "email": "adrien.mazarguil@6wind.com"
    },
    "delegate": {
        "id": 6624,
        "url": "http://patches.dpdk.org/api/users/6624/?format=api",
        "username": "shahafs",
        "first_name": "Shahaf",
        "last_name": "Shuler",
        "email": "shahafs@mellanox.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20180710155743.14448-7-adrien.mazarguil@6wind.com/mbox/",
    "series": [
        {
            "id": 501,
            "url": "http://patches.dpdk.org/api/series/501/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=501",
            "date": "2018-07-10T16:04:39",
            "name": "net/mlx5: add port representor support",
            "version": 5,
            "mbox": "http://patches.dpdk.org/series/501/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/42734/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/42734/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 916531B459;\n\tTue, 10 Jul 2018 18:05:14 +0200 (CEST)",
            "from mail-wm0-f68.google.com (mail-wm0-f68.google.com\n\t[74.125.82.68]) by dpdk.org (Postfix) with ESMTP id 710741B450\n\tfor <dev@dpdk.org>; Tue, 10 Jul 2018 18:05:09 +0200 (CEST)",
            "by mail-wm0-f68.google.com with SMTP id n17-v6so24952435wmh.2\n\tfor <dev@dpdk.org>; Tue, 10 Jul 2018 09:05:09 -0700 (PDT)",
            "from 6wind.com (host.78.145.23.62.rev.coltfrance.com.\n\t[62.23.145.78]) by smtp.gmail.com with ESMTPSA id\n\tb11-v6sm7507715wrv.82.2018.07.10.09.05.08\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tTue, 10 Jul 2018 09:05:08 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=6wind-com.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:in-reply-to;\n\tbh=kJ968xsTRYu7vz89QNcs7eJmdg27NpUefHP1YnfREhg=;\n\tb=BPdTSn3jtuwkU1zJMykXYZP0p/n38JsT50Ou7mr+se/USMpZX01BFmJkXR6TDddWmW\n\tRpxiGmQiEll4bQeprqJJdAvKxO3Ps19oyLi79K9+6MJ2O2qn4FB3us1lX5BxVmLYXG+c\n\txLtfWCzLiombzZoRC9DmZYycTdLzMpeov8uX/0CCJEes9Lc8uWl7uWsD6eJ++AOo8hYR\n\tWHjnghuid7IzGgAr73PoIovVSDTBBujPgMYQpYXlkPjy6Gjt/uCuTdY8uHx7h5PUHjV9\n\t7K+QmfLwoztGvjGH4DHkkbALCuAdFHRCsJi6PqiWD9pRwEflNGL8HuFvEeoOXO94B09Q\n\t6zrw==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:in-reply-to;\n\tbh=kJ968xsTRYu7vz89QNcs7eJmdg27NpUefHP1YnfREhg=;\n\tb=PIx9VGwgL9/RlgvJLi7sEFPVqw2h8A0DkUx3G74yykvL5F+tPJyKKnYlBctCVPkD3y\n\t6fqXnlG0HVuGPozuMH0DmyaA05gQVuHnbeIhq2TcpGy+nwi63CD0ZnWbwXv/oicINzcS\n\tCdQBs48t68kML58S2vZ92F0Hpa3Ptvu22XRcyeumYmLsUt20wvakW46T7vm+s8NWVKsw\n\tICWyYZq6Pc22ZZG6oh9idtOxLA7uRD9DI8GTfsFDVnsvpO6rlHtTlWbGEcUEqfSh5IWZ\n\tMDpwGP5IkQgQyDbxVaXxI6+Uvssph9609XlWgbjYXGB49OugXLmIZ6GcZIaYbKL72WDR\n\tk6kw==",
        "X-Gm-Message-State": "APt69E2IH2Ct3gWMi7ea6GdcFRR6mh6MY9cEpBNVnf72ahQ9ae4VV+M9\n\t8oI4ModHuv5cA1T8O6ao3woutElp",
        "X-Google-Smtp-Source": "AAOMgpf5mJ0q9xJWqe3fvI964sFESMiTjk77Rm4YwwbDIawN5Ur/L3nVYx9s7ZIsgVZkxaSa239CaQ==",
        "X-Received": "by 2002:a1c:e5cd:: with SMTP id\n\tc196-v6mr15131749wmh.101.1531238708855; \n\tTue, 10 Jul 2018 09:05:08 -0700 (PDT)",
        "Date": "Tue, 10 Jul 2018 18:04:52 +0200",
        "From": "Adrien Mazarguil <adrien.mazarguil@6wind.com>",
        "To": "Shahaf Shuler <shahafs@mellanox.com>",
        "Cc": "dev@dpdk.org, Xueming Li <xuemingl@mellanox.com>",
        "Message-ID": "<20180710155743.14448-7-adrien.mazarguil@6wind.com>",
        "References": "<20180705083934.5535-1-adrien.mazarguil@6wind.com>\n\t<20180710155743.14448-1-adrien.mazarguil@6wind.com>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=us-ascii",
        "Content-Disposition": "inline",
        "In-Reply-To": "<20180710155743.14448-1-adrien.mazarguil@6wind.com>",
        "X-Mailer": "git-send-email 2.11.0",
        "Subject": "[dpdk-dev] [PATCH v5 06/10] net/mlx5: add port representor awareness",
        "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\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "The current PCI probing method is not aware of Verbs port representors,\nwhich appear as standard Verbs devices bound to the same PCI address and\ncannot be distinguished.\n\nProblem is that more often than not, the wrong Verbs device is used,\nresulting in unexpected traffic.\n\nThis patch makes the driver discard representors to only use the master\ndevice. If unable to identify it (e.g. kernel drivers not recent enough),\neither:\n\n- There is only one matching device which isn't identified as a\n  representor, in that case use it.\n- Otherwise log an error and do not probe the device.\n\n(Patch based on prior work from Yuanhan Liu)\n\nSigned-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>\nReviewed-by: Xueming Li <xuemingl@mellanox.com>\nCc: Xueming Li <xuemingl@mellanox.com>\n--\nv5 changes:\n\n- Fixed linux/rdma_netlink.h -> rdma/rdma_netlink.h in Makefile.\n- Added automatic detection for RDMA_NL_NLDEV, IFLA_PHYS_SWITCH_ID and\n  IFLA_PHYS_PORT_NAME to allow compilation on systems without those.\n\nv3 changes:\n\n- Replaced all heuristics (including mlx5_cmp_ibv_name()) with Netlink\n  queries to associate IB devices with network interfaces.\n- Reworded commit log.\n\nv2 changes:\n\n- Fixed digit detection in mlx5_cmp_ibv_name() so that \"foo1\" and \"foo10\"\n  are compared on the integer conversion of \"1\" against \"10\" instead of \"\"\n  and \"0\".\n---\n drivers/net/mlx5/Makefile  |  45 ++++++\n drivers/net/mlx5/mlx5.c    | 109 ++++++++++++--\n drivers/net/mlx5/mlx5.h    |  16 ++-\n drivers/net/mlx5/mlx5_nl.c | 308 ++++++++++++++++++++++++++++++++++++++--\n 4 files changed, 454 insertions(+), 24 deletions(-)",
    "diff": "diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile\nindex 955861a41..9e274964b 100644\n--- a/drivers/net/mlx5/Makefile\n+++ b/drivers/net/mlx5/Makefile\n@@ -152,6 +152,51 @@ mlx5_autoconf.h.new: $(RTE_SDK)/buildtools/auto-config-h.sh\n \t\tinfiniband/verbs.h \\\n \t\tenum IBV_FLOW_SPEC_ACTION_COUNT \\\n \t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NL_NLDEV \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NL_NLDEV \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NLDEV_CMD_GET \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NLDEV_CMD_GET \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NLDEV_CMD_PORT_GET \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NLDEV_CMD_PORT_GET \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NLDEV_ATTR_DEV_INDEX \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NLDEV_ATTR_DEV_INDEX \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NLDEV_ATTR_DEV_NAME \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NLDEV_ATTR_DEV_NAME \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NLDEV_ATTR_PORT_INDEX \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NLDEV_ATTR_PORT_INDEX \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_RDMA_NLDEV_ATTR_NDEV_INDEX \\\n+\t\trdma/rdma_netlink.h \\\n+\t\tenum RDMA_NLDEV_ATTR_NDEV_INDEX \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_IFLA_PHYS_SWITCH_ID \\\n+\t\tlinux/if_link.h \\\n+\t\tenum IFLA_PHYS_SWITCH_ID \\\n+\t\t$(AUTOCONF_OUTPUT)\n+\t$Q sh -- '$<' '$@' \\\n+\t\tHAVE_IFLA_PHYS_PORT_NAME \\\n+\t\tlinux/if_link.h \\\n+\t\tenum IFLA_PHYS_PORT_NAME \\\n+\t\t$(AUTOCONF_OUTPUT)\n \n # Create mlx5_autoconf.h or update it in case it differs from the new one.\n \ndiff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c\nindex 1054bf6d0..d06ba9886 100644\n--- a/drivers/net/mlx5/mlx5.c\n+++ b/drivers/net/mlx5/mlx5.c\n@@ -13,6 +13,7 @@\n #include <errno.h>\n #include <net/if.h>\n #include <sys/mman.h>\n+#include <linux/netlink.h>\n #include <linux/rtnetlink.h>\n \n /* Verbs header. */\n@@ -274,8 +275,10 @@ mlx5_dev_close(struct rte_eth_dev *dev)\n \t\tmlx5_socket_uninit(dev);\n \tif (priv->config.vf)\n \t\tmlx5_nl_mac_addr_flush(dev);\n-\tif (priv->nl_socket >= 0)\n-\t\tclose(priv->nl_socket);\n+\tif (priv->nl_socket_route >= 0)\n+\t\tclose(priv->nl_socket_route);\n+\tif (priv->nl_socket_rdma >= 0)\n+\t\tclose(priv->nl_socket_rdma);\n \tret = mlx5_hrxq_ibv_verify(dev);\n \tif (ret)\n \t\tDRV_LOG(WARNING, \"port %u some hash Rx queue still remain\",\n@@ -876,6 +879,10 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \tpriv->device_attr = attr;\n \tpriv->pd = pd;\n \tpriv->mtu = ETHER_MTU;\n+\t/* Some internal functions rely on Netlink sockets, open them now. */\n+\tpriv->nl_socket_rdma = mlx5_nl_init(0, NETLINK_RDMA);\n+\tpriv->nl_socket_route =\tmlx5_nl_init(RTMGRP_LINK, NETLINK_ROUTE);\n+\tpriv->nl_sn = 0;\n \terr = mlx5_args(&config, dpdk_dev->devargs);\n \tif (err) {\n \t\terr = rte_errno;\n@@ -1010,14 +1017,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \teth_dev->dev_ops = &mlx5_dev_ops;\n \t/* Register MAC address. */\n \tclaim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0));\n-\tpriv->nl_socket = -1;\n-\tpriv->nl_sn = 0;\n-\tif (vf && config.vf_nl_en) {\n-\t\tpriv->nl_socket = mlx5_nl_init(RTMGRP_LINK);\n-\t\tif (priv->nl_socket < 0)\n-\t\t\tpriv->nl_socket = -1;\n+\tif (vf && config.vf_nl_en)\n \t\tmlx5_nl_mac_addr_sync(eth_dev);\n-\t}\n \tTAILQ_INIT(&priv->flows);\n \tTAILQ_INIT(&priv->ctrl_flows);\n \t/* Hint libmlx5 to use PMD allocator for data plane resources */\n@@ -1078,8 +1079,13 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,\n \trte_rwlock_write_unlock(&mlx5_shared_data->mem_event_rwlock);\n \treturn eth_dev;\n error:\n-\tif (priv)\n+\tif (priv) {\n+\t\tif (priv->nl_socket_route >= 0)\n+\t\t\tclose(priv->nl_socket_route);\n+\t\tif (priv->nl_socket_rdma >= 0)\n+\t\t\tclose(priv->nl_socket_rdma);\n \t\trte_free(priv);\n+\t}\n \tif (pd)\n \t\tclaim_zero(mlx5_glue->dealloc_pd(pd));\n \tif (eth_dev)\n@@ -1110,6 +1116,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n {\n \tstruct ibv_device **ibv_list;\n \tstruct rte_eth_dev *eth_dev = NULL;\n+\tunsigned int n = 0;\n \tint vf;\n \tint ret;\n \n@@ -1121,6 +1128,9 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \t\tDRV_LOG(ERR, \"cannot list devices, is ib_uverbs loaded?\");\n \t\treturn -rte_errno;\n \t}\n+\n+\tstruct ibv_device *ibv_match[ret + 1];\n+\n \twhile (ret-- > 0) {\n \t\tstruct rte_pci_addr pci_addr;\n \n@@ -1132,10 +1142,81 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \t\t    pci_dev->addr.devid != pci_addr.devid ||\n \t\t    pci_dev->addr.function != pci_addr.function)\n \t\t\tcontinue;\n-\t\tDRV_LOG(INFO, \"PCI information matches, using device \\\"%s\\\"\",\n+\t\tDRV_LOG(INFO, \"PCI information matches for device \\\"%s\\\"\",\n \t\t\tibv_list[ret]->name);\n+\t\tibv_match[n++] = ibv_list[ret];\n+\t}\n+\tibv_match[n] = NULL;\n+\n+\tunsigned int ifindex[n];\n+\tstruct mlx5_switch_info info[n];\n+\tint nl_route = n ? mlx5_nl_init(0, NETLINK_ROUTE) : -1;\n+\tint nl_rdma = n ? mlx5_nl_init(0, NETLINK_RDMA) : -1;\n+\tunsigned int i;\n+\n+\t/*\n+\t * The existence of several matching entries (n > 1) means port\n+\t * representors have been instantiated. No existing Verbs call nor\n+\t * /sys entries can tell them apart, this can only be done through\n+\t * Netlink calls assuming kernel drivers are recent enough to\n+\t * support them.\n+\t *\n+\t * In the event of identification failure through Netlink, either:\n+\t *\n+\t * 1. No device matches (n == 0), complain and bail out.\n+\t * 2. A single IB device matches (n == 1) and is not a representor,\n+\t *    assume no switch support.\n+\t * 3. Otherwise no safe assumptions can be made; complain louder and\n+\t *    bail out.\n+\t */\n+\tfor (i = 0; i != n; ++i) {\n+\t\tif (nl_rdma < 0)\n+\t\t\tifindex[i] = 0;\n+\t\telse\n+\t\t\tifindex[i] = mlx5_nl_ifindex(nl_rdma,\n+\t\t\t\t\t\t     ibv_match[i]->name);\n+\t\tif (nl_route < 0 ||\n+\t\t    !ifindex[i] ||\n+\t\t    mlx5_nl_switch_info(nl_route, ifindex[i], &info[i])) {\n+\t\t\tifindex[i] = 0;\n+\t\t\tmemset(&info[i], 0, sizeof(info[i]));\n+\t\t\tcontinue;\n+\t\t}\n+\t}\n+\tif (nl_rdma >= 0)\n+\t\tclose(nl_rdma);\n+\tif (nl_route >= 0)\n+\t\tclose(nl_route);\n+\t/* Look for master device. */\n+\tfor (i = 0; i != n; ++i) {\n+\t\tif (!info[i].master)\n+\t\t\tcontinue;\n+\t\t/* Make it the first entry. */\n+\t\tif (i == 0)\n+\t\t\tbreak;\n+\t\tibv_match[n] = ibv_match[0];\n+\t\tibv_match[0] = ibv_match[i];\n+\t\tibv_match[n] = NULL;\n \t\tbreak;\n \t}\n+\tif (n && i == n) {\n+\t\tif (n == 1 && !info[0].representor) {\n+\t\t\t/* Case #2. */\n+\t\t\tDRV_LOG(INFO, \"no switch support detected\");\n+\t\t} else if (n == 1) {\n+\t\t\t/* Case #3. */\n+\t\t\tDRV_LOG(ERR,\n+\t\t\t\t\"device looks like a port representor, this is\"\n+\t\t\t\t\" not supported yet\");\n+\t\t\tn = 0;\n+\t\t} else {\n+\t\t\t/* Case #3. */\n+\t\t\tDRV_LOG(ERR,\n+\t\t\t\t\"unable to tell which of the matching devices\"\n+\t\t\t\t\" is the master (lack of kernel support?)\");\n+\t\t\tn = 0;\n+\t\t}\n+\t}\n \tswitch (pci_dev->id.device_id) {\n \tcase PCI_DEVICE_ID_MELLANOX_CONNECTX4VF:\n \tcase PCI_DEVICE_ID_MELLANOX_CONNECTX4LXVF:\n@@ -1146,10 +1227,10 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,\n \tdefault:\n \t\tvf = 0;\n \t}\n-\tif (ret >= 0)\n-\t\teth_dev = mlx5_dev_spawn(&pci_dev->device, ibv_list[ret], vf);\n+\tif (n)\n+\t\teth_dev = mlx5_dev_spawn(&pci_dev->device, ibv_match[0], vf);\n \tmlx5_glue->free_device_list(ibv_list);\n-\tif (!ret) {\n+\tif (!n) {\n \t\tDRV_LOG(WARNING,\n \t\t\t\"no Verbs device matches PCI device \" PCI_PRI_FMT \",\"\n \t\t\t\" are kernel drivers loaded?\",\ndiff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h\nindex f55ff4a21..704046270 100644\n--- a/drivers/net/mlx5/mlx5.h\n+++ b/drivers/net/mlx5/mlx5.h\n@@ -53,6 +53,14 @@ enum {\n \tPCI_DEVICE_ID_MELLANOX_CONNECTX5BF = 0xa2d2,\n };\n \n+/** Switch information returned by mlx5_nl_switch_info(). */\n+struct mlx5_switch_info {\n+\tuint32_t master:1; /**< Master device. */\n+\tuint32_t representor:1; /**< Representor device. */\n+\tint32_t port_name; /**< Representor port name. */\n+\tuint64_t switch_id; /**< Switch identifier. */\n+};\n+\n LIST_HEAD(mlx5_dev_list, priv);\n \n /* Shared memory between primary and secondary processes. */\n@@ -195,7 +203,8 @@ struct priv {\n \tstruct mlx5_dev_config config; /* Device configuration. */\n \tstruct mlx5_verbs_alloc_ctx verbs_alloc_ctx;\n \t/* Context for Verbs allocator. */\n-\tint nl_socket; /* Netlink socket. */\n+\tint nl_socket_rdma; /* Netlink socket (NETLINK_RDMA). */\n+\tint nl_socket_route; /* Netlink socket (NETLINK_ROUTE). */\n \tuint32_t nl_sn; /* Netlink message sequence number. */\n };\n \n@@ -342,7 +351,7 @@ int mlx5_socket_connect(struct rte_eth_dev *priv);\n \n /* mlx5_nl.c */\n \n-int mlx5_nl_init(uint32_t nlgroups);\n+int mlx5_nl_init(uint32_t nlgroups, int protocol);\n int mlx5_nl_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac,\n \t\t\t uint32_t index);\n int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct ether_addr *mac,\n@@ -351,5 +360,8 @@ void mlx5_nl_mac_addr_sync(struct rte_eth_dev *dev);\n void mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev);\n int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);\n int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);\n+unsigned int mlx5_nl_ifindex(int nl, const char *name);\n+int mlx5_nl_switch_info(int nl, unsigned int ifindex,\n+\t\t\tstruct mlx5_switch_info *info);\n \n #endif /* RTE_PMD_MLX5_H_ */\ndiff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c\nindex dca85835a..008cd2c31 100644\n--- a/drivers/net/mlx5/mlx5_nl.c\n+++ b/drivers/net/mlx5/mlx5_nl.c\n@@ -3,10 +3,21 @@\n  * Copyright 2018 Mellanox Technologies, Ltd\n  */\n \n+#include <errno.h>\n+#include <linux/if_link.h>\n #include <linux/netlink.h>\n #include <linux/rtnetlink.h>\n+#include <net/if.h>\n+#include <rdma/rdma_netlink.h>\n+#include <stdbool.h>\n+#include <stdint.h>\n+#include <stdlib.h>\n+#include <string.h>\n+#include <sys/socket.h>\n #include <unistd.h>\n \n+#include <rte_errno.h>\n+\n #include \"mlx5.h\"\n #include \"mlx5_utils.h\"\n \n@@ -27,6 +38,40 @@\n \t((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))\n #endif\n \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_PHYS_SWITCH_ID\n+#define IFLA_PHYS_SWITCH_ID 36\n+#endif\n+#ifndef HAVE_IFLA_PHYS_PORT_NAME\n+#define IFLA_PHYS_PORT_NAME 38\n+#endif\n+\n /* Add/remove MAC address through Netlink */\n struct mlx5_nl_mac_addr {\n \tstruct ether_addr (*mac)[];\n@@ -34,18 +79,27 @@ struct mlx5_nl_mac_addr {\n \tint mac_n; /**< Number of addresses in the array. */\n };\n \n+/** Data structure used by mlx5_nl_ifindex_cb(). */\n+struct mlx5_nl_ifindex_data {\n+\tconst char *name; /**< IB device name (in). */\n+\tuint32_t ibindex; /**< IB device index (out). */\n+\tuint32_t ifindex; /**< Network interface index (out). */\n+};\n+\n /**\n  * Opens a Netlink socket.\n  *\n  * @param nl_groups\n  *   Netlink group value (e.g. RTMGRP_LINK).\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(uint32_t nl_groups)\n+mlx5_nl_init(uint32_t nl_groups, int protocol)\n {\n \tint fd;\n \tint sndbuf_size = MLX5_SEND_BUF_SIZE;\n@@ -56,7 +110,7 @@ mlx5_nl_init(uint32_t nl_groups)\n \t};\n \tint ret;\n \n-\tfd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);\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@@ -334,9 +388,9 @@ mlx5_nl_mac_addr_list(struct rte_eth_dev *dev, struct ether_addr (*mac)[],\n \tint ret;\n \tuint32_t sn = priv->nl_sn++;\n \n-\tif (priv->nl_socket == -1)\n+\tif (priv->nl_socket_route == -1)\n \t\treturn 0;\n-\tfd = priv->nl_socket;\n+\tfd = priv->nl_socket_route;\n \tret = mlx5_nl_request(fd, &req.hdr, sn, &req.ifm,\n \t\t\t      sizeof(struct ifinfomsg));\n \tif (ret < 0)\n@@ -398,9 +452,9 @@ mlx5_nl_mac_addr_modify(struct rte_eth_dev *dev, struct ether_addr *mac,\n \tint ret;\n \tuint32_t sn = priv->nl_sn++;\n \n-\tif (priv->nl_socket == -1)\n+\tif (priv->nl_socket_route == -1)\n \t\treturn 0;\n-\tfd = priv->nl_socket;\n+\tfd = priv->nl_socket_route;\n \tmemcpy(RTA_DATA(&req.rta), mac, ETHER_ADDR_LEN);\n \treq.hdr.nlmsg_len = NLMSG_ALIGN(req.hdr.nlmsg_len) +\n \t\tRTA_ALIGN(req.rta.rta_len);\n@@ -569,9 +623,9 @@ mlx5_nl_device_flags(struct rte_eth_dev *dev, uint32_t flags, int enable)\n \tint ret;\n \n \tassert(!(flags & ~(IFF_PROMISC | IFF_ALLMULTI)));\n-\tif (priv->nl_socket < 0)\n+\tif (priv->nl_socket_route < 0)\n \t\treturn 0;\n-\tfd = priv->nl_socket;\n+\tfd = priv->nl_socket_route;\n \tret = mlx5_nl_send(fd, &req.hdr, priv->nl_sn++);\n \tif (ret < 0)\n \t\treturn ret;\n@@ -625,3 +679,241 @@ mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable)\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_ifindex_cb(struct nlmsghdr *nh, void *arg)\n+{\n+\tstruct mlx5_nl_ifindex_data *data = arg;\n+\tsize_t off = NLMSG_HDRLEN;\n+\tuint32_t ibindex = 0;\n+\tuint32_t ifindex = 0;\n+\tint found = 0;\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\tibindex = *(uint32_t *)payload;\n+\t\t\tbreak;\n+\t\tcase RDMA_NLDEV_ATTR_DEV_NAME:\n+\t\t\tif (!strcmp(payload, data->name))\n+\t\t\t\tfound = 1;\n+\t\t\tbreak;\n+\t\tcase RDMA_NLDEV_ATTR_NDEV_INDEX:\n+\t\t\tifindex = *(uint32_t *)payload;\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+\tif (found) {\n+\t\tdata->ibindex = ibindex;\n+\t\tdata->ifindex = ifindex;\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+ *\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)\n+{\n+\tstatic const uint32_t pindex = 1;\n+\tuint32_t seq = random();\n+\tstruct mlx5_nl_ifindex_data data = {\n+\t\t.name = name,\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+\tint ret;\n+\n+\tret = mlx5_nl_send(nl, &req.nh, seq);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tret = mlx5_nl_recv(nl, seq, mlx5_nl_ifindex_cb, &data);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tif (!data.ibindex)\n+\t\tgoto error;\n+\t++seq;\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, seq);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tret = mlx5_nl_recv(nl, seq, mlx5_nl_ifindex_cb, &data);\n+\tif (ret < 0)\n+\t\treturn 0;\n+\tif (!data.ifindex)\n+\t\tgoto error;\n+\treturn data.ifindex;\n+error:\n+\trte_errno = ENODEV;\n+\treturn 0;\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.port_name = 0,\n+\t\t.switch_id = 0,\n+\t};\n+\tsize_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg));\n+\tbool port_name_set = false;\n+\tbool switch_id_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\tchar *end;\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_PHYS_PORT_NAME:\n+\t\t\terrno = 0;\n+\t\t\tinfo.port_name = strtol(payload, &end, 0);\n+\t\t\tif (errno ||\n+\t\t\t    (size_t)(end - (char *)payload) != strlen(payload))\n+\t\t\t\tgoto error;\n+\t\t\tport_name_set = true;\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+\tinfo.master = switch_id_set && !port_name_set;\n+\tinfo.representor = switch_id_set && port_name_set;\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, struct mlx5_switch_info *info)\n+{\n+\tuint32_t seq = random();\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(req.info)),\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};\n+\tint ret;\n+\n+\tret = mlx5_nl_send(nl, &req.nh, seq);\n+\tif (ret >= 0)\n+\t\tret = mlx5_nl_recv(nl, seq, mlx5_nl_switch_info_cb, info);\n+\treturn ret;\n+}\n",
    "prefixes": [
        "v5",
        "06/10"
    ]
}