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?
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).
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 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.
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?
#!/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
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.
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.