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"
26 #include "chase-symlinks.h"
27 #include "device-util.h"
28 #include "dirent-util.h"
31 #include "netif-naming-scheme.h"
32 #include "parse-util.h"
33 #include "proc-cmdline.h"
34 #include "stdio-util.h"
35 #include "string-util.h"
38 #include "udev-builtin.h"
39 #include "udev-netlink.h"
41 #define ONBOARD_14BIT_INDEX_MAX ((1U << 14) - 1)
42 #define ONBOARD_16BIT_INDEX_MAX ((1U << 16) - 1)
44 typedef enum NetNameType
{
57 typedef struct NetNames
{
61 char pci_slot
[ALTIFNAMSIZ
];
62 char pci_path
[ALTIFNAMSIZ
];
63 char pci_onboard
[ALTIFNAMSIZ
];
64 const char *pci_onboard_label
;
66 char usb_ports
[ALTIFNAMSIZ
];
67 char bcma_core
[ALTIFNAMSIZ
];
68 char ccw_busid
[ALTIFNAMSIZ
];
69 char vio_slot
[ALTIFNAMSIZ
];
70 char xen_slot
[ALTIFNAMSIZ
];
71 char platform_path
[ALTIFNAMSIZ
];
72 char netdevsim_path
[ALTIFNAMSIZ
];
75 /* skip intermediate virtio devices */
76 static sd_device
*skip_virtio(sd_device
*dev
) {
77 /* there can only ever be one virtio bus per parent device, so we can
78 * safely ignore any virtio buses. see
79 * http://lists.linuxfoundation.org/pipermail/virtualization/2015-August/030331.html */
81 const char *subsystem
;
83 if (sd_device_get_subsystem(dev
, &subsystem
) < 0)
86 if (!streq(subsystem
, "virtio"))
89 if (sd_device_get_parent(dev
, &dev
) < 0)
96 static int get_virtfn_info(sd_device
*pcidev
, sd_device
**ret_physfn_pcidev
, char **ret_suffix
) {
97 _cleanup_(sd_device_unrefp
) sd_device
*physfn_pcidev
= NULL
;
98 const char *physfn_syspath
, *syspath
;
99 _cleanup_closedir_
DIR *dir
= NULL
;
103 assert(ret_physfn_pcidev
);
106 r
= sd_device_get_syspath(pcidev
, &syspath
);
110 /* Get physical function's pci device. */
111 physfn_syspath
= strjoina(syspath
, "/physfn");
112 r
= sd_device_new_from_syspath(&physfn_pcidev
, physfn_syspath
);
116 r
= sd_device_get_syspath(physfn_pcidev
, &physfn_syspath
);
120 /* Find the virtual function number by finding the right virtfn link. */
121 dir
= opendir(physfn_syspath
);
125 FOREACH_DIRENT_ALL(de
, dir
, break) {
126 _cleanup_free_
char *virtfn_link_file
= NULL
, *virtfn_pci_syspath
= NULL
;
129 n
= startswith(de
->d_name
, "virtfn");
133 virtfn_link_file
= path_join(physfn_syspath
, de
->d_name
);
134 if (!virtfn_link_file
)
137 if (chase_symlinks(virtfn_link_file
, NULL
, 0, &virtfn_pci_syspath
, NULL
) < 0)
140 if (streq(syspath
, virtfn_pci_syspath
)) {
143 suffix
= strjoin("v", n
);
147 *ret_physfn_pcidev
= TAKE_PTR(physfn_pcidev
);
148 *ret_suffix
= suffix
;
156 static bool is_valid_onboard_index(unsigned long idx
) {
157 /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
158 * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
159 * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
160 * interface a system might have. Ideally the kernel would already filter this crap for us, but it
161 * doesn't currently. The initial cut-off value (2^14-1) was too conservative for s390 PCI which
162 * allows for index values up 2^16-1 which is now enabled with the NAMING_16BIT_INDEX naming flag. */
163 return idx
<= (naming_scheme_has(NAMING_16BIT_INDEX
) ? ONBOARD_16BIT_INDEX_MAX
: ONBOARD_14BIT_INDEX_MAX
);
166 /* retrieve on-board index number and label from firmware */
167 static int dev_pci_onboard(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
168 unsigned long idx
, dev_port
= 0;
178 /* ACPI _DSM — device specific method for naming a PCI or PCI Express device */
179 if (sd_device_get_sysattr_value(names
->pcidev
, "acpi_index", &attr
) >= 0)
180 log_device_debug(names
->pcidev
, "acpi_index=%s", attr
);
182 /* SMBIOS type 41 — Onboard Devices Extended Information */
183 r
= sd_device_get_sysattr_value(names
->pcidev
, "index", &attr
);
186 log_device_debug(names
->pcidev
, "index=%s", attr
);
189 r
= safe_atolu(attr
, &idx
);
191 return log_device_debug_errno(names
->pcidev
, r
,
192 "Failed to parse onboard index \"%s\": %m", attr
);
193 if (idx
== 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX
))
194 return log_device_debug_errno(names
->pcidev
, SYNTHETIC_ERRNO(EINVAL
),
195 "Naming scheme does not allow onboard index==0.");
196 if (!is_valid_onboard_index(idx
))
197 return log_device_debug_errno(names
->pcidev
, SYNTHETIC_ERRNO(ENOENT
),
198 "Not a valid onboard index: %lu", idx
);
200 /* kernel provided port index for multiple ports on a single PCI function */
201 if (sd_device_get_sysattr_value(dev
, "dev_port", &attr
) >= 0) {
202 r
= safe_atolu_full(attr
, 10, &dev_port
);
204 log_device_debug_errno(dev
, r
, "Failed to parse dev_port, ignoring: %m");
205 log_device_debug(dev
, "dev_port=%lu", dev_port
);
208 s
= names
->pci_onboard
;
209 l
= sizeof(names
->pci_onboard
);
210 l
= strpcpyf(&s
, l
, "o%lu", idx
);
211 if (!isempty(info
->phys_port_name
))
212 /* kernel provided front panel port name for multiple port PCI device */
213 l
= strpcpyf(&s
, l
, "n%s", info
->phys_port_name
);
214 else if (dev_port
> 0)
215 l
= strpcpyf(&s
, l
, "d%lu", dev_port
);
217 names
->pci_onboard
[0] = '\0';
218 log_device_debug(dev
, "Onboard index identifier: index=%lu phys_port=%s dev_port=%lu → %s",
219 idx
, strempty(info
->phys_port_name
), dev_port
,
220 empty_to_na(names
->pci_onboard
));
222 if (sd_device_get_sysattr_value(names
->pcidev
, "label", &names
->pci_onboard_label
) >= 0)
223 log_device_debug(dev
, "Onboard label from PCI device: %s", names
->pci_onboard_label
);
225 names
->pci_onboard_label
= NULL
;
230 /* read the 256 bytes PCI configuration space to check the multi-function bit */
231 static bool is_pci_multifunction(sd_device
*dev
) {
232 _cleanup_close_
int fd
= -1;
233 const char *filename
, *syspath
;
236 if (sd_device_get_syspath(dev
, &syspath
) < 0)
239 filename
= strjoina(syspath
, "/config");
240 fd
= open(filename
, O_RDONLY
| O_CLOEXEC
);
243 if (read(fd
, &config
, sizeof(config
)) != sizeof(config
))
246 /* bit 0-6 header type, bit 7 multi/single function device */
247 return config
[PCI_HEADER_TYPE
] & 0x80;
250 static bool is_pci_ari_enabled(sd_device
*dev
) {
253 if (sd_device_get_sysattr_value(dev
, "ari_enabled", &a
) < 0)
256 return streq(a
, "1");
259 static bool is_pci_bridge(sd_device
*dev
) {
262 if (sd_device_get_sysattr_value(dev
, "modalias", &v
) < 0)
265 if (!startswith(v
, "pci:"))
274 /* PCI device subclass 04 corresponds to PCI bridge */
275 bool b
= strneq(p
+ 2, "04", 2);
277 log_device_debug(dev
, "Device is a PCI bridge.");
281 static int parse_hotplug_slot_from_function_id(sd_device
*dev
, const char *slots
, uint32_t *ret
) {
282 uint64_t function_id
;
287 /* The <sysname>/function_id attribute is unique to the s390 PCI driver. If present, we know
288 * that the slot's directory name for this device is /sys/bus/pci/XXXXXXXX/ where XXXXXXXX is
289 * the fixed length 8 hexadecimal character string representation of function_id. Therefore we
290 * can short cut here and just check for the existence of the slot directory. As this directory
291 * has to exist, we're emitting a debug message for the unlikely case it's not found. Note that
292 * the domain part doesn't belong to the slot name here because there's a 1-to-1 relationship
293 * between PCI function and its hotplug slot. */
299 if (!naming_scheme_has(NAMING_SLOT_FUNCTION_ID
))
302 if (sd_device_get_sysattr_value(dev
, "function_id", &attr
) < 0)
305 r
= safe_atou64(attr
, &function_id
);
307 return log_device_debug_errno(dev
, r
, "Failed to parse function_id, ignoring: %s", attr
);
309 if (function_id
<= 0 || function_id
> UINT32_MAX
)
310 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EINVAL
),
311 "Invalid function id (0x%"PRIx64
"), ignoring.",
314 if (!snprintf_ok(path
, sizeof path
, "%s/%08"PRIx64
, slots
, function_id
))
315 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
316 "PCI slot path is too long, ignoring.");
318 if (access(path
, F_OK
) < 0)
319 return log_device_debug_errno(dev
, errno
, "Cannot access %s, ignoring: %m", path
);
321 *ret
= (uint32_t) function_id
;
325 static int dev_pci_slot(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
326 const char *sysname
, *attr
, *syspath
;
327 _cleanup_(sd_device_unrefp
) sd_device
*pci
= NULL
;
328 _cleanup_closedir_
DIR *dir
= NULL
;
329 unsigned domain
, bus
, slot
, func
;
330 sd_device
*hotplug_slot_dev
;
331 unsigned long dev_port
= 0;
332 uint32_t hotplug_slot
= 0;
333 char slots
[PATH_MAX
], *s
;
341 r
= sd_device_get_sysname(names
->pcidev
, &sysname
);
343 return log_device_debug_errno(names
->pcidev
, r
, "Failed to get sysname: %m");
345 r
= sscanf(sysname
, "%x:%x:%x.%u", &domain
, &bus
, &slot
, &func
);
346 log_device_debug(dev
, "Parsing slot information from PCI device sysname \"%s\": %s",
347 sysname
, r
== 4 ? "success" : "failure");
351 if (naming_scheme_has(NAMING_NPAR_ARI
) &&
352 is_pci_ari_enabled(names
->pcidev
))
353 /* ARI devices support up to 256 functions on a single device ("slot"), and interpret the
354 * traditional 5-bit slot and 3-bit function number as a single 8-bit function number,
355 * where the slot makes up the upper 5 bits. */
358 /* kernel provided port index for multiple ports on a single PCI function */
359 if (sd_device_get_sysattr_value(dev
, "dev_port", &attr
) >= 0) {
360 log_device_debug(dev
, "dev_port=%s", attr
);
362 r
= safe_atolu_full(attr
, 10, &dev_port
);
364 log_device_debug_errno(dev
, r
, "Failed to parse attribute dev_port, ignoring: %m");
366 /* With older kernels IP-over-InfiniBand network interfaces sometimes erroneously
367 * provide the port number in the 'dev_id' sysfs attribute instead of 'dev_port',
368 * which thus stays initialized as 0. */
370 info
->iftype
== ARPHRD_INFINIBAND
&&
371 sd_device_get_sysattr_value(dev
, "dev_id", &attr
) >= 0) {
372 log_device_debug(dev
, "dev_id=%s", attr
);
374 r
= safe_atolu_full(attr
, 10, &dev_port
);
376 log_device_debug_errno(dev
, r
, "Failed to parse attribute dev_id, ignoring: %m");
380 /* compose a name based on the raw kernel's PCI bus, slot numbers */
382 l
= sizeof(names
->pci_path
);
384 l
= strpcpyf(&s
, l
, "P%u", domain
);
385 l
= strpcpyf(&s
, l
, "p%us%u", bus
, slot
);
386 if (func
> 0 || is_pci_multifunction(names
->pcidev
))
387 l
= strpcpyf(&s
, l
, "f%u", func
);
388 if (!isempty(info
->phys_port_name
))
389 /* kernel provided front panel port name for multi-port PCI device */
390 l
= strpcpyf(&s
, l
, "n%s", info
->phys_port_name
);
391 else if (dev_port
> 0)
392 l
= strpcpyf(&s
, l
, "d%lu", dev_port
);
394 names
->pci_path
[0] = '\0';
396 log_device_debug(dev
, "PCI path identifier: domain=%u bus=%u slot=%u func=%u phys_port=%s dev_port=%lu → %s",
397 domain
, bus
, slot
, func
, strempty(info
->phys_port_name
), dev_port
,
398 empty_to_na(names
->pci_path
));
400 /* ACPI _SUN — slot user number */
401 r
= sd_device_new_from_subsystem_sysname(&pci
, "subsystem", "pci");
403 return log_debug_errno(r
, "sd_device_new_from_subsystem_sysname failed: %m");
405 r
= sd_device_get_syspath(pci
, &syspath
);
407 return log_device_debug_errno(pci
, r
, "sd_device_get_syspath failed: %m");
409 if (!snprintf_ok(slots
, sizeof slots
, "%s/slots", syspath
))
410 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
411 "Cannot access %s/slots: %m", syspath
);
413 dir
= opendir(slots
);
415 return log_device_debug_errno(dev
, errno
, "Cannot access %s: %m", slots
);
417 hotplug_slot_dev
= names
->pcidev
;
418 while (hotplug_slot_dev
) {
419 r
= parse_hotplug_slot_from_function_id(hotplug_slot_dev
, slots
, &hotplug_slot
);
423 domain
= 0; /* See comments in parse_hotplug_slot_from_function_id(). */
427 r
= sd_device_get_sysname(hotplug_slot_dev
, &sysname
);
429 return log_device_debug_errno(hotplug_slot_dev
, r
, "Failed to get sysname: %m");
431 FOREACH_DIRENT_ALL(de
, dir
, break) {
432 _cleanup_free_
char *address
= NULL
;
436 if (dot_or_dot_dot(de
->d_name
))
439 r
= safe_atou32(de
->d_name
, &i
);
443 /* match slot address with device by stripping the function */
444 if (snprintf_ok(str
, sizeof str
, "%s/%s/address", slots
, de
->d_name
) &&
445 read_one_line_file(str
, &address
) >= 0 &&
446 startswith(sysname
, address
)) {
449 /* We found the match between PCI device and slot. However, we won't use the
450 * slot index if the device is a PCI bridge, because it can have other child
451 * devices that will try to claim the same index and that would create name
453 if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT
) && is_pci_bridge(hotplug_slot_dev
)) {
454 if (naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT
) && !is_pci_multifunction(names
->pcidev
)) {
455 log_device_debug(dev
, "Not using slot information because the PCI device associated with the hotplug slot is a bridge and the PCI device has single function.");
459 if (!naming_scheme_has(NAMING_BRIDGE_MULTIFUNCTION_SLOT
)) {
460 log_device_debug(dev
, "Not using slot information because the PCI device is a bridge.");
468 if (hotplug_slot
> 0)
470 if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev
, "pci", NULL
, &hotplug_slot_dev
) < 0)
475 if (hotplug_slot
> 0) {
477 l
= sizeof(names
->pci_slot
);
479 l
= strpcpyf(&s
, l
, "P%u", domain
);
480 l
= strpcpyf(&s
, l
, "s%"PRIu32
, hotplug_slot
);
481 if (func
> 0 || is_pci_multifunction(names
->pcidev
))
482 l
= strpcpyf(&s
, l
, "f%u", func
);
483 if (!isempty(info
->phys_port_name
))
484 l
= strpcpyf(&s
, l
, "n%s", info
->phys_port_name
);
485 else if (dev_port
> 0)
486 l
= strpcpyf(&s
, l
, "d%lu", dev_port
);
488 names
->pci_slot
[0] = '\0';
490 log_device_debug(dev
, "Slot identifier: domain=%u slot=%"PRIu32
" func=%u phys_port=%s dev_port=%lu → %s",
491 domain
, hotplug_slot
, func
, strempty(info
->phys_port_name
), dev_port
,
492 empty_to_na(names
->pci_slot
));
498 static int names_vio(sd_device
*dev
, NetNames
*names
) {
500 unsigned busid
, slotid
, ethid
;
501 const char *syspath
, *subsystem
;
504 /* check if our direct parent is a VIO device with no other bus in-between */
505 r
= sd_device_get_parent(dev
, &parent
);
507 return log_device_debug_errno(dev
, r
, "sd_device_get_parent failed: %m");
509 r
= sd_device_get_subsystem(parent
, &subsystem
);
511 return log_device_debug_errno(parent
, r
, "sd_device_get_subsystem failed: %m");
512 if (!streq("vio", subsystem
))
514 log_device_debug(dev
, "Parent device is in the vio subsystem.");
516 /* The devices' $DEVPATH number is tied to (virtual) hardware (slot id
517 * selected in the HMC), thus this provides a reliable naming (e.g.
518 * "/devices/vio/30000002/net/eth1"); we ignore the bus number, as
519 * there should only ever be one bus, and then remove leading zeros. */
520 r
= sd_device_get_syspath(dev
, &syspath
);
522 return log_device_debug_errno(dev
, r
, "sd_device_get_syspath failed: %m");
524 r
= sscanf(syspath
, "/sys/devices/vio/%4x%4x/net/eth%u", &busid
, &slotid
, ðid
);
525 log_device_debug(dev
, "Parsing vio slot information from syspath \"%s\": %s",
526 syspath
, r
== 3 ? "success" : "failure");
530 xsprintf(names
->vio_slot
, "v%u", slotid
);
531 names
->type
= NET_VIO
;
532 log_device_debug(dev
, "Vio slot identifier: slotid=%u → %s", slotid
, names
->vio_slot
);
536 #define PLATFORM_TEST "/sys/devices/platform/vvvvPPPP"
537 #define PLATFORM_PATTERN4 "/sys/devices/platform/%4s%4x:%2x/net/eth%u"
538 #define PLATFORM_PATTERN3 "/sys/devices/platform/%3s%4x:%2x/net/eth%u"
540 static int names_platform(sd_device
*dev
, NetNames
*names
, bool test
) {
543 unsigned model
, instance
, ethid
;
544 const char *syspath
, *pattern
, *validchars
, *subsystem
;
547 /* check if our direct parent is a platform device with no other bus in-between */
548 r
= sd_device_get_parent(dev
, &parent
);
550 return log_device_debug_errno(dev
, r
, "sd_device_get_parent failed: %m");
552 r
= sd_device_get_subsystem(parent
, &subsystem
);
554 return log_device_debug_errno(parent
, r
, "sd_device_get_subsystem failed: %m");
556 if (!streq("platform", subsystem
))
558 log_device_debug(dev
, "Parent device is in the platform subsystem.");
560 r
= sd_device_get_syspath(dev
, &syspath
);
562 return log_device_debug_errno(dev
, r
, "sd_device_get_syspath failed: %m");
564 /* syspath is too short, to have a valid ACPI instance */
565 if (strlen(syspath
) < STRLEN(PLATFORM_TEST
) + 1)
566 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EINVAL
),
567 "Syspath \"%s\" is too short for a valid ACPI instance.",
570 /* Vendor ID can be either PNP ID (3 chars A-Z) or ACPI ID (4 chars A-Z and numerals) */
571 if (syspath
[STRLEN(PLATFORM_TEST
)] == ':') {
572 pattern
= PLATFORM_PATTERN4
;
573 validchars
= UPPERCASE_LETTERS DIGITS
;
575 pattern
= PLATFORM_PATTERN3
;
576 validchars
= UPPERCASE_LETTERS
;
579 /* Platform devices are named after ACPI table match, and instance id
580 * eg. "/sys/devices/platform/HISI00C2:00");
581 * The Vendor (3 or 4 char), followed by hexadecimal model number : instance id. */
583 DISABLE_WARNING_FORMAT_NONLITERAL
;
584 r
= sscanf(syspath
, pattern
, vendor
, &model
, &instance
, ðid
);
586 log_device_debug(dev
, "Parsing platform device information from syspath \"%s\": %s",
587 syspath
, r
== 4 ? "success" : "failure");
591 if (!in_charset(vendor
, validchars
))
592 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENOENT
),
593 "Platform vendor contains invalid characters: %s", vendor
);
595 ascii_strlower(vendor
);
597 xsprintf(names
->platform_path
, "a%s%xi%u", vendor
, model
, instance
);
598 names
->type
= NET_PLATFORM
;
599 log_device_debug(dev
, "Platform identifier: vendor=%s model=%u instance=%u → %s",
600 vendor
, model
, instance
, names
->platform_path
);
604 static int names_pci(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
605 _cleanup_(sd_device_unrefp
) sd_device
*physfn_pcidev
= NULL
;
606 _cleanup_free_
char *virtfn_suffix
= NULL
;
608 const char *subsystem
;
615 r
= sd_device_get_parent(dev
, &parent
);
618 /* skip virtio subsystem if present */
619 parent
= skip_virtio(parent
);
624 /* check if our direct parent is a PCI device with no other bus in-between */
625 if (sd_device_get_subsystem(parent
, &subsystem
) >= 0 &&
626 streq("pci", subsystem
)) {
627 names
->type
= NET_PCI
;
628 names
->pcidev
= parent
;
630 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "pci", NULL
, &names
->pcidev
);
635 if (naming_scheme_has(NAMING_SR_IOV_V
) &&
636 get_virtfn_info(names
->pcidev
, &physfn_pcidev
, &virtfn_suffix
) >= 0) {
637 NetNames vf_names
= {};
639 /* If this is an SR-IOV virtual device, get base name using physical device and add virtfn suffix. */
640 vf_names
.pcidev
= physfn_pcidev
;
641 dev_pci_onboard(dev
, info
, &vf_names
);
642 dev_pci_slot(dev
, info
, &vf_names
);
644 if (vf_names
.pci_onboard
[0])
645 if (strlen(vf_names
.pci_onboard
) + strlen(virtfn_suffix
) < sizeof(names
->pci_onboard
))
646 strscpyl(names
->pci_onboard
, sizeof(names
->pci_onboard
),
647 vf_names
.pci_onboard
, virtfn_suffix
, NULL
);
648 if (vf_names
.pci_slot
[0])
649 if (strlen(vf_names
.pci_slot
) + strlen(virtfn_suffix
) < sizeof(names
->pci_slot
))
650 strscpyl(names
->pci_slot
, sizeof(names
->pci_slot
),
651 vf_names
.pci_slot
, virtfn_suffix
, NULL
);
652 if (vf_names
.pci_path
[0])
653 if (strlen(vf_names
.pci_path
) + strlen(virtfn_suffix
) < sizeof(names
->pci_path
))
654 strscpyl(names
->pci_path
, sizeof(names
->pci_path
),
655 vf_names
.pci_path
, virtfn_suffix
, NULL
);
657 dev_pci_onboard(dev
, info
, names
);
658 dev_pci_slot(dev
, info
, names
);
664 static int names_usb(sd_device
*dev
, NetNames
*names
) {
666 char name
[256], *ports
, *config
, *interf
, *s
;
674 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "usb", "usb_interface", &usbdev
);
676 return log_device_debug_errno(dev
, r
, "sd_device_get_parent_with_subsystem_devtype() failed: %m");
678 r
= sd_device_get_sysname(usbdev
, &sysname
);
680 return log_device_debug_errno(usbdev
, r
, "sd_device_get_sysname() failed: %m");
682 /* get USB port number chain, configuration, interface */
683 strscpy(name
, sizeof(name
), sysname
);
684 s
= strchr(name
, '-');
686 return log_device_debug_errno(usbdev
, SYNTHETIC_ERRNO(EINVAL
),
687 "sysname \"%s\" does not have '-' in the expected place.", sysname
);
690 s
= strchr(ports
, ':');
692 return log_device_debug_errno(usbdev
, SYNTHETIC_ERRNO(EINVAL
),
693 "sysname \"%s\" does not have ':' in the expected place.", sysname
);
697 s
= strchr(config
, '.');
699 return log_device_debug_errno(usbdev
, SYNTHETIC_ERRNO(EINVAL
),
700 "sysname \"%s\" does not have '.' in the expected place.", sysname
);
704 /* prefix every port number in the chain with "u" */
706 while ((s
= strchr(s
, '.')))
708 s
= names
->usb_ports
;
709 l
= strpcpyl(&s
, sizeof(names
->usb_ports
), "u", ports
, NULL
);
711 /* append USB config number, suppress the common config == 1 */
712 if (!streq(config
, "1"))
713 l
= strpcpyl(&s
, sizeof(names
->usb_ports
), "c", config
, NULL
);
715 /* append USB interface number, suppress the interface == 0 */
716 if (!streq(interf
, "0"))
717 l
= strpcpyl(&s
, sizeof(names
->usb_ports
), "i", interf
, NULL
);
719 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
720 "Generated USB name would be too long.");
721 log_device_debug(dev
, "USB name identifier: ports=%.*s config=%s interface=%s → %s",
722 (int) strlen(ports
), sysname
+ (ports
- name
), config
, interf
, names
->usb_ports
);
723 names
->type
= NET_USB
;
727 static int names_bcma(sd_device
*dev
, NetNames
*names
) {
736 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "bcma", NULL
, &bcmadev
);
738 return log_device_debug_errno(dev
, r
, "sd_device_get_parent_with_subsystem_devtype() failed: %m");
740 r
= sd_device_get_sysname(bcmadev
, &sysname
);
742 return log_device_debug_errno(dev
, r
, "sd_device_get_sysname() failed: %m");
744 /* bus num:core num */
745 r
= sscanf(sysname
, "bcma%*u:%u", &core
);
746 log_device_debug(dev
, "Parsing bcma device information from sysname \"%s\": %s",
747 sysname
, r
== 1 ? "success" : "failure");
750 /* suppress the common core == 0 */
752 xsprintf(names
->bcma_core
, "b%u", core
);
754 names
->type
= NET_BCMA
;
755 log_device_debug(dev
, "BCMA core identifier: core=%u → \"%s\"", core
, names
->bcma_core
);
759 static int names_ccw(sd_device
*dev
, NetNames
*names
) {
761 const char *bus_id
, *subsys
;
762 size_t bus_id_start
, bus_id_len
;
768 /* Retrieve the associated CCW device */
769 r
= sd_device_get_parent(dev
, &cdev
);
771 return log_device_debug_errno(dev
, r
, "sd_device_get_parent() failed: %m");
773 /* skip virtio subsystem if present */
774 cdev
= skip_virtio(cdev
);
778 r
= sd_device_get_subsystem(cdev
, &subsys
);
780 return log_device_debug_errno(cdev
, r
, "sd_device_get_subsystem() failed: %m");
782 /* Network devices are either single or grouped CCW devices */
783 if (!STR_IN_SET(subsys
, "ccwgroup", "ccw"))
785 log_device_debug(dev
, "Device is CCW.");
787 /* Retrieve bus-ID of the CCW device. The bus-ID uniquely
788 * identifies the network device on the Linux on System z channel
789 * subsystem. Note that the bus-ID contains lowercase characters.
791 r
= sd_device_get_sysname(cdev
, &bus_id
);
793 return log_device_debug_errno(cdev
, r
, "Failed to get sysname: %m");
795 /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID;
796 * alternatively, improve this check and parse and verify each bus-ID part...
798 bus_id_len
= strlen(bus_id
);
799 if (!IN_SET(bus_id_len
, 8, 9))
800 return log_device_debug_errno(cdev
, SYNTHETIC_ERRNO(EINVAL
),
801 "Invalid bus_id: %s", bus_id
);
803 /* Strip leading zeros from the bus id for aesthetic purposes. This
804 * keeps the ccw names stable, yet much shorter in general case of
805 * bus_id 0.0.0600 -> 600. This is similar to e.g. how PCI domain is
806 * not prepended when it is zero. Preserve the last 0 for 0.0.0000.
808 bus_id_start
= strspn(bus_id
, ".0");
809 bus_id
+= bus_id_start
< bus_id_len
? bus_id_start
: bus_id_len
- 1;
811 /* Store the CCW bus-ID for use as network device name */
812 if (!snprintf_ok(names
->ccw_busid
, sizeof(names
->ccw_busid
), "c%s", bus_id
))
813 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(ENAMETOOLONG
),
814 "Generated CCW name would be too long.");
815 names
->type
= NET_CCW
;
816 log_device_debug(dev
, "CCW identifier: ccw_busid=%s → \"%s\"", bus_id
, names
->ccw_busid
);
820 static int names_mac(sd_device
*dev
, const LinkInfo
*info
) {
828 /* The persistent part of a hardware address of an InfiniBand NIC is 8 bytes long. We cannot
829 * fit this much in an iface name.
830 * TODO: but it can be used as alternative names?? */
831 if (info
->iftype
== ARPHRD_INFINIBAND
)
832 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EOPNOTSUPP
),
833 "Not generating MAC name for infiniband device.");
834 if (info
->hw_addr
.length
!= 6)
835 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EOPNOTSUPP
),
836 "Not generating MAC name for device with MAC address of length %zu.",
837 info
->hw_addr
.length
);
839 /* check for NET_ADDR_PERM, skip random MAC addresses */
840 r
= sd_device_get_sysattr_value(dev
, "addr_assign_type", &s
);
842 return log_device_debug_errno(dev
, r
, "Failed to read addr_assign_type: %m");
843 r
= safe_atou(s
, &i
);
845 return log_device_debug_errno(dev
, r
, "Failed to parse addr_assign_type: %m");
846 if (i
!= NET_ADDR_PERM
)
847 return log_device_debug_errno(dev
, SYNTHETIC_ERRNO(EINVAL
),
848 "addr_assign_type=%d, MAC address is not permanent.", i
);
852 static int names_netdevsim(sd_device
*dev
, const LinkInfo
*info
, NetNames
*names
) {
853 sd_device
*netdevsimdev
;
858 if (!naming_scheme_has(NAMING_NETDEVSIM
))
865 if (isempty(info
->phys_port_name
))
868 r
= sd_device_get_parent_with_subsystem_devtype(dev
, "netdevsim", NULL
, &netdevsimdev
);
871 r
= sd_device_get_sysname(netdevsimdev
, &sysname
);
875 if (sscanf(sysname
, "netdevsim%u", &addr
) != 1)
878 if (!snprintf_ok(names
->netdevsim_path
, sizeof(names
->netdevsim_path
), "i%un%s", addr
, info
->phys_port_name
))
881 names
->type
= NET_NETDEVSIM
;
886 static int names_xen(sd_device
*dev
, NetNames
*names
) {
889 const char *syspath
, *subsystem
, *p
, *p2
;
895 if (!naming_scheme_has(NAMING_XEN_VIF
))
898 /* check if our direct parent is a Xen VIF device with no other bus in-between */
899 r
= sd_device_get_parent(dev
, &parent
);
903 /* Do an exact-match on subsystem "xen". This will miss on "xen-backend" on
904 * purpose as the VIFs on the backend (dom0) have their own naming scheme
905 * which we don't want to affect
907 r
= sd_device_get_subsystem(parent
, &subsystem
);
910 if (!streq("xen", subsystem
))
913 /* Use the vif-n name to extract "n" */
914 r
= sd_device_get_syspath(dev
, &syspath
);
918 p
= path_startswith(syspath
, "/sys/devices/");
921 p
= startswith(p
, "vif-");
927 p
= strndupa_safe(p
, p2
- p
);
930 r
= safe_atou_full(p
, SAFE_ATO_REFUSE_PLUS_MINUS
| SAFE_ATO_REFUSE_LEADING_ZERO
|
931 SAFE_ATO_REFUSE_LEADING_WHITESPACE
| 10, &id
);
934 xsprintf(names
->xen_slot
, "X%u", id
);
935 names
->type
= NET_XENVIF
;
939 /* IEEE Organizationally Unique Identifier vendor string */
940 static int ieee_oui(sd_device
*dev
, const LinkInfo
*info
, bool test
) {
946 if (info
->hw_addr
.length
!= 6)
949 /* skip commonly misused 00:00:00 (Xerox) prefix */
950 if (info
->hw_addr
.bytes
[0] == 0 &&
951 info
->hw_addr
.bytes
[1] == 0 &&
952 info
->hw_addr
.bytes
[2] == 0)
955 xsprintf(str
, "OUI:%02X%02X%02X%02X%02X%02X",
956 info
->hw_addr
.bytes
[0],
957 info
->hw_addr
.bytes
[1],
958 info
->hw_addr
.bytes
[2],
959 info
->hw_addr
.bytes
[3],
960 info
->hw_addr
.bytes
[4],
961 info
->hw_addr
.bytes
[5]);
962 return udev_builtin_hwdb_lookup(dev
, NULL
, str
, NULL
, test
);
965 static int builtin_net_id(sd_device
*dev
, sd_netlink
**rtnl
, int argc
, char *argv
[], bool test
) {
966 _cleanup_(link_info_clear
) LinkInfo info
= LINK_INFO_NULL
;
967 const char *devtype
, *prefix
= "en";
971 r
= sd_device_get_ifindex(dev
, &ifindex
);
975 r
= link_info_get(rtnl
, ifindex
, &info
);
979 if (!info
.phys_port_name_supported
) {
982 r
= sd_device_get_sysattr_value(dev
, "phys_port_name", &s
);
984 info
.phys_port_name
= strdup(s
);
985 if (!info
.phys_port_name
)
990 r
= device_cache_sysattr_from_link_info(dev
, &info
);
994 /* skip stacked devices, like VLANs, ... */
995 if (info
.ifindex
!= (int) info
.iflink
)
998 /* handle only ARPHRD_ETHER, ARPHRD_SLIP and ARPHRD_INFINIBAND devices */
999 switch (info
.iftype
) {
1003 case ARPHRD_INFINIBAND
:
1004 if (naming_scheme_has(NAMING_INFINIBAND
))
1016 if (sd_device_get_devtype(dev
, &devtype
) >= 0) {
1017 if (streq("wlan", devtype
))
1019 else if (streq("wwan", devtype
))
1023 udev_builtin_add_property(dev
, test
, "ID_NET_NAMING_SCHEME", naming_scheme()->name
);
1025 if (names_mac(dev
, &info
) >= 0) {
1026 char str
[ALTIFNAMSIZ
];
1028 xsprintf(str
, "%sx%s", prefix
, HW_ADDR_TO_STR_FULL(&info
.hw_addr
, HW_ADDR_TO_STRING_NO_COLON
));
1029 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_MAC", str
);
1030 log_device_debug(dev
, "MAC address identifier: hw_addr=%s → %s",
1031 HW_ADDR_TO_STR(&info
.hw_addr
), str
+ strlen(prefix
));
1033 ieee_oui(dev
, &info
, test
);
1036 /* get path names for Linux on System z network devices */
1037 if (names_ccw(dev
, &names
) >= 0 && names
.type
== NET_CCW
) {
1038 char str
[ALTIFNAMSIZ
];
1040 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.ccw_busid
))
1041 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1045 /* get ibmveth/ibmvnic slot-based names. */
1046 if (names_vio(dev
, &names
) >= 0 && names
.type
== NET_VIO
) {
1047 char str
[ALTIFNAMSIZ
];
1049 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.vio_slot
))
1050 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1054 /* get ACPI path names for ARM64 platform devices */
1055 if (names_platform(dev
, &names
, test
) >= 0 && names
.type
== NET_PLATFORM
) {
1056 char str
[ALTIFNAMSIZ
];
1058 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.platform_path
))
1059 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1063 /* get netdevsim path names */
1064 if (names_netdevsim(dev
, &info
, &names
) >= 0 && names
.type
== NET_NETDEVSIM
) {
1065 char str
[ALTIFNAMSIZ
];
1067 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.netdevsim_path
))
1068 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1073 /* get xen vif "slot" based names. */
1074 if (names_xen(dev
, &names
) >= 0 && names
.type
== NET_XENVIF
) {
1075 char str
[ALTIFNAMSIZ
];
1077 if (snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.xen_slot
))
1078 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1082 /* get PCI based path names, we compose only PCI based paths */
1083 if (names_pci(dev
, &info
, &names
) < 0)
1086 /* plain PCI device */
1087 if (names
.type
== NET_PCI
) {
1088 char str
[ALTIFNAMSIZ
];
1090 if (names
.pci_onboard
[0] &&
1091 snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.pci_onboard
))
1092 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_ONBOARD", str
);
1094 if (names
.pci_onboard_label
&&
1095 snprintf_ok(str
, sizeof str
, "%s%s",
1096 naming_scheme_has(NAMING_LABEL_NOPREFIX
) ? "" : prefix
,
1097 names
.pci_onboard_label
))
1098 udev_builtin_add_property(dev
, test
, "ID_NET_LABEL_ONBOARD", str
);
1100 if (names
.pci_path
[0] &&
1101 snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.pci_path
))
1102 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1104 if (names
.pci_slot
[0] &&
1105 snprintf_ok(str
, sizeof str
, "%s%s", prefix
, names
.pci_slot
))
1106 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1111 if (names_usb(dev
, &names
) >= 0 && names
.type
== NET_USB
) {
1112 char str
[ALTIFNAMSIZ
];
1114 if (names
.pci_path
[0] &&
1115 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_path
, names
.usb_ports
))
1116 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1118 if (names
.pci_slot
[0] &&
1119 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_slot
, names
.usb_ports
))
1120 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1125 if (names_bcma(dev
, &names
) >= 0 && names
.type
== NET_BCMA
) {
1126 char str
[ALTIFNAMSIZ
];
1128 if (names
.pci_path
[0] &&
1129 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_path
, names
.bcma_core
))
1130 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_PATH", str
);
1132 if (names
.pci_slot
[0] &&
1133 snprintf_ok(str
, sizeof str
, "%s%s%s", prefix
, names
.pci_slot
, names
.bcma_core
))
1134 udev_builtin_add_property(dev
, test
, "ID_NET_NAME_SLOT", str
);
1141 const UdevBuiltin udev_builtin_net_id
= {
1143 .cmd
= builtin_net_id
,
1144 .help
= "Network device properties",