Add mlx5_nl_devlink_port_info_get() which will query specific devlink
port by its:

- bus name
- device name
- port index

As of now, only port's flavour is parsed.

Signed-off-by: Dariusz Sosnowski <[email protected]>
Acked-by: Viacheslav Ovsiienko <[email protected]>
---
 drivers/common/mlx5/linux/mlx5_nl.c | 91 +++++++++++++++++++++++++++++
 drivers/common/mlx5/linux/mlx5_nl.h | 19 ++++++
 2 files changed, 110 insertions(+)

diff --git a/drivers/common/mlx5/linux/mlx5_nl.c 
b/drivers/common/mlx5/linux/mlx5_nl.c
index 786158fb99..e57007831c 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.c
+++ b/drivers/common/mlx5/linux/mlx5_nl.c
@@ -190,6 +190,8 @@ static RTE_ATOMIC(uint32_t) atomic_sn;
 #define MLX5_NL_SN_GENERATE (rte_atomic_fetch_add_explicit(&atomic_sn, 1, \
        rte_memory_order_relaxed) + 1)
 
+static void nl_attr_put(struct nlmsghdr *nlh, int type, const void *data, int 
alen);
+
 /**
  * Opens a Netlink socket.
  *
@@ -1573,6 +1575,95 @@ mlx5_nl_netdev_info_get(int nl, struct mlx5_netdev_info 
*info)
        return ret;
 }
 
+static int
+mlx5_nl_devlink_port_info_get_cb(struct nlmsghdr *nh, void *arg)
+{
+       struct mlx5_devlink_port_info *out = arg;
+       struct mlx5_devlink_port_info info;
+       struct genlmsghdr *genlhdr;
+       struct nlattr *nla;
+       ssize_t len;
+
+       memset(&info, 0, sizeof(info));
+       info.bus_name = out->bus_name;
+       info.dev_name = out->dev_name;
+       info.index = out->index;
+
+       if (nh->nlmsg_len < NLMSG_LENGTH(GENL_HDRLEN))
+               goto error;
+
+       genlhdr = NLMSG_DATA(nh);
+       if (genlhdr->cmd != DEVLINK_CMD_PORT_NEW)
+               goto error;
+
+       nla = RTE_PTR_ADD(genlhdr, GENL_HDRLEN);
+       len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
+       while (nla_ok(nla, len)) {
+               void *payload = RTE_PTR_ADD(nla, NLA_HDRLEN);
+               size_t payload_len = nla->nla_len - NLA_HDRLEN;
+
+               switch (nla->nla_type & NLA_TYPE_MASK) {
+               case DEVLINK_ATTR_PORT_FLAVOUR:
+                       if (payload_len < sizeof(uint16_t))
+                               break;
+                       info.flavour = *(uint16_t *)payload;
+                       info.flags |= MLX5_DEVLINK_PORT_INFO_FLAG_FLAVOUR;
+                       break;
+               }
+
+               nla = nla_next(nla, &len);
+       }
+       *out = info;
+       return 0;
+error:
+       rte_errno = EINVAL;
+       return -rte_errno;
+}
+
+static int __rte_unused
+mlx5_nl_devlink_port_info_get(int nl, int family, struct 
mlx5_devlink_port_info *info)
+{
+       struct nlmsghdr *nlh;
+       struct genlmsghdr *genl;
+       uint8_t *buf;
+       size_t bus_name_len = strlen(info->bus_name) + 1;
+       size_t dev_name_len = strlen(info->dev_name) + 1;
+       size_t buf_size;
+       uint32_t sn = MLX5_NL_SN_GENERATE;
+       int ret;
+
+       buf_size = NLMSG_ALIGN(sizeof(struct nlmsghdr));
+       buf_size += NLMSG_ALIGN(sizeof(struct genlmsghdr));
+       buf_size += NLMSG_ALIGN(sizeof(struct nlattr) + bus_name_len);
+       buf_size += NLMSG_ALIGN(sizeof(struct nlattr) + dev_name_len);
+       buf_size += NLMSG_ALIGN(sizeof(struct nlattr) + sizeof(info->index));
+       buf = calloc(1, buf_size);
+       if (buf == NULL) {
+               rte_errno = ENOMEM;
+               return -rte_errno;
+       }
+
+       nlh = (struct nlmsghdr *)buf;
+       nlh->nlmsg_len = NLMSG_ALIGN(sizeof(struct nlmsghdr));
+       nlh->nlmsg_type = family;
+       nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+
+       genl = RTE_PTR_ADD(nlh, nlh->nlmsg_len);
+       genl->cmd = DEVLINK_CMD_PORT_GET;
+       genl->version = DEVLINK_GENL_VERSION;
+       nlh->nlmsg_len += NLMSG_ALIGN(sizeof(struct genlmsghdr));
+
+       nl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, info->bus_name, bus_name_len);
+       nl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, info->dev_name, dev_name_len);
+       nl_attr_put(nlh, DEVLINK_ATTR_PORT_INDEX, &info->index, 
sizeof(info->index));
+
+       ret = mlx5_nl_send(nl, nlh, sn);
+       if (ret >= 0)
+               ret = mlx5_nl_recv(nl, sn, mlx5_nl_devlink_port_info_get_cb, 
info);
+       free(buf);
+       return ret;
+}
+
 /**
  * Analyze gathered port parameters via Netlink to recognize master
  * and representor devices for E-Switch configuration.
diff --git a/drivers/common/mlx5/linux/mlx5_nl.h 
b/drivers/common/mlx5/linux/mlx5_nl.h
index 5a9ccfbb7e..0a9aab6610 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.h
+++ b/drivers/common/mlx5/linux/mlx5_nl.h
@@ -95,6 +95,25 @@ mlx5_netdev_info_has_devlink_port(struct mlx5_netdev_info 
*info)
               (info->flags & MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_INDEX);
 }
 
+#define MLX5_DEVLINK_PORT_INFO_FLAG_FLAVOUR RTE_BIT32(0)
+
+#define MLX5_DEVLINK_PORT_FLAVOUR_PHYSICAL (0)
+#define MLX5_DEVLINK_PORT_FLAVOUR_CPU (1)
+#define MLX5_DEVLINK_PORT_FLAVOUR_DSA (2)
+#define MLX5_DEVLINK_PORT_FLAVOUR_PCI_PF (3)
+#define MLX5_DEVLINK_PORT_FLAVOUR_PCI_VF (4)
+#define MLX5_DEVLINK_PORT_FLAVOUR_VIRTUAL (5)
+#define MLX5_DEVLINK_PORT_FLAVOUR_UNUSED (6)
+#define MLX5_DEVLINK_PORT_FLAVOUR_PCI_SF (7)
+
+struct mlx5_devlink_port_info {
+       const char *bus_name; /* [in] */
+       const char *dev_name; /* [in] */
+       uint32_t index; /* [in] */
+       uint32_t flags; /* [out] */
+       uint16_t flavour; /* [out] */
+};
+
 __rte_internal
 int mlx5_nl_init(int protocol, int groups);
 __rte_internal
-- 
2.43.0

Reply via email to