From 30a86157f6d56d112a73bc3bbdda5c24acdb4c79 Mon Sep 17 00:00:00 2001 From: Viacheslav Ovsiienko Date: Tue, 16 Apr 2019 14:10:28 +0000 Subject: [PATCH] net/mlx5: support PF representor On BlueField platform we have the new entity - PF representor. This one represents the PCI PF attached to external host on the side of ARM. The traffic sent by the external host to the NIC via PF will be seem by ARM on this PF representor. This patch refactors port recognizing capability on the base of physical port name. We have two groups of name formats. Legacy name formats are supported by kernels before ver 5.0 (being more precise - before the patch [1]) or before Mellanox OFED 4.6, and new naming formats added by the patch [1]. Legacy naming formats are supported: - missing physical port name (no sysfs/netlink key) at all, master is assumed - decimal digits (for example "12"), representor is assumed, the value is the index of attached VF New naming formats are supported: - "p" followed by decimal digits, for example "p2", master is assumed - "pf" followed by PF index concatenated with "vf" followed by VF index, for example "pf0vf1", representor is assumed. If index of VF is "-1" it is a special case of host PF representor, this representor must be indexed in devargs as 65535, for example representor=[0-3,65535] will allow representors for VF0, VF1, VF2, VF3 and for host PF. Note: do not specify representor=[0-65535], it causes devargs processing error, because number of ports (rte_eth_dev) is limited. Applications should distinguish representors and master devices exclusively by device flag RTE_ETH_DEV_REPRESENTOR and do not rely on switch port_id (mlx5 PMD deduces ones from representor_id) values returned by dev_infos_get() API. [1] https://www.spinics.net/lists/netdev/msg547007.html Linux-tree: c12ecc23 (Or Gerlitz 2018-04-25 17:32 +0300) "net/mlx5e: Move to use common phys port names for vport representors" Signed-off-by: Viacheslav Ovsiienko Acked-by: Shahaf Shuler --- drivers/net/mlx5/mlx5.h | 18 +++- drivers/net/mlx5/mlx5_ethdev.c | 163 ++++++++++++++++++++++++++++----- drivers/net/mlx5/mlx5_nl.c | 20 +--- 3 files changed, 158 insertions(+), 43 deletions(-) diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 14c7f3c6fb..2069fad85c 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -80,11 +80,21 @@ struct mlx5_mp_param { /** Key string for IPC. */ #define MLX5_MP_NAME "net_mlx5_mp" +/* Recognized Infiniband device physical port name types. */ +enum mlx5_phys_port_name_type { + MLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */ + MLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */ + MLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */ + MLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */ + MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */ +}; + /** Switch information returned by mlx5_nl_switch_info(). */ struct mlx5_switch_info { uint32_t master:1; /**< Master device. */ uint32_t representor:1; /**< Representor device. */ - uint32_t port_name_new:1; /**< Rep. port name is in new format. */ + enum mlx5_phys_port_name_type name_type; /** < Port name type. */ + int32_t pf_num; /**< PF number (valid for pfxvfx format only). */ int32_t port_name; /**< Representor port name. */ uint64_t switch_id; /**< Switch identifier. */ }; @@ -404,7 +414,11 @@ unsigned int mlx5_dev_to_port_id(const struct rte_device *dev, unsigned int port_list_n); int mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info); -bool mlx5_translate_port_name(const char *port_name_in, +void mlx5_sysfs_check_switch_info(bool device_dir, + struct mlx5_switch_info *switch_info); +void mlx5_nl_check_switch_info(bool nun_vf_set, + struct mlx5_switch_info *switch_info); +void mlx5_translate_port_name(const char *port_name_in, struct mlx5_switch_info *port_info_out); /* mlx5_mac.c */ diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index 3992918c57..9c24462553 100644 --- a/drivers/net/mlx5/mlx5_ethdev.c +++ b/drivers/net/mlx5/mlx5_ethdev.c @@ -1395,12 +1395,11 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) struct mlx5_switch_info data = { .master = 0, .representor = 0, - .port_name_new = 0, + .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET, .port_name = 0, .switch_id = 0, }; DIR *dir; - bool port_name_set = false; bool port_switch_id_set = false; bool device_dir = false; char c; @@ -1423,8 +1422,7 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) ret = fscanf(file, "%s", port_name); fclose(file); if (ret == 1) - port_name_set = mlx5_translate_port_name(port_name, - &data); + mlx5_translate_port_name(port_name, &data); } file = fopen(phys_switch_id, "rb"); if (file == NULL) { @@ -1440,8 +1438,10 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) closedir(dir); device_dir = true; } - data.master = port_switch_id_set && (!port_name_set || device_dir); - data.representor = port_switch_id_set && port_name_set && !device_dir; + if (port_switch_id_set) { + /* We have some E-Switch configuration. */ + mlx5_sysfs_check_switch_info(device_dir, &data); + } *info = data; assert(!(data.master && data.representor)); if (data.master && data.representor) { @@ -1453,42 +1453,155 @@ mlx5_sysfs_switch_info(unsigned int ifindex, struct mlx5_switch_info *info) return 0; } +/** + * Analyze gathered port parameters via Netlink to recognize master + * and representor devices for E-Switch configuration. + * + * @param[in] num_vf_set + * flag of presence of number of VFs port attribute. + * @param[inout] switch_info + * Port information, including port name as a number and port name + * type if recognized + * + * @return + * master and representor flags are set in switch_info according to + * recognized parameters (if any). + */ +void +mlx5_nl_check_switch_info(bool num_vf_set, + struct mlx5_switch_info *switch_info) +{ + switch (switch_info->name_type) { + case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: + /* + * Name is not recognized, assume the master, + * check the number of VFs key presence. + */ + switch_info->master = num_vf_set; + break; + case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: + /* + * Name is not set, this assumes the legacy naming + * schema for master, just check if there is a + * number of VFs key. + */ + switch_info->master = num_vf_set; + break; + case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: + /* New uplink naming schema recognized. */ + switch_info->master = 1; + break; + case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: + /* Legacy representors naming schema. */ + switch_info->representor = !num_vf_set; + break; + case MLX5_PHYS_PORT_NAME_TYPE_PFVF: + /* New representors naming schema. */ + switch_info->representor = 1; + break; + } +} + +/** + * Analyze gathered port parameters via sysfs to recognize master + * and representor devices for E-Switch configuration. + * + * @param[in] device_dir + * flag of presence of "device" directory under port device key. + * @param[inout] switch_info + * Port information, including port name as a number and port name + * type if recognized + * + * @return + * master and representor flags are set in switch_info according to + * recognized parameters (if any). + */ +void +mlx5_sysfs_check_switch_info(bool device_dir, + struct mlx5_switch_info *switch_info) +{ + switch (switch_info->name_type) { + case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: + /* + * Name is not recognized, assume the master, + * check the device directory presence. + */ + switch_info->master = device_dir; + break; + case MLX5_PHYS_PORT_NAME_TYPE_NOTSET: + /* + * Name is not set, this assumes the legacy naming + * schema for master, just check if there is + * a device directory. + */ + switch_info->master = device_dir; + break; + case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: + /* New uplink naming schema recognized. */ + switch_info->master = 1; + break; + case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: + /* Legacy representors naming schema. */ + switch_info->representor = !device_dir; + break; + case MLX5_PHYS_PORT_NAME_TYPE_PFVF: + /* New representors naming schema. */ + switch_info->representor = 1; + break; + } +} + /** * Extract port name, as a number, from sysfs or netlink information. * * @param[in] port_name_in * String representing the port name. * @param[out] port_info_out - * Port information, including port name as a number. + * Port information, including port name as a number and port name + * type if recognized * * @return - * true on success, false otherwise. + * port_name field set according to recognized name format. */ -bool +void mlx5_translate_port_name(const char *port_name_in, struct mlx5_switch_info *port_info_out) { char pf_c1, pf_c2, vf_c1, vf_c2; char *end; - int32_t pf_num; - bool port_name_set = false; + int sc_items; /* * Check for port-name as a string of the form pf0vf0 - * (support kernel ver >= 5.0) + * (support kernel ver >= 5.0 or OFED ver >= 4.6). */ - port_name_set = (sscanf(port_name_in, "%c%c%d%c%c%d", &pf_c1, &pf_c2, - &pf_num, &vf_c1, &vf_c2, - &port_info_out->port_name) == 6); - if (port_name_set) { - port_info_out->port_name_new = 1; - } else { - /* Check for port-name as a number (support kernel ver < 5.0 */ - errno = 0; - port_info_out->port_name = strtol(port_name_in, &end, 0); - if (!errno && - (size_t)(end - port_name_in) == strlen(port_name_in)) - port_name_set = true; + sc_items = sscanf(port_name_in, "%c%c%d%c%c%d", + &pf_c1, &pf_c2, &port_info_out->pf_num, + &vf_c1, &vf_c2, &port_info_out->port_name); + if (sc_items == 6 && + pf_c1 == 'p' && pf_c2 == 'f' && + vf_c1 == 'v' && vf_c2 == 'f') { + port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_PFVF; + return; + } + /* + * Check for port-name as a string of the form p0 + * (support kernel ver >= 5.0, or OFED ver >= 4.6). + */ + sc_items = sscanf(port_name_in, "%c%d", + &pf_c1, &port_info_out->port_name); + if (sc_items == 2 && pf_c1 == 'p') { + port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UPLINK; + return; + } + /* Check for port-name as a number (support kernel ver < 5.0 */ + errno = 0; + port_info_out->port_name = strtol(port_name_in, &end, 0); + if (!errno && + (size_t)(end - port_name_in) == strlen(port_name_in)) { + port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_LEGACY; + return; } - return port_name_set; + port_info_out->name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; + return; } diff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c index fd9226bddf..0ff96671f6 100644 --- a/drivers/net/mlx5/mlx5_nl.c +++ b/drivers/net/mlx5/mlx5_nl.c @@ -887,12 +887,11 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg) struct mlx5_switch_info info = { .master = 0, .representor = 0, - .port_name_new = 0, + .name_type = MLX5_PHYS_PORT_NAME_TYPE_NOTSET, .port_name = 0, .switch_id = 0, }; size_t off = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - bool port_name_set = false; bool switch_id_set = false; bool num_vf_set = false; @@ -910,9 +909,7 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg) num_vf_set = true; break; case IFLA_PHYS_PORT_NAME: - port_name_set = - mlx5_translate_port_name((char *)payload, - &info); + mlx5_translate_port_name((char *)payload, &info); break; case IFLA_PHYS_SWITCH_ID: info.switch_id = 0; @@ -926,17 +923,8 @@ mlx5_nl_switch_info_cb(struct nlmsghdr *nh, void *arg) off += RTA_ALIGN(ra->rta_len); } if (switch_id_set) { - if (info.port_name_new) { - /* New representors naming schema. */ - if (port_name_set) { - info.master = (info.port_name == -1); - info.representor = (info.port_name != -1); - } - } else { - /* Legacy representors naming schema. */ - info.master = (!port_name_set || num_vf_set); - info.representor = port_name_set && !num_vf_set; - } + /* We have some E-Switch configuration. */ + mlx5_nl_check_switch_info(num_vf_set, &info); } assert(!(info.master && info.representor)); memcpy(arg, &info, sizeof(info)); -- 2.20.1