Commit Graph

9775 Commits

Author SHA1 Message Date
Yakun Xu 87fdaa6946 [simulation] add IPv6 loopback address support (#12828)
This commit adds support for IPv6 loopback address (::1) in the
simulation platform. When the local interface is set to the IPv6
loopback address, it uses the interface-local multicast group
(ff01::116) instead of the link-local group (ff02::116) for
node-to-node communication.

It also ensures that the `sin6_scope_id` is correctly set for the
loopback address in the transmission socket.
2026-05-07 07:37:40 -07:00
Jonathan Hui 3d731aae2f [coap] fix null-pointer dereference on Block2 invalid requests (#13079)
This commit fixes a deterministic null-pointer dereference in
CoapBase::ProcessBlock2Request when receiving a Block2 request
with block number greater than 0 without a preceding active
blockwise transfer.

Previously, when mLastResponse was null, the option copying logic
would unconditionally attempt to initialize the iterator with a
dereferenced mLastResponse pointer (iterator.Init(*mLastResponse)),
causing a segmentation fault crash.

This fix inserts a VerifyOrExit check on mLastResponse inside
ProcessBlock2Request. If mLastResponse is null, it returns the
kErrorNoFrameReceived error code. In ProcessBlockwiseRequest, this
is mapped to a 4.08 Request Entity Incomplete response, matching the
spec-compliant error handling behavior of Block1.

An automated reproduction and verification test case has also been
added to tests/nexus/test_coap_block.cpp.
2026-05-07 07:31:04 -07:00
Jonathan Hui 772ddb9802 [nexus] fix occasional failure of test 1_1_5_8_4 (#13075)
This commit fixes the occasional/flaky failure of the Nexus test
1_1_5_8_4 by addressing a joiner expiration issue and strictly
verifying MLE Discovery Responses.

In test_1_1_5_8_4.cpp, the joiner was added with a timeout of 100s in
Step 1. However, the total simulated elapsed time before Step 11
(when the joiner is checked) is exactly 104s. This causes the
joiner to expire occasionally/consistently, resulting in the Leader
skipping the MLE Discovery Response in Step 12.

We increase the joiner timeout to 1000s so that it stays active
throughout the test. In addition, we update verify_1_1_5_8_4.py to
strictly verify the Step 12 Discovery Response and perform packet
matching chronologically rather than relying on seeking backward to
idx10.
2026-05-07 07:30:51 -07:00
Abtin Keshavarzian 41e07366fa [mlr] extract address registration success evaluation into helper (#13071)
This commit introduces a new static helper method,
`Manager::DidRegisterSuccessfully()`, to evaluate whether a specific
multicast address was successfully registered based on the MLR response
status and the list of failed addresses.

Previously, this evaluation logic was duplicated and inline within
`Manager::Finish()` using the expression:
`success = aSuccess || !aFailedAddresses.IsEmptyOrContains(addr)`.
This logic was not immediately intuitive and required reasoning through
the boolean conditions to understand the intended behavior.

Extracting this into a dedicated helper method improves code
readability and maintainability. It simplifies `Finish()` by
clearly separating the outcome evaluation from the actual state
transition logic (`kStateRegistering` to `kStateRegistered` or
`kStateToRegister`).

Additionally, the unused `AddressArray::IsEmptyOrContains()` method
has been removed.
2026-05-07 07:30:14 -07:00
Abtin Keshavarzian dd33295ce9 [mac] add RxFrame::IsSecuredWith() helper method (#13064)
This commit introduces a new helper method, `RxFrame::IsSecuredWith()`,
which allows callers to cleanly verify if a received MAC frame has
security enabled and uses a specific set of allowed Key ID Modes.

This eliminates redundant logic in `ThreadLinkInfo::SetFrom()`, where
the code previously had to manually check `GetSecurityEnabled()`,
extract the Key ID Mode, and validate it against `kKeyIdMode0` or
`kKeyIdMode1`. Mac::ProcessCsl()` is updated to use this new method
to cleanly enforce that CSL IE processing only occurs on frames
secured with Key ID Mode 1

Crucially, this commit also updates `DataPollHandler::HandleDataPoll()`
to use this new helper. Previously, it only checked if the frame
was secured (`GetSecurityEnabled()`), which would accept frames
using any Key ID Mode (including mode 2 with fixed/known keys). By
restricting the data poll handling to only accept Key ID Mode 1, we
ensure that data polls are only processed if they are secured with
a valid Thread network key.
2026-05-06 22:32:57 -07:00
Abtin Keshavarzian e6134cb828 [ip6] enforce filter rules when Thread role is disabled (#13050)
This commit updates `Ip6::Filter::Apply()` to remove the exception
that allowed all unsecure link-local IPv6 datagrams to pass through
when the Thread role was disabled (e.g., when the interface is up
but Thread has not yet started).

By removing this check, the device now consistently enforces strict
port filtering at all times. Only explicitly allowed traffic, such
as MLE messages, commissioner traffic, or user-configured unsecure
ports, will be permitted, improving the overall security posture
regardless of the current Thread role state.

For testing and backward compatibility on reference devices, the
`mAllowUnsecureWhenDisabled` flag is introduced (available when
`OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled). This allows
the legacy behavior to be restored via the new public APIs
`otIp6SetAllowUnsecureWhenDisabled()`. The new APIs are also provided
in CLI under `unsecureport allwhendisabled` command.
2026-05-06 22:29:13 -07:00
Abtin Keshavarzian 3c77c52136 [mlr] extract registration criteria into ShouldRegister() helper (#13073)
This commit introduces a new private helper method, `ShouldRegister()`,
to the `Manager` class. This method consolidates the checks required
to determine if the device should perform MLR.
2026-05-06 22:26:18 -07:00
Abtin Keshavarzian 129afad2f5 [key-manager] add ClearKek() to remove KEK when no longer needed (#13072)
This commit introduces the `KeyManager::ClearKek()` method, which clears
the `Kek` and resets the `mIsKekSet` flag.

The KEK is a temporary key used during the commissioning and entrust
phases. To improve security and key hygiene, this commit updates the
`Joiner` and `JoinerRouter` to explicitly clear the KEK once these
operations have concluded.

Specifically:
- `Joiner::Finish()` clears the KEK when finishing in `kStateEntrust`
  or `kStateJoined`.
- `JoinerRouter::HandleJoinerEntrustResponse()` clears the KEK
  immediately upon handling the entrust response, before scheduling
  any delayed entrusts (which set their own KEK from metadata).
2026-05-06 21:03:07 -07:00
Abtin Keshavarzian 763af19c5d [nexus] remove redundant cast in SendMlrRequest() (#13076)
This commit removes a redundant `static_cast<const uint8_t *>` when
calling `Tlv::Append<Ip6AddressesTlv>()` in `SendMlrRequest()` in
`test_1_2_MATN_TC_21.cpp`. Since the method accepts `const void *`
as its value argument, the explicit cast is unnecessary and can be
safely removed to simplify the code.
2026-05-06 22:59:44 -05:00
Yakun Xu 2fbc9f43d9 [test] separate size report workflow (#13057)
This commit breaks the size report workflow into two workflows so that
we can use `pull-request` to collect the data.
2026-05-06 17:52:37 -07:00
Abtin Keshavarzian 0db06ebc77 [network-data] reject Context ID 0 in ContextTlv::IsValid() (#13069)
This commit updates the `ContextTlv::IsValid()` method to reject
Context TLVs that specify a Context ID of zero.

According to the Thread specification, Context ID 0 is reserved for
the Mesh-Local Prefix and should not be distributed in the Network Data.
Adding this check ensures that such invalid TLVs are correctly
identified as malformed and dropped during Network Data processing.
2026-05-06 17:51:17 -07:00
Abtin Keshavarzian 7b200c79df [srp] clear name on ExtractLabels() failure in AdvertisingProxy (#13061)
This commit updates `AdvertisingProxy::CopyNameAndRemoveDomain()` to
properly handle potential errors returned by `Dns::Name::ExtractLabels()`.

Previously, any error returned by `ExtractLabels()` was ignored, which
could leave the output name buffer in an indeterminate state. With this
change, if extracting the labels fails, the name buffer is explicitly
cleared by setting its first character to `kNullChar`.

This prevents subsequent code from using uninitialized or partially
written data in the event of a parsing or buffer size error.
2026-05-06 17:46:54 -07:00
Jonathan Hui 35fe1f3fbe [nexus] fix flakiness in history_tracker test (#13070)
This commit resolves the flaky test failures occasionally observed
in the history_tracker Nexus test during ping verification.

The flakiness was caused by two primary issues:
1. Concurrent background Thread control traffic (e.g. multicast
   Hop-by-Hop Options packets) sometimes interleaving with the Echo
   Request pings, polluting the HistoryTracker queues and causing
   the strict chronological checks to fail.
2. The FTD child node upgrading to a Router due to the
   TooFewRouters network threshold rule, which dynamically changed
   its RLOC16 and caused NeighborRloc16 history checks to fail.

To fix these, we:
1. Set the child node's router eligibility to false after joining
   to prevent any unwanted topology changes or Rloc16 updates.
2. Refactored the strict Leader TX and Child RX chronological checks
   with robust iterative loops filtering specifically for the
   OT_ICMP6_TYPE_ECHO_REQUEST packets.

Verified 100% stable after executing a loop of 50 successful runs.
2026-05-06 17:41:05 -07:00
Jonathan Hui 76dab3b963 [ip6] enforce strictly in-order IPv6 fragment reassembly (#13067)
This commit enforces strictly in-order IPv6 fragment reassembly
in the core stack to improve reassembly robustness and correctness.

Previously, the reassembly engine did not track contiguous bytes
received. An out-of-order or gapped fragment containing the M=0
flag could incorrectly trigger reassembly completion, potentially
leading to the forwarding or processing of incomplete packets.

To resolve this, we now:
1. Enforce that reassembly must start with a fragment offset
   of 0.
2. Verify that any subsequent fragment aligns perfectly with the
   offset where the contiguous payload data currently ends
   (`offset == message->GetOffset()`).
3. Safely advance `message->GetOffset()` as each fragment is
   successfully appended to keep track of the contiguous
   reassembled byte range.
4. Added a robust Nexus test case verifying that gapped
   reassembly is properly dropped and blocked.

This strictly in-order validation approach is consistent with the
preexisting 6LoWPAN fragment reassembly in MeshForwarder.
2026-05-06 17:40:25 -07:00
Jonathan Hui 88188e958b [lowpan] cap recursion depth in Lowpan::Compress to 4 (#13066)
This commit adds aRecursionDepth tracking and limit check in
Lowpan::Compress methods to prevent excessive recursive stack usage
from recursive compression of highly nested IP-in-IP headers.

Specifically:
- Threads aRecursionDepth parameter through 3-arg and 4-arg (now
  5-arg) Compress wrappers.
- Enforces aRecursionDepth <= kMaxRecursionDepth (4) in Compress.
- Increments recursion depth on nested IP-in-IP calls (Ip6::kProtoIp6).
- Adds a Nexus integration test to verify that highly nested packets
  are compressed up to the threshold limit, and successfully fall back
  to uncompressed inline transmission without excessive stack usage.
2026-05-06 15:33:42 -07:00
Jonathan Hui e2e7a78af5 [mac] enforce KEK validation for Key ID Mode 0 frames (#13056)
This commit adds validation to ensure that Key ID Mode 0 (implied KEK)
secured frames are only accepted if a KEK is configured. If KEK is not
configured, the frame is rejected.

Specifically:
- Added `mIsKekSet` boolean member variable to `KeyManager` to track
  KEK status.
- Implemented `KeyManager::IsKekSet()` to check if a KEK is
  configured.
- Enforced a guard in `Mac::ProcessReceiveSecurity()` under
  `kKeyIdMode0` to immediately reject incoming frames with
  `kErrorSecurity` when the KEK is not configured.
- Added unit test `TestKeyManagerKek()` in `test_pskc.cpp` to
  verify that `IsKekSet()` transitions from `false` to `true` as
  expected.
2026-05-06 14:51:38 -07:00
Jonathan Hui 74c2531738 [mle] handle invalid leader mask in HandleAddressSolicitResponse (#13063)
This commit resolves an issue in HandleAddressSolicitResponse where
a malformed or invalid leader-supplied Router ID Mask omitting the
leader ID could trigger an assertion.

When a node receives an Address Solicit Response, it installs the new
router ID mask. If the leader's router ID is missing from the mask,
the Router entry for the leader is removed from the local router table.
Subsequently, when the node tries to ensure it has a valid next hop
and cost towards the leader, `mRouterTable.GetLeader()` returns `nullptr`,
leading to an `OT_ASSERT(leader != nullptr)` failure or a null-pointer
write when assertions are disabled.

This is resolved by safely verifying that the leader's router ID is
indeed present in the received router ID mask before applying the
routing update, ensuring `GetLeader()` is guaranteed to find it.
2026-05-06 13:38:40 -07:00
Jonathan Hui 6954667dca [mac] enforce KeyIdMode1 for CSL synchronization processing (#13062)
This commit updates `Mac::ProcessCsl` to explicitly verify that CSL IE
data frames are secured using `KeyIdMode1` (utilizing the network key
and per-neighbor frame counter freshness checks).
2026-05-06 13:38:28 -07:00
Jonathan Hui 02d000c747 [dns-client] fix double-free of mSavedResponse on duplicate response (#13060)
Fix a double-free of `mSavedResponse` in `Dns::Client` when processing
duplicate DNS responses matching an active query.

When an SRV/TXT query needs to resolve a host address (AAAA), the DNS
client allocates a chained `newQuery` to handle it. If duplicate
responses are processed before the query chain is finalized, they
trigger multiple AAAA resolution allocations for the same parent query.
Because the new query inherits `mSavedResponse` from the parent query's
`QueryInfo`, multiple chained queries end up aliasing/sharing the same
cloned `mSavedResponse` message. During finalization, `FreeQuery`
walks the chain and frees `mSavedResponse` for each query, leading to
a double-free of the shared `Message` and free-list/heap corruption.

This commit resolves the issue by:
1. Rejecting duplicate responses early in `ParseResponse` if a response
   has already been received and saved for the query
   (`info.mSavedResponse != nullptr`), returning `kErrorDrop`.
2. Initializing the `mSavedResponse` field of the `QueryInfo` struct
   to `nullptr` before allocating the host resolution query (`newQuery`)
   to prevent it from inheriting a potentially non-null saved response
   from its parent.
2026-05-06 12:32:11 -07:00
Abtin Keshavarzian 7e646d19dc [cli] add OutputResult() in Utils (#13034)
This commit add a `OutputResult()` wrapper method in the `Utils` base
class.

Previously, several CLI sub-modules (`Dns`, `History`, `LinkMetrics`,
`MeshDiag`, and `PingSender`) implemented their own `OutputResult()`
wrappers that simply delegated to the `Interpreter`. Since all these
sub-modules inherit from `Utils`, this functionality is now provided
directly by the base class, removing redundant code and simplifying
the sub-module implementations.
2026-05-06 11:10:09 -07:00
Abtin Keshavarzian aae952a8a2 [mlr] introduce Mlr namespace and rename types (#13053)
This commit introduces the `Mlr` namespace to encapsulate all
Multicast Listener Registration related types and logic, improving
overall code organization and readability.

The following primary renames were performed:
- `MlrManager` to `Mlr::Manager`
- `MlrState` to `Mlr::State`
- `MlrStatus` to `Mlr::Status`
- Constants like `kMlrSuccess` to `Mlr::kStatusSuccess`

Additionally, methods within the newly scoped `Mlr::Manager` class
have been simplified by removing redundant `Mlr` prefixes (e.g.,
`SendMlr()` is now `Send()`, `FinishMlr()` is now `Finish()`).

External modules and tests have been updated to reference the new
scoped names.
2026-05-06 10:41:20 -07:00
Abtin Keshavarzian 8cbf0daae4 [thread-tlvs] add Ip6AddressesTlv::AppendTo() helper method (#13049)
This commit extracts the logic for appending an `Ip6AddressesTlv` into
a new `static` helper method, `Ip6AddressesTlv::AppendTo()`.

Previously, multiple locations in the codebase manually managed the
TLV construction and appending. This change centralizes this logic,
simplifying the call sites in `BackboneRouter::Manager` and
`MlrManager`.
2026-05-06 10:40:31 -07:00
Jonathan Hui 2dfac4d545 [ip6] restrict MPL option processing to Hop-by-Hop header (#13055)
RFC 7731 Section 4 specifies that the MPL Option MUST only reside
within a Hop-by-Hop Options extension header. However, previously,
Ip6::HandleOptions processed MplOption::kType regardless of whether the
enclosing header was Hop-by-Hop or Destination Options.

This commit fixes the issue by adding a boolean parameter to
Ip6::HandleOptions indicating if the enclosing header is Hop-by-Hop.
MplOption::kType is now only processed if this parameter is true.
If the MPL Option is encountered in a Destination Options header,
it is treated as unrecognized, and because its type action mandates
discarding the packet, the datagram is dropped safely.
2026-05-06 10:36:56 -07:00
Jonathan Hui 430034214e [mesh-forwarder] enhance EID-RLOC cache updates (#13054)
Gate `MeshForwarder::UpdateEidRlocCacheAndStaleChild` on link
security, ensuring that the received frame has security enabled.

Adding the link security check ensures that only fully authenticated
data frames (successfully decrypted and verified at the MAC layer)
can influence the EID-to-RLOC cache and the child table states.
2026-05-06 10:35:15 -07:00
Jonathan Hui e29e44b0c2 [ip6] drop host-untrusted IP-in-IP packets (#13052)
Host-untrusted IP-in-IP packets could reach the local TMF socket
without the intended port checks on the receive path if destined to
the Border Router's own OMR address with an inner destination set to
the Thread-side link-local address. When the outer message is
decapsulated, it recurses through the IPv6 stack receive path while
retaining its HOST_UNTRUSTED origin, but local UDP socket dispatching
lacks equivalent origin checks.

This commit introduces a validation check in Ip6::HandleDatagram to
immediately drop any message from a host-untrusted origin with a
next header of kProtoIp6 (IP-in-IP encapsulation). This securely
prevents this receive-path processing and the corresponding
forwarding behavior.

Added the tmf_origin Nexus integration test to verify that
host-untrusted IP-in-IP packets are successfully dropped by
returning kErrorDrop.
2026-05-06 10:35:01 -07:00
Abtin Keshavarzian 941a317899 [nexus] group and reorder methods in Node class (#13029)
This commit reorganizes the `Node` class declaration in
`nexus_node.hpp` to improve readability and maintainability.

The methods and members are now logically grouped into marked
sections.
2026-05-05 17:58:17 -07:00
Jonathan Hui 99e21445b5 [mle] fix child state handling in ProcessAddressRegistrationTlv (#13051)
This commit removes an overly strict `OT_ASSERT` on child state
validity inside `ProcessAddressRegistrationTlv`.

When a valid child transitions to a link-reestablishment state
(e.g., `kStateChildUpdateRequest` or `kStateChildIdRequest`) with
registered MLR addresses, its MLR registered set is preserved. The
subsequent processing of the Child Update Response or Child ID Request
causes `ProcessAddressRegistrationTlv` to be invoked while the child
is not yet back in `kStateValid`, which triggers the assertion on the
parent router/leader.

Since the parsing logic and `MlrManager` handle non-valid child states
gracefully, this assertion is deleted.
2026-05-05 17:26:28 -07:00
Jonathan Hui 36b398ef61 [tmf] enforce link security for all TMF messages (#13048)
This commit updates Tmf::Agent::Filter to require link-layer security
for all incoming TMF requests.

Thread Management Framework (TMF) messages are used for network
management and configuration. The Thread specification requires that
all TMF messages be secured. While individual handlers often have
specific checks, enforcing this at the TMF Agent level provides a
consistent security layer for all TMF traffic.

For most TMF messages, security is provided by the Network Key. For
commissioning-related messages (like Joiner Entrust), security is
provided by the Key Encryption Key (KEK). In all cases, a valid TMF
message must have link-layer security enabled.

This change prevents unauthenticated attackers from sending unsecured
TMF messages to manipulate network state or configuration.
2026-05-05 15:22:45 -07:00
Abtin Keshavarzian bf79332530 [tasklet] fix Unpost() behavior during tasklet processing (#13039)
This commit fixes an issue where a tasklet could not be successfully
unposted if it was already scheduled for execution in the current
event loop iteration.

Previously, `Scheduler::ProcessQueuedTasklets()` copied and cleared the
queued tasklets before running them. If a running tasklet called
`Unpost()` on another tasklet that was also in the copied list, the
unpost operation would fail to remove it because it only checked the
main queue.

To address this, the `Scheduler` now explicitly maintains two separate
queues: `mPostedQueue` and `mRuningQueue`. The `Tasklet::Unpost()`
method is updated to remove the target tasklet from both queues,
ensuring it is correctly dequeued even if it is pending in the running
list.

The queue logic is encapsulated into a nested `Queue` class to manage
the circular singly linked-list operations cleanly. Additionally, unit
tests are expanded to cover scenarios where tasklets post or unpost
other tasklets during execution.
2026-05-05 12:12:37 -07:00
Jonathan Hui d0cab9aaba [joiner] require link security for Joiner Entrust (#13046)
This commit adds an explicit check in Joiner::HandleTmf<kUriJoinerEntrust>
to verify that the received message has link-layer security enabled.

According to the Thread specification, the Joiner Entrust message MUST
be protected by link-layer security using the Key Encryption Key (KEK).
Previously, this check was missing, allowing an unauthenticated
attacker to send unsecured Joiner Entrust messages. Such messages
could inject invalid network configuration, causing the device to
fail to attach to the correct network after a reboot.

By verifying IsLinkSecurityEnabled(), we ensure that the message
was successfully decrypted using the KEK (since the network key is
not yet known by the Joiner), thus authenticating the sender as the
valid Commissioner or Joiner Router.
2026-05-05 11:14:49 -07:00
Abtin Keshavarzian b45a1ad57c [cli] handle duplicate registration in Interpreter::SetUserCommands() (#13018)
This commit updates the `Interpreter::SetUserCommands()` method to
detect if a set of CLI commands is already registered. If a duplicate
registration is detected, the method now returns `OT_ERROR_NONE` and
exits early without consuming an additional slot in the user commands
table. It also ensures that `OT_ERROR_FAILED` is only returned when
there are no available slots for a new registration.
2026-05-05 09:36:49 -07:00
Abtin Keshavarzian 69dd33699f [mlr] simplify SendMlrMessage() arguments (#13043)
This commit simplifies the `MlrManager::SendMlrMessage()` method by
removing the `void *aContext` parameter.

Previously, all callers (`SendMlr()` and `RegisterMulticastListeners()`)
were passing `this` as the context for the CoAP response handler. The
context is now passed directly as `this` when invoking
`Tmf::Agent::SendMessageTo()`, removing the need to thread it through
the method arguments.
2026-05-05 07:50:10 -07:00
Abtin Keshavarzian 40ebd8d07f [router-table] append Route TLV directly to message (#13042)
This commit updates the way Route TLV is constructed and appended to
messages. Previously, a `RouteTlv` object with a large fixed-size
`mRouteData` array was allocated on the stack, filled by
`RouterTable`, and then appended to the message.

To simplify the code and improve efficiently a new helper method
`RouterTable::AppendRouteTlv()` is introduced which appends the TLV
content directly in the `Message`. It uses `Tlv::StartTlv()` and
`Tlv::EndTlv()` to encapsulate the `RouterIdMask` and the iteratively
appended route data entries.

A helper method `RouteTlv::AppendRouteDataEntry()` is added  which
handles encoding and adding a Route Data Entry, including the the
bit-packing logic(the staggered 1.5-byte packing under
`OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE`).
2026-05-05 07:49:35 -07:00
Jonathan Hui 8e0e65da63 [github-actions] migrate simulation tests to Nexus (#13041)
This commit removes several simulation test jobs from the GitHub Actions
workflows, specifically 'simulation-1.1.yml' and 'simulation-1.4.yml'.

The following jobs were removed:
- packet-verification
- cli-ftd
- cli-mtd
- cli-time-sync
- thread-1-4

These tests have been migrated to the Nexus test framework, which
allows for more efficient and scalable network simulations by
running multiple OpenThread nodes within a single process.
2026-05-05 07:48:32 -07:00
Abtin Keshavarzian 3f82c1dfa5 [bbr] simplify MulticastListenersTable implementation (#13036)
This commit simplifies the `MulticastListenersTable` by replacing the
custom heap-based sorting logic with a standard `Array` and integrating
an internal `TimerMilli` (`mTimer`) to handle entry expirations.

Previously, the table maintained a min-heap based on expiration times
(`FixHeap`, `SiftHeapElemDown`, `SiftHeapElemUp`) and required
external calls to `Expire()` every second. The new implementation
uses `mListeners.FindMatching()` and `mListeners.RemoveAllMatching()`,
significantly reducing code complexity and maintenance overhead.

The unit tests in `test_multicast_listeners_table.cpp` are also updated
to reflect the simplified model
2026-05-05 07:46:31 -07:00
Abtin Keshavarzian 4c12431b68 [cli] replace static Interpreter::GetInterpreter() calls (#13033)
This commit updates the CLI sub-modules to use a new, non-static
`GetInterpreter()` method provided by the `Utils` base class, rather
than relying on the static `Interpreter::GetInterpreter()` which
returns a global singleton.

The `Utils::GetInterpreter()` method downcasts its associated
`OutputImplementer` reference to the specific `Interpreter` instance
it belongs to. `OutputImplementer` is a base class of `Interpreter`.

This change is a step towards adding support for multiple CLI
interpreters (per OpenThread instance).

Additionally, the `OutputImplementer` constructor is made `protected`
as it is intended to serve as a base class.
2026-05-05 07:45:19 -07:00
Abtin Keshavarzian dca8d995d5 [instance] use constexpr for instance alignment size calculations (#13026)
This commit refactors the instance allocation logic in `Instance` to
use `constexpr size_t` constants replacing the preprocessor macros
(`OT_DEFINE_ALIGNED_VAR` and `OT_ALIGNED_VAR_SIZE`).

The new constants `kInstanceSizeInUint64s` and
`kMultiInstanceSizeInUint64s` provide better type safety and are more
idiomatic C++. The raw storage arrays (`gInstanceRaw` and
`gMultiInstanceRaw`) are now explicitly defined as `uint64_t` arrays
using these calculated sizes.

Additionally, this commit introduces `kNumStaticInstances` to represent
the configured number of multiple static instances.
2026-05-05 07:44:14 -07:00
Abtin Keshavarzian 4384c66e7b [mle] consolidate role transition management in RoleTransitioner (#12983)
This commit introduces the `RoleTransitioner` class (renamed from
`RouterRoleTransition`) to centralize the management of router role
eligibility, thresholds, and transitions.

The following state and logic are moved from the `Mle` class into
the `RoleTransitioner`:
- Router role eligibility and allowance state (`mRouterEligible`,
  `mRouterRoleAllowed`).
- Upgrade and downgrade thresholds.
- Downgrade blocking state (`mDowngradeBlocked`).
- Transition decision logic (`DecideWhetherToUpgrade()`,
  `DecideWhetherToDowngrade()`).
- The transition jitter timer and its management.

By consolidating these responsibilities, the complexity of the main
`Mle` class is reduced, and the role transition process is more
explicitly managed within its own sub-component.
2026-05-05 07:42:08 -07:00
Abtin Keshavarzian bdea2ae98c [trel] defer channel check in Link::ProcessReceivedPacket() (#13011)
This commit updates `Trel::Link::ProcessReceivedPacket()` to move
channel mismatch validation until after the acknowledgment logic.

TREL ACKs serve as a mechanism to monitor link status between peers.
By deferring the channel check, we ensure that TREL packets requiring
an acknowledgment are correctly acknowledged at the TREL layer even
if they are not further processed.

A primary use case is the MLE Announce message, which is sent on a
different channel as a broadcast. At the TREL layer, this broadcast
is converted to unicast TREL packet transmissions to each peer on the
same PAN, with packets marked to request a TREL ACK. This change
ensures the receiving TREL peer sends an ACK for such packets,
maintaining link monitoring, while still dropping the packet at the
TREL link layer due to the channel mismatch.
2026-05-04 10:02:55 -07:00
sarveshkumarv3 73cc8a5c05 [posix] add uart-exclusive option to enable flock / TIOCEXCL (#13015)
When uart-exclusive is specified as a radio URL parameter, the UART
device is locked using flock(LOCK_EX) to prevent concurrent access,
and TIOCEXCL is set where supported.
2026-05-04 09:23:57 -07:00
arnulfrupp 928c78a01b [tcat] implement rate limitation for TCAT TLVs 0x10, 0x11 and 0x12 and remove TLV 0x14 (#12211)
This commit implements rate limitation for the TCAT commands Present
PSKd Hash TLV (0x10), Present PSKc Hash TLV (0x11) and Present
Install-code Hash TLV (0x12) to prevent password guessing attacks.

It also removes the TCAT command Request PSKd Hash TLV (0x14), to
prevent offline password guessing attacks with a single Hash value
retrieved from the device.

Note: The commit does not remove the Request PSKd Hash TLV
implementation in the Python commissioner such that the non-existence
of the command TLV can still be tested.
2026-05-04 07:10:19 -07:00
sarveshkumarv3 d27c618ccb [posix] handle RCP disconnection (EOF from read()) (#13006)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-05-04 07:07:54 -07:00
Abtin Keshavarzian 611c62126a [mle] use compact Route TLV in Link Accept to child neighbors (#13012)
This commit enhances MLE where a full Route TLV could be appended to
a Link Accept message sent to a child neighbor, potentially leading
to a message requiring lowpan fragmentation.

Previously, `Mle::SendLinkAccept()` relied on a `Router` pointer to
determine whether to use a full or compact Route TLV. When the Link
Request originated from a child, this pointer was null, causing a
full Route TLV to be used.

The changes in this commit include:
- Updating the `LinkAcceptInfo` struct to track the RLOC16 of the Link
  Request sender.
- Updating `Mle::TxMessage::AppendRouteTlv()` and adding
  `AppendCompactRouteTlv()` to replace the previous single method that
  took a `Neighbor` pointer. This makes the intent clearer and
  supports both router and child neighbors.
- Updating `RouterTable::FillRouteTlv()` to take an RLOC16 instead of
  a `Neighbor` pointer. It uses `Mle::RouterIdFromRloc16()` to ensure
  that if the destination is a child, its parent's Router ID is
  included in the compact Route TLV.
- Includes new Nexus test `test_compact_route_tlv` to validate the
  use of compact Route TLV in Link Accept.
2026-05-04 06:46:25 -07:00
Jonathan Hui 1e3fd039e2 [tests] remove test_route_table.py (#13025)
This commit removes the test_route_table.py test file
from the thread-cert test suite.
2026-05-04 06:42:12 -07:00
Jonathan Hui e7565cc51c [tests] remove test_ping.py (#13024)
This commit removes the test_ping.py test file from the
thread-cert test suite.

The ping functionality tested by this file is already
well covered by existing Nexus tests (e.g.,
test_ipv6_source_selection.cpp, test_radio_filter.cpp),
so this file is no longer needed.
2026-05-04 06:41:57 -07:00
dependabot[bot] 864f5ed373 github-actions: bump actions/download-artifact from 5.0.0 to 8.0.1 (#13040)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5.0.0 to 8.0.1.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/634f93cb2916e3fdff6788551b99b062d0335ce0...3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: 8.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-04 06:40:49 -07:00
Jonathan Hui fb274efe68 [nexus] migrate test_history_tracker to Nexus (#13023)
This commit migrates the test_history_tracker.py test
from the thread-cert test suite to the Nexus test
framework as a new C++ test.

The new C++ test, test_history_tracker.cpp, covers:
- Role changes (detached -> leader -> disabled)
- NetInfo age up to 49 days
- Child mode Rn changes
- Ping between leader and child, verifying message
  types, checksums, priority, and success flags

It directly uses HistoryTracker::Local methods instead
of the C APIs.
2026-04-30 18:52:22 -07:00
Jonathan Hui d4a7f2d0a4 [tests] remove test_set_mliid cert test (#13022) 2026-04-30 18:52:12 -07:00
Abtin Keshavarzian e0650292e2 [neighbor-table] introduce core Iterator type (#13020)
This commit introduces `NeighborTable::Iterator` and
`NeighborTable::kIteratorInit` as core type aliases for
the public `otNeighborInfoIterator` and its initializer
`OT_NEIGHBOR_INFO_ITERATOR_INIT`.
2026-04-30 16:31:08 -07:00
Abtin Keshavarzian fe3594e4e6 [tests] add nexus test for FED rx-only link establishment (#13019)
This commit adds a new Nexus test `TestFedRxOnlyLinkEstablishment` to
verify that a Full End Device (FED) successfully establishes rx-only
links with all its neighboring routers in the network.

The test forms a topology with a leader and 15 routers, then adds an
FED child. It uses the `NeighborTable` callback to track the addition
of routers to the FED's neighbor table and ensures that it
eventually establishes links with all available neighboring routers.
2026-04-30 16:30:26 -07:00