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

Reply via email to