The predictable network interface naming scheme (used by systemd since v197) follows specific patterns based on hardware topology:
enpXsY
- PCI devices (X=bus number, Y=slot)ensX
- onboard devices with indexenxMAC
- MAC address-based naming
The PCI bus info format pci@0000:XX:YY.Z
contains the components needed for interface naming:
0000:XX:YY.Z
|| | | |
|| | | +-> Function number (usually 0 for NICs)
|| | +---> Slot/device number
|| +------> Bus number
+-----------> Domain (typically 0000)
For your specific case with bus info pci@0000:41:00.0
:
Bus number: 41
Slot number: 00
Function: 0
Resulting interface name: enp41s0
While booting the target system would be definitive, these commands in the rescue system can help predict names:
# List all PCI network devices with bus info
lspci -D -nn | grep -i ethernet
# Cross-reference with detailed hardware info
lshw -class network -businfo
# Alternative method using udev rules simulation
udevadm test-builtin net_id /sys/class/net/eth0 2>/dev/null | grep ID_NET_NAME_
Here's a bash script to predict interface names from PCI info:
#!/bin/bash
for dev in $(ls /sys/class/net/ | grep -v lo); do
pci_path=$(readlink -f /sys/class/net/$dev/device)
if [[ $pci_path == *pci* ]]; then
bus=$(basename $(dirname $pci_path) | cut -d':' -f2)
slot=$(basename $pci_path | cut -d':' -f3 | cut -d'.' -f1)
echo "$dev → predicted name: enp${bus}s${slot}"
fi
done
Some special situations to consider:
- Virtual interfaces (bridges, bonds, veth pairs) won't follow this scheme
- Multi-function cards might use different function numbers (rare for NICs)
- Some embedded systems might have inconsistent numbering
To pre-configure networking in your target system:
# Example /etc/netplan/01-netcfg.yaml for enp8s0 and enp41s0
network:
version: 2
renderer: networkd
ethernets:
enp8s0:
dhcp4: true
enp41s0:
addresses: [192.168.1.100/24]
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
Modern Linux distributions like Ubuntu (since version 15.10) use predictable network interface names based on the systemd naming scheme. This replaces the traditional eth0, eth1 convention with names like enp8s0 or enp41s0 that are derived from physical hardware attributes.
The predictable naming scheme follows this pattern:
en - Ethernet
p8 - PCI bus 8
s0 - Slot 0
From your example, pci@0000:08:00.0
translates to enp8s0
, while pci@0000:41:00.0
would indeed become enp41s0
.
Here's how to determine interface names from the rescue system:
# First, list all network devices
lshw -class network -businfo
# Sample output:
Bus info Device Class Description
=====================================================
pci@0000:08:00.0 eth0 network Ethernet controller
pci@0000:41:00.0 none network Ethernet controller (disabled)
For a more automated approach, use this script to generate predictable names:
#!/bin/bash
for device in $(lshw -class network -short | grep pci | awk '{print $2}'); do
bus=$(echo $device | cut -d@ -f2 | cut -d: -f2)
slot=$(echo $device | cut -d: -f3 | cut -d. -f1)
echo "PCI $device will be enp${bus}s${slot}"
done
If you need to verify names before configuration, consider these approaches:
- Check udev rules in
/etc/udev/rules.d/70-persistent-net.rules
- Examine
/sys/class/net/
directory structure - Use
ip link show
after temporary boot
If you prefer the old naming scheme, you can disable predictable names by adding:
net.ifnames=0 biosdevname=0
to your kernel boot parameters in /etc/default/grub
.