wwand: add cellular connection manager - #30185
Conversation
BKPepe
left a comment
There was a problem hiding this comment.
Thanks for working on this. I can see the motivation behind having a lightweight, event-driven WWAN manager tightly integrated with netifd, and some of the functionality here is certainly interesting.
However, I don't think this is ready to be merged into the OpenWrt packages feed in its current form.
My main concern is the scope and the amount of functionality being reimplemented. This is not merely another frontend or connection manager using the existing OpenWrt WWAN stack. wwand implements QMI, MBIM and NCM/AT itself and the corresponding packages explicitly conflict with and replace uqmi, umbim and comgt-ncm.
That effectively introduces a second implementation of a significant part of the OpenWrt WWAN stack which we would then need to maintain and review in parallel with the existing implementations.
The scope is also very large for a newly introduced project: QMI, MBIM, NCM/AT, QMAP/multiple PDP contexts, SIM/APDU handling, eSIM, SMS, telemetry, recovery, board profiles, netifd integration and automatic migration of existing configurations are all being introduced at once.
Host-side tests are useful, but they cannot replace real-world modem interoperability testing for protocols such as QMI and MBIM. The PR currently mentions production testing on four devices/modems. Considering the number of modem vendors, firmware versions, protocol quirks and failure/recovery scenarios encountered in the OpenWrt ecosystem, I don't think this provides enough coverage yet to justify replacing the established handlers.
Another concern is project maturity. This is a relatively new implementation of protocol parsers and fairly complex asynchronous state machines, and a substantial part of the implementation was AI-generated. I don't consider the use of AI itself a reason to reject code, but for this kind of low-level protocol and state-machine implementation it makes independent review and real-world validation especially important. At the moment there does not appear to be enough independent review or deployment history to establish that confidence.
There is also a broader architectural question here.
Since this project is specifically designed around OpenWrt (ucode, uloop, ubus, UCI and netifd) and aims to replace several existing OpenWrt WWAN components, I think the architecture should first be discussed with the maintainers of the existing WWAN/netifd components. In particular, it should be considered whether the missing functionality could be implemented by improving the existing stack instead of introducing another complete QMI/MBIM/NCM implementation.
Features such as better recovery, persistent context handling, QMAP support or improved netifd integration may indeed solve real shortcomings. If so, contributing those improvements to the existing components could benefit all existing users without creating two competing OpenWrt-specific WWAN stacks.
I would therefore prefer to see wwand mature as an external feed first, gain broader hardware coverage and users, accumulate real-world bug reports and fixes, and receive independent review of the protocol/state-machine implementation.
Once that has happened, and if there is consensus that maintaining a separate WWAN implementation is preferable to improving the existing stack, inclusion in the official packages feed could be reconsidered.
So for now, I would be against merging this PR. This is not because the project has no value, but because replacing several established OpenWrt WWAN components with a young and very broad implementation creates a substantial long-term maintenance and review burden that I don't think has been justified yet.
|
Thanks for taking a deep look. This code is based on my personal QMI dial-in handler which I developed since 2014. All of my knowledge about quirks with modems is in this project. I can understand you to not support inclusion, but is not the package feed exactly for this? Optional packages, which the user selects if he want's it. The user may use old style stack with all of it's stability problems or may use wwand instead. So this is not about replacing, it is about giving a stable alternative with features which are needed in the field (plmn lock i.e.), that nothing else provides. André |
Shouldn't that only be a showstopper if wwand is set to the default install for wwan interfaces? Since there are already so much packages for manageing WWAN stuff, why is this section important for adding another package? The options you get with wwand are mostly missing on ALL other packages... Cheers, 4920441 |
openwrt-ai
left a comment
There was a problem hiding this comment.
Packaging-level review of net/wwand/Makefile only — the inclusion/scope discussion in the existing review is a maintainer call and I'm not restating it.
Nothing here blocks a merge on its own. The two worth acting on regardless of how the scope question lands are the unresolvable CONFLICTS entry and the glob-then-rm split in Package/wwand/install, which can silently produce two packages owning the same path. The rest are small.
Metadata otherwise checks out: PKG_RELEASE:=1 is correct for a new package, PKG_MAINTAINER is set, the define blocks follow the 2-spaces-for-metadata / tabs-for-recipes convention, all ucode-mod-* and kmod-* dependencies resolve against openwrt main, lpac in this feed is at 2.3.0 so the >= 2.3.0 note holds, and the codeload.github.com/.../refs/tags/ source URL matches what 243 other Makefiles in this feed do. I could not verify PKG_HASH or the v1.0.0 tag — this session's GitHub access is scoped to openwrt/packages.
Generated by Claude Code
|
Thanks for the very thorough and fair review — the scope and maintenance-burden concerns are legitimate, and I've reworked the most load-bearing part in response. The biggest change: wwand no longer replaces the stock WWAN stack. I've removed all
So it's no longer "a second implementation that replaces the existing handlers" — it's additive and opt-in per interface. That directly targets the "two competing OpenWrt-specific WWAN stacks" and "replacing established handlers" concerns: nothing is replaced unless the operator explicitly opts in, and the stock stack keeps owning On maturity and independent review — I fully agree these matter for low-level protocol/state-machine code. It's being maintained and shipped from an external feed (github.com/ddimension/openwrt-repo), runs on production hardware here (QMI/MBIM/NCM across several modems), and I'm actively hardening it. I'd like to keep improving it in the open rather than sit on it. Given the coexistence rework removes the "replaces the existing stack" objection, would you be open to leaving this open for another ~2 weeks while I continue to mature it — broaden hardware coverage, gather field bug reports, and address review feedback? I'll keep the PR updated regularly as that happens. If after that you still feel the scope is too broad for the feed, I completely understand keeping it external for now. |
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review of the one new commit since my last pass (d802b81, "wwand: 1.1.0 — coexist with the stock WWAN stack"). Packaging-level only; the inclusion/scope discussion is a maintainer call and I'm not restating it.
The three packaging points from the previous round are all addressed: ucode-mod-wwand-io now depends on +ucode, wwand-esim gained SUBMENU:=WWAN, and the install step uses $(CMAKE_BINARY_DIR) — which expands to $(PKG_BUILD_DIR)/build given CMAKE_BINARY_SUBDIR:=build, so the path is unchanged and now tracks L29. The dead qmi-advanced CONFLICTS entry went away with the rest of the CONFLICTS lines. The version bump keeps PKG_RELEASE:=1, which is correct for a PKG_VERSION change. Commit message matches the diff.
Nothing new blocks a merge. The one worth an answer before this lands is device ownership under the new coexistence model: CONFLICTS is what previously guaranteed only one stack could touch a given /dev/cdc-wdmX, and the replacement guarantee is a runtime property of the daemon that the packaging can't show. The takeover / proto qmi alias question is the same theme from the netifd side. The other two are nits.
Two earlier threads are still open and I haven't repeated them: the glob-then-rm split in Package/wwand/install, and the missing test-version.sh for the generic CI version check. Only the FormalityCheck jobs have reported on this head (all green), so the build/test CI hasn't exercised the latter yet.
I still can't verify PKG_HASH or the v1.1.0 tag — this session's GitHub access is scoped to openwrt/packages, so ddimension/wwand is unreachable to both the API and a plain fetch. Treat those as unchecked rather than checked-and-fine.
Generated by Claude Code
| # coexists with the stock OpenWrt MBIM stack (netifd `mbim` proto, package | ||
| # umbim): wwand manages a cdc_mbim modem only once its interface has been | ||
| # migrated to `proto wwand` (LuCI modem list / migrate CLI), so both stacks can | ||
| # be installed side by side. |
There was a problem hiding this comment.
The coexistence claim here is about interfaces, but device ownership is what actually collides. The base package installs /etc/hotplug.d/usbmisc/20-wwand at Makefile:94-95 unconditionally, so the daemon gets poked for every cdc-wdm that appears, regardless of whether any interface is proto wwand. With CONFLICTS removed, the realistic install now has umbim/uqmi driving /dev/cdc-wdm0 for a proto mbim/proto qmi interface while wwand is also present on the box.
Does the daemon leave a control device completely untouched — no open, no MBIM OPEN, no QMI client allocation — when no proto wwand interface references it? If it probes on hotplug to build the modem list, two stacks are on the same cdc-wdm channel and MBIM in particular does not tolerate a second session owner. That would undercut "both stacks can be installed side by side" for exactly the users this change targets. Same question for the NCM comment at L179-182 and the AT tty hook at L101-102.
If the daemon already gates probing on the presence of a proto wwand interface (or on takeover), saying so in these comments would settle it — it is the one thing a reader can't confirm from the packaging.
Generated by Claude Code
There was a problem hiding this comment.
Repointed at v1.4.3, which adds the runtime half of this.
Your framing was right and the answer I gave earlier — "wwand opens a control device only for an interface it manages" — was too comfortable. Dropping the qmi alias gave exactly one owner per interface and said nothing about the device. Two holes were left: a hand-written wwand_modem could point at a node uqmi drives, and autosetup's guard recognised only cellular protos, so a proto dhcp left on wwan0 by a comgt-ncm setup did not stop it claiming that netdev.
wwand now collects every device claim made by a non-wwand interface and refuses to bind a claimed one, with the owner on the modem's control_note rather than the modem merely looking absent:
device blocklist: /dev/cdc-wdm0 (interface bt_mbim, proto mbim), wwan0 (interface bt_ncm, proto ncm), ...
modem wwmodem1: device /dev/cdc-wdm0 is owned by interface bt_mbim (proto mbim) — ignoring this modem
Coverage was read off the handlers' own proto_config_add_* lists rather than assumed, which is what caught the interesting part — the first cut would have missed the configurations that matter most:
| handler | binds hardware with |
|---|---|
qmi.sh (uqmi) |
device, devpath |
mbim.sh (umbim) |
device, devpath |
ncm.sh (comgt) |
device, ifname |
wwan.sh (generic) |
bus — declares no device option at all |
devpath is how uqmi/umbim bind by sysfs path instead of an unstable node name — the careful configuration — and wwan.sh claims hardware purely by USB bus id. Both are path-shaped, so they are normalised to the /sys/devices/-relative form and compared on the hardware path; a claim on a USB device covers its functions. A claim that resolves nowhere under /sys/devices is dropped rather than matched against everything. PROTO_DEFAULT_OPTIONS is defaultroute peerdns metric, so nothing device-shaped arrives via proto_config_add_defaults.
Two deliberate exclusions: a disabled interface claims nothing (netifd never brings it up, so a stale section must not block a device forever), and @name references an interface rather than a device.
Verified on hardware (two modems, a MikroTik Chateau): proto mbim + device, proto ncm + ifname/ctldevice all block; proto qmi + disabled 1 does not; removing the sections brings both modems back.
I am not resolving this thread, because it does not close the case you actually raised. With zero-config autosetup on — the default — a box with no wwand configuration still claims a modem nobody has claimed. What is now guaranteed is the narrower thing: wwand never takes a device somebody else has. Whether the autosetup default is right for a package that installs alongside uqmi is still the maintainer call you framed it as, and option autosetup 0 is the opt-out.
Package-G artefacts for the openwrt/packages#30185 + openwrt/luci#8917 push: - upstream/dossier-packages-30185.md — maturity/coexistence dossier to post as a PR comment (ModemManager precedent, independent-verification story, HW/test matrix, audit changelog, device-ownership answer, re-review request). - upstream/rfc-openwrt-devel.md — the architecture RFC (improve-existing-stack vs. a separate opt-in proto) for openwrt-devel. - upstream/checklist.md — the push/tag/PR/feed action sequence. Drafts for author review; sending/posting is manual. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Updated to wwand 1.2.0 (tag Since 1.1.0:
LuCI side is updated in openwrt/luci#8917. |
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review of the one new commit since my last pass (345c8b1, "wwand: 1.2.0"). Packaging-level only; the inclusion/scope discussion in the maintainer review above is a maintainer call and I'm not restating it.
The bump itself is clean: PKG_RELEASE stays at 1, which is correct for a PKG_VERSION change, and the new /usr/bin/wwandctl install is properly paired with a wwandctl.uc entry in the base package's strip list, so it doesn't also leak into $(UCDIR). The commit message matches the diff. I confirmed the v1.2.0 tag exists in ddimension/wwand (resolves to commit 1d75ae8); PKG_HASH I still can't verify — codeload.github.com is not reachable from this session — so treat that one as unchecked rather than checked-and-fine.
One finding is worth acting on before merge: 1.2.0 also adds files/wwand.hotplug.wwan, a fourth hotplug script that this Makefile never installs, which leaves the "PCIe/MHI (kernel wwan subsystem) discovery" listed in the commit message working only for modems already present when the daemon starts. The other two comments are nits.
Earlier threads are still open and I haven't repeated them: the glob-then-rm split in Package/wwand/install, the missing test-version.sh (one new comment does extend that one, since 1.2.0 adds a second executable that definitely fails the generic check), the proto qmi alias ownership question under takeover, the cdc-wdm device-ownership question, and the PR body still describing the pre-1.1.0 CONFLICTS / auto-migrate model. Only the three FormalityCheck jobs have reported on this head, all green, so the build/test CI still hasn't exercised any of this.
Generated by Claude Code
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review of the one new commit since my last pass. 345c8b1 was amended into fc0388e (same subject, wwand: 1.2.0); the only delta against what I reviewed last time is the four-line wwan hotplug hunk in Package/wwand/install. Packaging-level only; the inclusion/scope discussion in the maintainer review above is a maintainer call and I'm not restating it.
That hunk resolves the one finding I flagged as worth acting on last round: files/wwand.hotplug.wwan is now installed to /etc/hotplug.d/wwan/20-wwand, and the paired $(INSTALL_DIR) is what arms the dispatch — procd only calls hotplug-call for a subsystem whose directory exists (hotplug.json:83-86). INSTALL_DATA matches the three sibling hotplug installs above it and the in-tree precedent for this same subsystem (modemmanager Makefile:158-160), and the filename doesn't collide with modemmanager's 25-modemmanager-wwan, so both can be installed. Commit message matches the diff, PKG_RELEASE stays at 1, which is correct for the PKG_VERSION change.
Nothing new to flag on this head. Earlier threads are still open and I haven't repeated them: the glob-then-rm split in Package/wwand/install, the missing test-version.sh (three installed executables now), the proto qmi alias ownership question under takeover, the cdc-wdm device-ownership question, the MHI kmod hint in Package/wwand-qmi/description, the bare wwand: 1.2.0 commit subject, and the PR body still describing the pre-1.1.0 CONFLICTS / auto-migrate model.
Two things I could verify last round but cannot on this one: PKG_HASH and the v1.2.0 tag. This session's GitHub access is scoped to openwrt/packages, and codeload.github.com is unreachable, so ddimension/wwand is out of reach to both the API and a plain fetch. PKG_HASH is unchanged by this amend, so nothing new rests on it — but treat it as unchecked here rather than checked-and-fine.
Only the three FormalityCheck jobs have reported on this head, all green, so the build/test CI still hasn't exercised any of this.
Generated by Claude Code
|
Pushed a squashed head (
Answering the two open questions, since they're the ones that can't be read off the packaging:
cdc-wdm device ownership. wwand opens a control device only when a glob-then- |
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review against the new head. The branch was squashed since my last pass — the four commits I had reviewed (fc0388e and its ancestors) are now the single commit 8ffb9e3, "wwand: add cellular connection manager". Diffing fc0388e..8ffb9e3 on net/wwand/, the only content delta is two things, both closing threads from earlier rounds:
net/wwand/test-version.sh(new) — opts all six binary packages out of the generic version check. It follows the in-tree$PKG_NAMEcase/*)-fallback shape (e.g.libs/expat/test-version.sh), has nogrep -q, and lists every package the Makefile builds, so the*)branch can't fire.Package/wwand-qmi/description(L130-134) — the MHI kmod hint. All three names check out against openwrt main:kmod-mhi-wwan-ctrl,kmod-mhi-net,kmod-mhi-pci-generic.
The squash also resolved the bare-wwand: 1.2.0 subject nit on its own. The single commit's message matches its diff, and PKG_RELEASE:=1 is correct for a new package. Nothing new blocks a merge; the one comment below is a nit.
Worth noting because it changes what is actually verified: the full build CI has now run on this head and is green on all ten architectures, so test-version.sh is confirmed working rather than assumed — the x86_64 runtime job logs wwand-qmi: Version test override script found and [pass] Version check override for each package, then All tests passed. (The * Failed to connect to ubus lines around the wwand post-install/pre-deinstall in that log are just default_postinst's "$i" start on a procd init script in a container with no ubus — not a defect here.) lpac in this feed is still at 2.3.0, so the >= 2.3.0 note in Package/wwand-esim/description continues to hold.
Earlier threads are still open and I'm not repeating them: the glob-then-rm split in Package/wwand/install, the proto qmi alias ownership question under takeover, the cdc-wdm device-ownership question, the qmi-advanced mention that survives in the L121 prose, the ucode-mod-io reuse question, and the PR body still describing the pre-1.1.0 CONFLICTS / auto-migrate model. The scope and inclusion discussion in the maintainer review above is a maintainer call and I'm not restating it.
PKG_HASH and the v1.2.0 tag I still cannot check — this session's GitHub access is scoped to openwrt/packages, so ddimension/wwand is unreachable to both the API and a plain fetch. Neither changed in this delta, but treat them as unchecked rather than checked-and-fine.
Generated by Claude Code
|
Updated to wwand 1.3.0 (tag
New in 1.3.0 as well: the ucode tree ships precompiled to bytecode by default (repo-root CMakeLists, built next to On the broader architecture question: I'd still welcome a discussion with the WWAN/netifd maintainers. wwand is deliberately additive here (opt-in per interface, nothing replaced by default), and I'm happy to feed back any of the recovery / persistent-context / QMAP / netifd-integration work into the existing stack where that's the better home. |
|
I very much welcome and look forward to this component, because the existing proto_qmi, proto_mbim, and proto_ncm only implement basic connection functionality, lacking a GUI interface and advanced features such as band locking, SMS reading, signal strength, etc. This component can provide unified management and reduce the learning cost for users. As for the possibility that the author might stop maintaining it in the future, we can simply remove this package then. |
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review against the new head. The branch was squashed again — 8ffb9e3 is now the single commit 8e33265 with the same subject, so I diffed 8ffb9e3..8e33265. The delta is the 1.3.0 bump plus four structural changes: the ucode tree is now precompiled to bytecode by a repo-root cmake build (PKG_BUILD_DEPENDS:=ucode/host, UCODE_COMPILER/UCODE_PRECOMPILE, the new CONFIG_WWAND_UCODE_SOURCE opt-out), the base install switched from glob-then-rm to explicit WWAND_BASE_UC/_CODEC/_SCHEMA lists, ucode-mod-wwand-io was folded into the base package (PROVIDES:=ucode-mod-wwand-io) and replaced in the package set by the new wwand-mhi transport bundle, which is also where the wwan hotplug now lives. Packaging-level only; the inclusion/scope discussion in the maintainer review above is a maintainer call and I'm not restating it.
Three earlier threads close with this head, and the replacements check out: the base package no longer installs anything a backend owns; wwand-mhi's DEPENDS names four kmods that all exist in openwrt main, including kmod-mhi-wwan-mbim, which answers the MBIM-over-MHI question I raised last round; and test-version.sh was updated in step with the package set (wwand-mhi in, ucode-mod-wwand-io out), so the *) fallback still cannot fire. The single commit's message matches its diff and PKG_RELEASE:=1 is correct for a new package, so no commit checks.
What is new is that the default build path changed shape. Three of the comments below are questions about that path — bytecode/interpreter skew, whether the SDK's host ucode can compile modules that import ubus/uci/uloop/rtnl, and whether a precompiled main.uc is still directly executable as /usr/sbin/wwand. None is a defect I can demonstrate from the packaging alone, and each has a one-line answer if the upstream build already handles it; I raise them because bytecode is the default while every build and runtime test this PR has accumulated so far exercised the source path, and only the three FormalityCheck jobs have reported on this head. The other two comments are nits.
Earlier threads I'm not repeating: the proto qmi alias ownership under takeover and the cdc-wdm device-ownership question (both answered in the PR conversation but the threads are still open), and the PR body still describing the pre-1.1.0 CONFLICTS / auto-migrate model.
PKG_HASH and the v1.3.0 tag remain unchecked — this session's GitHub access is scoped to openwrt/packages, so ddimension/wwand is unreachable to both the API and a plain fetch. Treat them as unverified rather than verified-fine.
Generated by Claude Code
|
Here is my addition to the findings by the AI reviewer. It reviewed the coexistence model (based on blocklisting device nodes) with older uqmi/umbim/comgt-ncm protos, but completely forgot about protos 3g, directip, and modemmmanager. The first two live in the comgt package, same as ncm. The third one is in modemmanager. Check if the existing code covers these extra setups. |
…ames Raised by a maintainer on openwrt/packages#30185: the device blocklist was checked against qmi/mbim/ncm/wwan, but not against comgt's `3g` and `directip` or against `modemmanager`. Checked all three against their handlers: - comgt `3g.sh` and `directip.sh` declare `device:device` — a real device node — which the existing name branch already collects. Covered, no change. - `modemmanager.sh` declares a plain `device` and puts a SYSFS PATH in it ("validate sysfs path given in config", and it passes the value straight to `mmcli --modem=`). That can never match a /dev node or a netdev name, so a modemmanager interface claimed its modem entirely invisibly to us — the one spelling the blocklist did not see. A `device` value under /sys/ is now recorded as a path-shaped claim as well, so it resolves through the same claim_path()/same_hw_path() comparison as uqmi's `devpath` and wwan.sh's `bus`. Keyed on the prefix rather than on the proto name: `mmcli --modem=` also accepts an index or a D-Bus path, and neither names hardware anything could resolve — blocking on those would be wrong, not safer.
|
@patrakov Thank you — one of the three was a real hole. Checked all of them
Fixed in v1.4.6, which this PR now pins: a Keyed on the Your framing exposed the general shape of the mistake, which is worth stating |
Netifd protocol handler for `proto wwand`, the cellular connection manager proposed in openwrt/packages#30185. It renders the connection options the daemon consumes — APN, PDP type, authentication, MUX id, MTU handling — and resolves the modem an interface is bound to. wwand registers `proto wwand` only; the historical `qmi` proto name stays uqmi's, so this handler never competes with the stock one for an interface. Signed-off-by: André Valentin <avalentin@marcant.net>
Status and management UI for the wwand cellular connection manager proposed in openwrt/packages#30185: modem overview, per-modem tools (radio technologies, band selection, network selection and scan, cell lock), SIM and eSIM profile management, SMS, and the per-interface migration entry point that converts a stock cellular interface to `proto wwand` in place. Everything is driven over the daemon's ubus API; the ACL file lists exactly the methods the pages call. Signed-off-by: André Valentin <avalentin@marcant.net>
wwand -> v1.4.6 (373e18e). A maintainer on openwrt/packages#30185 pointed out that the device blocklist had been checked against qmi/mbim/ncm/wwan but not against comgt's 3g and directip or against modemmanager. Checked all three against their handlers: 3g and directip declare `device:device` (a real device node) and were already covered; modemmanager declares a plain `device` and puts a SYSFS PATH in it, which could never match a /dev node or a netdev name — so such an interface claimed its modem invisibly. A `device` under /sys/ is now a path-shaped claim too, resolved like uqmi's devpath and wwan.sh's bus. luci-proto-wwand -> 680692f. Drops a dead `require wwand.simlist`: SIM overrides live on the Modems page, only the require stayed behind. Found in review on openwrt/luci#8917. The Makefile comment named the shared modules wrongly in both directions — it claimed one (bands) when five are used, and after a first correction claimed six by counting the dead one.
Status and management UI for the wwand cellular connection manager proposed in openwrt/packages#30185: modem overview, per-modem tools (radio technologies, band selection, network selection and scan, cell lock), SIM and eSIM profile management, SMS, and the per-interface migration entry point that converts a stock cellular interface to `proto wwand` in place. Everything is driven over the daemon's ubus API; the ACL file lists exactly the methods the pages call. Signed-off-by: André Valentin <avalentin@marcant.net>
Status and management UI for the wwand cellular connection manager proposed in openwrt/packages#30185: modem overview, per-modem tools (radio technologies, band selection, network selection and scan, cell lock), SIM and eSIM profile management, SMS, and the per-interface migration entry point that converts a stock cellular interface to `proto wwand` in place. Everything is driven over the daemon's ubus API; the ACL file lists exactly the methods the pages call. Signed-off-by: André Valentin <avalentin@marcant.net>
openwrt-ai
left a comment
There was a problem hiding this comment.
Reviewed 1 new commit; no new issues found.
The branch was squashed again — the delta since my last pass (d6b13de, v1.4.5) is the single commit f2b7a26, same subject. Diffing d6b13de..f2b7a26 on net/wwand/, the whole change is four lines: PKG_VERSION 1.4.5 → 1.4.7 and the matching PKG_HASH. PKG_RELEASE:=1 is correct for a new package, and the commit message matches its diff, so no commit checks. Packaging-level only; the scope/inclusion discussion in the maintainer review above is a maintainer call and I'm not restating it.
Verified against the release this now pins. Tag v1.4.7 exists in ddimension/wwand (annotated tag 3becd75 → commit 4134174), and comparing that tree with v1.4.5:
- No files were added or removed upstream —
v1.4.5..v1.4.7touches onlysrc-ucode/config.uc,daemon.uc,main.uc,telemetry_ncm.ucplus docs and tests. That is the thing a bump can silently break here, since every package installs an explicit per-file list rather than a glob: a new module would ship in no package at all. Re-running the ownership check againstv1.4.7anyway — 38WWAND_BASE_UC+ 4WWAND_BASE_CODEC+ 13WWAND_BASE_SCHEMA,main.uc,wwandctl.uc, the qmi/mbim/ncm/esim lists andcodec/mbim_schema/*.uc— gives no duplicates and no orphans: every.ucin the release is owned by exactly one package. All eight$(PKG_BUILD_DIR)/files/...paths resolve too, includingfiles/examples/99-wwand-migrate. - No new module or binary dependency. The only native ucode modules the tree pulls are
fs,struct,uloop,ubus,uci,rtnl(viarequire('rtnl')innetlink.uc) andwwand_io— all covered byDEPENDSon the base package. The four dynamicrequire()s of wwand's own modules (wwand.atport,codec.schema.loc_lazy,codec.schema.wms_lazy,wwand.esim_bridge) each resolve to a file some package installs, so lazy loading can't hit a module that shipped nowhere. The upstream delta adds no external-binary spawn, so nothing new is owed aDEPENDSentry. main.ucandwwandctl.ucstill start with#!/usr/bin/env ucode, so the source-default path installs them directly executable as/usr/sbin/wwandand/usr/bin/wwandctl.test-version.shis unchanged and still names all six packages, so the*)branch cannot fire;lpacin this feed is still 2.3.0, so the>= 2.3.0note inPackage/wwand-esim/descriptioncontinues to hold.
PKG_HASH is the one thing I still cannot check: codeload.github.com is blocked by this session's egress policy (403 on the archive URL) even though the git endpoint for the same repo is reachable, so the tarball itself is out of reach. Treat it as unverified rather than verified-fine.
Only the three FormalityCheck jobs have reported on this head, all green. The full build/runtime CI has not run since 8ffb9e3, so neither the current install lists nor the source-default build path have been exercised by CI.
The cdc-wdm device-ownership thread remains open and answered in the conversation rather than closed — a maintainer call; I'm not restating it. The one comment below is a nit.
Generated by Claude Code
| include $(TOPDIR)/rules.mk | ||
|
|
||
| PKG_NAME:=wwand | ||
| PKG_VERSION:=1.4.7 |
There was a problem hiding this comment.
nit: the PR body has drifted behind this line again — it says "Current release: v1.4.5 — the release this Makefile pins", but this pins 1.4.7. Same mismatch I raised on the b28b266 round (body said v1.3.0 against a v1.4.2 pin); that one was fixed by updating the body, and it has fallen behind by two releases once more.
Everything else in the body still matches the Makefile (source-by-default with CONFIG_WWAND_UCODE_PRECOMPILE opt-in, no CONFLICTS, explicit per-file install lists, the inert examples/ migrate script), so this is just the one number. Purely cosmetic — it does not affect what gets built.
Generated by Claude Code
There was a problem hiding this comment.
Fixed, and the pin moved on since: the Makefile now pins 1.4.9 and the body says "Current release: v1.4.9 — the release this Makefile pins". The stale check count went with it (2856 -> 2935).
Worth saying plainly, since this is the third time the body lagged the pin: the drift is not an oversight in one direction, it is that the two live in different places and only one of them is in the diff you review. The release procedure here now treats the body as part of the bump rather than as prose, so a pin change that leaves it behind is an incomplete change.
Status and management UI for the wwand cellular connection manager proposed in openwrt/packages#30185: modem overview, per-modem tools (radio technologies, band selection, network selection and scan, cell lock), SIM and eSIM profile management, SMS, and the per-interface migration entry point that converts a stock cellular interface to `proto wwand` in place. Everything is driven over the daemon's ubus API; the ACL file lists exactly the methods the pages call. Signed-off-by: André Valentin <avalentin@marcant.net>
|
Hi, |
|
root@OpenWrt:~# Thu Aug 27 13:27:04 2026 daemon.warn wwand[4399]: modem wwmodem0: uim read of file 6f60 failed: { "error": "qmi", "result": 1, "code": 48 } |
|
Hi simass, thanks for testing. |
Plese send more logs and used version. Thanks a lot! |
|
Daemon fails to recover after deleting all configuration with multiplexing: |
|
Hi! Thanks for all the detailed reports. I could identify the problems, hopefully mips also.
|
ed35221 to
c96f904
Compare
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review against the new head. The branch was squashed again — my last pass was f2b7a26 (v1.4.7), and the delta is the single commit c96f904 with the same subject. Diffing f2b7a26..c96f904 on net/wwand/, the whole packaging change is two lines: PKG_VERSION 1.4.7 → 1.5.1 and the matching PKG_HASH. PKG_RELEASE:=1 is correct for a new package and the commit message matches its diff, so no commit checks. Packaging-level only; the scope/inclusion discussion in the maintainer review above is a maintainer call and I'm not restating it.
One finding, and it is precisely the failure mode the explicit-per-file install lists exist to make visible. Every bump I have checked so far added no ucode modules, so the lists never had to move. 1.5.0 does add two — src-ucode/atcmd_mbim.uc and src-ucode/atcmd_mbim_lazy.uc, the AT-over-MBIM transport — and the install lists did not move with them, so those two files ship in no package at all. Because modem_common.uc (base package) require()s the shim unguarded, that is a runtime throw on any modem with no AT tty, not merely a missing feature. Details and a suggestion are inline; the second comment is a question about which package should carry them once they are packaged, given that the modems this transport was written for are wwand-mhi + wwand-qmi installs.
Verified against tag v1.5.1, which exists in ddimension/wwand (annotated tag 28f73a2 → commit fc013f1):
- Ownership check: 80 of the 82
.ucfiles in the release are owned by exactly one package, with no duplicates. The only two orphans are the pair above; nothing named by the Makefile is missing from the release. Upstream'sCMakeLists.txtmodule lists were updated for both files, which is what makes the omission here a packaging-side gap rather than an upstream one. - No new dependency is owed. The tree imports only the native modules
fs,struct,ubus,uci,uloopplusrtnl(viarequire()innetlink.uc) andwwand_io— all covered by the base package'sDEPENDS.v1.4.7..v1.5.1adds no external-binary spawn; thepatches/kernel/directory it adds is documentation for users patching their own kernel, not something the packaging installs. - All eight
$(PKG_BUILD_DIR)/files/...paths resolve, includingfiles/examples/99-wwand-migrate;main.ucandwwandctl.ucstill start with#!/usr/bin/env ucode, so the source-default path installs them directly executable. test-version.shis unchanged and still names all six packages, so the*)branch cannot fire;lpacin this feed is still 2.3.0, so the>= 2.3.0note inPackage/wwand-esim/descriptioncontinues to hold.- The PR body's "Current release: v1.5.1 — the release this Makefile pins" matches this head, so the drift nit from earlier rounds stays closed.
PKG_HASH is the one thing I still cannot check: codeload.github.com returns 403 for this session's egress policy even though the git endpoint for the same repo is reachable, so the tarball itself is out of reach. Treat it as unverified rather than verified-fine.
Only the three FormalityCheck jobs have reported on this head, all green. The full build/runtime CI has not run since 8ffb9e3, so neither the current install lists nor the source-default build path have been exercised by CI — which is why the orphaned modules above went unnoticed by anything but a read of the release tree.
The cdc-wdm device-ownership thread remains open and answered in the conversation rather than closed — a maintainer call; I'm not restating it.
Generated by Claude Code
| $(INSTALL_DATA) $(WWAND_UCODE)/mbim_backend.uc $(1)$(UCDIR)/ | ||
| $(INSTALL_DATA) $(WWAND_UCODE)/mbim_client.uc $(1)$(UCDIR)/ | ||
| $(INSTALL_DATA) $(WWAND_UCODE)/qmi_over_mbim.uc $(1)$(UCDIR)/ | ||
| $(INSTALL_DATA) $(WWAND_UCODE)/mbim_lazy.uc $(1)$(UCDIR)/ |
There was a problem hiding this comment.
The 1.4.7 → 1.5.1 bump added two ucode modules that no package in this Makefile installs: src-ucode/atcmd_mbim.uc and src-ucode/atcmd_mbim_lazy.uc (the AT-over-MBIM transport, new in 1.5.0). Cross-checking the union of WWAND_BASE_UC/_CODEC/_SCHEMA and the four backend install lists against the v1.5.1 tree, these are the only two orphans — the other 80 .uc files are each owned by exactly one package, and nothing named here is missing upstream. Upstream's own build lists were updated for both (CMakeLists.txt:86, CMakeLists.txt:114); the explicit per-file lists here were not, which is exactly the drift the explicit-list design is meant to surface.
The consequence is a runtime failure, not just a missing feature. modem_common.uc is in WWAND_BASE_UC, and it require()s the shim unguarded at modem_common.uc:985 and :1006 — the path open_at() takes whenever a modem has no AT tty. Unlike the backend loader in daemon.uc:23-42, which wraps require() in try/catch so a missing backend package "surfaces as a status note instead of a failure", there is no guard here, so this throws on a module that shipped nowhere instead of falling through to o.next().
The shim's own header says which package should own it — "it lives in the wwand-mbim package (it needs mbim_client + codec/mbim)" (atcmd_mbim_lazy.uc:5-7) — and atcmd_mbim.uc imports wwand.mbim_client and wwand.codec.mbim, both wwand-mbim files. atcmd_mbim.uc is an ES module and atcmd_mbim_lazy.uc a plain script, matching how mbim_lazy.uc is already handled, so both install the same way:
| $(INSTALL_DATA) $(WWAND_UCODE)/mbim_lazy.uc $(1)$(UCDIR)/ | |
| $(INSTALL_DATA) $(WWAND_UCODE)/mbim_lazy.uc $(1)$(UCDIR)/ | |
| $(INSTALL_DATA) $(WWAND_UCODE)/atcmd_mbim.uc $(1)$(UCDIR)/ | |
| $(INSTALL_DATA) $(WWAND_UCODE)/atcmd_mbim_lazy.uc $(1)$(UCDIR)/ |
Generated by Claude Code
There was a problem hiding this comment.
Both orphaned — thank you, this was a real packaging hole and not a cosmetic one. Fixed: wwand-mbim now installs atcmd_mbim.uc and atcmd_mbim_lazy.uc alongside mbim_lazy.uc.
They were added upstream in 1.5.0 and the bump here only moved PKG_VERSION/PKG_HASH, so the file lists never followed. The consequence was worse than a missing feature: modem_common.uc reaches the AT-over-MBIM pipe through require('wwand.atcmd_mbim_lazy'), so on an MBIM-driven modem the require would have thrown out of open_at rather than degrading.
I checked the rest of the tree the same way rather than fixing just the two you named — every .uc in src-ucode/ is now referenced by some install section, so there are no other orphans.
| DEPENDS:=+wwand +kmod-mhi-pci-generic +kmod-mhi-wwan-ctrl \ | ||
| +kmod-mhi-wwan-mbim +kmod-mhi-net |
There was a problem hiding this comment.
Follow-on question to the orphaned-module comment above: once atcmd_mbim*.uc is packaged into wwand-mbim, does an MHI modem still reach it?
The AT-over-MBIM transport exists primarily for this package's hardware. Its header explains that the generic Qualcomm MHI profile "declares DIAG/MBIM/QMI/IPCR/FIREHOSE/IP_SW0/IP_HW0 but no DUN channel, and DUN is what mhi_wwan_ctrl turns into /dev/wwanNat0" (atcmd_mbim.uc:6-11) — so a QMI-driven MHI modem has no AT tty and falls into the discovery.wwan_sibling_port(self.device, 'mbim', …) branch, opening the sibling MBIM node purely as an AT side-channel. wwand-mhi already pulls kmod-mhi-wwan-mbim, so the kernel side of that node is covered here, but DEPENDS is +wwand only, and the install this package's own description recommends for such a modem is wwand-mhi + wwand-qmi — which would carry neither atcmd_mbim.uc nor its mbim_client/codec/mbim imports.
Is +wwand-mbim meant to be part of wwand-mhi's DEPENDS (or at least hinted at in its description, the way the MHI pairing hint was added to the qmi/mbim descriptions), or is the AT-over-MBIM path only expected to be reachable on MBIM-driven modems? Asking rather than asserting because the answer depends on how much of the vendor telemetry / protocol-switch / AT+QSIMDET path you consider load-bearing for a QMI-over-MHI install.
Generated by Claude Code
There was a problem hiding this comment.
It does not, and that is the sharper half of the question — thank you.
atcmd_mbim needs the MBIM client and codec, so wwand-mbim is where it belongs. But an MHI modem driven over QMI installs wwand-qmi + wwand-mhi, and nothing there pulls wwand-mbim in. That combination is precisely where the pipe is wanted, because the generic Qualcomm entry in mhi-pci-generic declares no DUN channel and such a modem therefore has no AT port at all.
Two changes, upstream in the tree this pins next:
-
The require is no longer bare. It now follows the shape
daemon.ucalready uses for the backend packages (lazy_backend): try once, remember the failure, and report the capability as absent with a log line naming the package to install. So the missing package is a limitation, not a traceback — the same contract the control backends already have. -
wwand-mhi's description says so: addingwwand-mbimis worthwhile even on a QMI-driven MHI modem, because it is what makes AT reachable at all there.
I deliberately did not make wwand-mhi DEPEND on wwand-mbim. It would pull the whole MBIM backend onto every MHI box for a fallback that many will not need — some MHI modems do expose DUN, and a kernel that declares the channel gives them a real AT port, which is better than the pipe anyway (full duplex, and it carries URCs, which a request/response pipe cannot).
atcmd_mbim lives in wwand-mbim, because it needs that package's MBIM client and codec — and an MHI box is exactly where it is wanted and may be absent: such a modem installs wwand-qmi + wwand-mhi, and nothing there pulls wwand-mbim in. The require() was bare, so on that combination it threw straight out of open_at instead of reporting a capability we do not have. It now follows the shape daemon.uc already uses for the backend packages (lazy_backend): try once, remember the failure, and treat absence as "no AT over MBIM" with a log line that names the package to install. The loader is injectable for the same reason open_transport and open_mbim_at are — the module is always present in a source tree, so its absence can only be exercised through a seam. Caught by the reviewer on openwrt/packages#30185, who also spotted the other half: the PR's Makefile did not install the two new modules at all.
wwand is an event-driven cellular connection manager written in ucode. It drives netifd over ubus with no_proto_task, so the daemon owns the modem and context lifecycle while netifd keeps ownership of all addressing and routing. Six packages: a backend-neutral base (daemon, netifd shim, codec, the native wwand_io.so) plus wwand-qmi, wwand-mbim, wwand-ncm, wwand-mhi and wwand-esim. A backend is loaded lazily, so a missing backend package surfaces as a status note instead of a failure. It coexists with the stock stack rather than replacing it. There is no CONFLICTS on uqmi/umbim/comgt-ncm, and the shim registers `proto wwand` and nothing else — the `qmi` proto name stays uqmi's, so netifd's handler load order never decides who owns an interface. Handing one over is always an explicit act that rewrites it in place to `proto wwand`: the LuCI modem list, /usr/libexec/wwand/migrate, or the example uci-defaults script shipped inert under /usr/share/wwand/examples/. Nothing is installed under /etc/uci-defaults, so installing or upgrading cannot rewrite an existing configuration. The ucode tree ships as source. Bytecode precompilation is available via CONFIG_WWAND_UCODE_PRECOMPILE but stays opt-in: bytecode carries a format version (UCODE_BYTECODE_VERSION) that an interpreter upgraded past it refuses to load, and that version is independent of libucode's PKG_ABI_VERSION/SONAME, so no package relation expresses the coupling. It is only sound when ucode and wwand are built in the same tree, which a self-built image is and a feed is not. Signed-off-by: André Valentin <avalentin@marcant.net>
wwand 2311728 (tagged v1.5.2). One fix, found by the reviewer on openwrt/packages#30185: a missing wwand-mbim threw out of open_at instead of reporting a capability we do not have. atcmd_mbim lives in wwand-mbim because it needs that package's MBIM client and codec, and an MHI modem driven over QMI installs wwand-qmi + wwand-mhi without it — which is exactly where the AT-over-MBIM pipe is wanted, since the generic Qualcomm MHI profile declares no DUN channel and such a modem has no AT port at all. The require now behaves like daemon.uc's lazy_backend: try once, remember the failure, name the package in the log. wwand-mhi's description says why adding wwand-mbim is worthwhile there. PKG_MIRROR_HASH recomputed by the SDK and checked against the previous value (738ef785 -> 43098025).
openwrt-ai
left a comment
There was a problem hiding this comment.
Re-review against the new head. The branch was squashed again — 4e7d45d and the commits that followed it are now the single commit d99277e, same subject — so I diffed 4e7d45d..d99277e. Two files: the 1.3.0 → 1.5.2 bump plus the precompile inversion in net/wwand/Makefile, and a 644 → 755 mode change on test-version.sh. Packaging-level only; the scope and inclusion discussion in the maintainer review above is a maintainer call and I'm not restating it.
Nothing here blocks a merge. Both comments below are questions, and the second is arguably a design preference rather than a defect.
Earlier threads that close on this head
- The gated
ucode/hostbuild dependency now actually arms. The$(if $(CONFIG_...),ucode/host)form I flagged last round was dropped forWWAND_UCODE_PRECOMPILE:ucode/host(L48), and that prefix form is honoured:gen_package_mksplits eachBuild-Dependsentry on:into condition and package (package-metadata.pl:523-531) and feeds the condition toget_conditional_dep, which emits$(if $(CONFIG_WWAND_UCODE_PRECOMPILE),$(curdir)/package/utils/ucode/host/compile)into.packagedeps— evaluated with.configincluded, so the DUMP=1 problem does not apply. In-tree precedent for the same shape:elfutils/Makefile:25(!USE_GLIBC:argp-standalone). The explanatory comment at L43-47 is accurate. - The orphaned AT-over-MBIM modules are packaged.
atcmd_mbim.ucandatcmd_mbim_lazy.ucnow install inwwand-mbim(L249-250). Cross-checking the union ofWWAND_BASE_UC/_CODEC/_SCHEMAand the four backend install lists, no module is claimed by two packages. - The comment blocks that still described bytecode as the default are all rewritten consistently — L15-22, L53-58, L65-66 and L86-88 now agree with each other, with the
$(if ...)at L67 and withdefault nat L95. /etc/uci-defaults/99-wwand-migrateis gone; the script ships inert under/usr/share/wwand/examples/(L158-164), which matches both the commit message and the PR body.- The PR body no longer lags the pin — it says v1.5.2 and L27 pins 1.5.2. That is the fourth round this drifted and the first where it did not.
test-version.sh is unchanged apart from the mode; it still names all six packages the Makefile builds, so the *) fallback cannot fire, and 755 is the majority mode for this file in the feed (71 of 104). PKG_RELEASE:=1 is correct for a new package, and the single commit's message matches its diff — no commit checks.
What I could not verify
PKG_HASH and the v1.5.2 tag remain unchecked. This session's GitHub access is scoped to openwrt/packages; codeload.github.com answers the tarball URL with an access-denied JSON body rather than an archive, so ddimension/wwand is out of reach to both the API and a plain fetch. For the same reason I could not repeat the orphaned-module cross-check against the actual 1.5.2 src-ucode file list — the check above is internal consistency only, not "every shipped module is installed by exactly one package". Same for files/examples/99-wwand-migrate existing at this tag. Treat all of these as unverified rather than verified-fine.
Only the three FormalityCheck jobs have reported on this head, all green. The full build/runtime CI has not run since 8ffb9e3 (the 1.3.0 head), so the build path that is now the default — ucode source, precompile off, no host ucode staged — has never been exercised in this repo's CI. That is the ground for the first comment below.
Earlier threads still open and not repeated here: the cdc-wdm device-ownership question, the ucode-mod-io reuse question, whether the SDK's host ucode (built UBUS_SUPPORT=OFF/UCI_SUPPORT=OFF/ULOOP_SUPPORT=OFF/RTNL_SUPPORT=OFF) can compile the modules that import those, and the bytecode/interpreter-skew question — the last two now apply only to the opt-in path, which lowers their stakes considerably.
Generated by Claude Code
| -DUCODE_COMPILER=$(STAGING_DIR_HOSTPKG)/bin/ucode \ | ||
| -DUCODE_PRECOMPILE=$(if $(CONFIG_WWAND_UCODE_PRECOMPILE),ON,OFF) |
There was a problem hiding this comment.
UCODE_COMPILER is still passed unconditionally, but the binary it names is no longer guaranteed to exist. Until this head, PKG_BUILD_DEPENDS:=ucode/host (unconditional) made $(STAGING_DIR_HOSTPKG)/bin/ucode present for every build; now that L48 gates it on WWAND_UCODE_PRECOMPILE, the default build stages no host ucode at all, so cmake is configured with -DUCODE_COMPILER=<path that does not exist> -DUCODE_PRECOMPILE=OFF.
That is fine if the repo-root CMakeLists.txt only touches UCODE_COMPILER inside if(UCODE_PRECOMPILE) — the comment at L53-58 says the capability probe is on the opt-in path, which implies it does — but a bare find_program()/execute_process() or an if(NOT EXISTS ${UCODE_COMPILER}) at top level would fail configure on the path that is now the default. Can you confirm the option is unused when UCODE_PRECOMPILE=OFF?
Worth an explicit answer because nothing has built this configuration yet: the only full build/runtime CI run on this PR was on 8ffb9e3, where bytecode was the default and ucode/host was an unconditional build dependency. Every head since has only had the three FormalityCheck jobs report, so the source-default + no-host-ucode combination has never been exercised here.
(The gating change itself is correct — see the review body.)
Generated by Claude Code
| Adding wwand-mbim is worthwhile even on a QMI-driven MHI modem: many of them | ||
| expose no DUN channel and therefore no AT port at all, and wwand can then | ||
| carry AT over the modem's MBIM channel instead (Quectel QDU). Without that | ||
| package the capability is simply absent — vendor AT commands, the protocol | ||
| switch and AT telemetry are unavailable, which is a limitation rather than a | ||
| failure. |
There was a problem hiding this comment.
This now recommends wwand-mbim to users who have no USB modem, and wwand-mbim hard-requires the USB MBIM transport: DEPENDS:=+wwand-qmi +kmod-usb-net-cdc-mbim. Following the advice on a PCIe/MHI box therefore drags in kmod-usb-net-cdc-mbim and, through it, kmod-usb-wdm, kmod-usb-net-cdc-ncm, kmod-usb-net-cdc-ether, kmod-usb-net and kmod-mii — none of which the modem uses, since the transport on this path is kmod-mhi-wwan-mbim, which wwand-mhi already pulls.
The sharper edge is availability rather than size: that chain ends at kmod-usb-core, which is DEPENDS:=@USB_SUPPORT, so on a target built without USB support wwand-mbim is not selectable at all and the AT-over-MBIM capability this paragraph describes is simply unreachable — even though everything it actually needs (mbim_client.uc, codec/mbim*, atcmd_mbim*.uc, kmod-mhi-wwan-mbim) is available there.
The ucode side of wwand-mbim is transport-neutral; only the kmod line is not. Is the intent that MHI users accept the USB kmods, or should the cdc-mbim dependency move so the MBIM control backend and the USB transport can be selected separately (the way wwand-mhi already separates transport from backend)? Not prescribing a shape — it's your call whether that is worth a package split. Flagging it because the recommendation is new on this head and pushes users into exactly that combination.
Generated by Claude Code




Adds wwand, an event-driven cellular connection manager written in ucode: native QMI, MBIM and NCM/AT control (no uqmi/qmicli/libqmi/glib), direct netifd integration (the daemon owns the context lifecycle — no per-interface monitor process; transient loss renews in place so IPv6-PD/VRF survive), multi-modem + multi-PDP-context via QMAP multiplexing, SIM/eSIM management (SGP.22 via lpac), SMS (send + receive), telemetry, a recovery ladder, board profiles and zero-config autosetup. A
wwandctlCLI and a LuCI app (openwrt/luci#8917) sit on top.Upstream repo: https://github.com/ddimension/wwand (GPL-2.0-only, 2935 host-side checks run without hardware). Current release: v1.5.2 — the release this Makefile pins.
One source package, six binary packages:
wwand— backend-neutral base (daemon, codec, netifd proto shim, SIM/APDU layer,wwandctlCLI). It also ships the small native C transport modulewwand_io.so(message-oriented cdc-wdm/tty I/O + rmnet netlink helper) — wwand-private and always version-locked to the ucode side, so it lives inside the base package (PROVIDES ucode-mod-wwand-iofor older configs).wwand-qmi/wwand-mbim/wwand-ncm— per-protocol control backends; install only what the modems need (wwand-qmipulls inwwand; a typical QMI router needs just that).wwand-mhi— PCIe/MHI transport bundle (MHI bus/PCI/control/data kmods + the kernel-wwan-subsystem hotplug) for modems whose control port appears under/sys/class/wwaninstead ofusbmisc. Backend-neutral: pair withwwand-qmiorwwand-mbim.wwand-esim— optional SGP.22 profile management + SM-DP+ download (depends onlpac>= 2.3.0).Packaging. The ucode tree is flat; each package installs an explicit per-file list — no glob-then-
rm, so every module is owned by exactly one package and a new backend file can never silently ship in the base too. The ucode tree ships as source. Bytecode precompilation is available viaCONFIG_WWAND_UCODE_PRECOMPILEbut stays opt-in: bytecode carries a format version (UCODE_BYTECODE_VERSION) that an interpreter upgraded past it refuses to load, and that version is independent of libucode'sPKG_ABI_VERSION/SONAME, so no package relation expresses the coupling. It is only sound when ucode and wwand are built in the same tree — which a self-built image is and a feed is not.Good-citizen coexistence (no stock stack replaced). The packages do not
CONFLICTSuqmi/umbim/comgt-ncm — they install alongside them. The netifd shim registersproto wwandand nothing else: theqmiproto name stays uqmi's, so netifd's handler load order never decides who owns an interface, and there is no switch that changes this. wwand manages onlyproto wwandinterfaces and never adopts a bareproto qmi/mbim/ncmone, so exactly one dialer owns a given interface and the control device behind it. Handing one over is always user-triggered and rewrites it in place toproto wwand: a "Migratable interfaces" list in the LuCI modem page, themigrateubus method / CLI, or an example uci-defaults script shipped inert under/usr/share/wwand/examples/. Nothing is installed under/etc/uci-defaults, so installing or upgrading wwand cannot rewrite an existing configuration. Inclusion is additive and opt-in per interface, not a second implementation that displaces the existing handlers.Hardware-tested on MikroTik Chateau 5G R17 ax (Quectel RG650E, 5G NSA), Zyxel NR7101 (RG502Q), Zyxel LTE3301-Plus (EG06) and Cudy LT300 v3 (MeiG SLM770A-R), plus a GL.iNet GL-X3000 (RM520N-GL); the PCIe/MHI path (
wwand-mhi) is under active validation with community testers on Foxconn T99W175 hardware. Maintained and shipped from an external feed (github.com/ddimension/openwrt-repo) while it broadens coverage and gathers field reports.🤖 Generated with Claude Code