Repository navigation
mdev: load the tethering drivers for a phone, and bring usb0 up when it appears - #2652
Conversation
…it appears A phone in USB tethering mode gave no usb0 (#1112). rndis_host, cdc_ether and cdc_ncm are built as modules on the boards that have them, and nothing loads a module when a USB device enumerates: mdev.conf has no MODALIAS rule, so the phone's RNDIS interfaces sat there with no driver bound. mdev now loads a driver for the RNDIS, ECM and NCM interface classes only. It is not a blanket MODALIAS rule, because that would also load usbserial for a modem before rndis_host, which /etc/wireless/modem exists to prevent. With the driver loaded by hand, usb0 still came up bare whenever it appeared after S40network: Android switches tethering off each time the cable is pulled, so that is the usual case. /lib/mdev/usbnet.sh runs ifup when usb0 appears and ifdown -f when it goes. Without the ifdown, the next plug got "ifup: interface usb0 already configured" and no address. It acts only on interfaces bound by those three drivers: a USB gadget's usb0 has no DHCP server across the cable, and udhcpc's leasefail would hand it the camera's ipaddr. A phone tethering at power-on was announced before mdev became the hotplug helper, and mdev -s walks only devices with a node, so S38mdev replays the USB interfaces' add events after it.
PR Summary by QodoLoad USB tethering drivers and manage usbN hotplug
AI Description
Diagram
High-Level Assessment
Files changed (3)
|
Code Review by Qodo
1.
|
…ring DHCP Review of the tethering hotplug found three gaps. A phone tethering at boot got its default route at the same metric as eth0, and could come up first. usb0's stanza now sets metric 10, which default.script already honours, so the cable keeps its default route and its DNS ahead of the phone's. The rule took any usbN, but only usb0 has a stanza. It now takes usb0 alone, and an ifup that fails says so in syslog. A pull while udhcpc was still in its foreground retries could leave usb0 recorded as configured, and the next plug got no address. Add and remove now share a lock. The add looks for the interface again once it holds the lock, and clears whatever ifupdown kept for the name before it brings the new interface up. Two traps on the way: - udhcpc daemonizes, and would inherit the lock and hold it for good. - ash execs a subshell's last command in place, so `ifup ... 9>&-` as the last command dropped the lock for the whole ifup. Every pull during DHCP left the state behind; with tracing added after it, none did.
Problem
With an Android phone in USB tethering mode, an OpenIPC board never got
usb0(#1112, reported on hi3536dv100). The kernel buildsrndis_host,cdc_etherandcdc_ncmas modules, and the image ships them. But nothing loads a module when a USB device enumerates:mdev.confhas noMODALIASrule, so the phone's RNDIS interfaces stayed with no driver bound.Loading the driver by hand was not enough either.
usb0came up bare whenever it appeared afterS40networkhad run. Android switches tethering off each time the cable is pulled, so that is the usual case. On the second plug,ifupalso refused withinterface usb0 already configured, because ifupdown still recorded the vanished interface.The fix:
mdev.confloads the driver for the RNDIS, ECM and NCM interface classes only. It is not a blanketMODALIASrule, because that would loadusbserialfor a modem beforerndis_host, which/etc/wireless/modemexists to prevent. When theusb0network interface appears or goes, it runs/lib/mdev/usbnet.sh./lib/mdev/usbnet.shrunsifupon add andifdown -fon remove, serialized under oneflock, so a pull while DHCP is still running cannot leave stale ifupdown state. It acts only on interfaces bound by those three drivers. A USB gadget'susb0has no DHCP server across the cable, and udhcpc'sleasefailwould give it the camera'sipaddr.interfaces.d/usb0setsmetric 10, so a tethered phone never takes the default route or DNS from the cable.S38mdevreplays the USB interfaces'addevents aftermdev -s. A phone already tethering at power-on was announced before mdev became the hotplug helper, andmdev -swalks only devices with a device node.Hardware tested on
hi3536dv100 (lab NVR board,
hi3536dv100_lite, kernel 4.9.37). The phone was a Samsung Galaxy A02 (SM-A022G, Android 11) in USB tethering mode, plugged into the board's USB port. I installed the three changed files over a local build ofhi3536dv100_litein the overlay, then removed them afterwards."Replug" below means
echo 1-1 > /sys/bus/usb/drivers/usb/unbindfollowed bybind. This re-enumerates the phone without anyone touching it. A physical replug and toggling tethering on the phone were not tested.Not tested: a phone that tethers over NCM, and the ECM class.
Evidence
Before (stock image, phone tethering):
Before, with
modprobe rndis_hostandifup usb0by hand, then a replug:After, a cold boot with the phone already tethering. Nothing was run by hand:
After, three replugs:
After the review round: the route order on a cold boot with the phone tethering, and pulls during DHCP (USB unbind at 0 to 3.5 s after the plug, 10 trials, all clean). The full output is in the review threads.
The guard leaves anything that is not a tether alone:
/dev/bus/usb/001/*nodes are still created.STRICT=1 test_shell_parse.shandtest_strip_shell_comments.shpass.Local cross build of
hi3536dv100_litefrom this branch, at 8c9a939:Scope
general/package/all-patches/linux/(those go to OpenIPC/linux)general/overlay/or in a sharedload_<vendor>script hardcodes a value specific to my boardLD_PRELOAD, and no binaries that cannot be rebuilt from sourceCloses #1112