Skip to content

otbr 2026.08.0: pending dataset, full NIM cluster data - #53

Open
LorbusChris wants to merge 12 commits into
project-chip:mainfrom
LorbusChris:otbr-netifd-thread-proto
Open

otbr 2026.08.0: pending dataset, full NIM cluster data#53
LorbusChris wants to merge 12 commits into
project-chip:mainfrom
LorbusChris:otbr-netifd-thread-proto

Conversation

@LorbusChris

@LorbusChris LorbusChris commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Updates the border-router stack to enable Matter management of the Thread network, including migration to a different dataset via the pending-dataset mechanism. In daily use on OpenWrt-based hardware:

  • openthread-br 2026.08.0. The existing ubus patch series (100–106, 110) is untouched — the original files apply cleanly to the new release. New patches continue the series: the host groundwork as 122–125 (upstream as [host] fix Leave and migration handling on the RCP path openthread/ot-br-posix#3489, same order; that series' two NCP-mode patches are left out, since this feed builds and starts otbr-agent in RCP mode only), the ubus methods as 130–135 (follow-up series, stacked on yours and [host] fix Leave and migration handling on the RCP path openthread/ot-br-posix#3489), and the router table method as 136. The new files are generated with git format-patch from the upstream PR branches, rebased onto v2026.08.0.
  • matter-netman: async provision/deprovision, a matter ubus object, pending-dataset support in the ubus delegate, and real data on all NIM clusters (upstream as [network-manager-app] pending dataset support over ubus connectedhomeip#73309).
  • RCP selection: an explicit bus-position selector now overrides the USB product-string match, since many dongles (Home Assistant's ZBT-2 for one) do not carry "OpenThread" in their product string.
  • avahi variant dropped (mdnsresponder stays); feature options aligned with the openwrt packaging.

Gone since the last revision, per review: the netifd protocol integration — its proto script derived from the GPL-2.0-only one in openwrt/packages, which the CLA cannot accept, so the feed stays with the init-based model — and the GCC 14 patch for the vendored mbedtls, which this feed does not compile.

(On our Turris OS builds we additionally run the nftables firewall backend from openthread/ot-br-posix#3325; it is not carried in this PR.)

@ksperling-apple — the ubus series upstream: the 100–106/110 patches are your commits, and I'd like to see them land in ot-br-posix proper so the packagings can stop carrying them. Since the CLA has to come from the author, would you open that upstream PR yourself? My follow-on work is already in flight — openthread/ot-br-posix#3487 and openthread/ot-br-posix#3489 — and the ubus methods series that builds on yours (130–135 here) would follow, stacked on your PR.

The controller side works as well: Home Assistant imports the Thread dataset and Wi-Fi credentials from the network manager, surfaces the diagnostics, and can hand a border router a new network as a pending migration — those changes are heading upstream to home-assistant/core as a series of PRs.

@CLAassistant

CLAassistant commented Jul 30, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the matter-netman service on OpenWrt to fully support the Network Infrastructure Manager (NIM) cluster set using real system data. Key updates include publishing a 'matter' ubus object for onboarding and commissioning control, integrating real-time diagnostics for Wi-Fi, Thread, and Ethernet clusters, and migrating the OpenThread border router agent to a netifd protocol handler. Feedback on these changes identifies a build issue in the Makefile due to an invalid $(INSTALL_CONF) macro, potential information leaks and globbing bugs in the init script's reload logic, and a deprecated -a shell operator in the RCP script.

Comment thread service/matter-netman/Makefile
Comment thread service/matter-netman/files/matter.init
Comment thread third_party/openthread-br/files/otbr-rcp Outdated
@LorbusChris

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the OpenThread Border Router (OTBR) agent configuration on OpenWrt by moving it to a netifd protocol handler (thread-proto.sh) and implements real data providers for the NIM clusters (Wi-Fi, Thread, and Ethernet diagnostics). It also publishes a new 'matter' ubus object to expose commissioning status and control. The review feedback is highly constructive, pointing out that in multi-interface setups, ot-ctl needs to be directed to the correct socket path. It suggests introducing an otctl helper function in thread-proto.sh to ensure commands are routed correctly based on the active device.

Comment thread third_party/openthread-br/files/openthread-proto.sh Outdated
Comment thread third_party/openthread-br/files/thread-proto.sh Outdated
Comment thread third_party/openthread-br/files/openthread-proto.sh Outdated
Comment thread third_party/openthread-br/files/thread-proto.sh Outdated
@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from 50a0964 to dd5bab4 Compare July 30, 2026 10:53
@LorbusChris

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request integrates the full Network Infrastructure Manager (NIM) cluster set for OpenWrt, including Wi-Fi Network Management, Thread Network Diagnostics, Thread Network Directory, and Ethernet Network Diagnostics. It also updates the openthread-br package to support pending datasets, asynchronous provisioning/deprovisioning, and publishing a matter ubus object. The feedback recommends avoiding the suppression of stderr from the RCP discovery tool in thread-proto.sh to facilitate debugging.

Comment thread third_party/openthread-br/files/thread-proto.sh Outdated
@LorbusChris

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the matter-netman service and openthread-br package to improve Thread network management and integration with OpenWrt. Key changes include migrating to a new netifd protocol for Thread, implementing asynchronous ubus calls for provisioning, and adding a matter ubus object for commissioning. I have reviewed the code and identified two issues: a potential race condition in the protocol handler that could permanently block the interface at boot, and an unsafe string comparison in the OsReleaseField helper that could lead to undefined behavior.

Comment thread third_party/openthread-br/files/thread-proto.sh Outdated
@LorbusChris

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request integrates the Matter Network Infrastructure Manager (NIM) service with OpenWrt, enabling full support for Thread Border Router Management, Wi-Fi Network Management, and diagnostics clusters. It replaces the legacy procd service for otbr-agent with a native netifd protocol handler (thread) and introduces a series of patches to OpenThread Border Router (OTBR) and the Matter daemon to support asynchronous provisioning, pending datasets, and local commissioning control via a published Ubus object. The review feedback highlights two shell scripting issues: a syntax error in thread-proto.sh due to unsupported default value syntax in json_get_vars, and a potential false positive in the hotplug script when matching unconfigured backbone networks.

Comment thread third_party/openthread-br/files/openthread-proto.sh Outdated
Comment thread service/matter-netman/files/matter.iface-hotplug Outdated
@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from a8c3077 to 79885b9 Compare July 30, 2026 12:03
@LorbusChris

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces comprehensive improvements to the Matter Network Infrastructure Manager (NIM) and OpenThread Border Router (OTBR) integration on OpenWrt. Key changes include migrating the OTBR service to a native netifd protocol handler (thread), implementing full NIM cluster support (Wi-Fi Network Management, Thread Network Diagnostics, Thread Network Directory, and Ethernet Network Diagnostics) backed by real system data via ubus, publishing a matter ubus object for local commissioning control, and resolving several commissioning-flow issues such as asynchronous provisioning and fail-safe revert guarding. Additionally, the openthread-br package is updated, and several patches are introduced to enhance dataset handling, mDNS hostname advertising, and robustness. As there are no review comments, no further feedback is provided.

@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from 79885b9 to 07049b4 Compare August 1, 2026 00:35
@ksperling-apple

Copy link
Copy Markdown
Contributor

Hi @LorbusChris, thanks for this PR, it looks like a very substantial piece of work! I will have a detailed look next week.

In regards to upstreaming my OTBR patches, yes, I’m going through our company internal contribution review process at the moment, so I should be able to upstream them in a few weeks time.

@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch 2 times, most recently from caee27d to 015a51b Compare August 2, 2026 20:59
Comment thread third_party/openthread-br/files/openthread-proto.sh Outdated
@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from 015a51b to cc2895b Compare August 3, 2026 21:35
Comment thread third_party/openthread-br/patches/060-fix-gcc14-build.patch Outdated
Comment thread service/matter-netman/patches/030-network-manager-fake-revert.patch
@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from cc2895b to 61503f7 Compare August 5, 2026 18:30
@LorbusChris LorbusChris changed the title otbr 2026.07.0: pending dataset, full NIM cluster data, netifd thread protocol otbr 2026.08.0: pending dataset, full NIM cluster data Aug 5, 2026
Comment thread third_party/openthread-br/Makefile
Comment thread third_party/openthread-br/patches/120-ncp-active-dataset-refresh.patch Outdated
@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from 61503f7 to b105240 Compare August 6, 2026 04:22
Comment thread service/matter-netman/Makefile
Comment thread service/matter-netman/Makefile
Comment thread service/matter-netman/Makefile
Comment thread service/matter-netman/Makefile
Comment thread third_party/openthread-br/files/otbr-rcp
@@ -0,0 +1,24 @@
#!/bin/sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a real issue with the minimal-mdns provider matter-netman currently uses, but I don't think this is quite the right fix; in particular gating this on the AIL of the otbr seems like a strange way of phrasing the policy that we don't care about the Thread (wpan*) interface going up or down.

Getting Claude to look through the minimal-mdns implementation, it looks like this should be relatively straightforward to fix directly in that code. (Separately, we probably want to factor out a copy of the mDNSResponder-based dnssd backend out of the Darwin platform code, so it can be used on Linux, but that's a larger piece of work.)

Here's Claude's take / suggestion:

What's going on. minimal-mdns creates one socket per (interface, address family), each pinned to a specific interface index (Server.cpp:198 (https://github.com/project-chip/connectedhomeip/blob/master/src/lib/dnssd/minimal_mdns/Server.cpp#L198)) — but the interface list is enumerated exactly once, at Advertiser::Init(). The code says so itself (Advertiser_ImplMinimalMdns.cpp:365 (https://github.com/project-chip/connectedhomeip/blob/master/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp#L365)):

// TODO: ... we don't handle updates to our set of interfaces right now,
// so rely on the logic in this function to shut down and restart the
// GlobalMinimalMdnsServer to handle that.

So when netifd recreates a device, the new ifindex is never picked up and the existing sockets point at a dead one. Same if the daemon starts before the bridge exists. There's also no re-announcement (RFC 6762 §8) on an address-set change, so caches keep stale data until TTL. The A/AAAA records themselves are generated live per query from the source interface, so addresses do self-heal — it really is just socket/interface lifecycle.

Suggested fix. The plumbing is already there: DeviceEventType::kDnssdRestartNeeded → DnssdServer::StartServer() → Advertiser::Init(), which tears down endpoints, re-enumerates, re-listens and re-announces (Dnssd.cpp:59 (https://github.com/project-chip/connectedhomeip/blob/master/src/app/server/Dnssd.cpp#L59)). Several Zephyr WiFi backends post that event on reconnect; Linux posts it from nowhere. So:

  1. Add a netlink watcher in src/platform/Linux on RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR that posts a debounced kDnssdRestartNeeded. There's already a netlink socket in PlatformManagerImpl.cpp, but it's IPv4-addr-only, WiFi-only, and posts an event no DNS-SD code consumes. Debouncing matters — a bounce emits a storm of messages, and announcements should be rate-limited anyway.
  2. Harden Listen() first. It currently uses ReturnErrorOnFailure on Bind() under a ShutdownOnError guard, so one interface that's reported IFF_UP but fails to bind (normal mid-bounce) tears down every endpoint with no retry. Per-interface failures need to be non-fatal, like JoinMulticastGroup already is — otherwise a re-listen racing a bounce is worse than what we have today.
  3. On the Thread interface: AddressPolicy_DefaultImpl already skips wpan* (#72559), but AddressPolicy_LibNlImpl doesn't — it only filters IFF_UP/IFF_LOOPBACK/BROADCAST|MULTICAST. If the OpenWrt build uses the libnl policy, that's the gap worth closing, and it's the right place to express "we don't care about Thread" rather than reaching into otbr's infra_if_name.

With that, the hotplug script goes away entirely.

Meanwhile, if you want something that works before the SDK change lands: the expensive part of the current workaround isn't the rebind, it's that a full daemon restart drops all CASE sessions and subscriptions — which is also why it has to be gated so narrowly. Handling SIGHUP by posting kDnssdRestartNeeded (AppMain.cpp only wires SIGINT/SIGTERM today) would let procd's reload_signal give you /etc/init.d/matter reload, and then the hook can fire on any ifup without caring which interface it was.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this is now up, following your sketch:

For the meantime, this PR now does the cheap half of your interim suggestion: 75aa8ac makes the hook call a new rebind action that SIGHUPs the daemon (patch 046) instead of restarting it, so the sessions survive, and patch 045 carries the Listen() hardening so a rebind racing a bounce can't end with no endpoints. The SIGHUP patch is deliberately not proposed upstream -- #73559 is the real fix and removes the need for the signal and the hook entirely; both patches and the hook go when it lands.

One deviation from your suggestion: I used a dedicated rebind action rather than reload_signal + /etc/init.d/matter reload, because reload_service() already means "the configuration changed" (it diffs the command line and either reloads wifi credentials or restarts), and overloading it with "your interfaces moved" would conflate the two. Happy to switch if you prefer reload.

The hook also no longer gates on otbr's infra_if_name -- it fires on any ifup and skips wpan* by name, which is what that lookup was trying to say.

@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from b105240 to 9359bd4 Compare August 8, 2026 18:27
LorbusChris added a commit to LorbusChris/matter-openwrt that referenced this pull request Aug 9, 2026
Moves the pin from the 13 June revision to 72ecdc2b of 30 July. PKG_RELEASE
goes back to 1 with the new version.

Both patches still apply at fuzz zero against the new revision, so neither
needed refreshing.

The mirror hash is the one this same revision already produces in CI on project-chip#53,
where the source is fetched with the same URL, proto and submodule list, so the
archive -- and therefore the hash -- is byte for byte the same.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
LorbusChris added a commit to LorbusChris/matter-openwrt that referenced this pull request Aug 13, 2026
Moves the pin from the 13 June revision to 72ecdc2b of 30 July. PKG_RELEASE
goes back to 1 with the new version.

Both patches still apply at fuzz zero against the new revision, so neither
needed refreshing.

The mirror hash is the one this same revision already produces in CI on project-chip#53,
where the source is fetched with the same URL, proto and submodule list, so the
archive -- and therefore the hash -- is byte for byte the same.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
LorbusChris added a commit to LorbusChris/matter-openwrt that referenced this pull request Aug 17, 2026
Moves the pin from the 13 June revision to 72ecdc2b of 30 July. PKG_RELEASE
goes back to 1 with the new version.

Both patches still apply at fuzz zero against the new revision, so neither
needed refreshing.

The mirror hash is the one this same revision already produces in CI on project-chip#53,
where the source is fetched with the same URL, proto and submodule list, so the
archive -- and therefore the hash -- is byte for byte the same.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
ksperling-apple added a commit that referenced this pull request Aug 18, 2026
…equirement (#58)

* matter-netman: say in the package what the attestation is worth

The daemon reports a real manufacturer and product name, read from the
firmware, beside the Connectivity Standards Alliance test vendor id 0xFFF1.
That pairing is the right one — the names are accurate and useful, and a
community build cannot claim a vendor id it does not hold — but it leaves the
package silent about what the device attestation actually establishes.

Not much. The build attests with the SDK's development certificate for
0xFFF1/0x8013. The same certificate ships in every build of that example and
its private key is published in the SDK source, so attestation cannot
distinguish this router from anything else presenting the same credential, and
succeeding at it says nothing about who built the device or what is running on
it. Whether a controller notices depends on which roots it trusts: the chain
ends at a development root that some trust stores carry and some do not.

So the package says so itself, in terms of what is true of this device rather
than what some other implementation might be expected to do about it.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>

* matter-netman: state the mbedTLS and base-name facts in the package

Two things the package knew but did not say.

CHIP's mbedTLS crypto backend calls AES-CCM, so the mbedtls variant does not
link unless mbedtls is built with MBEDTLS_CCM_C. That option is `default n` in
OpenWrt, and the requirement was recorded only as an English sentence in the
package description, where the build system cannot act on it. .config.ci sets
the option, so this repository's own builds were fine — but anyone building
without that seed got an undefined reference to mbedtls_ccm_init rather than an
unmet dependency they could see in menuconfig. Say it in DEPENDS instead.

Neither variant declared PROVIDES, so the name matter-netman existed for nobody
to depend on or install; the variants had to be named explicitly. Declare it in
the shared block, the way miniupnpd, geoip-shell and mtr do.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>

* matter-netman: update to the 2026-07-30 Matter SDK

Moves the pin from the 13 June revision to 72ecdc2b of 30 July. PKG_RELEASE
goes back to 1 with the new version.

Both patches still apply at fuzz zero against the new revision, so neither
needed refreshing.

The mirror hash is the one this same revision already produces in CI on #53,
where the source is fetched with the same URL, proto and submodule list, so the
archive -- and therefore the hash -- is byte for byte the same.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>

* Remove CONFIG_MBEDTLS_CCM_C from CI config now that it's set via DEPENDS

---------

Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
Co-authored-by: Karsten Sperling <ksperling@apple.com>
Moves the pin 108 commits forward, from 9e56492e to the v2026.08.0 tag.

Drop OTBR_SRP_ADVERTISING_PROXY. The 2026.07.0 release turned the OT core
Advertising Proxy on by default whenever OTBR_MDNS is set, and the two are
mutually exclusive, so forcing the POSIX proxy on now fails configure with
"Only one Advertising Proxy can be enabled." Dropping the flag adopts the
OT core proxy, which is upstream's default build. The mDNS provider is
unchanged; both the mDNSResponder and avahi variants keep their own
responder.

OTBR_PRODUCT_NAME is not needed even though vendor and model are mandatory
now, because otbr-agent.init already passes --model-name from board.json at
runtime.

020-external-mbedtls stopped applying with strict context at 2026.07.0. A
three way apply resolves every hunk without conflict, so it is refreshed
with no change in what it does. The other build patches and the whole ubus
series apply unchanged, as nothing upstream touched src/openwrt/ubus in
that range.

PKG_MIRROR_HASH is regenerated for the new tarball.

Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
Assisted-By: Claude Fable 5
The ubus surface can form a Thread network but cannot change one that is
already running. Replacing the credentials or the channel of a live network
has to go through the pending dataset, so every node switches together when
the delay timer expires rather than being orphaned.

The existing ubus series (100-106, 110) stays untouched: the original
patch files apply cleanly to 2026.07.0 as they are. New patches continue
the series in three clean blocks, generated with git format-patch from
the upstream PR branches:

- 122-125: host groundwork (openthread/ot-br-posix#3489) — do not report
  the result of Leave twice, value-initialise the dataset in
  ScheduleMigration, erase the dataset in Leave based on the device role,
  report a dataset erase to state-change subscribers. That series also
  carries two NCP-mode patches, which this feed leaves out: it builds and
  starts otbr-agent in RCP mode only, and the ubus object is constructed
  only there.
- 130-135: the ubus methods — provision through the host abstraction,
  set_pending forwarding to ThreadHost::ScheduleMigration()
  (MGMT_PENDING_SET), a pending_dataset_changed notification, a
  deprovision method (detach + erase; gentler than factory-reset leave,
  needed for Matter's RevertActiveDataset()), respond to provision once
  the join is under way, and threadstart/threadstop through the host
  abstraction.
- 140: advertise mDNS under the system host name
  (openthread/ot-br-posix#3488).

Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
Assisted-By: Claude Opus 5
This release rejects it outright: configure fails with "OTBR_MDNS=avahi
is no longer supported", so the variant has stopped being buildable and
only mDNSResponder remains. With no backend choice left there is
nothing for the variants to vary, and openthread-br becomes a single
package selecting mDNSResponder explicitly.

Assisted-By: Claude Fable 5
Enable the border router feature set the other packagings build with:
OT_BORDER_ROUTER for the management surface the ubus methods sit on,
the channel manager and monitor so a channel can be changed and judged
at runtime, and the SRP server's auto-enable. The REST API is switched
off explicitly rather than by relying on the upstream default, since
nothing here consumes it and it would listen on the infrastructure
interface.

Assisted-By: Claude Fable 5
The Matter Thread Network Diagnostics cluster needs a router table, which the
neighbour list does not cover: a leader with a populated mesh has routers it
is not a direct neighbour of. The neighbour rows also carry two mandatory
frame counters that otNeighborInfo has had all along.

Stacked on the ubus method series; see the openthread-br patch table for what
is proposed upstream and what is carried here.

Assisted-By: Claude Opus 5
The delegate advertised no PANChange support and answered SetPendingDataset
and RevertActiveDataset with NOT_IMPLEMENTED, so a controller could form a
Thread network through it but never change one already running, and a
fail-safe expiry left the border router holding a dataset the controller had
abandoned.

With the ubus methods added to openthread-br, the delegate can now report
PANChange, invoke set_pending to schedule a migration and deprovision to
revert, and serve the pending dataset that status and pending_dataset_changed
report. 030 also implements RevertActiveDataset in the fake delegate, so
fail-safe rollback can be exercised without hardware.
Also install an interface hotplug hook that restarts the daemon when the
network device otbr-agent is configured with as infra_if_name comes back
up: the daemon's mDNS sockets do not survive the interface they are bound
to bouncing, which leaves the node undiscoverable for CASE until a
restart.

Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
Assisted-By: Claude Fable 5
Patch 035 replaces the demo stubs behind the NIM device type with live
router state: the Wi-Fi Network Management cluster shares the LAN access
point credentials read from netifd (guest networks excluded; wifi_share,
wifi_network and wifi_iface in /etc/config/matter adjust or disable the
sharing), Thread Network Diagnostics is fed from otbr-agent over ubus,
the Thread Network Directory is seeded with the border router own
network, and Ethernet Network Diagnostics reports the uplink counters.

The service gains a procd reload trigger on wireless/network config
changes that pokes the daemon over ubus, and the ubusd ACL grants the
matter user read access to exactly network.wireless status. Applying a
new ubusd ACL needs a ubusd restart, which breaks clients holding the
old connection (rpcd, lighttpd, foris) - a reboot after install is the
clean path.

Assisted-By: Claude Fable 5
010-zap-disable-arl removes the ReviewFabricRestrictions commands from the
checked-in data model. It has no effect on what the device does: the Access
Control cluster is written in code and ignores its ZAP input entirely — the
kManagedDevice feature bit, the Arl and CommissioningARL attributes and the
command dispatch are all hardcoded under #if CHIP_CONFIG_USE_ACCESS_RESTRICTIONS
(access-control-cluster.cpp:507, :552-554, :591), and the example provider is
instantiated under the same guard.

What actually turns the feature off is --enable-access-restrictions=no in
CONFIGURE_OPTIONS, which has been there since the same commit that added this
patch. That still holds, so removing the patch changes nothing except one less
file to rebase.

Assisted-By: Claude Opus 5
Five more patches out of the network-manager branch, from an audit of what this
node tells a controller against what it can actually establish.

- the setup passcode no longer goes to the system log on every start, where it
  outlived commissioning by the life of the device
- CONFIG_BUILD_FOR_HOST_UNIT_TEST is off, so the encoder keeps the range check
  the specification requires of a device rather than of a test host
- ProductName comes from the distribution name in /etc/os-release, with the
  product_name uci option to override; it read as an empty string before
- BorderRouterName comes from the host name rather than being the same literal
  on every unit, which makes a mesh with more than one border router readable
- ThreadVersion and InterfaceEnabled come from otbr rather than a constant and
  a guess at what a configured dataset implies
- the Thread state cached from otbr-agent is dropped when it goes away, instead
  of being reported as current
- SecurityPolicy, ChannelPage0Mask, the route table and the neighbour frame
  counters are served instead of encoded as null, empty or zero
- the Ethernet counters answer with zero rather than a Failure status when they
  are switched off, ResetCounts does what it says, and RebootCount counts
  reboots of the router rather than restarts of this daemon

Assisted-By: Claude Opus 5
The Thread Network Directory kept every network this node had ever been on. An
entry is a whole operational dataset, network key included, readable by any
commissioned fabric; Thread Border Router Management only returns the current
one, so a superseded network's key was reachable through the directory and
nowhere else. On a router that offers credential rotation that is a key the
operator believes they have replaced.

Two patches, because they belong in different places upstream. The first adds
AddOrUpdateNetwork and ForgetNetwork to the ThreadNetworkDirectory cluster, so
an application recording a network goes through the cluster rather than behind
it and subscribers are told. The second is the application: it retracts the
entry this node seeded when that network is superseded or when otbr reports
none, and only that entry.

Assisted-By: Claude Opus 5
ThreadBorderRouterManagementCluster uses the delegate Init() for two opposite
things: Startup() passes the attribute-change callback, Shutdown() passes
nullptr to detach it. The OpenWrt delegate treated both as initialisation and
registered its ubus watch either way -- but the second call arrives after
ApplicationShutdown() has stopped the ubus manager, whose Register() asserts it
is initialised. Every clean stop ended in VerifyOrDie.

The flaw is upstream, present since the OpenWrt border router integration
landed, so the patch is a candidate to send back rather than something this
packaging invented.

Assisted-By: Claude Opus 5
The hotplug hook restarted the daemon when the backbone device came back up,
because minimal-mDNS binds its sockets to the interfaces that existed when the
Matter server started and has no way to be told they changed. A restart does fix
the sockets, but it also drops every CASE session and subscription, so each
controller has to re-establish the connection and attribute reporting stops
until it does. On a border router the backbone comes up on every network
reconfiguration, so this is not a rare event.

Carry two patches to make a cheaper answer possible:

- 045 keeps a single interface that fails to bind from taking the whole mDNS
  server down with it (proposed upstream as
  project-chip/connectedhomeip#73558). Without this,
  re-binding while interfaces are still settling can leave the daemon with no
  endpoints at all -- worse than the state it started from.

- 046 makes the daemon re-run its interface enumeration on SIGHUP. This one is
  deliberately not proposed upstream: the real fix is the SDK noticing
  interface changes itself
  (project-chip/connectedhomeip#73559), which removes
  the need for the signal and for this hook entirely. Until that lands, the
  signal is the cheapest interim.

The init script grows a `rebind` action that signals the running instance, and
the hotplug hook calls that instead of `restart`. Sessions survive.

Because a rebind is cheap, the hook no longer works out whether the device that
came up is the one otbr-agent uses as its backbone -- asking otbr which
interface it cares about was a roundabout way of saying "not the Thread
interface". It now fires on any ifup and skips wpan* by name, which is the thing
that was actually meant: the Thread interface is never advertised on, so it
cannot change what is bound, and on a border router it changes often.

The handler is installed just before the event loop starts, so a hotplug event
in the window between the daemon forking and reaching that point still finds
SIGHUP at its default action and kills it. procd respawns it, which lands on the
old restart behaviour rather than anything worse, and the window is the daemon's
startup.

Both patches can go, along with the hook, once the upstream watcher lands.

Assisted-By: Claude Opus 5
Signed-off-by: Christian Glombek <c.glombek@cosa.systems>
@LorbusChris
LorbusChris force-pushed the otbr-netifd-thread-proto branch from 75aa8ac to 86b987f Compare August 18, 2026 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants