A devlink port may be for a controller consist of PCI device. A devlink instance holds ports of two types of controllers. (1) controller discovered on same system where eswitch resides This is the case where PCI PF/VF of a controller and devlink eswitch instance both are located on a single system. (2) controller located on other system. This is the case where a controller is located in one system and its devlink eswitch ports are located in a different system. In this case devlink instance of the eswitch only have access to ports of the controller.
When a devlink eswitch instance serves the devlink ports of both controllers together, PCI PF/VF numbers may overlap. Due to this a unique phys_port_name cannot be constructed. To differentiate ports of a controller external/remote to the devlink instance, consider external controller number while forming the phys_port_name. Also return this optional controller number of the port via netlink interface. An example output: $ devlink port show pci/0000:00:08.0/2 pci/0000:00:08.0/2: type eth netdev eth7 controller 0 flavour pcivf pfnum 0 vfnum 1 splittable false function: hw_addr 00:00:00:00:00:00 $ devlink port show -jp pci/0000:00:08.0/2 { "port": { "pci/0000:00:08.0/1": { "type": "eth", "netdev": "eth7", "controller": 0, "flavour": "pcivf", "pfnum": 0, "vfnum": 1, "splittable": false, "function": { "hw_addr": "00:00:00:00:00:00" } } } } An example representor netdev udev name consist of controller annotation for external controller with controller number = 0, for PF 0 and VF 1: udevadm test-builtin net_id /sys/class/net/eth7 Using default interface naming scheme 'v245'. ID_NET_NAMING_SCHEME=v245 ID_NET_NAME_PATH=enp0s8f0nc0pf0vf1 Unload module index Unloaded link configuration context. Signed-off-by: Parav Pandit <pa...@mellanox.com> Reviewed-by: Jiri Pirko <j...@nvidia.com> Reviewed-by: Roi Dayan <r...@mellanox.com> --- include/net/devlink.h | 7 ++++++- include/uapi/linux/devlink.h | 1 + net/core/devlink.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/net/devlink.h b/include/net/devlink.h index 3c7ba3e1f490..612f107b94ab 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -71,16 +71,20 @@ struct devlink_port_pci_vf_attrs { * @flavour: flavour of the port * @split: indicates if this is split port * @splittable: indicates if the port can be split. + * @controller_valid: indicates if the controller_num field is valid. * @lanes: maximum number of lanes the port supports. 0 value is not passed to netlink. * @switch_id: if the port is part of switch, this is buffer with ID, otherwise this is NULL * @phys: physical port attributes * @pci_pf: PCI PF port attributes * @pci_vf: PCI VF port attributes + * @controller_num: Controller number if a port is for other controller. */ struct devlink_port_attrs { u8 split:1, - splittable:1; + splittable:1, + controller_valid:1; u32 lanes; + u32 controller_num; enum devlink_port_flavour flavour; struct netdev_phys_item_id switch_id; union { @@ -1206,6 +1210,7 @@ void devlink_port_type_ib_set(struct devlink_port *devlink_port, void devlink_port_type_clear(struct devlink_port *devlink_port); void devlink_port_attrs_set(struct devlink_port *devlink_port, struct devlink_port_attrs *devlink_port_attrs); +void devlink_port_attrs_controller_set(struct devlink_port *devlink_port, u32 controller); void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u16 pf); void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u16 pf, u16 vf); diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index cfef4245ea5a..886cddf6a0a9 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -458,6 +458,7 @@ enum devlink_attr { DEVLINK_ATTR_PORT_LANES, /* u32 */ DEVLINK_ATTR_PORT_SPLITTABLE, /* u8 */ + DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, /* u32 */ /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX, diff --git a/net/core/devlink.c b/net/core/devlink.c index 58c8bb07fa19..b9b71f119446 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -553,6 +553,11 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg, default: break; } + + if (attrs->controller_valid && + nla_put_u32(msg, DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, attrs->controller_num)) + return -EMSGSIZE; + return 0; } @@ -7711,6 +7716,22 @@ void devlink_port_attrs_set(struct devlink_port *devlink_port, } EXPORT_SYMBOL_GPL(devlink_port_attrs_set); +/** + * devlink_port_attrs_controller_set - Set external controller identifier + * + * @devlink_port: devlink port + * @controller: associated controller number for the devlink port instance + * devlink_port_attrs_controller_set() Sets the external controller identifier + * for the port. This should be called by the driver for a devlink port which is associated + * with the controller which is external to the devlink instance. + */ +void devlink_port_attrs_controller_set(struct devlink_port *devlink_port, u32 controller) +{ + devlink_port->attrs.controller_valid = true; + devlink_port->attrs.controller_num = controller; +} +EXPORT_SYMBOL_GPL(devlink_port_attrs_controller_set); + /** * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes * @@ -7762,6 +7783,14 @@ static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, if (!devlink_port->attrs_set) return -EOPNOTSUPP; + if (attrs->controller_valid) { + n = snprintf(name, len, "c%u", attrs->controller_num); + if (n >= len) + return -EINVAL; + len -= n; + name += n; + } + switch (attrs->flavour) { case DEVLINK_PORT_FLAVOUR_PHYSICAL: case DEVLINK_PORT_FLAVOUR_VIRTUAL: -- 2.26.2