Repository navigation
Conversation
The Pi 5 image builds the USB modem drivers but leaves them out of the rootfs, and a modem link named usb0 or wwan0 matches the stock 80-wired.network, which gives it Ethernet's route metric. A device with Ethernet and a modem would then pick between them by accident. The reference carries the network and serial drivers a modem needs whichever USB mode it presents, a networkd profile that sorts ahead of 80-wired and sets the modem's route metric to 300, and a unit that reloads networkd after the extension merge. networkd starts before the merge, so without the reload the profile is not read until someone runs networkctl reload by hand, which a cold boot never does. Tested on a Pi 5 on the 2026 next feed without a modem attached: all 19 modules resolve and load, and after a cold reboot a link named usb0 or wwan0 matches the new profile with no manual reload. Behaviour with a real modem is not covered. Signed-off-by: Javier Tia <javier@peridio.com>
Avocado References — Build Check
Totals: 1 ✅ passed · 0 ❌ failed Per-reference logs: workflow run |
| enable_services: | ||
| - cellular-modems-networkd.service |
There was a problem hiding this comment.
cellular-modems-networkd.service does not run after avocado deploy. It runs only after a reboot.
The guide's prerequisite is a Pi 5 that already runs 2026 next. On that device, avocado deploy calls avocadoctl runtime add. avocadoctl sees no OS change and does a hot refresh: merge, daemon-reload, then the on_merge commands. enable_services only adds the multi-user.target.wants link. Nothing starts the unit, so networkd keeps its old configuration.
Result: a user who follows Deploy and then Verify step 2 sees 80-wired.network, not 30-cellular.network. Also, on a later deploy that changes 30-cellular.network, RemainAfterExit=yes keeps the unit active, so networkd does not reload until the next reboot. The PR testing ran the checks after a cold reboot, so this did not show up.
Suggested fix:
- Add a reload to the extension's merge hooks.
rubicon/avocado.yamlalready does this. In avocadoctl, a failedon_mergecommand only logs a warning, so it cannot break the merge.on_merge: - networkctl reload
- If you keep the current unit instead, tell the user in getting_started.md to reboot after
avocado deploy.
| # networkd starts before the extension merge, so on a cold boot it has not read | ||
| # this extension's 30-cellular.network. Until it does, a modem link named usb0 | ||
| # matches the stock 80-wired.network and gets Ethernet's route metric. This unit | ||
| # exists only after the merge, which makes it the first point that can ask | ||
| # networkd to re-read its configuration. | ||
| After=systemd-networkd.service | ||
| Wants=systemd-networkd.service |
There was a problem hiding this comment.
The boot race is in the platform, so each reference has to work around it.
avocado-extension.service is ordered Before=sysinit.target, but systemd-networkd.service has DefaultDependencies=no and no ordering against the merge. The two can start in parallel, so networkd can read its configuration before the extensions are merged.
As a result, every reference that ships a .network file must include its own fix. #37 adds wifi-station.service for the same problem, and rubicon uses on_merge: networkctl reload. That gives three patterns for one problem, and customers copy references.
Suggested fix:
- In meta-avocado, add a drop-in at
systemd-networkd.service.d/avocado.conf:This is the same pattern as[Unit] After=avocado-extension.service
sshdgenkeys-after-extensions.confinmeta-avocado-distro/recipes-avocado/avocadoctl/avocadoctl/. - In this PR, keep the unit as a stopgap. Add a comment that links to the meta-avocado ticket, so that the unit is removed when the platform fix ships.
| # which matches every Ethernet-type link and would otherwise give a modem the | ||
| # same low route metric as Ethernet. | ||
| [Match] | ||
| Name=usb0 wwan0 |
There was a problem hiding this comment.
Name=usb0 wwan0 matches only the first interface of each type.
Predictable interface labels are off in Avocado (the NamePolicy= sed in systemd_258.1.bb), so the kernel labels apply. A modem link misses this match when:
- A second modem is attached (
usb1,wwan1). - The modem exposes two data interfaces, for example multi-PDN QMI or a composite configuration.
- The modem resets its firmware and comes back as
usb1beforeusb0is removed. cdc_etherorrndis_hostgets a MAC that is not locally administered. usbnet then gives the linketh%d.
All of these links are Type=ether, so they match 80-wired.network and get DHCP at metric 10. The modem then becomes the default route ahead of Ethernet, which is the problem this PR fixes. On a metered SIM, that costs money. Verify step 2 does not find this, because the tap test sets the label to usb0.
Suggested fix:
- Minimum:
Name=usb* wwan*. - Better: match on the driver, so the kernel label does not matter:
Some USB Ethernet dongles run in ECM mode under
[Match] Driver=cdc_ether cdc_ncm cdc_mbim qmi_wwan rndis_host sierra_net
cdc_etherand would also get metric 300. Add a comment about that.
| ssh root@<device-ip> 'lsusb; dmesg | tail -20; ip -br link; networkctl status usb0 wwan0 --no-pager' | ||
| ``` | ||
|
|
||
| An ECM, NCM or RNDIS modem shows up as `usb0`; a QMI or MBIM modem as `wwan0`. Once it has an address, `ip route` lists a default route through it at metric 300, behind `eth0` at 10 and `wlan0` at 200. |
There was a problem hiding this comment.
QMI and MBIM modems do not get an address with this reference.
The extension has no qmicli, mbimcli or ModemManager. On a QMI or MBIM modem, DHCP on wwan0 gets no reply until a tool starts the data session. Common Pi modems such as the Quectel EC25/EG25 and the Sierra EM7455 start in QMI or MBIM mode.
A user with a SIM runs step 3, sees wwan0 with no address and no route, and has no tool on the device to fix it. Line 77 states this limit, but this line still promises a default route at metric 300, and the prerequisites ask for an active SIM and data plan.
Suggested fix:
- Say that the route check in step 3 applies only to ECM, NCM and RNDIS modems.
- Add the
libqmiandlibmbimtools if the feed has them. Or give the AT command that switches a common modem to ECM, for example QuectelAT+QCFG="usbnet",1.
| kernel-module-ppp-generic: "*" | ||
| kernel-module-ppp-async: "*" | ||
| kernel-module-ppp-deflate: "*" | ||
| kernel-module-slhc: "*" |
There was a problem hiding this comment.
The PPP kernel modules do nothing without pppd.
The extension adds ppp_generic, ppp_async, ppp_deflate and slhc, but no userspace dialer. The README says that the reference covers serial AT ports. A user with a serial-only or PPP modem gets /dev/ttyUSB* but cannot dial, and must find the missing package by themselves.
Suggested fix:
- Add the
ppppackage if the feed has it. - If the feed does not have it, remove these four modules and add PPP to "What this reference does not do" in getting_started.md.
Problem
The Pi 5 image builds the USB cellular modem drivers but leaves them out of the rootfs. A modem link named
usb0orwwan0also matches the stock80-wired.network, which gives it Ethernet's route metric of 10, so a device with Ethernet and a modem picks between them by accident.Change
Adds the
pi5-cellular-modemsreference:cellular-modemsextension with the network drivers (usbnet,cdc_ether,cdc_ncm,cdc_mbim,cdc_wdm,qmi_wwan,rndis_host), the serial and PPP ones (cdc_acm,option,usb_wwan,usbserial,qcserial,sierra,sierra_net,ppp_*,slhc) andtun, pluslsusb,ethtoolandiproute2.30-cellular.networkforusb0andwwan0: DHCP at route metric 300, behind Ethernet (10) and Wi-Fi (200). The number sorts it ahead of80-wired.network.cellular-modems-networkd.service, a oneshot that runsnetworkctl reload. networkd starts before the extension merge, so without it the profile is not read on a cold boot.getting_started.mdwith install, build, deploy and three checks, and a list of what the reference does not do (no USB mode switching, no ModemManager or APN handling).It builds on the same extension-merge ordering problem as #37, and the two do not depend on each other.
Testing
On a Pi 5 running the 2026
nextfeed (kernel 6.12.87, avocado-cli 1.0.0-rc.4), built and deployed withavocado buildandavocado deploy, with no modem attached:modprobe -nand load withmodprobe.usb0and one namedwwan0both reportNetwork File: /usr/lib/systemd/network/30-cellular.network. Before the reload unit existed, the sameusb0matched80-wired.networkuntilnetworkctl reloadwas run by hand.getting_started.mdwere run exactly as written.Not tested: a real modem in any USB mode, DHCP over a modem link, and the route metric on a live modem link. The README and guide say so.
avocado.lockis in the reference's.gitignore, as no other reference tracks it.