From 1b98452d7e035c68849ebcb3242ecae25d5a9795 Mon Sep 17 00:00:00 2001 From: Ritika Chopra Date: Mon, 20 Jul 2026 12:47:51 -0700 Subject: T8329: Fix interface naming for Azure VF interfaces with Accelerated Networking enabled ROOT-CAUSE: Some Azure VF interfaces miss to get renamed leading to errors in the downstream rules and mess up with the interface names. Two main problematic scenarios were found which prohibited the renaming of a VF interface to vf_ethN: 1. Missing udev add event, when change event is received directly 2. A VF interface registering during rootfs stage FIX: Rule 63: -Azure VF naming is now handled by a dedicated helper - vyos_vf_name to provide collision-free names for VF interfaces. The helper vyos_vf_name would be packaged into initramfs so the same behavior works in early boot and normal boot (a separate PR). -Rule 63 is now guarded to prevent recursive renaming of VF interfaces. Rule 65: -A fallback VF rename path has been added for any leftover VF interfaces that were missed to be renamed due to some unexpected situation. Those VF interfaces are renamed prior to running persistent renaming of synthetic interfaces. This prevents VF interfaces from being considered as synthetic interfaces which may lead to errors in the flow of execution. -Rule 65 is now guarded so generic persistent naming does not override VF names. --- src/etc/udev/rules.d/63-hyperv-vf-net.rules | 6 +- src/etc/udev/rules.d/65-vyos-net.rules | 15 +++++ src/udev/vyos_vf_name | 88 +++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100755 src/udev/vyos_vf_name (limited to 'src') 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..35e40ba8c 100644 --- a/src/etc/udev/rules.d/65-vyos-net.rules +++ b/src/etc/udev/rules.d/65-vyos-net.rules @@ -4,6 +4,21 @@ ACTION!="add", GOTO="vyos_net_end" SUBSYSTEM!="net", GOTO="vyos_net_end" +# Fallback path for Azure VFs: if any Azure Mellanox 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" + +# VF interfaces are not handled by vyos_net_name, so skip them. +# KERNEL=="vf_*" catches already-renamed VFs. +# DRIVERS=="mlx*_core" on Azure catches VFs that reached here in an unexpected +# intermediate state, are still named ethN/eN and 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" + # Do name change for ethernet and wireless devices only KERNEL!="eth*|wlan*|e*", GOTO="vyos_net_end" 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 +# 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}" -- cgit v1.2.3 From 44703a8ef2f56bac995e33770a74fba47117c354 Mon Sep 17 00:00:00 2001 From: Ritika Chopra Date: Mon, 3 Aug 2026 16:58:59 -0700 Subject: T8329: Add support to handle Azure MANA interfaces in the udev naming rules --- src/etc/udev/rules.d/65-vyos-net.rules | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/etc/udev/rules.d/65-vyos-net.rules b/src/etc/udev/rules.d/65-vyos-net.rules index 35e40ba8c..0e7567cf8 100644 --- a/src/etc/udev/rules.d/65-vyos-net.rules +++ b/src/etc/udev/rules.d/65-vyos-net.rules @@ -4,20 +4,23 @@ ACTION!="add", GOTO="vyos_net_end" SUBSYSTEM!="net", GOTO="vyos_net_end" -# Fallback path for Azure VFs: if any Azure Mellanox 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. +# 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 VFs. -# DRIVERS=="mlx*_core" on Azure catches VFs that reached here in an unexpected -# intermediate state, are still named ethN/eN and 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 +# 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" -- cgit v1.2.3 From a1360d645df8a82cd593d55ca592a8a1d60b34b3 Mon Sep 17 00:00:00 2001 From: Ritika Chopra Date: Fri, 14 Aug 2026 12:03:26 -0700 Subject: T8329: Skip enslaved interfaces to be considered as independent physical interfaces during hw-id naming These interfaces include the Azure VF interfaces which share the same mac address with their master synthetic interface --- src/system/vyos-net-name-resolve.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/system/vyos-net-name-resolve.py b/src/system/vyos-net-name-resolve.py index 7934e8442..993fd6f3e 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: -- cgit v1.2.3