1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
4 * Predictable network interface device names based on:
5 * - firmware/bios-provided index numbers for on-board devices
6 * - firmware-provided pci-express hotplug slot index number
7 * - physical/geographical location of the hardware
8 * - the interface's MAC address
10 * https://systemd.io/PREDICTABLE_INTERFACE_NAMES
12 * When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too.
21 #include <linux/if_arp.h>
22 #include <linux/netdevice.h>
23 #include <linux/pci_regs.h>
25 #include "alloc-util.h"
27 #include "device-private.h"
28 #include "device-util.h"
29 #include "dirent-util.h"
30 #include "ether-addr-util.h"
33 #include "glyph-util.h"
34 #include "netif-naming-scheme.h"
35 #include "parse-util.h"
36 #include "proc-cmdline.h"
37 #include "stdio-util.h"
38 #include "string-util.h"
41 #include "udev-builtin.h"
43 #define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
44 #define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
46 typedef enum NetNameType
{
60 typedef struct NetNames
{
64 char pci_slot
[ALTIFNAMSIZ
];
65 char pci_path
[ALTIFNAMSIZ
];
66 char pci_onboard
[ALTIFNAMSIZ
];
67 const char *pci_onboard_label
;
69 char usb_ports
[ALTIFNAMSIZ
];
70 char bcma_core
[ALTIFNAMSIZ
];
71 char ccw_busid
[ALTIFNAMSIZ
];
72 char vio_slot
[ALTIFNAMSIZ
];
73 char xen_slot
[ALTIFNAMSIZ
];
74 char platform_path
[ALTIFNAMSIZ
];
75 char netdevsim_path
[ALTIFNAMSIZ
];
76 char devicetree_onboard
[ALTIFNAMSIZ
];
79 typedef struct LinkInfo
{
83 int vf_representor_id
;
85 const char *phys_port_name
;
86 struct hw_addr_data hw_addr
;
89 /* skip intermediate virtio devices */
90 static sd_device
*skip_virtio(sd_device
*dev
) {
91 /* there can only ever be one virtio bus per parent device, so we can
92 * safely ignore any virtio buses. see
93 * http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html */
95 const char *subsystem
;
97 if (sd_device_get_subsystem(dev
, &subsystem
) < 0)
100 if (!streq(subsystem
, "virtio"))
103 if (sd_device_get_parent(dev
, &dev
) < 0)
110 static int get_virtfn_info(sd_device
*pcidev
, sd_device
**ret_physfn_pcidev
, char **ret_suffix
) {
111 _cleanup_(sd_device_unrefp
) sd_device
*physfn_pcidev
= NULL
;
112 const char *syspath
, *name
;
117 assert(ret_physfn_pcidev
);
120 r
= sd_device_get_syspath(pcidev
, &syspath
);
124 /* Get physical function's pci device. */
125 r
= sd_device_new_child(&physfn_pcidev
, pcidev
, "physfn");
129 /* Find the virtual function number by finding the right virtfn link. */
130 FOREACH_DEVICE_CHILD_WITH_SUFFIX(physfn_pcidev
, child
, name
) {
133 /* Only accepts e.g. virtfn0, virtfn1, and so on. */
134 n
= startswith(name
, "virtfn");
135 if (isempty(n
) || !in_charset(n
, DIGITS
))
138 if (sd_device_get_syspath(child
, &s
) < 0)
141 if (streq(s
, syspath
)) {
144 suffix
= strjoin("v", n
);
148 *ret_physfn_pcidev
= sd_device_ref(physfn_pcidev
);
149 *ret_suffix
= suffix
;
157 static bool is_valid_onboard_index(unsigned long idx
) {
158 /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
159 * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
160 * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
161 * interface a system might have. Ideally the kernel would already filter this crap for us, but it
162 * doesn't currently. The initial cut-off value (2^14-1) was too conservative for s390 PCI which
163 * allows for index values up 2^16-1 which is now enabled with the NAMING_16BIT_INDEX naming flag. */
164 return idx
<= (naming_scheme_has(NAMING_16BIT_INDEX
) ? ONBOARD_16BIT_INDEX_MAX
: ONBOARD_14BIT_INDEX_MAX
);
167 /* retrieve on-board index number and label from firmware */
168 static int dev_pci_onboard(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
169 unsigned long idx
, dev_port
= 0;
179 /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
180 if (sd_device_get_sysattr_value(names
->pcidev
, "acpi_index", &attr
) >= 0)
181 log_device_debug(names
->pcidev
, "acpi_index=%s", attr
);
183 /* SMBIOS type 41 — Onboard Devices Extended Information */
184 r
= sd_device_get_sysattr_value(names
->pcidev
, "index", &attr
);
187 log_device_debug(names
->pcidev
, "index=%s", attr
);
190 r
= safe_atolu(attr
, &idx
);
192 return log_device_debug_errno(names
->pcidev
, r
,
193 "Failed to parse onboard index \"%s\": %m", attr
);
194 if (idx
== 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX
))
195 return log_device_debug_errno(names
->pcidev
, SYNTHETIC_ERRNO(EINVAL
),
196 "Naming scheme does not allow onboard index==0.");
197 if (!is_valid_onboard_index(idx
))
198 return log_device_debug_errno(names
->pcidev
, SYNTHETIC_ERRNO(ENOENT
),
199 "Not a valid onboard index: %lu", idx
);
201 /* kernel provided port index for multiple ports on a single PCI function */
202 if (sd_device_get_sysattr_value(dev
, "dev_port", &attr
) >= 0) {
203 r
= safe_atolu_full(attr
, 10, &dev_port
);
205 log_device_debug_errno(dev
, r
, "Failed to parse dev_port, ignoring: %m");
206 log_device_debug(dev
, "dev_port=%lu", dev_port
);
209 s
= names
->pci_onboard
;
210 l
= sizeof(names
->pci_onboard
);
211 l
= strpcpyf(&s
, l
, "o%lu", idx
);
212 if (naming_scheme_has(NAMING_SR_IOV_R
) && info
->vf_representor_id
>= 0)
213 /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
214 l
= strpcpyf(&s
, l
, "r%d", info
->vf_representor_id
);
215 else if (!isempty(info
->phys_port_name
))
216 /* kernel provided front panel port name for multiple port PCI device */
217 l
= strpcpyf(&s
, l
, "n%s", info
->phys_port_name
);
218 else if (dev_port
> 0)
219 l
= strpcpyf(&s
, l
, "d%lu", dev_port
);
221 names
->pci_onboard
[0] = '\0';
222 log_device_debug(dev
, "Onboard index identifier: index=%lu phys_port=%s dev_port=%lu %s %s",
223 idx
, strempty(info
->phys_port_name
), dev_port
,
224 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), empty_to_na(names
->pci_onboard
));
226 if (sd_device_get_sysattr_value(names
->pcidev
, "label", &names
->pci_onboard_label
) >= 0)
227 log_device_debug(dev
, "Onboard label from PCI device: %s", names
->pci_onboard_label
);
229 names
->pci_onboard_label
= NULL
;
234 /* read the 256 bytes PCI configuration space to check the multi-function bit */
235 static int is_pci_multifunction(sd_device
*dev
) {
236 _cleanup_free_
uint8_t *config
= NULL
;
237 const char *filename
, *syspath
;
241 r
= sd_device_get_syspath(dev
, &syspath
);
245 filename
= strjoina(syspath
, "/config");
246 r
= read_virtual_file(filename
, PCI_HEADER_TYPE
+ 1, (char **) &config
, &len
);
249 if (len
< PCI_HEADER_TYPE
+ 1)
252 #ifndef PCI_HEADER_TYPE_MULTIFUNC
253 #define PCI_HEADER_TYPE_MULTIFUNC 0x80
256 /* bit 0-6 header type, bit 7 multi/single function device */
257 return config
[PCI_HEADER_TYPE
] & PCI_HEADER_TYPE_MULTIFUNC
;
260 static bool is_pci_ari_enabled(sd_device
*dev
) {
263 if (sd_device_get_sysattr_value(dev
, "ari_enabled", &a
) < 0)
266 return streq(a
, "1");
269 static bool is_pci_bridge(sd_device
*dev
) {
272 if (sd_device_get_sysattr_value(dev
, "modalias", &v
) < 0)
275 if (!startswith(v
, "pci:"))
284 /* PCI device subclass 04 corresponds to PCI bridge */
285 bool b
= strneq(p
+ 2, "04", 2);
287 log_device_debug(dev
, "Device is a PCI bridge.");
291 static int parse_hotplug_slot_from_function_id(sd_device
*dev
, int slots_dirfd
, uint32_t *ret
) {
292 uint64_t function_id
;
293 char filename
[NAME_MAX
+1];
297 /* The <sysname>/function_id attribute is unique to the s390 PCI driver. If present, we know
298 * that the slot's directory name for this device is /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is
299 * the fixed length 8 hexadecimal character string representation of function_id. Therefore we
300 * can short cut here and just check for the existence of the slot directory. As this directory
301 * has to exist, we're emitting a debug message for the unlikely case it's not found. Note that
302 * the domain part doesn't belong to the slot name here because there's a 1-to-1 relationship
303 * between PCI function and its hotplug slot. */
306 assert(slots_dirfd
>= 0);
309 if (!naming_scheme_has(NAMING_SLOT_FUNCTION_ID
))
312 if (sd_device_get_sysattr_value(dev
, "function_id", &attr
) < 0)
315 r
= safe_atou64(attr
, &function_id
);
317 return log_device_debug_errno(dev
, r
, "Failed to parse function_id, ignoring: %s", attr
);
319 if (function_id
<= 0 || function_id
> UINT32_MAX
)
320 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EINVAL
),
321 "Invalid function id (0x%"PRIx64
"), ignoring.",
324 if (!snprintf_ok(filename
, sizeof(filename
), "%08"PRIx64
, function_id
))
325 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
326 "PCI slot path is too long, ignoring.");
328 if (faccessat(slots_dirfd
, filename
, F_OK
, 0) < 0)
329 return log_device_debug_errno(dev
, errno
, "Cannot access %s under pci slots, ignoring: %m", filename
);
331 *ret
= (uint32_t) function_id
;
335 static int dev_pci_slot(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
336 const char *sysname
, *attr
;
337 _cleanup_(sd_device_unrefp
) sd_device
*pci
= NULL
;
338 _cleanup_closedir_
DIR *dir
= NULL
;
339 unsigned domain
, bus
, slot
, func
;
340 sd_device
*hotplug_slot_dev
;
341 unsigned long dev_port
= 0;
342 uint32_t hotplug_slot
= 0;
351 r
= sd_device_get_sysname(names
->pcidev
, &sysname
);
353 return log_device_debug_errno(names
->pcidev
, r
, "Failed to get sysname: %m");
355 r
= sscanf(sysname
, "%x:%x:%x.%u", &domain
, &bus
, &slot
, &func
);
356 log_device_debug(dev
, "Parsing slot information from PCI device sysname \"%s\": %s",
357 sysname
, r
== 4 ? "success" : "failure");
361 if (naming_scheme_has(NAMING_NPAR_ARI
) &&
362 is_pci_ari_enabled(names
->pcidev
))
363 /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
364 * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
365 * where the slot makes up the upper 5 bits. */
368 /* kernel provided port index for multiple ports on a single PCI function */
369 if (sd_device_get_sysattr_value(dev
, "dev_port", &attr
) >= 0) {
370 log_device_debug(dev
, "dev_port=%s", attr
);
372 r
= safe_atolu_full(attr
, 10, &dev_port
);
374 log_device_debug_errno(dev
, r
, "Failed to parse attribute dev_port, ignoring: %m");
376 /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
377 * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
378 * which thus stays initialized as 0. */
380 info
->iftype
== ARPHRD_INFINIBAND
&&
381 sd_device_get_sysattr_value(dev
, "dev_id", &attr
) >= 0) {
382 log_device_debug(dev
, "dev_id=%s", attr
);
384 r
= safe_atolu_full(attr
, 10, &dev_port
);
386 log_device_debug_errno(dev
, r
, "Failed to parse attribute dev_id, ignoring: %m");
390 /* compose a name based on the raw kernel's PCI bus, slot numbers */
392 l
= sizeof(names
->pci_path
);
394 l
= strpcpyf(&s
, l
, "P%u", domain
);
395 l
= strpcpyf(&s
, l
, "p%us%u", bus
, slot
);
396 if (func
> 0 || is_pci_multifunction(names
->pcidev
) > 0)
397 l
= strpcpyf(&s
, l
, "f%u", func
);
398 if (naming_scheme_has(NAMING_SR_IOV_R
) && info
->vf_representor_id
>= 0)
399 /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
400 l
= strpcpyf(&s
, l
, "r%d", info
->vf_representor_id
);
401 else if (!isempty(info
->phys_port_name
))
402 /* kernel provided front panel port name for multi-port PCI device */
403 l
= strpcpyf(&s
, l
, "n%s", info
->phys_port_name
);
404 else if (dev_port
> 0)
405 l
= strpcpyf(&s
, l
, "d%lu", dev_port
);
407 names
->pci_path
[0] = '\0';
409 log_device_debug(dev
, "PCI path identifier: domain=%u bus=%u slot=%u func=%u phys_port=%s dev_port=%lu %s %s",
410 domain
, bus
, slot
, func
, strempty(info
->phys_port_name
), dev_port
,
411 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), empty_to_na(names
->pci_path
));
413 /* ACPI _SUN — slot user number */
414 r
= sd_device_new_from_subsystem_sysname(&pci
, "subsystem", "pci");
416 return log_debug_errno(r
, "sd_device_new_from_subsystem_sysname() failed: %m");
418 r
= device_opendir(pci
, "slots", &dir
);
420 return log_device_debug_errno(dev
, r
, "Cannot access 'slots' subdirectory: %m");
422 hotplug_slot_dev
= names
->pcidev
;
423 while (hotplug_slot_dev
) {
424 r
= parse_hotplug_slot_from_function_id(hotplug_slot_dev
, dirfd(dir
), &hotplug_slot
);
428 domain
= 0; /* See comments in parse_hotplug_slot_from_function_id(). */
432 r
= sd_device_get_sysname(hotplug_slot_dev
, &sysname
);
434 return log_device_debug_errno(hotplug_slot_dev
, r
, "Failed to get sysname: %m");
436 FOREACH_DIRENT_ALL(de
, dir
, break) {
437 _cleanup_free_
char *path
= NULL
;
441 if (dot_or_dot_dot(de
->d_name
))
444 r
= safe_atou32(de
->d_name
, &i
);
448 path
= path_join("slots", de
->d_name
, "address");
452 if (sd_device_get_sysattr_value(pci
, path
, &address
) < 0)
455 /* match slot address with device by stripping the function */
456 if (!startswith(sysname
, address
))
461 /* We found the match between PCI device and slot. However, we won't use the slot
462 * index if the device is a PCI bridge, because it can have other child devices that
463 * will try to claim the same index and that would create name collision. */
464 if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT
) && is_pci_bridge(hotplug_slot_dev
)) {
465 if (naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT
) && is_pci_multifunction(names
->pcidev
) <= 0) {
466 log_device_debug(dev
,
467 "Not using slot information because the PCI device associated with "
468 "the hotplug slot is a bridge and the PCI device has a single function.");
472 if (!naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT
)) {
473 log_device_debug(dev
, "Not using slot information because the PCI device is a bridge.");
480 if (hotplug_slot
> 0)
482 if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev
, "pci", NULL
, &hotplug_slot_dev
) < 0)
487 if (hotplug_slot
> 0) {
489 l
= sizeof(names
->pci_slot
);
491 l
= strpcpyf(&s
, l
, "P%u", domain
);
492 l
= strpcpyf(&s
, l
, "s%"PRIu32
, hotplug_slot
);
493 if (func
> 0 || is_pci_multifunction(names
->pcidev
) > 0)
494 l
= strpcpyf(&s
, l
, "f%u", func
);
495 if (naming_scheme_has(NAMING_SR_IOV_R
) && info
->vf_representor_id
>= 0)
496 /* For VF representor append 'r<VF_NUM>' and not phys_port_name */
497 l
= strpcpyf(&s
, l
, "r%d", info
->vf_representor_id
);
498 else if (!isempty(info
->phys_port_name
))
499 l
= strpcpyf(&s
, l
, "n%s", info
->phys_port_name
);
500 else if (dev_port
> 0)
501 l
= strpcpyf(&s
, l
, "d%lu", dev_port
);
503 names
->pci_slot
[0] = '\0';
505 log_device_debug(dev
, "Slot identifier: domain=%u slot=%"PRIu32
" func=%u phys_port=%s dev_port=%lu %s %s",
506 domain
, hotplug_slot
, func
, strempty(info
->phys_port_name
), dev_port
,
507 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), empty_to_na(names
->pci_slot
));
513 static int names_vio(sd_device
*dev
, NetNames
*names
) {
515 unsigned busid
, slotid
, ethid
;
516 const char *syspath
, *subsystem
;
519 /* check if our direct parent is a VIO device with no other bus in-between */
520 r
= sd_device_get_parent(dev
, &parent
);
522 return log_device_debug_errno(dev
, r
, "sd_device_get_parent() failed: %m");
524 r
= sd_device_get_subsystem(parent
, &subsystem
);
526 return log_device_debug_errno(parent
, r
, "sd_device_get_subsystem() failed: %m");
527 if (!streq("vio", subsystem
))
529 log_device_debug(dev
, "Parent device is in the vio subsystem.");
531 /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id
532 * selected in the HMC), thus this provides a reliable naming (e.g.
533 * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as
534 * there should only ever be one bus, and then remove leading zeros. */
535 r
= sd_device_get_syspath(dev
, &syspath
);
537 return log_device_debug_errno(dev
, r
, "sd_device_get_syspath() failed: %m");
539 r
= sscanf(syspath
, "/sys/devices/vio/%4x%4x/net/eth%u", &busid
, &slotid
, ðid
);
540 log_device_debug(dev
, "Parsing vio slot information from syspath \"%s\": %s",
541 syspath
, r
== 3 ? "success" : "failure");
545 xsprintf(names
->vio_slot
, "v%u", slotid
);
546 names
->type
= NET_VIO
;
547 log_device_debug(dev
, "Vio slot identifier: slotid=%u %s %s",
548 slotid
, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), names
->vio_slot
);
552 #define PLATFORM_TEST "/sys/devices/platform/vvvvPPPP"
553 #define PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
554 #define PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
556 static int names_platform(sd_device
*dev
, NetNames
*names
, bool test
) {
559 unsigned model
, instance
, ethid
;
560 const char *syspath
, *pattern
, *validchars
, *subsystem
;
563 /* check if our direct parent is a platform device with no other bus in-between */
564 r
= sd_device_get_parent(dev
, &parent
);
566 return log_device_debug_errno(dev
, r
, "sd_device_get_parent() failed: %m");
568 r
= sd_device_get_subsystem(parent
, &subsystem
);
570 return log_device_debug_errno(parent
, r
, "sd_device_get_subsystem() failed: %m");
572 if (!streq("platform", subsystem
))
574 log_device_debug(dev
, "Parent device is in the platform subsystem.");
576 r
= sd_device_get_syspath(dev
, &syspath
);
578 return log_device_debug_errno(dev
, r
, "sd_device_get_syspath() failed: %m");
580 /* syspath is too short, to have a valid ACPI instance */
581 if (strlen(syspath
) < STRLEN(PLATFORM_TEST
) + 1)
582 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EINVAL
),
583 "Syspath \"%s\" is too short for a valid ACPI instance.",
586 /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */
587 if (syspath
[STRLEN(PLATFORM_TEST
)] == ':') {
588 pattern
= PLATFORM_PATTERN4
;
589 validchars
= UPPERCASE_LETTERS DIGITS
;
591 pattern
= PLATFORM_PATTERN3
;
592 validchars
= UPPERCASE_LETTERS
;
595 /* Platform devices are named after ACPI table match, and instance id
596 * eg. "/sys/devices/platform/HISI00C2:00");
597 * The Vendor (3 or 4 char), followed by hexadecimal model number : instance id. */
599 DISABLE_WARNING_FORMAT_NONLITERAL
;
600 r
= sscanf(syspath
, pattern
, vendor
, &model
, &instance
, ðid
);
602 log_device_debug(dev
, "Parsing platform device information from syspath \"%s\": %s",
603 syspath
, r
== 4 ? "success" : "failure");
607 if (!in_charset(vendor
, validchars
))
608 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENOENT
),
609 "Platform vendor contains invalid characters: %s", vendor
);
611 ascii_strlower(vendor
);
613 xsprintf(names
->platform_path
, "a%s%xi%u", vendor
, model
, instance
);
614 names
->type
= NET_PLATFORM
;
615 log_device_debug(dev
, "Platform identifier: vendor=%s model=%u instance=%u %s %s",
616 vendor
, model
, instance
, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), names
->platform_path
);
620 static int dev_devicetree_onboard(sd_device
*dev
, NetNames
*names
) {
621 _cleanup_(sd_device_unrefp
) sd_device
*aliases_dev
= NULL
, *ofnode_dev
= NULL
, *devicetree_dev
= NULL
;
622 const char *alias
, *ofnode_path
, *ofnode_syspath
, *devicetree_syspath
;
626 if (!naming_scheme_has(NAMING_DEVICETREE_ALIASES
))
629 /* check if our direct parent has an of_node */
630 r
= sd_device_get_parent(dev
, &parent
);
634 r
= sd_device_new_child(&ofnode_dev
, parent
, "of_node");
638 r
= sd_device_get_syspath(ofnode_dev
, &ofnode_syspath
);
642 /* /proc/device-tree should be a symlink to /sys/firmware/devicetree/base. */
643 r
= sd_device_new_from_path(&devicetree_dev
, "/proc/device-tree");
647 r
= sd_device_get_syspath(devicetree_dev
, &devicetree_syspath
);
653 * devicetree_syspath = /sys/firmware/devicetree/base
654 * ofnode_syspath = /sys/firmware/devicetree/base/soc/ethernet@deadbeef
655 * ofnode_path = soc/ethernet@deadbeef
657 ofnode_path
= path_startswith(ofnode_syspath
, devicetree_syspath
);
661 /* Get back our leading / to match the contents of the aliases */
663 assert(path_is_absolute(ofnode_path
));
665 r
= sd_device_new_child(&aliases_dev
, devicetree_dev
, "aliases");
669 FOREACH_DEVICE_SYSATTR(aliases_dev
, alias
) {
670 const char *alias_path
, *alias_index
, *conflict
;
673 alias_index
= startswith(alias
, "ethernet");
677 if (sd_device_get_sysattr_value(aliases_dev
, alias
, &alias_path
) < 0)
680 if (!path_equal(ofnode_path
, alias_path
))
683 /* If there's no index, we default to 0... */
684 if (isempty(alias_index
)) {
686 conflict
= "ethernet0";
688 r
= safe_atou(alias_index
, &i
);
690 return log_device_debug_errno(dev
, r
,
691 "Could not get index of alias %s: %m", alias
);
692 conflict
= "ethernet";
695 /* ...but make sure we don't have an alias conflict */
696 if (i
== 0 && sd_device_get_sysattr_value(aliases_dev
, conflict
, NULL
) >= 0)
697 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EEXIST
),
698 "Ethernet alias conflict: ethernet and ethernet0 both exist");
700 xsprintf(names
->devicetree_onboard
, "d%u", i
);
701 names
->type
= NET_DEVICETREE
;
708 static int names_pci(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
709 _cleanup_(sd_device_unrefp
) sd_device
*physfn_pcidev
= NULL
;
710 _cleanup_free_
char *virtfn_suffix
= NULL
;
712 const char *subsystem
;
719 r
= sd_device_get_parent(dev
, &parent
);
722 /* skip virtio subsystem if present */
723 parent
= skip_virtio(parent
);
728 /* check if our direct parent is a PCI device with no other bus in-between */
729 if (sd_device_get_subsystem(parent
, &subsystem
) >= 0 &&
730 streq("pci", subsystem
)) {
731 names
->type
= NET_PCI
;
732 names
->pcidev
= parent
;
734 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "pci", NULL
, &names
->pcidev
);
739 if (naming_scheme_has(NAMING_SR_IOV_V
) &&
740 get_virtfn_info(names
->pcidev
, &physfn_pcidev
, &virtfn_suffix
) >= 0) {
741 NetNames vf_names
= {};
743 /* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
744 vf_names
.pcidev
= physfn_pcidev
;
745 dev_pci_onboard(dev
, info
, &vf_names
);
746 dev_pci_slot(dev
, info
, &vf_names
);
748 if (vf_names
.pci_onboard
[0])
749 if (strlen(vf_names
.pci_onboard
) + strlen(virtfn_suffix
) < sizeof(names
->pci_onboard
))
750 strscpyl(names
->pci_onboard
, sizeof(names
->pci_onboard
),
751 vf_names
.pci_onboard
, virtfn_suffix
, NULL
);
752 if (vf_names
.pci_slot
[0])
753 if (strlen(vf_names
.pci_slot
) + strlen(virtfn_suffix
) < sizeof(names
->pci_slot
))
754 strscpyl(names
->pci_slot
, sizeof(names
->pci_slot
),
755 vf_names
.pci_slot
, virtfn_suffix
, NULL
);
756 if (vf_names
.pci_path
[0])
757 if (strlen(vf_names
.pci_path
) + strlen(virtfn_suffix
) < sizeof(names
->pci_path
))
758 strscpyl(names
->pci_path
, sizeof(names
->pci_path
),
759 vf_names
.pci_path
, virtfn_suffix
, NULL
);
761 dev_pci_onboard(dev
, info
, names
);
762 dev_pci_slot(dev
, info
, names
);
768 static int names_usb(sd_device
*dev
, NetNames
*names
) {
770 char name
[256], *ports
, *config
, *interf
, *s
;
778 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "usb", "usb_interface", &usbdev
);
780 return log_device_debug_errno(dev
, r
, "sd_device_get_parent_with_subsystem_devtype() failed: %m");
782 r
= sd_device_get_sysname(usbdev
, &sysname
);
784 return log_device_debug_errno(usbdev
, r
, "sd_device_get_sysname() failed: %m");
786 /* get USB port number chain, configuration, interface */
787 strscpy(name
, sizeof(name
), sysname
);
788 s
= strchr(name
, '-');
790 return log_device_debug_errno(usbdev
, SYNTHETIC_ERRNO(EINVAL
),
791 "sysname \"%s\" does not have '-' in the expected place.", sysname
);
794 s
= strchr(ports
, ':');
796 return log_device_debug_errno(usbdev
, SYNTHETIC_ERRNO(EINVAL
),
797 "sysname \"%s\" does not have ':' in the expected place.", sysname
);
801 s
= strchr(config
, '.');
803 return log_device_debug_errno(usbdev
, SYNTHETIC_ERRNO(EINVAL
),
804 "sysname \"%s\" does not have '.' in the expected place.", sysname
);
808 /* prefix every port number in the chain with "u" */
810 while ((s
= strchr(s
, '.')))
812 s
= names
->usb_ports
;
813 l
= strpcpyl(&s
, sizeof(names
->usb_ports
), "u", ports
, NULL
);
815 /* append USB config number, suppress the common config == 1 */
816 if (!streq(config
, "1"))
817 l
= strpcpyl(&s
, sizeof(names
->usb_ports
), "c", config
, NULL
);
819 /* append USB interface number, suppress the interface == 0 */
820 if (!streq(interf
, "0"))
821 l
= strpcpyl(&s
, sizeof(names
->usb_ports
), "i", interf
, NULL
);
823 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
824 "Generated USB name would be too long.");
825 log_device_debug(dev
, "USB name identifier: ports=%.*s config=%s interface=%s %s %s",
826 (int) strlen(ports
), sysname
+ (ports
- name
), config
, interf
,
827 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), names
->usb_ports
);
828 names
->type
= NET_USB
;
832 static int names_bcma(sd_device
*dev
, NetNames
*names
) {
841 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "bcma", NULL
, &bcmadev
);
843 return log_device_debug_errno(dev
, r
, "sd_device_get_parent_with_subsystem_devtype() failed: %m");
845 r
= sd_device_get_sysname(bcmadev
, &sysname
);
847 return log_device_debug_errno(dev
, r
, "sd_device_get_sysname() failed: %m");
849 /* bus num:core num */
850 r
= sscanf(sysname
, "bcma%*u:%u", &core
);
851 log_device_debug(dev
, "Parsing bcma device information from sysname \"%s\": %s",
852 sysname
, r
== 1 ? "success" : "failure");
855 /* suppress the common core == 0 */
857 xsprintf(names
->bcma_core
, "b%u", core
);
859 names
->type
= NET_BCMA
;
860 log_device_debug(dev
, "BCMA core identifier: core=%u %s \"%s\"",
861 core
, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), names
->bcma_core
);
865 static int names_ccw(sd_device
*dev
, NetNames
*names
) {
867 const char *bus_id
, *subsys
;
868 size_t bus_id_start
, bus_id_len
;
874 /* Retrieve the associated CCW device */
875 r
= sd_device_get_parent(dev
, &cdev
);
877 return log_device_debug_errno(dev
, r
, "sd_device_get_parent() failed: %m");
879 /* skip virtio subsystem if present */
880 cdev
= skip_virtio(cdev
);
884 r
= sd_device_get_subsystem(cdev
, &subsys
);
886 return log_device_debug_errno(cdev
, r
, "sd_device_get_subsystem() failed: %m");
888 /* Network devices are either single or grouped CCW devices */
889 if (!STR_IN_SET(subsys
, "ccwgroup", "ccw"))
891 log_device_debug(dev
, "Device is CCW.");
893 /* Retrieve bus-ID of the CCW device. The bus-ID uniquely
894 * identifies the network device on the Linux on System z channel
895 * subsystem. Note that the bus-ID contains lowercase characters.
897 r
= sd_device_get_sysname(cdev
, &bus_id
);
899 return log_device_debug_errno(cdev
, r
, "Failed to get sysname: %m");
901 /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID;
902 * alternatively, improve this check and parse and verify each bus-ID part...
904 bus_id_len
= strlen(bus_id
);
905 if (!IN_SET(bus_id_len
, 8, 9))
906 return log_device_debug_errno(cdev
, SYNTHETIC_ERRNO(EINVAL
),
907 "Invalid bus_id: %s", bus_id
);
909 /* Strip leading zeros from the bus id for aesthetic purposes. This
910 * keeps the ccw names stable, yet much shorter in general case of
911 * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is
912 * not prepended when it is zero. Preserve the last 0 for 0.0.0000.
914 bus_id_start
= strspn(bus_id
, ".0");
915 bus_id
+= bus_id_start
< bus_id_len
? bus_id_start
: bus_id_len
- 1;
917 /* Store the CCW bus-ID for use as network device name */
918 if (!snprintf_ok(names
->ccw_busid
, sizeof(names
->ccw_busid
), "c%s", bus_id
))
919 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
920 "Generated CCW name would be too long.");
921 names
->type
= NET_CCW
;
922 log_device_debug(dev
, "CCW identifier: ccw_busid=%s %s \"%s\"",
923 bus_id
, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), names
->ccw_busid
);
927 static int names_mac(sd_device
*dev
, const LinkInfo
*info
) {
935 /* The persistent part of a hardware address of an InfiniBand NIC is 8 bytes long. We cannot
936 * fit this much in an iface name.
937 * TODO: but it can be used as alternative names?? */
938 if (info
->iftype
== ARPHRD_INFINIBAND
)
939 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EOPNOTSUPP
),
940 "Not generating MAC name for infiniband device.");
941 if (info
->hw_addr
.length
!= 6)
942 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EOPNOTSUPP
),
943 "Not generating MAC name for device with MAC address of length %zu.",
944 info
->hw_addr
.length
);
946 /* check for NET_ADDR_PERM, skip random MAC addresses */
947 r
= sd_device_get_sysattr_value(dev
, "addr_assign_type", &s
);
949 return log_device_debug_errno(dev
, r
, "Failed to read addr_assign_type: %m");
950 r
= safe_atou(s
, &i
);
952 return log_device_debug_errno(dev
, r
, "Failed to parse addr_assign_type: %m");
953 if (i
!= NET_ADDR_PERM
)
954 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EINVAL
),
955 "addr_assign_type=%u, MAC address is not permanent.", i
);
959 static int names_netdevsim(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
960 sd_device
*netdevsimdev
;
965 if (!naming_scheme_has(NAMING_NETDEVSIM
))
972 if (isempty(info
->phys_port_name
))
975 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "netdevsim", NULL
, &netdevsimdev
);
978 r
= sd_device_get_sysname(netdevsimdev
, &sysname
);
982 if (sscanf(sysname
, "netdevsim%u", &addr
) != 1)
985 if (!snprintf_ok(names
->netdevsim_path
, sizeof(names
->netdevsim_path
), "i%un%s", addr
, info
->phys_port_name
))
988 names
->type
= NET_NETDEVSIM
;
993 static int names_xen(sd_device
*dev
, NetNames
*names
) {
996 const char *syspath
, *subsystem
, *p
, *p2
;
1002 if (!naming_scheme_has(NAMING_XEN_VIF
))
1005 /* check if our direct parent is a Xen VIF device with no other bus in-between */
1006 r
= sd_device_get_parent(dev
, &parent
);
1010 /* Do an exact-match on subsystem "xen". This will miss on "xen-backend" on
1011 * purpose as the VIFs on the backend (dom0) have their own naming scheme
1012 * which we don't want to affect
1014 r
= sd_device_get_subsystem(parent
, &subsystem
);
1017 if (!streq("xen", subsystem
))
1020 /* Use the vif-n name to extract "n" */
1021 r
= sd_device_get_syspath(dev
, &syspath
);
1025 p
= path_startswith(syspath
, "/sys/devices/");
1028 p
= startswith(p
, "vif-");
1031 p2
= strchr(p
, '/');
1034 p
= strndupa_safe(p
, p2
- p
);
1037 r
= safe_atou_full(p
, SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_ZERO
|
1038 SAFE_ATO_REFUSE_LEADING_WHITESPACE
| 10, &id
);
1041 xsprintf(names
->xen_slot
, "X%u", id
);
1042 names
->type
= NET_XENVIF
;
1046 /* IEEE Organizationally Unique Identifier vendor string */
1047 static int ieee_oui(sd_device
*dev
, const LinkInfo
*info
, bool test
) {
1053 if (info
->hw_addr
.length
!= 6)
1056 /* skip commonly misused 00:00:00 (Xerox) prefix */
1057 if (info
->hw_addr
.bytes
[0] == 0 &&
1058 info
->hw_addr
.bytes
[1] == 0 &&
1059 info
->hw_addr
.bytes
[2] == 0)
1062 xsprintf(str
, "OUI:%02X%02X%02X%02X%02X%02X",
1063 info
->hw_addr
.bytes
[0],
1064 info
->hw_addr
.bytes
[1],
1065 info
->hw_addr
.bytes
[2],
1066 info
->hw_addr
.bytes
[3],
1067 info
->hw_addr
.bytes
[4],
1068 info
->hw_addr
.bytes
[5]);
1069 return udev_builtin_hwdb_lookup(dev
, NULL
, str
, NULL
, test
);
1072 static int get_link_info(sd_device
*dev
, LinkInfo
*info
) {
1079 r
= sd_device_get_ifindex(dev
, &info
->ifindex
);
1083 r
= device_get_sysattr_int(dev
, "iflink", &info
->iflink
);
1087 r
= device_get_sysattr_int(dev
, "type", &info
->iftype
);
1091 r
= sd_device_get_devtype(dev
, &info
->devtype
);
1092 if (r
< 0 && r
!= -ENOENT
)
1095 r
= sd_device_get_sysattr_value(dev
, "phys_port_name", &info
->phys_port_name
);
1097 /* Check if phys_port_name indicates virtual device representor */
1098 (void) sscanf(info
->phys_port_name
, "pf%*uvf%d", &info
->vf_representor_id
);
1100 r
= sd_device_get_sysattr_value(dev
, "address", &s
);
1101 if (r
< 0 && r
!= -ENOENT
)
1104 r
= parse_hw_addr(s
, &info
->hw_addr
);
1106 log_device_debug_errno(dev
, r
, "Failed to parse 'address' sysattr, ignoring: %m");
1112 static int builtin_net_id(UdevEvent
*event
, int argc
, char *argv
[], bool test
) {
1113 sd_device
*dev
= ASSERT_PTR(ASSERT_PTR(event
)->dev
);
1115 NetNames names
= {};
1117 .vf_representor_id
= -1,
1121 r
= get_link_info(dev
, &info
);
1125 /* skip stacked devices, like VLANs, ... */
1126 if (info
.ifindex
!= info
.iflink
)
1129 /* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */
1130 switch (info
.iftype
) {
1134 case ARPHRD_INFINIBAND
:
1135 if (naming_scheme_has(NAMING_INFINIBAND
))
1147 if (streq_ptr("wlan", info
.devtype
))
1149 else if (streq_ptr("wwan", info
.devtype
))
1152 udev_builtin_add_property(dev
, test
, "ID_NET_NAMING_SCHEME", naming_scheme()->name
);
1154 if (names_mac(dev
, &info
) >= 0) {
1155 char str
[ALTIFNAMSIZ
];
1157 xsprintf(str
, "%sx%s", prefix
, HW_ADDR_TO_STR_FULL(&info
.hw_addr
, HW_ADDR_TO_STRING_NO_COLON
));
1158 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_MAC", str
);
1159 log_device_debug(dev
, "MAC address identifier: hw_addr=%s %s %s",
1160 HW_ADDR_TO_STR(&info
.hw_addr
),
1161 special_glyph(SPECIAL_GLYPH_ARROW_RIGHT
), str
+ strlen(prefix
));
1163 ieee_oui(dev
, &info
, test
);
1166 /* get devicetree aliases; only ethernet supported for now */
1167 if (streq(prefix
, "en") && dev_devicetree_onboard(dev
, &names
) >= 0 &&
1168 names
.type
== NET_DEVICETREE
) {
1169 char str
[ALTIFNAMSIZ
];
1171 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.devicetree_onboard
))
1172 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_ONBOARD", str
);
1175 /* get path names for Linux on System z network devices */
1176 if (names_ccw(dev
, &names
) >= 0 && names
.type
== NET_CCW
) {
1177 char str
[ALTIFNAMSIZ
];
1179 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.ccw_busid
))
1180 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1184 /* get ibmveth/ibmvnic slot-based names. */
1185 if (names_vio(dev
, &names
) >= 0 && names
.type
== NET_VIO
) {
1186 char str
[ALTIFNAMSIZ
];
1188 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.vio_slot
))
1189 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1193 /* get ACPI path names for ARM64 platform devices */
1194 if (names_platform(dev
, &names
, test
) >= 0 && names
.type
== NET_PLATFORM
) {
1195 char str
[ALTIFNAMSIZ
];
1197 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.platform_path
))
1198 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1202 /* get netdevsim path names */
1203 if (names_netdevsim(dev
, &info
, &names
) >= 0 && names
.type
== NET_NETDEVSIM
) {
1204 char str
[ALTIFNAMSIZ
];
1206 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.netdevsim_path
))
1207 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1212 /* get xen vif "slot" based names. */
1213 if (names_xen(dev
, &names
) >= 0 && names
.type
== NET_XENVIF
) {
1214 char str
[ALTIFNAMSIZ
];
1216 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.xen_slot
))
1217 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1221 /* get PCI based path names */
1222 r
= names_pci(dev
, &info
, &names
);
1225 * check for usb devices that are not off pci interfaces to
1226 * support various on-chip asics that have usb ports
1229 naming_scheme_has(NAMING_USB_HOST
) &&
1230 names_usb(dev
, &names
) >= 0 && names
.type
== NET_USB
) {
1231 char str
[ALTIFNAMSIZ
];
1233 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.usb_ports
))
1234 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1240 /* plain PCI device */
1241 if (names
.type
== NET_PCI
) {
1242 char str
[ALTIFNAMSIZ
];
1244 if (names
.pci_onboard
[0] &&
1245 snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.pci_onboard
))
1246 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_ONBOARD", str
);
1248 if (names
.pci_onboard_label
&&
1249 snprintf_ok(str
, sizeof str
, "%s%s",
1250 naming_scheme_has(NAMING_LABEL_NOPREFIX
) ? "" : prefix
,
1251 names
.pci_onboard_label
))
1252 udev_builtin_add_property(dev
, test
, "ID_NET_LABEL_ONBOARD", str
);
1254 if (names
.pci_path
[0] &&
1255 snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.pci_path
))
1256 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1258 if (names
.pci_slot
[0] &&
1259 snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.pci_slot
))
1260 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1265 if (names_usb(dev
, &names
) >= 0 && names
.type
== NET_USB
) {
1266 char str
[ALTIFNAMSIZ
];
1268 if (names
.pci_path
[0] &&
1269 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_path
, names
.usb_ports
))
1270 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1272 if (names
.pci_slot
[0] &&
1273 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_slot
, names
.usb_ports
))
1274 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1279 if (names_bcma(dev
, &names
) >= 0 && names
.type
== NET_BCMA
) {
1280 char str
[ALTIFNAMSIZ
];
1282 if (names
.pci_path
[0] &&
1283 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_path
, names
.bcma_core
))
1284 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1286 if (names
.pci_slot
[0] &&
1287 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_slot
, names
.bcma_core
))
1288 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1295 static int builtin_net_id_init(void) {
1296 /* Load naming scheme here to suppress log messages in workers. */
1301 const UdevBuiltin udev_builtin_net_id
= {
1303 .cmd
= builtin_net_id
,
1304 .init
= builtin_net_id_init
,
1305 .help
= "Network device properties",