7

I am setting up a new server and installed Ubuntu Bionic, which uses Predictable Network Interface Names.

The installer is running on a rescue system, which still uses old interface names like eth0, eth1, but the newly installed system has configured the first network card as enp8s0.

Using lshw, the bus info for this card is:

bus info: pci@0000:08:00.0

I would like to set up the other network interfaces without booting into the newly installed system yet, but don't know how to determine the predictable network interface names for the other cards.

Using lshw, I found another network card, which is currently disabled:

bus info: pci@0000:41:00.0

Is it possible to determine the predictable network interface name from this? Would it be something like enp41s0?

I have searched for a while and could not find any tool which would simply list all the devices together with their predictable names.

Edit: Why do I not want to boot the new system to find out? Because this would add an extra step to the setup process. Using the old interface naming, I could run a script to set up the server from the rescue system provided by the hosting company and it was ready for use. Now I would have to set up the server minus the additional network config first. Then I have to set up networking manually once the new system has booted, just to know the names of the interfaces.

pymkin
  • 225
  • 3
  • 8

3 Answers3

8

Details of the naming scheme are in the source code: udev/udev-builtin-net_id.c. Previously, this had a nice readable comment block explaining things, but since a refactor removed that a better reference is at man systemd.net-naming-scheme.

Some common schemes are PCI physical, PCI hotplug, and onboard. Your enp interface suggests physical.

Stripping out exotic and irrelevant bits from the comments leaves these rules:

 * Two character prefixes based on the type of interface:
 *   en — Ethernet
 *
 * Type of names:
 *   [P<domain>]p<bus>s<slot>[f<function>][n<phys_port_name>|d<dev_port>]
 *                                         — PCI geographical location
 *
 * All multi-function PCI devices will carry the [f<function>] number in the
 * device name, including the function 0 device.
 *
 *
 * When using PCI geography, The PCI domain is only prepended when it is not 0.

That PCI bus name is formatted as domain:bus:slot.function.

Assuming it is not a multifunction device, pci@0000:41:00.0 appears as enp65s0, since hex 41 converts to decimal 65.

John Mahowald
  • 30,009
  • 1
  • 17
  • 32
  • Thanks for the explanation. Funnily, the device turned up as `enp65s0` after booting into the new OS. I was looking for a tool that could tell me these names without having to boot the new system, it slows down the server setup. – pymkin May 05 '19 at 05:13
  • 1
    @pymkin The PCI bus and other numbers shown in `lspci` etc. are in hex; the numbers used in the interface name are in decimal. So you have to convert from hex to decimal. – Michael Hampton May 05 '19 at 05:31
  • @MichaelHampton that explains it, thanks! HEX 41 -> DEC 65. So `pci@0000:41:00.0` becomes `enp65s0` – pymkin May 05 '19 at 05:36
3

There are some (new) possibilities to find the predictable network interface name directly. You can use udevadm info for this. Additionally you get some more info, which might be useful.

The command can export it as key-value pairs for easy use in scripts. See ID_NET_NAME in this example:

# udevadm info --export --query=property --path=/sys/class/net/eth0
DEVPATH='/devices/pci0000:00/0000:00:0d.0/0000:02:00.0/net/eth0'
INTERFACE='eth0'
IFINDEX='2'
SUBSYSTEM='net'
USEC_INITIALIZED='3750679'
ID_NET_NAME_MAC='enx0012345678'
ID_OUI_FROM_DATABASE='Super Micro Computer, Inc.'
ID_NET_NAME_PATH='enp2s0f0'
ID_BUS='pci'
ID_VENDOR_ID='0x8086'
ID_MODEL_ID='0x10c9'
ID_PCI_CLASS_FROM_DATABASE='Network controller'
ID_PCI_SUBCLASS_FROM_DATABASE='Ethernet controller'
ID_VENDOR_FROM_DATABASE='Intel Corporation'
ID_MODEL_FROM_DATABASE='82576 Gigabit Network Connection'
ID_PATH='pci-0000:02:00.0'
ID_PATH_TAG='pci-0000_02_00_0'
ID_NET_DRIVER='igb'
ID_NET_LINK_FILE='/lib/systemd/network/99-default.link'
ID_NET_NAME='enp2s0f0'
SYSTEMD_ALIAS='/sys/subsystem/net/devices/eth0'
TAGS=':systemd:'

Reminder: This example is for interfaces which still have the name "eth[0-9]". Otherwise the predictable name is the interface name.

Marco
  • 316
  • 1
  • 6
  • All I get is: `Unknown device "/sys//class/net/eth0": No such device` – Michael Hampton Aug 19 '20 at 14:53
  • If you already know the device name, why would you need to look it up?! – Michael Hampton Aug 20 '20 at 11:38
  • 2
    You know the "old" name and want to know the "predictable" name. Why? On upgrade, the "old" name could change to the "predictable" name after reboot. On Install (e.g. FAI) the install image uses the "old" name, but after boot into the installed image, you get the "predictable" name. During installation, you want to set up network interfaces and you need the "predictable" name. ... and so on ... – Marco Aug 23 '20 at 15:48
0

We're using the following "one-liner" in our company to map existing interfaces to their respective predictable name:

echo; [ -e /etc/systemd/network/99-default.link ] && echo '!!! Predictable Network Interface Names are disabled - /etc/systemd/network/99-default.link exists! !!!' && ls -l /etc/systemd/network/99-default.link && echo; echo; [ -e /etc/udev/rules.d/80-net-setup-link.rules  ] && echo '!!! Predictable Network Interface Names are disabled - /etc/udev/rules.d/80-net-setup-link.rules  exists! !!!' && ls -l /etc/udev/rules.d/80-net-setup-link.rules && echo; for i in /sys/class/net/*; do udevadm info -q property "$i" | perl -Mwarnings -Mstrict -e 'my $res = {}; while(<>) { chomp; my @f = split /=/, $_, 2; $res->{$f[0]} = $f[1]; }; printf "%s: %s\n", $res->{DEVPATH}, $res->{ID_NET_NAME_FROM_DATABASE} // $res->{ID_NET_NAME_ONBOARD} // $res->{ID_NET_NAME_SLOT} // $res->{ID_NET_NAME_PATH} // $res->{ID_NET_NAME_MAC} // "???";'; done

It implements the ordering described on https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ can be quickly copy-pasted via SSH.

Example output from my machine:

/devices/virtual/net/docker0: ???
/devices/pci0000:00/0000:00:01.2/0000:02:00.2/0000:03:09.0/0000:2a:00.0/net/enp42s0: enp42s0
/devices/virtual/net/lo: ???
/devices/virtual/net/tun0: ???
/devices/virtual/net/veth732bf87: ???
/devices/pci0000:00/0000:00:01.2/0000:02:00.2/0000:03:08.0/0000:29:00.0/net/wlo1: wlo1