Commit Graph

27 Commits

Author SHA1 Message Date
Abtin Keshavarzian 86b8bf6de4 [nexus] add support for CLI testing (#13110)
This commit adds support for interacting with nodes via the CLI in the
Nexus simulation framework. This enables writing higher-level
integration tests that verify stack behavior and state through
standard CLI commands.

Key changes:
- Integrated `Cli::Interpreter` into the `Nexus::Node` class.
- Added `Node::InputCli()` to allow sending commands to a node with
  `printf`-style formatting.
- Implemented output capturing logic in `Node::HandleCliOutput()` to
  buffer and parse CLI responses into individual lines, stored in a
  `CliOutputArray`.
- Added helper methods to `CliOutputLine` for matching and validating
  the captured output.
- Added a new `cli_basic` Nexus test to demonstrate and validate the
  CLI interaction functionality.
2026-05-18 13:03:46 -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 27321a2110 [nexus] add WebAssembly support using Emscripten (#12904)
This commit adds support for building the Nexus simulator for
WebAssembly (WASM) using the Emscripten toolchain. This enables the
simulator to run in a web browser environment with a JavaScript-based
control interface and visualization.

Key implementation details:
- Introduced `nexus_wasm.cpp` which defines Emscripten bindings (using
  Embind) for core simulation controls, including stepping time,
  node creation, topology orchestration, and state manipulation.
- Implemented a `WasmObserver` and a global event queue to capture
  simulation events (node state changes, link updates, packet events)
  and expose them to JavaScript via a polling mechanism (`pollEvent`).
- Updated the CMake build system to support the `EMSCRIPTEN` platform,
  configuring specific linker options for ES6 module export,
  modularization, and memory growth.
- Enhanced `build.sh` to allow targeting WASM via `emcmake`.
- Guarded file-system-dependent operations in `nexus_pcap.cpp` and
  adjusted `nexus_core.cpp` to handle WASM-specific constraints where
  standard I/O or multiple observers might not be applicable.
- Added `test_wasm_bindings.mjs`, a Node.js-based smoke test that
  verifies the integrity of the WASM bindings and event pipeline.
- Integrated `nexus-wasm-tests` into the GitHub Actions workflow to
  ensure continuous verification of the WASM build and functionality.
2026-04-17 15:25:28 -05:00
Abtin Keshavarzian 064529cbfc [nexus] add helper to allow link between nodes in nexus (#12906)
Added `Core::AllowLinkBetween()` and `Core::UnallowLinkBetween()`
helper methods to the Nexus test platform. These methods simplify
establishing bidirectional links between nodes in simulation tests by
handling the reciprocal `AllowList()` calls in a single step.

Updated various Nexus test cases to utilize these new helpers,
replacing manual bidirectional `AllowList()` calls. This change
reduces verbosity and ensures consistency in how links are established
in the test topology.
2026-04-17 13:22:27 -05:00
Jonathan Hui e2d07be235 [nexus] introduce simulation observer interface and hooks (#12894)
This commit introduces the `SimulationObserver` interface and integrates
it into the Nexus core simulation logic. This allows external systems to
observe node state changes, link updates, and packet events in real-time.

Key changes:
- Defined `SimulationObserver` interface to handle node state changes,
  link updates, packet events, and event clearing.
- Added `SetObserver` and `GetObserver` methods to the `Core` class.
- Implemented `Core::HandleNeighborTableChanged` to notify the observer
  of neighbor additions and removals.
- Implemented `Core::HandleStateChanged` to track node role transitions
  and parent changes, updating links accordingly.
- Integrated packet event notification in `Core::ProcessRadio`,
  including basic destination node ID resolution for unicast frames.
- Added `Core::SetNodeEnabled` to allow enabling or disabling Thread and
  MLE on specific nodes at runtime.
- Updated `Core::Reset` to clear events via the observer.
- Increased `OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS` to accommodate
  the new nexus state change handler.
- Added `mLastParentId` to `Node` class to correctly manage link updates
  during parent switches or detachment.
2026-04-14 23:26:09 -05:00
Abtin Keshavarzian a98813b30a [nexus] use Ip6::SetReceiveCallback() directly (#12865)
This commit updates the Nexus platform to use the internal core C++
API `Ip6::SetReceiveCallback()` instead of the public C API
`otIp6SetReceiveCallback()`.
2026-04-09 17:55:04 -05:00
Jonathan Hui 3b84b4c5cb [nexus] implement test 1_4_DNS_TC_3 for upstream DNS resolver selection (#12835)
This commit implements the Nexus test specification 1_4_DNS_TC_3 for
upstream DNS resolver selection in OpenThread.

Nexus Platform Enhancements:
- Added OPENTHREAD_CONFIG_DNS_UPSTREAM_QUERY_ENABLE and
  OPENTHREAD_CONFIG_PLATFORM_DNS_ENABLE to nexus config.
- Implemented platform DNS APIs in nexus_dns.cpp, supporting
  upstream server selection based on prefix lifetimes and reachability.
- Added UdpHook to Core to allow tests to intercept and simulate
  responses for backbone UDP traffic on port 53.
- Updated InfraIf::Receive to call Core::HandleUdp for generic UDP
  interception.
- Added raw buffer delivery overloads for InfraIf::SendUdp.

Test Implementation:
- Created test_1_4_DNS_TC_3.cpp which performs network formation,
  RA signaling (PIO/RIO/RDNSS), and DNS resolution triggers.
- Created verify_1_4_DNS_TC_3.py to validate network behavior,
  RA contents, and correct upstream query routing using pktverify.
- Integrated the new test into CMakeLists.txt and the default
  run_nexus_tests.sh suite.
2026-04-08 17:01:03 -05:00
Abtin Keshavarzian a44970bdb4 [nexus] simplify node lookup using LinkedList matching methods (#12849)
This commit updates the address-based node lookup methods in `Core`
to use the `FindMatching()` and `ContainsMatching()` methods provided
by the `LinkedList` class. This replaces manual `for` loops with
cleaner, built-in list operations.

To facilitate this, a new `AddressNetif` enum and a `Matches()` method
are added to the `Node` class. The `Matches()` method accepts an
`Ip6::Address` and an `AddressNetif` indicator, allowing it to check
if the node has the specified address on its Thread interface, its
Infrastructure interface, or any.

Additionally, a `const` overload for the `Get()` template method is
added to the `Node` class to ensure proper const-correctness.
2026-04-07 13:23:25 -05:00
Abtin Keshavarzian a24e841ad2 [nexus] optimize HandleIp6Receive and SendIp6 to use OwnedPtr (#12846)
This commit updates the IPv6 receive path in the Nexus platform to
utilize `OwnedPtr<Message>` for message lifecycle management. It
also removes the need for a large local buffer and redundant
message allocations.

Previously, `Node::HandleReceive()` copied the entire `otMessage`
payload into a local array, and `InfraIf::SendIp6()` allocated a new
`Message` to enqueue for transmission.

With this change:
- `Node::HandleIp6Receive()` wraps the received `otMessage` in an
  `OwnedPtr<Message>`, ensuring proper cleanup upon exit without
  explicitly calling `otMessageFree()`.
- The `Ip6::Header::ParseFrom` is used which reads and validates
  the IPv6 header and the message.
- The hop limit is updated in-place within the `Message` using
  `Write()` to overwrite previous header.
- `InfraIf::SendIp6()` accepts the `OwnedPtr<Message>` directly,
  taking ownership and enqueuing it without requiring reallocation
  or memory copying.
- Condition checks in `Node::HandleIp6Receive()` are reordered
  to match the comment.
2026-04-07 13:22:55 -05:00
Abtin Keshavarzian 754eefabb6 [nexus] fix IPv6 receive callback setup in node reset (#12845)
This commit updates `Node::Reset()` in the Nexus platform to correctly
set the IPv6 receive callback after the OpenThread `Instance` has been
re-initialized via placement `new`.

Previously, `otIp6SetReceiveCallback()` was called before the new
`Instance` was constructed, meaning the callback registration would
be lost when the instance memory was overwritten. Additionally, the
callback registration now passes the associated `Node` object as the
context.
2026-04-06 23:46:21 -05:00
Abtin Keshavarzian a5593e7980 [nexus] remove active node tracking (#12754)
This commit removes the active node tracking logic from the Nexus
simulation framework.

Previously, `Core` maintained a pointer to the `mActiveNode` and updated
it dynamically during processing and network events. This was necessary
so that log messages could be attributed to the correct node/instance.

With the recent introduction of "instance-aware logging" in the OpenThread
core, the logging mechanism natively knows which `otInstance` generated a
log. Therefore, manually tracking and context-switching the active node
in the Nexus framework is no longer required.

This change simplifies `nexus::Core`, removes context-switching overhead
from heavily utilized inline methods like `Node::Get<Type>()`, and allows
us to simplify the signature of `InfraIf::Receive()`.
2026-03-25 10:36:11 -05:00
Jonathan Hui 5e99ebaa51 [nexus] update mDNS traffic to flow through infrastructure link (#12720)
Update mDNS traffic simulation in the Nexus platform to flow through
the simulated infrastructure link. This ensures mDNS packets are
automatically written to the PCAP file generated by the simulated
infrastructure link.

Changes:
- Wrap mDNS messages in UDP/IPv6 headers and enqueue them on the
  simulated infrastructure interface (InfraIf).
- Implement a new SendUdp overload in InfraIf that accepts a Message
  payload.
- Update InfraIf::Receive to intercept mDNS UDP packets (port 5353)
  and deliver them to the Mdns module.
- Remove the dedicated ProcessMdns loop and manual PendingTx list from
  Core and Mdns, consolidating traffic processing through InfraIf.
- Initialize Mdns with a reference to the Node to allow access to
  InfraIf.
- Add GetMulticastAddress static helper to Mdns for 'ff02::fb'.
2026-03-20 17:05:32 -05:00
Jonathan Hui 244900a49a [nexus] add MATN-TC-12 test case for hop limit processing (#12701)
This commit implements the MATN-TC-12 test case in the Nexus
simulation framework to verify that a Primary BBR correctly
decrements the IPv6 Hop Limit when forwarding multicast packets
between the backbone link and the Thread network.

Key implementation details include:
- Implementation of MATN-TC-12 in C++ simulating a topology with a
  Border Router (BR_1 as DUT), a Thread Router, and a Host.
- Enhancement of the Nexus platform to support hop limit processing:
  - Updated InfraIf::Receive to decrement Hop Limit when forwarding
    from the backbone to the Thread network.
  - Updated Node::HandleReceive to decrement Hop Limit when forwarding
    from the Thread network to the backbone.
  - Added support for simulating packets with Hop Limit 0 by setting
    mAllowZeroHopLimit in Node::SendEchoRequest.
- Addition of a Python verification script to validate:
  - Multicast forwarding from backbone to Thread with decrement.
  - Multicast forwarding from Thread to backbone with decrement.
  - Dropping of packets with Hop Limit 1 (or 0) during forwarding.
  - Use of unique ICMPv6 identifiers to reliably distinguish between
    pings in different test steps.
- Inclusion of the full test specification as inline comments in
  both the C++ and Python files.
- Registration of the new test case in tests/nexus/CMakeLists.txt
  and tests/nexus/run_nexus_tests.sh.
2026-03-17 03:02:44 -05:00
Jonathan Hui 0f44bd990e [nexus] add MATN-TC-07 test case for BBR multicast forwarding (#12694)
This commit implements the MATN-TC-07 test case in the Nexus
simulation framework to verify default multicast forwarding
behavior on Border Routers.

Key implementation details include:
- Implementation of the MATN-TC-07 test scenario in C++ to
  trigger various multicast ping requests across different
  IPv6 scopes (realm-local, admin-local, site-local, global,
  and link-local).
- Enhancement of the Python verification script to strictly
  validate that only the Primary BBR forwards multicast
  packets to the backbone link using Ethernet source address
  filtering.
- Support for Ethernet link type in Nexus PCAP generation by
  prepending Ethernet headers to infrastructure IPv6 packets.
- Exposure of infrastructure MAC addresses (ethaddrs) in the
  test information JSON to enable identification of the
  forwarding node on the backbone link.
- Support for verifying source addresses of MPL-encapsulated
  multicast packets by checking both outer and inner headers.
- Addition of FindGlobalAddress() helper in the Nexus node
  platform.
2026-03-16 20:35:22 -05:00
Jonathan Hui 5df29f74e1 [nexus] implement infra interface for backbone simulation (#12683)
Implement the InfraIf class and associated platform logic to simulate
a shared infrastructure link (backbone) between Border Routers and
external hosts within the Nexus simulation environment.

Infra interface simulation:
- Implement shared Ethernet-like link for IPv6 traffic delivery.
- Add automated SLAAC address configuration based on ICMPv6 RAs.
- Support sending/receiving ICMPv6 Neighbor Discovery (RS, RA, NS, NA).
- Implement manual ICMPv6 checksum calculation for raw packets.
- Add infrastructure-level loop prevention and destination filtering.
- Provide helper methods to find nodes by infrastructure addresses.

Platform integration:
- Implement otPlatInfraIf APIs and integrate with otInstance.
- Use native Message and MessageQueue for pending traffic management.
- Add support for custom test variables in SaveTestInfo() JSON output.
- Update Node::Reset() to properly clear pending infra interface tasks.

Core enhancements:
- Add MulticastListenersTable::Has() to check for address presence.
- Add PrefixInfoOption::GetPrefixLength() and SetPrefixLength().
- Enable MLR and Backbone Router multicast routing in Nexus config.
2026-03-15 02:39:57 -05:00
Jonathan Hui 49582b3d9f [nexus] refactor test 1.2.LP.5.3.1 and remove kAsSsed mode (#12615)
This commit refactors Nexus test 1.2.LP.5.3.1 to better align with
the specification and improves the robustness of the test logic and
verification script. It also removes the kAsSsed join mode to favor
explicit CSL configuration in tests.

Changes:
- Removed kAsSsed from Nexus::Node::JoinMode and Node::Join() to
  encourage tests to manage CSL parameters explicitly.
- Updated test_1_2_LP_5_3_1.cpp to join as a regular SED first and
  enable CSL after attachment. This matches the specification's
  requirement to establish synchronization via Child Update Request.
- Introduced constants in test_1_2_LP_5_3_1.cpp for CSL period,
  synchronization time, and other parameters to avoid magic numbers.
- Enhanced verify_1_2_LP_5_3_1.py with comprehensive checks for:
    - MLE Child Update Request/Response exchange.
    - IEEE 802.15.4-2015 frame versions.
    - ICMPv6 Echo Request/Response forwarding through the Leader.
    - Absence of MAC Data Requests after CSL synchronization.
- Fixed an issue in verify_1_2_LP_5_3_1.py where packet numbers
  were not correctly handled in pkts.range().
2026-03-04 12:04:56 -06:00
Jonathan Hui e5169ea810 [nexus] add test 1.2.LP.5.3.1 for SSED attachment (#12594)
This commit adds a new Nexus test case 1.2.LP.5.3.1 which validates
SSED attachment and CSL synchronization.

Changes:
- Added kAsSsed JoinMode to Nexus::Node platform to support joining
  as a Synchronized Sleepy End Device with default CSL parameters.
- Implemented test_1_2_LP_5_3_1.cpp following the test specification
  for SSED attachment.
- Implemented verify_1_2_LP_5_3_1.py to verify pcap output, ensuring
  correct use of 802.15.4-2015 frames and CSL synchronization.
- Updated CMakeLists.txt and run_nexus_tests.sh to include the new
  test in the Nexus test suite.
2026-03-03 18:05:15 -06:00
Jonathan Hui 4866887933 [nexus] implement microsecond alarm platform APIs (#12580)
This commit implements the otPlatAlarmMicro* platform APIs in the
Nexus simulation environment. It also transitions the simulation's
internal time base from millisecond to microsecond granularity to
ensure that both millisecond and microsecond alarms operate on a
consistent and shared time reference.

Changes include:
- Enabled OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE in Nexus config.
- Updated Nexus::Core to use a 64-bit microsecond time base (mNow).
- Implemented otPlatAlarmMicroGetNow, otPlatAlarmMicroStartAt, and
  otPlatAlarmMicroStop.
- Refactored Nexus::Node to support separate millisecond and
  microsecond alarm instances (mAlarmMilli and mAlarmMicro).
- Updated radio timestamps and PCAP logging to use the new high-
  resolution microsecond time base.
- Adjusted simulation time advancement and alarm triggering logic to
  handle both alarm types correctly.
2026-03-02 11:31:27 -06:00
Abtin Keshavarzian db2d99176c [nexus] extend Node::Join() to allow specifying network data type on SED (#12451)
This commit updates `Node::Join()` to allow specifying whether a node
joining as an SED should request the full network data or only the
stable subset via the `JoinMode` parameter.

Previously, `kAsSed` implicitly requested full network data. This
change updates `kAsSed` to request only the stable subset (the
default behavior for an SED). A new `kAsSedWithFullNetData` mode is
introduced to explicitly request full network data when joining as
an SED.

This change provides more flexibility in test scenarios, allowing
validation of SEDs with different network data requirements.
2026-02-17 22:50:48 -06:00
Jonathan Hui 31f9693a6c [nexus] update Node::SetName() to use underscore as separator (#12452)
This commit updates the Nexus::Node::SetName(prefix, index) method
to use an underscore ('_') instead of a space between the prefix
and the index when generating the node name.

Corresponding verification scripts verify_5_2_3.py and
verify_5_2_4.py are also updated to match the new naming convention
when looking up nodes in the test environment.

All Nexus tests have been verified to pass with this change.
2026-02-13 20:25:37 -06:00
Abtin Keshavarzian da64c7cc95 [nexus] add Node::FindMatchingAddress() helper (#12437)
This commit adds the `Node::FindMatchingAddress()` helper method to the
`Nexus::Node` class. This method simplifies the process of finding a
unicast address on a node that matches a given IPv6 prefix.
2026-02-13 15:15:32 -06:00
Abtin Keshavarzian b347195b15 [nexus] add helpers for sending and validating ICMPv6 echo exchange (#12408)
This commit adds helper methods in Nexus to simplify ICMPv6 echo
exchanges:
- `Node::SendEchoRequest()`: sends an ICMPv6 Echo Request with
  configurable parameters such as payload size and hop limit.
- `Core::SendAndVerifyEchoRequest()`: sends an Echo Request and
  validates the matching Echo Reply within a timeout.

This commit also update various certification tests to use these
helpers, removing duplicate local utility functions.
2026-02-10 16:57:48 -08:00
Jonathan Hui 4c5d8f6a60 [nexus] add test 5.2.3 Leader rejects Address Solicit (2-hops away) (#12392)
Adds a new Nexus test case for 'Leader rejects CoAP Address Solicit
(2-hops from Leader)' (5.2.3) as specified in the test specification.

Summary of changes:
- Implemented Nexus test 5.2.3:
    - Added test_5_2_3.cpp: Sets up a topology with a Leader, 31 routers
      (fully connected to Leader), and a 32nd router (Router 32) that is
      2-hops away from the Leader via Router 1. Verifies that the Leader
      rejects the Address Solicit Request from the 33rd router with a
      'No Address Available' status (1).
    - Added verify_5_2_3.py: PCAP verification script for test 5.2.3.
      Ensures the Address Solicit Request is sent by Router 32 to the
      Leader, and that the Leader responds with a CoAP ACK containing
      a Status TLV with value 1 (NL_NO_ADDRESS_AVAILABLE).
- Updated build and execution scripts:
    - Modified CMakeLists.txt to build the new 5.2.3 test executable.
    - Updated run_nexus_tests.sh to include 5.2.3 in the default test
      list.
2026-02-09 15:23:58 -08:00
Abtin Keshavarzian a2fb36cd0b [nexus] add mechanism to emulate node reset (#11662)
This commit adds a new mechanism to emulate a node reset on
`Nexus::Node`. This is realized by resetting all platform components
while ensuring the non-volatile `mSettings` remains unchanged, then
reinitializing the `ot::Instance` by invoking its constructor.

This is used to add a new `test_full_network_reset` test, which
emulates a full simultaneous reset of all nodes in a large network,
tracking how long it takes for the network to stabilize after the
reset event.
2025-07-08 15:10:30 -07:00
Abtin Keshavarzian c2de9f646a [trel] manage mDNS/DNSSD and peer discovery in core (#11528)
This commit enhances the TREL module to manage mDNS/DNSSD service
registration and peer discovery (browse and resolving for TREL
services). This feature can be controlled through
`OPENTHREAD_CONFIG_TREL_MANAGE_DNSSD_ENABLE` (and/or the CMake option
`OT_TREL_MANAGE_DNSSD`).

When enabled, TREL will utilize the `Dnssd` module, which provides
mDNS-related APIs. This can be tied to OpenThread's native mDNS
implementation or to `otPlatDnssd` (i.e., provided by the platform
layer).

This commit also adds support for the TREL platform in the `Nexus`
test framework and uses this to add a detailed `test_trel` case. This
test covers basic TREL peer discovery and operation, along with
specific scenarios such as peer removal delay, delayed mDNS start,
TREL service name conflict resolution, host address changes, and
supporting multiple services on the same host (while unlikely in
actual deployments, this can be useful for testing and simulation
where a single machine may act as multiple Thread nodes, thus
advertising multiple TREL services from the same hostname. This is
explicitly supported by the implementation and covered in the
tests).
2025-06-02 12:45:39 -07:00
Abtin Keshavarzian 0c1dfa0796 [mle] refactor MleRouter and Mle classes into a single Mle class (#11411)
This commit refactors the `Mle` modules and combines the `MleRouter`
and `Mle` classes into a single `Mle` class which now handles both
FTD and MTD functionalities.

The `MleRouter` and `Mle` classes were originally intended as
sub-classes, where the base class `Mle` would provide MTD and common
behaviors, and `MleRouter` would implement FTD-specific behaviors.
However, over the years and as new features were implemented, these
two classes became more intertwined, and the `Mle` class began to
include many FTD-related functions and interactions with `MleRouter`
private variables and methods.

This commit simplifies the code by combining the two into a single
class. The previous `mle_router.cpp` file is also renamed to
`mle_ftd.cpp` to indicate that it implements FTD-specific MLE
behaviors.
2025-04-18 14:28:47 -07:00
Abtin Keshavarzian 287dbfa251 [test] introduce Nexus test framework and platform (#10533)
This commit introduces a new test framework named Nexus. The
framework includes the Nexus platform implementation that emulates
platform behavior, allowing multiple nodes running the OpenThread
core stack to be simulated and interact with each other within the
same process.

Unlike the simulation platform, where nodes run in separate processes
and interact via POSIX sockets, Nexus nodes are simulated within a
single process. Nexus tests can interact directly with the C++ or C
OT core APIs, providing more control than the simulation platform's
CLI-based interactions. The flow of time in Nexus tests is directly
controlled by the test itself, allowing for quick time interval
advancement.

This model allows for faster and more scalable simulations, enabling
quick simulation of larger networks for longer durations.

This commit introduces the basic platform implementation, including:
- `nexus_alarm`, `nexus_radio`, and `nexus_settings` modules.
- Logging support, allowing logs to be distinguished per emulated
  node.
2024-10-09 14:27:54 -07:00