fix(usb): assign deterministic gadget MAC so the host NIC stays stable (#828)

The USB network gadget (rndis.usb0 / ncm.usb0) is created without dev_addr or
host_addr, so the kernel picks a random MAC for both the device side and the
host side on every bind. S10uuid later pins the device-side usb0 via
'ip link set', but the host_addr -- the MAC the attached PC's RNDIS/NCM adapter
uses -- stays random and changes on every re-enumeration/reboot. The host then
registers a brand-new network adapter each time, piling up stale adapters/MACs
(e.g. ~10 after a few reboots) and breaking anything that keys off the MAC.

Derive both MACs from the chip UID (same scheme S10uuid already uses for eth0
and usb0), before binding the gadget:
  dev_addr  = 48:da:35:6e:<uid>
  host_addr = 48:da:35:6d:<uid>

Verified on a NanoKVM Cube: host_addr went from random a6:3f:5d:8a:7d:52 to a
stable 48:da:35:6d:26:62, identical across two reboots.

Fixes #740

Co-authored-by: BeaconCat <BeaconCat@users.noreply.github.com>
This commit is contained in:
BeaconCat
2026-07-29 16:29:53 +08:00
committed by GitHub
parent 57e1f6a4d6
commit dc050d1f19

View File

@@ -39,15 +39,30 @@ start_usb_dev(){
mkdir configs/c.1/strings/0x409
echo "NanoKVM" > configs/c.1/strings/0x409/configuration
# Deterministic gadget MACs from the chip UID so the host-side RNDIS/NCM
# interface keeps a STABLE MAC across re-enumeration/reboot. Without this
# the kernel assigns a random dev_addr/host_addr on every bind, so the
# attached PC sees a brand-new network adapter (and MAC) each time.
usb_uid=$(sha512sum /sys/class/cvi-base/base_uid | head -c 4)
if [ -n "$usb_uid" ]
then
usb_dev_mac="48:da:35:6e:${usb_uid%??}:${usb_uid#??}"
usb_host_mac="48:da:35:6d:${usb_uid%??}:${usb_uid#??}"
fi
if [ -e /boot/usb.ncm ]
then
mkdir functions/ncm.usb0
[ -n "$usb_dev_mac" ] && echo "$usb_dev_mac" > functions/ncm.usb0/dev_addr
[ -n "$usb_host_mac" ] && echo "$usb_host_mac" > functions/ncm.usb0/host_addr
echo WINNCM > functions/ncm.usb0/os_desc/interface.ncm/compatible_id
ln -s functions/ncm.usb0 configs/c.1/
else
if [ -e /boot/usb.rndis0 ]
then
mkdir functions/rndis.usb0
[ -n "$usb_dev_mac" ] && echo "$usb_dev_mac" > functions/rndis.usb0/dev_addr
[ -n "$usb_host_mac" ] && echo "$usb_host_mac" > functions/rndis.usb0/host_addr
echo e0 > functions/rndis.usb0/class
echo 01 > functions/rndis.usb0/subclass
echo 03 > functions/rndis.usb0/protocol