diff options
| author | John Estabrook <jestabro@vyos.io> | 2026-08-20 09:24:38 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-20 09:24:38 -0500 |
| commit | b30ccbf4a5fdcc2240664d9b6d3814c90f7b1868 (patch) | |
| tree | f893994eb0116893021d272705dd65231c11a186 /src | |
| parent | 79e70fbfe0c4b5b33c5c707f0b0fee904fedd79f (diff) | |
| parent | a1360d645df8a82cd593d55ca592a8a1d60b34b3 (diff) | |
| download | vyos-1x-b30ccbf4a5fdcc2240664d9b6d3814c90f7b1868.tar.gz vyos-1x-b30ccbf4a5fdcc2240664d9b6d3814c90f7b1868.zip | |
Merge pull request #5338 from ritika0313/T8329-azure-interface-naming-fix
T8329: Fix interface naming for Azure VF interfaces with Accelerated Networking enabled
Diffstat (limited to 'src')
| -rw-r--r-- | src/etc/udev/rules.d/63-hyperv-vf-net.rules | 6 | ||||
| -rw-r--r-- | src/etc/udev/rules.d/65-vyos-net.rules | 18 | ||||
| -rwxr-xr-x | src/system/vyos-net-name-resolve.py | 13 | ||||
| -rwxr-xr-x | src/udev/vyos_vf_name | 88 |
4 files changed, 124 insertions, 1 deletions
diff --git a/src/etc/udev/rules.d/63-hyperv-vf-net.rules b/src/etc/udev/rules.d/63-hyperv-vf-net.rules index b4dcb5a39..e5ecb4ede 100644 --- a/src/etc/udev/rules.d/63-hyperv-vf-net.rules +++ b/src/etc/udev/rules.d/63-hyperv-vf-net.rules @@ -1,5 +1,9 @@ ATTR{[dmi/id]sys_vendor}!="Microsoft Corporation", GOTO="end_hyperv_nic" -ACTION=="add", SUBSYSTEM=="net", DRIVERS=="hv_pci", NAME="vf_%k" +# Primary rename path for Azure VF. +# Use helper-based naming so the VFs that reuse eth0,eth1,.. names do not +# collide with already assigned vf_ethN names. Also, prevent renaming of +# the interfaces already renamed to vf_ethN +ACTION=="add", SUBSYSTEM=="net", DRIVERS=="hv_pci", KERNEL=="eth*", PROGRAM="vyos_vf_name %k", NAME="%c" LABEL="end_hyperv_nic" diff --git a/src/etc/udev/rules.d/65-vyos-net.rules b/src/etc/udev/rules.d/65-vyos-net.rules index 32ae352de..0e7567cf8 100644 --- a/src/etc/udev/rules.d/65-vyos-net.rules +++ b/src/etc/udev/rules.d/65-vyos-net.rules @@ -4,6 +4,24 @@ ACTION!="add", GOTO="vyos_net_end" SUBSYSTEM!="net", GOTO="vyos_net_end" +# Fallback path for Azure VF interfaces: if a VF still appears as plain ethN, +# rename it to vf_ethX before persistent synthetic interface naming runs to +# prevent it from incorrectly being considered as a synthetic interface. +ATTR{[dmi/id]sys_vendor}=="Microsoft Corporation", DRIVERS=="mlx*_core", KERNEL=="eth*", PROGRAM="vyos_vf_name %k", NAME="%c", GOTO="vyos_net_end" +ATTR{[dmi/id]sys_vendor}=="Microsoft Corporation", DRIVERS=="mana", KERNEL=="eth*", PROGRAM="vyos_vf_name %k", NAME="%c", GOTO="vyos_net_end" + +# VF interfaces are not handled by vyos_net_name, so skip them. +# KERNEL=="vf_*" catches already-renamed Mellanox and MANA VFs. +# DRIVERS=="mlx*_core" and DRIVERS=="mana" on Azure catch VF interfaces +# in an unexpected intermediate state (still named ethN/eN) that must not +# be remapped by vyos_net_name. +# This guard is intentionally scoped to Microsoft Azure to +# avoid excluding bare-metal Mellanox NICs on physical hardware, which do +# need persistent naming via vyos_net_name. +KERNEL=="vf_*", GOTO="vyos_net_end" +ATTR{[dmi/id]sys_vendor}=="Microsoft Corporation", DRIVERS=="mlx*_core", GOTO="vyos_net_end" +ATTR{[dmi/id]sys_vendor}=="Microsoft Corporation", DRIVERS=="mana", GOTO="vyos_net_end" + # Do name change for ethernet and wireless devices only KERNEL!="eth*|wlan*|e*", GOTO="vyos_net_end" diff --git a/src/system/vyos-net-name-resolve.py b/src/system/vyos-net-name-resolve.py index ca8ce02ea..5b1f36533 100755 --- a/src/system/vyos-net-name-resolve.py +++ b/src/system/vyos-net-name-resolve.py @@ -178,6 +178,11 @@ def discover_physical_interfaces(sys_class_net: str = '/sys/class/net') -> dict: """Return {kernel_name: mac} for every interface backed by a real bus device - excludes lo, bridges, bonds, VLANs, veth, tunnels, etc. + Also excludes interfaces enslaved to another netdev (master symlink + present), which covers Azure VF datapath interfaces bound under their + synthetic parent. Those are acceleration children, not independent + primary interfaces, and must not be candidates for hw-id naming. + sys_class_net is overridable for testing against a fake sysfs tree. """ interfaces = {} @@ -187,6 +192,14 @@ def discover_physical_interfaces(sys_class_net: str = '/sys/class/net') -> dict: for entry in net_dir.iterdir(): if not (entry / 'device').exists(): + logger.debug( + f"skipping '{entry.name}': no backing device in sysfs" + ) + continue + if (entry / 'master').exists(): + logger.debug( + f"skipping '{entry.name}': interface is enslaved via master link" + ) continue mac = get_permanent_mac(entry.name, sys_class_net) if mac: diff --git a/src/udev/vyos_vf_name b/src/udev/vyos_vf_name new file mode 100755 index 000000000..bd6c9d0cd --- /dev/null +++ b/src/udev/vyos_vf_name @@ -0,0 +1,88 @@ +#!/bin/sh +# vyos_vf_name - pick a non-colliding VF interface name. +# Called by udev rules for VF devices that still have plain ethN names. +# +# Written as a POSIX shell script so it works in both initramfs (no Python3) +# and the normal rootfs udev context. +# +# Usage: vyos_vf_name <current_ifname> +# Prints the target vf_ethN name to stdout. + +set -e + +if [ -z "$1" ]; then + exit 1 +fi + +IFNAME="$1" +LOCK_DIR="/run/udev" +LOCK_PATH="${LOCK_DIR}/vyos_vf_name.lock" + +# Already normalized - return as-is. +case "$IFNAME" in + vf_*) + echo "$IFNAME" + exit 0 + ;; +esac + +mkdir -p "$LOCK_DIR" + +# Acquire a lock to avoid race conditions when multiple VF devices are being +# renamed concurrently. +LOCK_ACQUIRED=0 +I=0 +while [ "$I" -lt 200 ]; do + if mkdir "$LOCK_PATH" 2>/dev/null; then + LOCK_ACQUIRED=1 + break + fi + I=$((I + 1)) + sleep 0.01 +done + +[ "$LOCK_ACQUIRED" -eq 1 ] || exit 1 + +cleanup() { + rmdir "$LOCK_PATH" 2>/dev/null || true +} +trap cleanup EXIT INT TERM + +# Preferred: preserve the original ethN index when vf_ethN is not yet taken. +case "$IFNAME" in + eth*) + PREFERRED="${IFNAME#eth}" + # Validate it is a pure integer. + case "$PREFERRED" in + *[!0-9]*) + ;; + *) + if ! [ -d "/sys/class/net/vf_eth${PREFERRED}" ]; then + echo "vf_eth${PREFERRED}" + exit 0 + fi + ;; + esac + ;; +esac + +# Fallback: allocate just above the highest ethN synthetic index present to +# avoid collisions. +MAX=-1 +for D in /sys/class/net/eth*; do + [ -d "$D" ] || continue + N="${D##*/eth}" + # Skip if not a pure integer (e.g. no match expands to literal path). + case "$N" in *[!0-9]*) continue;; esac + [ "$N" -gt "$MAX" ] && MAX="$N" +done + +IDX=$((MAX + 1)) +[ "$IDX" -lt 0 ] && IDX=0 + +# Skip any indices already occupied by existing vf_ethN interfaces. +while [ -d "/sys/class/net/vf_eth${IDX}" ]; do + IDX=$((IDX + 1)) +done + +echo "vf_eth${IDX}" |
