XCP-ng/XenServer Hypervisor NIC Static MAC Configuration Guide to Prevent NIC Ordering/Numbering Changes When Moving Slots Or Changing NICs (Also Corrects Issues With Intel Mezzanine NIC Port Numberings)

Xen/XCP-ng Hypervisor Network Interface Controller Solution to Set Static MAC Assignments to Prevent Out-of-Order / Re-ordering of NIC Numbering

Problem Description

XCP-ng can sometimes skip NIC numbers (e.g., having eth0-4, then eth6-7, missing eth5) or renumber NICs after hardware changes, BIOS updates, or system updates. This causes:

  • Inconsistent NIC naming with gaps in numbering
  • Broken network configurations after reboots
  • VMs losing network connectivity
  • Duplicate NICs with the same MAC address appearing
  • Management interface becoming unreachable

Step-by-Step Solution to Set Static MAC Assignments

Step 1: Create Static Rules for All Interfaces

First, backup the current configuration:

cp -r /etc/sysconfig/network-scripts/interface-rename-data /root/interface-rename-backup-$(date +%Y%m%d)

Get your current MAC addresses:

# List all current NICs with their MAC addresses
xe pif-list params=device,MAC

Then edit the static rules file:

vi /etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf

Add these rules based on your current MAC addresses (replace with YOUR actual MACs):

# Static rules to ensure consistent NIC naming
eth0: mac = "aa:bb:cc:dd:ee:00"
eth1: mac = "aa:bb:cc:dd:ee:01"
eth2: mac = "aa:bb:cc:dd:ee:02"
eth3: mac = "aa:bb:cc:dd:ee:03"
eth4: mac = "aa:bb:cc:dd:ee:04"
eth5: mac = "aa:bb:cc:dd:ee:05"
eth6: mac = "aa:bb:cc:dd:ee:06"

Note: If you’re fixing a gap in numbering (e.g., you have eth6 and eth7 but no eth5), map the MAC from eth6 to eth5, and eth7 to eth6 in your static rules.

Step 2: Clear Dynamic Rules

Clear the dynamic rules to prevent conflicts:

echo '{"lastboot": [], "old": []}' > /etc/sysconfig/network-scripts/interface-rename-data/dynamic-rules.json

Step 3: Regenerate udev Rules

Regenerate the network naming rules:

/etc/sysconfig/network-scripts/interface-rename.py --update-udev-rules

Step 4: Update XCP-ng Database

Before rebooting, you may need to update the XCP-ng database to reflect the changes. First, put the host in maintenance mode if it’s in a pool:

xe host-disable uuid=$(xe host-list name-label=$(hostname) --minimal)

Step 5: Reboot

Reboot the host for the changes to take effect:

reboot

Step 6: Verify After Reboot

After reboot, verify the new naming:

xe pif-list params=uuid,device,MAC,host-name-label
ip link show

Handling Stale or Duplicate NICs After Reboot

If after reboot you see duplicate NICs (both showing the same MAC address), you need to remove the stale entries.

Identify and Remove Duplicates

# Find PIFs with duplicate MACs
xe pif-list params=uuid,device,MAC

# Look for entries where two different devices show the same MAC
# Remove the stale PIF using its UUID
xe pif-forget uuid=<STALE-PIF-UUID>

# Rescan PIFs
xe pif-scan host-uuid=$(xe host-list name-label=$(hostname) --minimal)

# Reboot again
reboot

Complete Verification Process

After the final reboot, perform these verification steps:

1. Verify Current NIC Configuration

First, check that all NICs are properly numbered without gaps:

# Check all PIFs with their device names and MACs
xe pif-list params=device,MAC,host-name-label | grep -E "device|MAC|host-name" | paste - - - | sort

# Check that you have eth0 through eth6 (no gaps)
for i in {0..6}; do 
  echo -n "eth$i: "
  xe pif-list device=eth$i params=MAC --minimal
done

2. Verify No Duplicate MACs

Check for any duplicate MAC addresses:

# List all MACs and check for duplicates
xe pif-list params=MAC --minimal | tr ',' '\n' | sort | uniq -d

This should return nothing if there are no duplicates.

3. Verify Static Rules Are In Place

Check that your static rules are properly configured:

# View the static rules
cat /etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf

# Verify the rules match your current configuration
echo "=== Comparing static rules to actual MACs ==="
for i in {0..6}; do
  actual_mac=$(xe pif-list device=eth$i params=MAC --minimal 2>/dev/null)
  static_mac=$(grep "^eth$i:" /etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf | awk -F'"' '{print $2}')
  echo "eth$i: static=$static_mac actual=$actual_mac $([ "$static_mac" = "$actual_mac" ] && echo "✓ MATCH" || echo "✗ MISMATCH")"
done

4. Check udev Rules

Verify the udev rules were regenerated correctly:

# Check the timestamp to ensure it was recently updated
ls -la /etc/udev/rules.d/60-net.rules

# View the generated rules
cat /etc/udev/rules.d/60-net.rules

5. Verify Network Bonds/VLANs (if applicable)

If you have any bonds or VLANs configured, verify they’re still associated with the correct PIFs:

# Check bonds
xe bond-list params=uuid,master,slaves

# Check VLANs  
xe vlan-list params=uuid,tagged-PIF,untagged-PIF,tag

Expected Results

After successful configuration, you should see:

  1. Sequential NICs: eth0, eth1, eth2, eth3, eth4, eth5, eth6 (no gaps)
  2. No duplicates: Each NIC has a unique MAC address
  3. Static rules match: All static rules in the config file match actual NICs
  4. Persistent naming: NICs maintain their names after reboots

Example of correct output:

eth0: aa:bb:cc:dd:ee:00
eth1: aa:bb:cc:dd:ee:01
eth2: aa:bb:cc:dd:ee:02
eth3: aa:bb:cc:dd:ee:03
eth4: aa:bb:cc:dd:ee:04
eth5: aa:bb:cc:dd:ee:05
eth6: aa:bb:cc:dd:ee:06

Important Files

  • /etc/sysconfig/network-scripts/interface-rename-data/static-rules.conf
  • Contains MAC-to-interface name mappings
  • Overrides dynamic detection
  • Persists across reboots and updates
  • /etc/sysconfig/network-scripts/interface-rename-data/dynamic-rules.json
  • Contains boot-time detected mappings
  • Should be cleared when setting static rules
  • Automatically regenerated each boot
  • /etc/udev/rules.d/60-net.rules
  • Generated udev rules for network naming
  • Created from static and dynamic rules
  • Applied during boot process

Troubleshooting

Issue: NIC numbers still have gaps after reboot

  1. Verify static rules file has correct MAC addresses
  2. Ensure dynamic rules were cleared
  3. Check for typos in MAC addresses (must be lowercase)
  4. Regenerate udev rules and reboot again

Issue: Duplicate MACs persist after xe pif-forget

  1. List all PIFs to find all duplicates: xe pif-list params=uuid,device,MAC
  2. Remove ALL duplicate PIFs except one
  3. Run xe pif-scan to rescan
  4. Reboot the host

Issue: Lost management interface after changes

  1. Access via physical console or IPMI
  2. Run xsconsole from command line
  3. Navigate to “Network and Management Interface”
  4. Reconfigure management interface on correct NIC

Issue: NICs revert to old naming after XCP-ng update

  1. Check if static rules file still exists
  2. Verify /etc/sysconfig/network-scripts/interface-rename.py hasn’t been replaced
  3. Regenerate udev rules
  4. Reboot

Additional Notes

Some hardware (Intel X550, X710, Broadcom mezzanine cards) may present ports out of physical order. Static MAC rules will let you map them to match physical port layout if desired.

This guide only affects OS-level NIC naming in XCP-ng. It does not change BIOS/UEFI boot order or IPMI/iDRAC/iLO port assignments.

Why This Works

Static MAC-based rules provide reliable NIC naming because:

  • MAC addresses are unique and don’t change
  • Static rules override boot-time detection order
  • Rules persist through all system updates and hardware changes
  • Uses XCP-ng’s native interface rename system

Conclusion

Once static MAC-based rules are configured, your NICs will maintain consistent names regardless of system changes. The key is mapping each physical NIC’s MAC address to a specific ethX name in the static rules file. If you want to remove a NIC (or move it to a different slot) and you have Network Appliances or Storage Servers running in VMs (eg pfSense/OPNsense, WAZUH, NFS/SMB, etc) then you may have noticed the NIC ordering can change, cause chaos and headaches in your VMs. Hopefully, this guide helps!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.