Ethernet port order and status on X86

I have a Lanner FW-7525A network appliance with 6GBE ports (2 x Intel i210AT PCI-E, 4 x Marvell 88E1543) which I would like to use as OpenWRT based X86 router.
Here is a picture of the device: https://imgur.com/a/aiOQpzO
After installing OpenWRT 21.02, I have to configure the physical port assignments for LAN and WAN as shown below

root@7525:/sys/class/net# ls -l
lrwxrwxrwx    1 root     root             0 May 31 21:09 br-lan -> ../../devices/virtual/net/br-lan
lrwxrwxrwx    1 root     root             0 May 31 21:09 eth0 -> ../../devices/pci0000:00/0000:00:14.0/net/eth0
lrwxrwxrwx    1 root     root             0 May 31 21:09 eth1 -> ../../devices/pci0000:00/0000:00:14.1/net/eth1
lrwxrwxrwx    1 root     root             0 Jun  1 00:22 eth2 -> ../../devices/pci0000:00/0000:00:14.2/net/eth2
lrwxrwxrwx    1 root     root             0 Jun  1 00:22 eth3 -> ../../devices/pci0000:00/0000:00:14.3/net/eth3
lrwxrwxrwx    1 root     root             0 May 31 21:09 eth4 -> ../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/net/eth4
lrwxrwxrwx    1 root     root             0 Jun  1 00:22 eth5 -> ../../devices/pci0000:00/0000:00:02.0/0000:02:00.0/net/eth5

I want to change the two Intel PCI-E ports from 'eth4' and 'eth5' to 'eth0' and 'eth1' and use them as dual WAN ports. The remaining 4 ports I want to use them for LAN and would like all ports to be up by default (at first all ports are down and I have to turn them UP). How do I control the physical port assignments to WAN and LAN as described above?

Thanks in advance,
Abe

On OpenWrt/x86 there's no builtin way to do that directly. You will need to ship a script matching those devices by some unique criteria (e.g. the OUI part of the MAC or maybe the PCI ID) and renaming them as needed on boot.

The current naming is based on device enumeration and driver load order, so basically random (albeit the same on each boot).

1 Like

Are there examples somewhere of a PCI ID based script that would do this? I'm finding a number of common Intel based routers have there physical port assignment in OpenWrt completely different than whats labeled on the device!

You can always use the MAC

1 Like

You can determine the IDs (for PCI based devices) by checking /sys/class/net/eth0/device/vendor, /sys/class/net/eth0/device/device, /sys/class/net/eth0/device/subsystem_vendor, /sys/class/net/eth0/device/subsystem_device.

You can determine the (PCI) path of the device using readlink -f /sys/class/net/eth0/device

You would then require a kind of case switch mapping the IDs to their proper names:

#!/bin/sh

for dev in $(ls -1 /sys/class/net); do
    path=$(basename $(readlink -f "/sys/class/net/$dev/device" 2>/dev/null))
    vend=$(cat "/sys/class/net/$dev/device/vendor" 2>/dev/null)
    prod=$(cat "/sys/class/net/$dev/device/device" 2>/dev/null)
    svend=$(cat "/sys/class/net/$dev/device/subsystem_vendor" 2>/dev/null)
    sprod=$(cat "/sys/class/net/$dev/device/subsystem_device" 2>/dev/null)

    case "$path:$vend:$prod:$svend:$sprod" in
        0000:22:00.0:0x10ec:0x8168:*:*) ip link set name eth0 dev "$dev" ;;
        0000:22:00.1:0x10ec:0x8168:*:*) ip link set name eth1 dev "$dev" ;;
        mdio-bus:1f:*) ip link set name switch0 dev "$dev" ;;
        *)
            echo "Unrecognized device: $dev  path: $path  vendor: $vend  product: $prod  subsystem_vendor: $svend  subsystem_product: $sprod"
        ;;
    esac
done

A complete script would probably be a little more complicated because in order to swap names (e.g. eth0<>eth1), you would need to rename one of the two devices to a temporary name:

ip link set name eth0_temp dev eth0
ip link set name eth0 dev eth1
ip link set name eth1 dev eth0_temp

The script example above does not deal with that. A complete implementation would probably need to first rename all to-be-renamed devices to a temporary name (like appending a _rename or _tmp suffix or give a monotonically increasing name like rename0, rename1, rename2 ...) then do a second iteration where each eligible device is renamed to its final name, in order to avoid name clashes.

Such a script, once complete, would be ideally hooked into preinit so that it runs before any board-detection, network config autogeneration etc.

4 Likes

Thank you for providing a base script. In my case, the device, vendor, subsystem_device and subsystem_vendor are identical. I can use the path to make the case.

where would be the place to put the script so that it is executed before hardware detection?

view:

Thanks

#!/bin/sh /etc/rc.common

START=11

# don't run within buildroot
[ -n "${IPKG_INSTROOT}" ] && return 0

#use busybox grep as GNU grep may be set differently and break the script
grep(){
/bin/busybox 'grep' $@
}

#shutting down all interfaces, then assigning temporary name to free up interface names
#bridges and virtual interfaces are already excluded by  /sys/class/net/*/device/uevent as only physical interfaces have that
for i in $( ls /sys/class/net/*/device/uevent | awk -F'/' '{print $5}' | tr '\n' ' ' ) ;
do

	mac_address=$( grep $i /etc/config/mac-static-interfaces | awk '{print $3}' | tr -d '"' )
	if [ "$mac_address" != '' ]; then
	
		ip link set "$i" down 
		ip link set "$i" name old"$i"
		
	fi
done

for i in $( ls /sys/class/net/*/device/uevent | awk -F'/' '{print $5}' | tr '\n' ' ' ) ;
do

mac_address=$( cat /sys/class/net/$i/address  )
	interface_name=$( grep -i $mac_address /etc/config/mac-static-interfaces | awk '{print $2}' )
	if [ "$interface_name" != '' ]; then
	
		ip link set "$i" down 
		ip link set "$i" name "$interface_name"
		
	fi
done

1 Like

Thanks for attaching the proposed solution using MAC. But for my requirement, the MAC based mapping does not work because I will deploy multiple of these devices and I just want to correctly match the port numbers written on the cover of the device to match what is inside the system.

1 Like

I am pursuing the solution suggested by @jow based on the PCI ID. And I suggest you throw away the sarcasm, no need to belittle anyone seeking technical advice.,

The MAC would only be useful for a single device. I want a script that can be used with multiple of the same device which is why I believe that using PCI ID is the correct solution.

1 Like

PCI ID or in case multiple devices with the same PCI ID are built into the system, the PCI bus slot number ($path in the script above)

that is exactly my case as well.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.