Hi Slava, Friday, April 12, 2019 6:48 PM, Viacheslav Ovsiienko: > Subject: [dpdk-dev] [PATCH 1/1] net/mlx5: add support for 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 extends port recognizing capability on the base of physical port > name. The following naming formats are supported: > > - missing physical port name (no sysfs/netlink key) at all, > this is old style (before kernel 5.0) format, master assumed > - 1 (decimal digits) - old style (before kernel 5.0) format, > exists only for representors, master does not have physical > port name at all (see above) > - p0 ("p" followed by decimal digits), new style (kernel version > is 5.0 or higher, Mellanox OFED 4.6 or higher) name format > for uplink representor, plays the role of master > - pf0vf0 ("pf" followed by PF index concatenated with "vf" > followed by VF index), new style (kernel version is 5.0 > or higher, Mellanox OFED 4.6 or higher) name format for > VF representor. 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 host PF. > Note: do not specify representor=[0-65535] it causes devargs > processing error, because number of ports (rte_eth_dev) is > limited. >
The above is a bit complex to understand and in fact we have 2 modes: 1. legacy - phys_port_name are numbers. Master doesn't have phys_port_name 2. modern - phys_port_name are strings. uplink representor is p%d representors are (including PF representor) pf%dvf%d. the vf index for the PF representor is 65535. > 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. > Please also reference the kernel commit which introduce the name change. > Signed-off-by: Viacheslav Ovsiienko <viachesl...@mellanox.com> > --- > drivers/net/mlx5/mlx5.h | 11 ++++++- > drivers/net/mlx5/mlx5_ethdev.c | 68 +++++++++++++++++++++++++++---- > ----------- > drivers/net/mlx5/mlx5_nl.c | 42 +++++++++++++++++--------- > 3 files changed, 82 insertions(+), 39 deletions(-) > > diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index > 8eb1019..81c02ce 100644 > --- a/drivers/net/mlx5/mlx5.h > +++ b/drivers/net/mlx5/mlx5.h > @@ -80,11 +80,20 @@ 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_UNKNOWN = 0, /* Unrecognized. > */ > + 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 > */ }; > + > /** 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. */ }; diff --git > a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c index > 3992918..371989f 100644 > --- a/drivers/net/mlx5/mlx5_ethdev.c > +++ b/drivers/net/mlx5/mlx5_ethdev.c > @@ -1395,12 +1395,11 @@ int mlx5_fw_version_get(struct rte_eth_dev > *dev, char *fw_ver, size_t fw_size) > struct mlx5_switch_info data = { > .master = 0, > .representor = 0, > - .port_name_new = 0, > + .name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, > .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 @@ int mlx5_fw_version_get(struct rte_eth_dev *dev, > char *fw_ver, size_t fw_size) > 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,15 @@ int mlx5_fw_version_get(struct rte_eth_dev > *dev, char *fw_ver, size_t fw_size) > 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) { > + data.master = > + device_dir || > + data.name_type == > MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN || > + data.name_type == > MLX5_PHYS_PORT_NAME_TYPE_UPLINK; > + data.representor = !device_dir && > + (data.name_type == > MLX5_PHYS_PORT_NAME_TYPE_LEGACY || > + data.name_type == > MLX5_PHYS_PORT_NAME_TYPE_PFVF); Why we need to split the logic of the master/representor detection between the mlx5_translate_port_name and the caller function? The way I envision it is mlx5_tranlate_port_name receives the phys_port_name and maybe more metadata and return the port classification (master/representor) and the representor/pf number. No need for data.master = some_logic(translate_port_name_info). Inside the translate function I would expect to have 2 smaller function: 1. to handle the modern format (strings) 2. to handle the legacy format (integers) > + } > *info = data; > assert(!(data.master && data.representor)); > if (data.master && data.representor) { @@ -1459,10 +1464,11 @@ int > mlx5_fw_version_get(struct rte_eth_dev *dev, char *fw_ver, size_t > fw_size) > * @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. > + * true on success (if name format recognized), false otherwise. > */ > bool > mlx5_translate_port_name(const char *port_name_in, @@ -1470,25 > +1476,39 @@ int mlx5_fw_version_get(struct rte_eth_dev *dev, char > *fw_ver, size_t fw_size) { > 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 true; > + } > + /* > + * 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 true; > + } > + /* 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 true; > } > - return port_name_set; > + port_info_out->name_type = > MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN; > + return false; > } > diff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c index > fd9226b..669de76 100644 > --- a/drivers/net/mlx5/mlx5_nl.c > +++ b/drivers/net/mlx5/mlx5_nl.c > @@ -887,12 +887,11 @@ struct mlx5_nl_ifindex_data { > struct mlx5_switch_info info = { > .master = 0, > .representor = 0, > - .port_name_new = 0, > + .name_type = MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, > .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 @@ struct mlx5_nl_ifindex_data { > 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,16 +923,33 @@ struct mlx5_nl_ifindex_data { > 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 { > + /* We have some E-Switch configuration. */ > + switch (info.name_type) { > + case MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN: > + /* > + * Name is not recognized or not set, > + * it can not be representor, check > + * VF number to see if it is a master. > + */ > + info.master = num_vf_set; > + break; > + case MLX5_PHYS_PORT_NAME_TYPE_LEGACY: > /* Legacy representors naming schema. */ > - info.master = (!port_name_set || num_vf_set); > - info.representor = port_name_set && !num_vf_set; > + info.representor = !num_vf_set; > + break; > + case MLX5_PHYS_PORT_NAME_TYPE_UPLINK: > + /* New uplink naming schema. */ > + info.master = 1; > + break; > + case MLX5_PHYS_PORT_NAME_TYPE_PFVF: > + /* New representors naming schema. */ > + info.representor = 1; > + break; > + } > + if (!info.master && !info.representor) { > + DRV_LOG(INFO, > + "unable to recognize master/representors" > + " on the device in switch domain"); Same comment as above. Would like to avoid this switch case outside of the translate function . > } > } > assert(!(info.master && info.representor)); > -- > 1.8.3.1