Representor matching in mlx5 driver is based on physical port name (phys_port_name) reported by Linux kernel. Port type and its location in the topology was derived from this name. It is available only on representor netdevs.
As a result, when embedded switch is shared by netdevs based on real VFs/SFs mlx5 driver is unable to deduce port's type. As a replacement, flavour of a devlink port related to netdev can be used. This patch adds parsing of IFLA_DEVLINK_PORT attribute to mlx5_netdev_info_get(). This info will be used in follow up patches to query devlink port info. Signed-off-by: Dariusz Sosnowski <[email protected]> Acked-by: Viacheslav Ovsiienko <[email protected]> --- drivers/common/mlx5/linux/meson.build | 2 + drivers/common/mlx5/linux/mlx5_nl.c | 67 ++++++++++++++++++++++++++- drivers/common/mlx5/linux/mlx5_nl.h | 17 +++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/drivers/common/mlx5/linux/meson.build b/drivers/common/mlx5/linux/meson.build index 1b2104b48e..a69a8b77a0 100644 --- a/drivers/common/mlx5/linux/meson.build +++ b/drivers/common/mlx5/linux/meson.build @@ -158,6 +158,8 @@ has_sym_args = [ 'IFLA_PARENT_DEV_NAME' ], [ 'HAVE_IFLA_PARENT_DEV_BUS_NAME', 'linux/if_link.h', 'IFLA_PARENT_DEV_BUS_NAME' ], + [ 'HAVE_IFLA_DEVLINK_PORT', 'linux/if_link.h', + 'IFLA_DEVLINK_PORT' ], [ 'HAVE_RDMA_NL_NLDEV', 'rdma/rdma_netlink.h', 'RDMA_NL_NLDEV' ], [ 'HAVE_RDMA_NLDEV_CMD_GET', 'rdma/rdma_netlink.h', diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c index 4eebec5223..786158fb99 100644 --- a/drivers/common/mlx5/linux/mlx5_nl.c +++ b/drivers/common/mlx5/linux/mlx5_nl.c @@ -119,6 +119,9 @@ #ifndef HAVE_IFLA_PARENT_DEV_BUS_NAME #define IFLA_PARENT_DEV_BUS_NAME 57 #endif +#ifndef HAVE_IFLA_DEVLINK_PORT +#define IFLA_DEVLINK_PORT 62 +#endif /* * Some Devlink defines may be missed in old kernel versions, @@ -1385,6 +1388,64 @@ mlx5_nl_portnum(int nl, const char *name, struct mlx5_dev_info *dev_info) return mlx5_dev_info_set_portnum(name, dev_info, &data); } +static inline bool +nla_ok(const struct nlattr *nla, const ssize_t len) +{ + return len >= NLA_HDRLEN && + nla->nla_len >= NLA_HDRLEN && + nla->nla_len <= len; +} + +static inline struct nlattr * +nla_next(struct nlattr *nla, ssize_t *len) +{ + ptrdiff_t off = NLA_ALIGN(nla->nla_len); + + *len -= off; + return RTE_PTR_ADD(nla, off); +} + +static void +parse_ifla_devlink_port(void *payload, ssize_t len, struct mlx5_netdev_info *info) +{ + struct nlattr *nla = payload; + uint32_t *val; + size_t payload_len; + char *src; + + while (nla_ok(nla, len)) { + payload_len = nla->nla_len - NLA_HDRLEN; + + switch (nla->nla_type & NLA_TYPE_MASK) { + case DEVLINK_ATTR_BUS_NAME: + if (payload_len > 0 && payload_len < MLX5_NETDEV_INFO_NAME_MAX) { + src = RTE_PTR_ADD(nla, NLA_HDRLEN); + memcpy(info->devlink_port_bus_name, src, payload_len); + info->devlink_port_bus_name[payload_len] = 0; + info->flags |= MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_BUS_NAME; + } + break; + case DEVLINK_ATTR_DEV_NAME: + if (payload_len > 0 && payload_len < MLX5_NETDEV_INFO_NAME_MAX) { + src = RTE_PTR_ADD(nla, NLA_HDRLEN); + memcpy(info->devlink_port_dev_name, src, payload_len); + info->devlink_port_dev_name[payload_len] = 0; + info->flags |= MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_DEV_NAME; + } + break; + case DEVLINK_ATTR_PORT_INDEX: + if (payload_len < sizeof(uint32_t)) + break; + val = RTE_PTR_ADD(nla, NLA_HDRLEN); + info->devlink_port_index = *val; + info->flags |= MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_INDEX; + break; + } + + nla = nla_next(nla, &len); + } +} + static int mlx5_nl_netdev_info_cb(struct nlmsghdr *nh, void *arg) { @@ -1409,7 +1470,7 @@ mlx5_nl_netdev_info_cb(struct nlmsghdr *nh, void *arg) void *payload = RTA_DATA(ra); unsigned int i; - switch (ra->rta_type) { + switch (ra->rta_type & NLA_TYPE_MASK) { case IFLA_NUM_VF: if (RTA_PAYLOAD(ra) < sizeof(uint32_t)) goto error; @@ -1451,6 +1512,10 @@ mlx5_nl_netdev_info_cb(struct nlmsghdr *nh, void *arg) info.flags |= MLX5_NETDEV_INFO_FLAG_PARENT_DEV_BUS_NAME; } break; + case IFLA_DEVLINK_PORT: + payload_len = RTA_PAYLOAD(ra); + parse_ifla_devlink_port(payload, payload_len, &info); + break; } } *out = info; diff --git a/drivers/common/mlx5/linux/mlx5_nl.h b/drivers/common/mlx5/linux/mlx5_nl.h index 39691569bc..5a9ccfbb7e 100644 --- a/drivers/common/mlx5/linux/mlx5_nl.h +++ b/drivers/common/mlx5/linux/mlx5_nl.h @@ -62,11 +62,17 @@ struct mlx5_nl_port_info { /* Maximum length of parent device bus name. */ #define MLX5_PARENT_DEV_BUS_NAME_MAX 128 +/* Maximum length of a name stored inside netdev info */ +#define MLX5_NETDEV_INFO_NAME_MAX 128 + #define MLX5_NETDEV_INFO_FLAG_NUM_VF RTE_BIT32(0) #define MLX5_NETDEV_INFO_FLAG_PHYS_PORT_NAME RTE_BIT32(1) #define MLX5_NETDEV_INFO_FLAG_PHYS_SWITCH_ID RTE_BIT32(2) #define MLX5_NETDEV_INFO_FLAG_PARENT_DEV_NAME RTE_BIT32(3) #define MLX5_NETDEV_INFO_FLAG_PARENT_DEV_BUS_NAME RTE_BIT32(4) +#define MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_BUS_NAME RTE_BIT32(5) +#define MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_DEV_NAME RTE_BIT32(6) +#define MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_INDEX RTE_BIT32(7) struct mlx5_netdev_info { unsigned int ifindex; /* [in] */ @@ -76,8 +82,19 @@ struct mlx5_netdev_info { uint64_t phys_switch_id; /* [out] */ char parent_dev_name[MLX5_PARENT_DEV_NAME_MAX]; /* [out] */ char parent_dev_bus_name[MLX5_PARENT_DEV_BUS_NAME_MAX]; /* [out] */ + char devlink_port_bus_name[MLX5_NETDEV_INFO_NAME_MAX]; /* [out] */ + char devlink_port_dev_name[MLX5_NETDEV_INFO_NAME_MAX]; /* [out] */ + uint32_t devlink_port_index; /* [out] */ }; +static inline bool +mlx5_netdev_info_has_devlink_port(struct mlx5_netdev_info *info) +{ + return (info->flags & MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_BUS_NAME) && + (info->flags & MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_DEV_NAME) && + (info->flags & MLX5_NETDEV_INFO_FLAG_DEVLINK_PORT_INDEX); +} + __rte_internal int mlx5_nl_init(int protocol, int groups); __rte_internal -- 2.43.0

