[3/8] common/mlx5: add Netlink check for Multiport E-Switch

Message ID 20231031142733.2009166-4-dsosnowski@nvidia.com (mailing list archive)
State Accepted, archived
Delegated to: Raslan Darawsheh
Headers
Series net/mlx5: add Multiport E-Switch support |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Dariusz Sosnowski Oct. 31, 2023, 2:27 p.m. UTC
  This patch implements checking if Multiport E-Switch is enabled
on a given PCI device using Devlink Linux kernel interface.
This facility will be used in follow up commits, which add support
for such configuration to mlx5 PMD.

If mlx5_core Linux kernel module supports Multiport E-Switch,
then it can be configured through a Devlink boolean parameter
"esw_multiport". Checking the value of this parameter
is implemented in mlx5_nl_devlink_esw_multiport_get() function.
If such parameter does not exist, this function returns -EINVAL.

To manually check if mlx5_core kernel module supports "esw_multiport"
parameter, and check if Multiport E-Switch is enabled,
one can use the following command:

  # <pci-dbdf> should be substituted with PCI device address
  # in format <domain>:<bus>:<device>:<function>.
  $ devlink dev param show pci/0000:08:00.0 name esw_multiport
  pci/0000:08:00.0:
    name esw_multiport type driver-specific
      values:
        cmode runtime value true

If parameter is not supported, Devlink command fails with
"Invalid argument" error.

Signed-off-by: Dariusz Sosnowski <dsosnowski@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
---
 drivers/common/mlx5/linux/mlx5_nl.c | 70 +++++++++++++++++++++++++++++
 drivers/common/mlx5/linux/mlx5_nl.h |  5 +++
 drivers/common/mlx5/version.map     |  2 +
 3 files changed, 77 insertions(+)
  

Patch

diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c
index 33670bb5c8..28a1f56dba 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.c
+++ b/drivers/common/mlx5/linux/mlx5_nl.c
@@ -1962,3 +1962,73 @@  mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg)
 	}
 	return 0;
 }
+
+static int
+mlx5_nl_esw_multiport_cb(struct nlmsghdr *nh, void *arg)
+{
+
+	int ret = -EINVAL;
+	int *enable = arg;
+	struct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len);
+	struct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) +
+					NLMSG_ALIGN(sizeof(struct genlmsghdr)));
+
+	while (nla->nla_len && nla < tail) {
+		switch (nla->nla_type) {
+		/* Expected nested attributes case. */
+		case DEVLINK_ATTR_PARAM:
+		case DEVLINK_ATTR_PARAM_VALUES_LIST:
+		case DEVLINK_ATTR_PARAM_VALUE:
+			ret = 0;
+			nla += 1;
+			break;
+		case DEVLINK_ATTR_PARAM_VALUE_DATA:
+			*enable = 1;
+			return 0;
+		default:
+			nla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len));
+		}
+	}
+	*enable = 0;
+	return ret;
+}
+
+#define NL_ESW_MULTIPORT_PARAM "esw_multiport"
+
+int
+mlx5_nl_devlink_esw_multiport_get(int nlsk_fd, int family_id, const char *pci_addr, int *enable)
+{
+	struct nlmsghdr *nlh;
+	struct genlmsghdr *genl;
+	uint32_t sn = MLX5_NL_SN_GENERATE;
+	int ret;
+	uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+		    NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
+		    NLMSG_ALIGN(sizeof(struct nlattr)) * 4 +
+		    NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 4];
+
+	memset(buf, 0, sizeof(buf));
+	nlh = (struct nlmsghdr *)buf;
+	nlh->nlmsg_len = sizeof(struct nlmsghdr);
+	nlh->nlmsg_type = family_id;
+	nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
+	genl = (struct genlmsghdr *)nl_msg_tail(nlh);
+	nlh->nlmsg_len += sizeof(struct genlmsghdr);
+	genl->cmd = DEVLINK_CMD_PARAM_GET;
+	genl->version = DEVLINK_GENL_VERSION;
+	nl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, "pci", 4);
+	nl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1);
+	nl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME,
+		    NL_ESW_MULTIPORT_PARAM, sizeof(NL_ESW_MULTIPORT_PARAM));
+	ret = mlx5_nl_send(nlsk_fd, nlh, sn);
+	if (ret >= 0)
+		ret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_esw_multiport_cb, enable);
+	if (ret < 0) {
+		DRV_LOG(DEBUG, "Failed to get Multiport E-Switch enable on device %s: %d.",
+			pci_addr, ret);
+		return ret;
+	}
+	DRV_LOG(DEBUG, "Multiport E-Switch is %sabled for device \"%s\".",
+		*enable ? "en" : "dis", pci_addr);
+	return ret;
+}
diff --git a/drivers/common/mlx5/linux/mlx5_nl.h b/drivers/common/mlx5/linux/mlx5_nl.h
index db01d7323e..580de3b769 100644
--- a/drivers/common/mlx5/linux/mlx5_nl.h
+++ b/drivers/common/mlx5/linux/mlx5_nl.h
@@ -71,6 +71,7 @@  __rte_internal
 uint32_t mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,
 				  uint32_t ifindex, uint16_t tag);
 
+__rte_internal
 int mlx5_nl_devlink_family_id_get(int nlsk_fd);
 int mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr,
 			    int *enable);
@@ -82,4 +83,8 @@  int mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg);
 __rte_internal
 int mlx5_nl_parse_link_status_update(struct nlmsghdr *hdr, uint32_t *ifindex);
 
+__rte_internal
+int mlx5_nl_devlink_esw_multiport_get(int nlsk_fd, int family_id,
+				      const char *pci_addr, int *enable);
+
 #endif /* RTE_PMD_MLX5_NL_H_ */
diff --git a/drivers/common/mlx5/version.map b/drivers/common/mlx5/version.map
index 0758ba76de..074eed46fd 100644
--- a/drivers/common/mlx5/version.map
+++ b/drivers/common/mlx5/version.map
@@ -125,6 +125,8 @@  INTERNAL {
 	mlx5_mr_addr2mr_bh;
 
 	mlx5_nl_allmulti; # WINDOWS_NO_EXPORT
+	mlx5_nl_devlink_esw_multiport_get; # WINDOWS_NO_EXPORT
+	mlx5_nl_devlink_family_id_get; # WINDOWS_NO_EXPORT
 	mlx5_nl_ifindex; # WINDOWS_NO_EXPORT
 	mlx5_nl_init; # WINDOWS_NO_EXPORT
 	mlx5_nl_mac_addr_add; # WINDOWS_NO_EXPORT