0

tl;dr: During load of an initramfs (execution of dracut modules) on a PXE client, I need to rename the kernel-given (predictable) interface names (right now they're unpredictable ethX names). This way, the PXE client will always boot from a predictably named interface. Currently I'm reading the hardware info with dmesg during the dracut cmdline hook. Could I cat a udev rule to /usr/lib/udev/rules.d/ here so that the system could rename the interfaces when dracut later triggers udev?

Basically I have this in the dracut cmdline hook:

# First read hardware provided
if dmesg | grep -q "SOME_BOARD_NAME"; then
    root=$(echo "$root" | sed -e 's/PLACEHOLDER_FILE/SOME_ROOTFS.sqsh/')
    # Additionally, some udev rules are needed specific to this board.
#    mkdir -p /etc/udev/rules.d
#    echo "install these boards' rules!\n"
#    echo << EOF > /etc/udev/rules.d/70-persistent-net.rules
#SUBSYSTEM=="net", DEVPATH="/devices/pci*/*1c.0/0000:07:00.0/net/*", NAME="eth0"
#SUBSYSTEM=="net", DEVPATH="/devices/pci*/*01.1/0000:05:00.0/net/*", NAME="eth1"
#SUBSYSTEM=="net", DEVPATH="/devices/pci*/*01.1/0000:05:00.1/net/*", NAME="eth2"
#EOF
elif dmesg | grep -q "SOME_OTHER_BOARD_NAME"; then
    root=$(echo "$root" | sed -e 's/PLACEHOLDER_FILE/SOME_OTHER_ROOTFS.sqsh/')
    echo "install other board-specific rules!\n"
#    mkdir -p /etc/udev/rules.d
#    echo << EOF > /etc/udev/rules.d/70-persistent-net.rules
#SUBSYSTEM=="net", DEVPATH="/devices/pci*/*1c.5/0000:09:00.0/net/*", NAME="eth0"
#SUBSYSTEM=="net", DEVPATH="/devices/pci*/*02.2/0000:02:00.0/net/*", NAME="eth1"
#SUBSYSTEM=="net", DEVPATH="/devices/pci*/*02.2/0000:02:00.1/net/*", NAME="eth2"
#EOF
else
    warn "Did not detect either board - defaulting to SOME_OTHER_ROOTFS.sqsh"
    root=$(echo "$root" | sed -e 's/PLACEHOLDER_FILE/SOME_OTHER_ROOTFS.sqsh/')
fi

More info: My team and I have a single board computer that PXE boots from an external server. This follows a sequence of:

  1. The SBC pulls an initramfs and loads that.
  2. The initramfs executes a dracut module that reads the hardware info of the SBC (during the dracut hook "cmdline").
  3. The SBC pulls down a particular root filesystem depending on its hardware.

Unfortunately, the old ethX (unpredictable) interface names sometimes cause the SBC to pull down the root filesystem over the wrong network interface.

My plan is to remove net.ifnames=0 and biosdevname=0 from the kernel command line used to PXE boot (step 1). Then after the kernel has assigned predictable names, I want to extend the dracut module to add udev rules to rename them to the old names. I'm hoping when dracut triggers udev, the SBC will then always pull the root filesystem over the correct interface.

brimhalgh
  • 1
  • 1
  • eth0 is predictable , they are in the order they are detected, The (Un)PredictableNetworkNames mess uses properties of the device which is often unknown (and thus random) and in no way predictable. If you have multiple interfaces, what you probably need is to have your PXE boot inform the kernel of which Ethernet Address (mac) that is used for booting, and make sure system uses that device. – NiKiZe Jun 11 '22 at 09:14
  • The name is in a sense "predictable" but the order they are detected is not. I think that's why sources like this say "unpredictable": https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/ The mac address is a good idea; unfortunately this installation will be repeated on a fleet of SBCs which will have different physical NICs and mac addresses. – brimhalgh Jun 14 '22 at 14:07
  • You need to have the PXE loading part add the mac to the kernel commandline and then parse that to know which nic it was actually booted from. – NiKiZe Jun 15 '22 at 15:45
  • In dracut you could parse the commandline for MACs. If they're always assigned (and predictably incremented) in the same order for every physical NIC, the problem is solved. If we're just passing some values that we have to parse and handle ourselves, it's kicking the can down the road. The problem is, if we're checking which NIC it booted from, that's already too late. We need to tell it which NIC in dracut to boot from. In any case, the issue is resolved. :) – brimhalgh Jun 16 '22 at 20:08

1 Answers1

0

Ultimately we kept net.ifnames=0 but we set biosdevname=1. During the dracut installation, we added a module to sed the network interface related scripts (that were up next in the install process) to bypass the net.ifnames=0 logic and instead only use biosdevname.

It certainly felt hack-y, but it got the job done for this system.

brimhalgh
  • 1
  • 1