diff options
Diffstat (limited to 'src/udev')
-rw-r--r-- | src/udev/udev-builtin-net_id.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c index 5be158f527..b5a88c667c 100644 --- a/src/udev/udev-builtin-net_id.c +++ b/src/udev/udev-builtin-net_id.c @@ -34,7 +34,8 @@ * * Type of names: * b<number> — BCMA bus core number - * c<bus_id> — CCW bus group name, without leading zeros [s390] + * c<bus_id> — bus id of a grouped CCW or CCW device, + * with all leading zeros stripped [s390] * o<index>[n<phys_port_name>|d<dev_port>] * — on-board device index number * s<slot>[f<function>][n<phys_port_name>|d<dev_port>] @@ -87,6 +88,11 @@ * /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2 * ID_NET_NAME_MAC=enxd626b3450fb5 * ID_NET_NAME_PATH=enp0s29u1u2 + * + * s390 grouped CCW interface: + * /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0 + * ID_NET_NAME_MAC=enx026d3c00000a + * ID_NET_NAME_PATH=encf5f0 */ #include <errno.h> @@ -115,7 +121,7 @@ enum netname_type{ NET_USB, NET_BCMA, NET_VIRTIO, - NET_CCWGROUP, + NET_CCW, }; struct netnames { @@ -132,9 +138,21 @@ struct netnames { char usb_ports[IFNAMSIZ]; char bcma_core[IFNAMSIZ]; - char ccw_group[IFNAMSIZ]; + char ccw_busid[IFNAMSIZ]; }; +/* skip intermediate virtio devices */ +static struct udev_device *skip_virtio(struct udev_device *dev) { + struct udev_device *parent = dev; + + /* there can only ever be one virtio bus per parent device, so we can + safely ignore any virtio buses. see + <http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html> */ + while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent))) + parent = udev_device_get_parent(parent); + return parent; +} + /* retrieve on-board index number and label from firmware */ static int dev_pci_onboard(struct udev_device *dev, struct netnames *names) { unsigned dev_port = 0; @@ -308,12 +326,8 @@ static int names_pci(struct udev_device *dev, struct netnames *names) { assert(names); parent = udev_device_get_parent(dev); - - /* there can only ever be one virtio bus per parent device, so we can - safely ignore any virtio buses. see - <http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html> */ - while (parent && streq_ptr("virtio", udev_device_get_subsystem(parent))) - parent = udev_device_get_parent(parent); + /* skip virtio subsystem if present */ + parent = skip_virtio(parent); if (!parent) return -ENOENT; @@ -414,21 +428,26 @@ static int names_ccw(struct udev_device *dev, struct netnames *names) { struct udev_device *cdev; const char *bus_id; size_t bus_id_len; + size_t bus_id_start; int rc; + char *subsys; assert(dev); assert(names); /* Retrieve the associated CCW device */ cdev = udev_device_get_parent(dev); + /* skip virtio subsystem if present */ + cdev = skip_virtio(cdev); if (!cdev) return -ENOENT; - /* Network devices are always grouped CCW devices */ - if (!streq_ptr("ccwgroup", udev_device_get_subsystem(cdev))) + /* Network devices are either single or grouped CCW devices */ + subsys = udev_device_get_subsystem(cdev); + if (!STRPTR_IN_SET(subsys, "ccwgroup", "ccw")) return -ENOENT; - /* Retrieve bus-ID of the grouped CCW device. The bus-ID uniquely + /* Retrieve bus-ID of the CCW device. The bus-ID uniquely * identifies the network device on the Linux on System z channel * subsystem. Note that the bus-ID contains lowercase characters. */ @@ -447,14 +466,15 @@ static int names_ccw(struct udev_device *dev, struct netnames *names) { /* Strip leading zeros from the bus id for aesthetic purposes. This * keeps the ccw names stable, yet much shorter in general case of * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is - * not prepended when it is zero. + * not prepended when it is zero. Preserve the last 0 for 0.0.0000. */ - bus_id += strspn(bus_id, ".0"); + bus_id_start = strspn(bus_id, ".0"); + bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1; /* Store the CCW bus-ID for use as network device name */ - rc = snprintf(names->ccw_group, sizeof(names->ccw_group), "c%s", bus_id); - if (rc >= 0 && rc < (int)sizeof(names->ccw_group)) - names->type = NET_CCWGROUP; + rc = snprintf(names->ccw_busid, sizeof(names->ccw_busid), "c%s", bus_id); + if (rc >= 0 && rc < (int)sizeof(names->ccw_busid)) + names->type = NET_CCW; return 0; } @@ -564,10 +584,10 @@ static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool /* get path names for Linux on System z network devices */ err = names_ccw(dev, &names); - if (err >= 0 && names.type == NET_CCWGROUP) { + if (err >= 0 && names.type == NET_CCW) { char str[IFNAMSIZ]; - if (snprintf(str, sizeof(str), "%s%s", prefix, names.ccw_group) < (int)sizeof(str)) + if (snprintf(str, sizeof(str), "%s%s", prefix, names.ccw_busid) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); goto out; } |