[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.
This commit is contained in:
Jonathan Hui
2026-03-17 03:02:44 -05:00
committed by GitHub
parent 27d57f9925
commit 244900a49a
16 changed files with 680 additions and 34 deletions
+8 -4
View File
@@ -124,6 +124,7 @@ void Node::SendEchoRequest(const Ip6::Address &aDestination,
messageInfo.SetPeerAddr(aDestination);
messageInfo.SetHopLimit(aHopLimit);
messageInfo.mAllowZeroHopLimit = true;
if (aSrcAddress != nullptr)
{
@@ -145,21 +146,24 @@ void Node::HandleIp6Receive(otMessage *aMessage, void *aContext)
void Node::HandleReceive(otMessage *aMessage)
{
uint16_t length = otMessageGetLength(aMessage);
uint8_t buffer[1500];
const Ip6::Header *header;
uint16_t length = otMessageGetLength(aMessage);
uint8_t buffer[1500];
Ip6::Header *header;
VerifyOrExit(length <= sizeof(buffer));
VerifyOrQuit(otMessageRead(aMessage, 0, buffer, length) == length);
VerifyOrExit(length >= sizeof(Ip6::Header));
header = reinterpret_cast<const Ip6::Header *>(buffer);
header = reinterpret_cast<Ip6::Header *>(buffer);
// Forward packets to InfraIf if they are intended for the backbone.
// We avoid forwarding link-local and realm-local scope packets.
VerifyOrExit(mInfraIf.IsInitialized());
VerifyOrExit(header->GetHopLimit() > 1);
header->SetHopLimit(header->GetHopLimit() - 1);
VerifyOrExit(header->GetDestination().GetScope() > Ip6::Address::kRealmLocalScope);
Core::Get().SetActiveNode(this);