mirror of
https://github.com/espressif/openthread.git
synced 2026-08-09 20:27:47 +00:00
[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.
This commit is contained in:
@@ -239,6 +239,7 @@ ot_nexus_test(1_2_MATN_TC_2 "cert;nexus")
|
||||
ot_nexus_test(1_2_MATN_TC_3 "cert;nexus")
|
||||
ot_nexus_test(1_2_MATN_TC_4 "cert;nexus")
|
||||
ot_nexus_test(1_2_MATN_TC_5 "cert;nexus")
|
||||
ot_nexus_test(1_2_MATN_TC_7 "cert;nexus")
|
||||
|
||||
# Misc tests
|
||||
ot_nexus_test(border_admitter "core;nexus")
|
||||
|
||||
@@ -168,6 +168,18 @@ void Core::SaveTestInfo(const char *aFilename, Node *aLeaderNode)
|
||||
}
|
||||
fprintf(file, " },\n");
|
||||
|
||||
fprintf(file, " \"ethaddrs\": {\n");
|
||||
for (Node &node : mNodes)
|
||||
{
|
||||
InfraIf::LinkLayerAddress mac;
|
||||
|
||||
node.mInfraIf.GetLinkLayerAddress(mac);
|
||||
fprintf(file, " \"%u\": \"%02x:%02x:%02x:%02x:%02x:%02x\"%s\n", node.GetInstance().GetId(), mac.mAddress[0],
|
||||
mac.mAddress[1], mac.mAddress[2], mac.mAddress[3], mac.mAddress[4], mac.mAddress[5],
|
||||
(&node == tail) ? "" : ",");
|
||||
}
|
||||
fprintf(file, " },\n");
|
||||
|
||||
fprintf(file, " \"rloc16s\": {\n");
|
||||
for (Node &node : mNodes)
|
||||
{
|
||||
@@ -547,7 +559,40 @@ void Core::ProcessInfraIf(Node &aNode)
|
||||
VerifyOrQuit(message->GetLength() >= sizeof(Ip6::Header) && header.IsVersion6());
|
||||
|
||||
SuccessOrQuit(msgData.SetFrom(*message, 0, message->GetLength()));
|
||||
mPcap.WritePacket(msgData.GetBytes(), msgData.GetLength(), mNow);
|
||||
|
||||
{
|
||||
InfraIf::LinkLayerAddress srcMac;
|
||||
InfraIf::LinkLayerAddress dstMac;
|
||||
|
||||
aNode.mInfraIf.GetLinkLayerAddress(srcMac);
|
||||
|
||||
if (header.GetDestination().IsMulticast())
|
||||
{
|
||||
dstMac.mLength = 6;
|
||||
dstMac.mAddress[0] = 0x33;
|
||||
dstMac.mAddress[1] = 0x33;
|
||||
dstMac.mAddress[2] = header.GetDestination().mFields.m8[12];
|
||||
dstMac.mAddress[3] = header.GetDestination().mFields.m8[13];
|
||||
dstMac.mAddress[4] = header.GetDestination().mFields.m8[14];
|
||||
dstMac.mAddress[5] = header.GetDestination().mFields.m8[15];
|
||||
}
|
||||
else
|
||||
{
|
||||
Node *dstNode = FindNodeByInfraIfAddress(header.GetDestination());
|
||||
|
||||
if (dstNode != nullptr)
|
||||
{
|
||||
dstNode->mInfraIf.GetLinkLayerAddress(dstMac);
|
||||
}
|
||||
else
|
||||
{
|
||||
dstMac.mLength = 6;
|
||||
memset(dstMac.mAddress, 0xff, 6);
|
||||
}
|
||||
}
|
||||
|
||||
mPcap.WritePacket(srcMac, dstMac, msgData.GetBytes(), msgData.GetLength(), mNow);
|
||||
}
|
||||
|
||||
if (!header.GetDestination().IsMulticast())
|
||||
{
|
||||
|
||||
@@ -43,9 +43,9 @@ InfraIf::InfraIf(void)
|
||||
|
||||
void InfraIf::Init(Node &aNode)
|
||||
{
|
||||
Ip6::Address address;
|
||||
otPlatInfraIfLinkLayerAddress mac;
|
||||
Ip6::InterfaceIdentifier iid;
|
||||
Ip6::Address address;
|
||||
LinkLayerAddress mac;
|
||||
Ip6::InterfaceIdentifier iid;
|
||||
|
||||
mIfIndex = 1;
|
||||
mNode = &aNode;
|
||||
@@ -188,9 +188,9 @@ exit:
|
||||
|
||||
void InfraIf::HandlePrefixInfoOption(const Ip6::Nd::PrefixInfoOption &aPio)
|
||||
{
|
||||
Ip6::Prefix prefix;
|
||||
Ip6::Address address;
|
||||
otPlatInfraIfLinkLayerAddress mac;
|
||||
Ip6::Prefix prefix;
|
||||
Ip6::Address address;
|
||||
LinkLayerAddress mac;
|
||||
|
||||
VerifyOrExit(aPio.IsAutoAddrConfigFlagSet());
|
||||
|
||||
@@ -437,7 +437,7 @@ void InfraIf::HandleEchoRequest(const Ip6::Header &aHeader, Message &aMessage)
|
||||
mPendingTxQueue.Enqueue(*replyMessage);
|
||||
}
|
||||
|
||||
void InfraIf::GetLinkLayerAddress(otPlatInfraIfLinkLayerAddress &aLinkLayerAddress) const
|
||||
void InfraIf::GetLinkLayerAddress(LinkLayerAddress &aLinkLayerAddress) const
|
||||
{
|
||||
// Use a unique MAC address based on Node ID
|
||||
ClearAllBytes(aLinkLayerAddress);
|
||||
|
||||
@@ -40,6 +40,8 @@ class Node;
|
||||
class InfraIf
|
||||
{
|
||||
public:
|
||||
typedef otPlatInfraIfLinkLayerAddress LinkLayerAddress; ///< A link-layer address
|
||||
|
||||
InfraIf(void);
|
||||
|
||||
void Init(Node &aNode);
|
||||
@@ -70,7 +72,7 @@ public:
|
||||
uint16_t aDestPort,
|
||||
uint16_t aPayloadSize);
|
||||
void Receive(Node &aSrcNode, const Ip6::Header &aHeader, Message &aMessage);
|
||||
void GetLinkLayerAddress(otPlatInfraIfLinkLayerAddress &aLinkLayerAddress) const;
|
||||
void GetLinkLayerAddress(LinkLayerAddress &aLinkLayerAddress) const;
|
||||
|
||||
Node &GetNode(void);
|
||||
const Node &GetNode(void) const;
|
||||
|
||||
@@ -164,8 +164,17 @@ void Node::HandleReceive(otMessage *aMessage)
|
||||
|
||||
Core::Get().SetActiveNode(this);
|
||||
|
||||
if (header->GetDestination().IsMulticast())
|
||||
{
|
||||
VerifyOrExit(Get<BackboneRouter::Local>().IsPrimary());
|
||||
}
|
||||
|
||||
VerifyOrExit(Get<NetworkData::Leader>().IsOnMesh(header->GetSource()));
|
||||
|
||||
// Only forward if source is NOT Link-Local and NOT Mesh-Local.
|
||||
VerifyOrExit(!header->GetSource().IsLinkLocalUnicastOrMulticast());
|
||||
VerifyOrExit(!Get<Mle::Mle>().IsMeshLocalAddress(header->GetSource()));
|
||||
|
||||
mInfraIf.SendIp6(header->GetSource(), header->GetDestination(), buffer, length);
|
||||
|
||||
exit:
|
||||
@@ -201,5 +210,25 @@ const Ip6::Address &Node::FindMatchingAddress(const char *aPrefix)
|
||||
return *matchedAddress;
|
||||
}
|
||||
|
||||
const Ip6::Address &Node::FindGlobalAddress(void)
|
||||
{
|
||||
const Ip6::Address *matchedAddress = nullptr;
|
||||
|
||||
for (const Ip6::Netif::UnicastAddress &unicastAddress : Get<ThreadNetif>().GetUnicastAddresses())
|
||||
{
|
||||
const Ip6::Address &address = unicastAddress.GetAddress();
|
||||
|
||||
if (address.GetScope() == Ip6::Address::kGlobalScope && !Get<Mle::Mle>().IsMeshLocalAddress(address))
|
||||
{
|
||||
matchedAddress = &address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrQuit(matchedAddress != nullptr, "no global address found");
|
||||
|
||||
return *matchedAddress;
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
} // namespace ot
|
||||
|
||||
@@ -104,6 +104,16 @@ public:
|
||||
// a test failure (emits error message and exits the program.)
|
||||
const Ip6::Address &FindMatchingAddress(const char *aPrefix);
|
||||
|
||||
/**
|
||||
* Finds and returns a global scope address on the device.
|
||||
*
|
||||
* It requires a global scope address to be found, otherwise it is treated as a test failure (emits error message
|
||||
* and exits the program).
|
||||
*
|
||||
* @returns A reference to the global scope address.
|
||||
*/
|
||||
const Ip6::Address &FindGlobalAddress(void);
|
||||
|
||||
void SetName(const char *aName) { mName.Clear().Append("%s", aName); }
|
||||
void SetName(const char *aPrefix, uint16_t aIndex);
|
||||
const char *GetName(void) const { return mName.AsCString(); }
|
||||
|
||||
@@ -104,7 +104,7 @@ void Pcap::Open(const char *aFilename)
|
||||
ClearAllBytes(idb);
|
||||
idb.mBlockType = LittleEndian::HostSwap(kPcapngIdbType);
|
||||
idb.mBlockTotalLength = LittleEndian::HostSwap(static_cast<uint32_t>(sizeof(idb)));
|
||||
idb.mLinkType = LittleEndian::HostSwap(static_cast<uint16_t>(kPcapngLinkTypeIPv6));
|
||||
idb.mLinkType = LittleEndian::HostSwap(static_cast<uint16_t>(kPcapngLinkTypeEthernet));
|
||||
idb.mSnapLen = LittleEndian::HostSwap(kPcapngSnapLen);
|
||||
idb.mBlockTotalLength2 = idb.mBlockTotalLength;
|
||||
VerifyOrExit(fwrite(&idb, sizeof(idb), 1, mFile) == 1, Close());
|
||||
@@ -201,34 +201,55 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Pcap::WritePacket(const uint8_t *aBuffer, uint16_t aLength, uint64_t aTimeUs)
|
||||
void Pcap::WritePacket(const otPlatInfraIfLinkLayerAddress &aSrcAddr,
|
||||
const otPlatInfraIfLinkLayerAddress &aDstAddr,
|
||||
const uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
uint64_t aTimeUs)
|
||||
{
|
||||
Epb epb;
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct EthernetHeader
|
||||
{
|
||||
uint8_t mDst[6];
|
||||
uint8_t mSrc[6];
|
||||
uint16_t mType;
|
||||
} OT_TOOL_PACKED_END;
|
||||
EthernetHeader ethHeader;
|
||||
|
||||
uint32_t packetLen;
|
||||
uint32_t paddedLen;
|
||||
uint32_t blockTotalLength;
|
||||
uint32_t padding = 0;
|
||||
|
||||
VerifyOrExit(mFile != nullptr);
|
||||
|
||||
paddedLen = (aLength + 3) & ~3u;
|
||||
ClearAllBytes(ethHeader);
|
||||
memcpy(ethHeader.mDst, aDstAddr.mAddress, 6);
|
||||
memcpy(ethHeader.mSrc, aSrcAddr.mAddress, 6);
|
||||
ethHeader.mType = BigEndian::HostSwap16(kEtherTypeIPv6);
|
||||
|
||||
packetLen = sizeof(ethHeader) + aLength;
|
||||
paddedLen = (packetLen + 3) & ~3u;
|
||||
blockTotalLength = sizeof(epb) + paddedLen + sizeof(uint32_t);
|
||||
|
||||
ClearAllBytes(epb);
|
||||
epb.mBlockType = LittleEndian::HostSwap(kPcapngEpbType);
|
||||
epb.mBlockTotalLength = LittleEndian::HostSwap(blockTotalLength);
|
||||
epb.mInterfaceId = LittleEndian::HostSwap(1u); // Use Interface ID 1 for IPv6
|
||||
epb.mInterfaceId = LittleEndian::HostSwap(1u); // Use Interface ID 1 for Ethernet
|
||||
epb.mTimestampHigh = LittleEndian::HostSwap(static_cast<uint32_t>(aTimeUs >> 32));
|
||||
epb.mTimestampLow = LittleEndian::HostSwap(static_cast<uint32_t>(aTimeUs & 0xffffffff));
|
||||
epb.mCapturedLen = LittleEndian::HostSwap(static_cast<uint32_t>(aLength));
|
||||
epb.mOriginalLen = LittleEndian::HostSwap(static_cast<uint32_t>(aLength));
|
||||
epb.mCapturedLen = LittleEndian::HostSwap(packetLen);
|
||||
epb.mOriginalLen = LittleEndian::HostSwap(packetLen);
|
||||
VerifyOrExit(fwrite(&epb, sizeof(epb), 1, mFile) == 1, Close());
|
||||
|
||||
VerifyOrExit(fwrite(ðHeader, sizeof(ethHeader), 1, mFile) == 1, Close());
|
||||
VerifyOrExit(fwrite(aBuffer, aLength, 1, mFile) == 1, Close());
|
||||
|
||||
if (paddedLen > aLength)
|
||||
if (paddedLen > packetLen)
|
||||
{
|
||||
VerifyOrExit(fwrite(&padding, paddedLen - aLength, 1, mFile) == 1, Close());
|
||||
VerifyOrExit(fwrite(&padding, paddedLen - packetLen, 1, mFile) == 1, Close());
|
||||
}
|
||||
|
||||
VerifyOrExit(fwrite(&epb.mBlockTotalLength, sizeof(epb.mBlockTotalLength), 1, mFile) == 1, Close());
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
|
||||
#include <openthread/platform/infra_if.h>
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
namespace ot {
|
||||
@@ -66,11 +67,17 @@ public:
|
||||
/**
|
||||
* Writes a packet to the pcapng file.
|
||||
*
|
||||
* @param[in] aBuffer The packet buffer to write.
|
||||
* @param[in] aLength The packet length.
|
||||
* @param[in] aTimeUs The timestamp in microseconds.
|
||||
* @param[in] aSrcAddr The source link-layer address.
|
||||
* @param[in] aDstAddr The destination link-layer address.
|
||||
* @param[in] aBuffer The packet buffer to write.
|
||||
* @param[in] aLength The packet length.
|
||||
* @param[in] aTimeUs The timestamp in microseconds.
|
||||
*/
|
||||
void WritePacket(const uint8_t *aBuffer, uint16_t aLength, uint64_t aTimeUs);
|
||||
void WritePacket(const otPlatInfraIfLinkLayerAddress &aSrcAddr,
|
||||
const otPlatInfraIfLinkLayerAddress &aDstAddr,
|
||||
const uint8_t *aBuffer,
|
||||
uint16_t aLength,
|
||||
uint64_t aTimeUs);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kPcapngShbType = 0x0a0d0d0a;
|
||||
@@ -81,7 +88,9 @@ private:
|
||||
static constexpr uint32_t kPcapngEpbType = 0x00000006;
|
||||
static constexpr uint32_t kPcapngSnapLen = 65535;
|
||||
static constexpr uint32_t kPcapngLinkTypeIeee802154 = 283; // DLT_IEEE802_15_4_TAP
|
||||
static constexpr uint32_t kPcapngLinkTypeIPv6 = 101; // LINKTYPE_RAW
|
||||
static constexpr uint32_t kPcapngLinkTypeEthernet = 1; // LINKTYPE_ETHERNET
|
||||
|
||||
static constexpr uint16_t kEtherTypeIPv6 = 0x86dd;
|
||||
|
||||
static constexpr uint8_t kTapVersion = 0;
|
||||
|
||||
|
||||
@@ -174,6 +174,7 @@ DEFAULT_TESTS=(
|
||||
"1_2_MATN_TC_3"
|
||||
"1_2_MATN_TC_4"
|
||||
"1_2_MATN_TC_5"
|
||||
"1_2_MATN_TC_7"
|
||||
)
|
||||
|
||||
# Use provided arguments or the default test list
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright (c) 2026, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "platform/nexus_core.hpp"
|
||||
#include "platform/nexus_node.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Nexus {
|
||||
|
||||
/**
|
||||
* Time to advance for a node to form a network and become leader, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kFormNetworkTime = 10 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for a node to join as a router, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kAttachToRouterTime = 200 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for the network to stabilize, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kStabilizationTime = 10 * 1000;
|
||||
|
||||
/**
|
||||
* ICMPv6 Echo Request identifier.
|
||||
*/
|
||||
static constexpr uint16_t kEchoIdentifier = 0x1234;
|
||||
|
||||
/**
|
||||
* ICMPv6 Echo Request payload size.
|
||||
*/
|
||||
static constexpr uint16_t kEchoPayloadSize = 10;
|
||||
|
||||
/**
|
||||
* Infrastructure interface index.
|
||||
*/
|
||||
static constexpr uint32_t kInfraIfIndex = 1;
|
||||
|
||||
/**
|
||||
* Multicast address MA5 (realm-local).
|
||||
*/
|
||||
static const char kMA5[] = "ff03::1234:777a:1";
|
||||
|
||||
/**
|
||||
* Multicast address (admin-local).
|
||||
*/
|
||||
static const char kAdminLocalMcast[] = "ff04::1234:777a:1";
|
||||
|
||||
/**
|
||||
* Multicast address (site-local).
|
||||
*/
|
||||
static const char kSiteLocalMcast[] = "ff05::1234:777a:1";
|
||||
|
||||
/**
|
||||
* Multicast address (global).
|
||||
*/
|
||||
static const char kGlobalMcast[] = "ff0e::1234:777a:1";
|
||||
|
||||
/**
|
||||
* Multicast address (link-local).
|
||||
*/
|
||||
static const char kLinkLocalMcast[] = "ff02::1234:777a:1";
|
||||
|
||||
void TestMatnTc7(void)
|
||||
{
|
||||
/**
|
||||
* 5.10.6 MATN-TC-07: Default BR multicast forwarding
|
||||
*
|
||||
* 5.10.6.1 Topology
|
||||
* - BR_1
|
||||
* - BR_2
|
||||
* - ROUTER
|
||||
*
|
||||
* 5.10.6.2 Purpose & Description
|
||||
* Verify if the default forwarding of multicast on a Primary BBR is correct. Note: this can be changed by
|
||||
* forwarding flags of the BBR; however, this is application specific and change is not tested. This test case
|
||||
* also verifies that a Secondary BBR does not forward multicast packets to the backbone link.
|
||||
*
|
||||
* Spec Reference | V1.2 Section | V1.3.0 Section
|
||||
* -----------------|--------------|---------------
|
||||
* Multicast | 5.10.6 | N/A
|
||||
*/
|
||||
|
||||
Core nexus;
|
||||
Node &br1 = nexus.CreateNode();
|
||||
Node &br2 = nexus.CreateNode();
|
||||
Node &router = nexus.CreateNode();
|
||||
|
||||
Ip6::Address ma5;
|
||||
Ip6::Address adminLocalMcast;
|
||||
Ip6::Address siteLocalMcast;
|
||||
Ip6::Address globalMcast;
|
||||
Ip6::Address linkLocalMcast;
|
||||
|
||||
br1.SetName("BR_1");
|
||||
br2.SetName("BR_2");
|
||||
router.SetName("ROUTER");
|
||||
|
||||
SuccessOrQuit(ma5.FromString(kMA5));
|
||||
SuccessOrQuit(adminLocalMcast.FromString(kAdminLocalMcast));
|
||||
SuccessOrQuit(siteLocalMcast.FromString(kSiteLocalMcast));
|
||||
SuccessOrQuit(globalMcast.FromString(kGlobalMcast));
|
||||
SuccessOrQuit(linkLocalMcast.FromString(kLinkLocalMcast));
|
||||
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
Instance::SetLogLevel(kLogLevelNote);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 0: Topology formation - BR_1, BR_2, ROUTER");
|
||||
|
||||
/**
|
||||
* Step 0
|
||||
* - Device: N/A
|
||||
* - Description: Topology formation - BR_1, BR_2, ROUTER
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
|
||||
br1.AllowList(br2);
|
||||
br1.AllowList(router);
|
||||
br2.AllowList(br1);
|
||||
br2.AllowList(router);
|
||||
router.AllowList(br1);
|
||||
router.AllowList(br2);
|
||||
|
||||
br1.Form();
|
||||
nexus.AdvanceTime(kFormNetworkTime);
|
||||
VerifyOrQuit(br1.Get<Mle::Mle>().IsLeader());
|
||||
|
||||
br1.Get<BorderRouter::InfraIf>().Init(kInfraIfIndex, true);
|
||||
br1.Get<BorderRouter::RoutingManager>().Init();
|
||||
SuccessOrQuit(br1.Get<BorderRouter::RoutingManager>().SetEnabled(true));
|
||||
br1.Get<BackboneRouter::Local>().SetEnabled(true);
|
||||
|
||||
br2.Join(br1, Node::kAsFtd);
|
||||
router.Join(br1, Node::kAsFtd);
|
||||
nexus.AdvanceTime(kAttachToRouterTime);
|
||||
|
||||
VerifyOrQuit(br2.Get<Mle::Mle>().IsRouter());
|
||||
VerifyOrQuit(router.Get<Mle::Mle>().IsRouter());
|
||||
|
||||
br2.Get<BorderRouter::InfraIf>().Init(kInfraIfIndex, true);
|
||||
br2.Get<BorderRouter::RoutingManager>().Init();
|
||||
SuccessOrQuit(br2.Get<BorderRouter::RoutingManager>().SetEnabled(true));
|
||||
br2.Get<BackboneRouter::Local>().SetEnabled(true);
|
||||
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
VerifyOrQuit(br1.Get<BackboneRouter::Local>().IsPrimary());
|
||||
VerifyOrQuit(!br2.Get<BackboneRouter::Local>().IsPrimary());
|
||||
|
||||
const Ip6::Address &routerGlobalAddr = router.FindGlobalAddress();
|
||||
|
||||
nexus.AddTestVar("MA5", kMA5);
|
||||
nexus.AddTestVar("ADMIN_LOCAL_MCAST", kAdminLocalMcast);
|
||||
nexus.AddTestVar("SITE_LOCAL_MCAST", kSiteLocalMcast);
|
||||
nexus.AddTestVar("GLOBAL_MCAST", kGlobalMcast);
|
||||
nexus.AddTestVar("LINK_LOCAL_MCAST", kLinkLocalMcast);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 1: ROUTER sends an ICMPv6 Echo (ping) Request packet with realm-local scope MA5.");
|
||||
|
||||
/**
|
||||
* Step 1
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to send an ICMPv6 Echo (ping) Request packet with realm-local scope
|
||||
* MA5.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(ma5, kEchoIdentifier, kEchoPayloadSize, 64, &routerGlobalAddr);
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 2: BR_1 does not forward the multicast ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 2
|
||||
* - Device: BR_1
|
||||
* - Description: Does not forward the multicast ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST NOT forward the multicast ICMPv6 Echo (ping) Request packet with realm-local scope address
|
||||
* MA5 to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 3: BR_2 does not forward the multicast ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 3
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ICMPv6 Echo (ping) Request packet with realm-local scope address
|
||||
* MA5 to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 4: ROUTER sends an ICMPv6 Echo Request with admin-local scope, encapsulated in an MPL packet.");
|
||||
|
||||
/**
|
||||
* Step 4
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to sends an ICMPv6 Echo (ping) Request packet with admin-local scope
|
||||
* (address ff04::…), encapsulated in an MPL packet.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(adminLocalMcast, kEchoIdentifier, kEchoPayloadSize, 64, &routerGlobalAddr);
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 5: BR_1 automatically forwards the ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 5
|
||||
* - Device: BR_1
|
||||
* - Description: Automatically forwards the ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST forward the multicast ICMPv6 Echo (ping) Request packet with admin-local scope (address
|
||||
* ff04::…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 6: BR_2 does not forward the multicast ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 6
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ICMPv6 Echo (ping) Request packet with admin-local scope (address
|
||||
* ff04::…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 7: ROUTER sends an ICMPv6 Echo Request with site-local scope, encapsulated in an MPL packet.");
|
||||
|
||||
/**
|
||||
* Step 7
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request packet with site-local scope
|
||||
* (address ff05::…), encapsulated in an MPL packet.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(siteLocalMcast, kEchoIdentifier, kEchoPayloadSize, 64, &routerGlobalAddr);
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 8: BR_1 automatically forwards the ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 8
|
||||
* - Device: BR_1
|
||||
* - Description: Automatically forwards the ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST forward the multicast ICMPv6 Echo (ping) Request packet with site-local scope (address
|
||||
* ff05::…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 9: BR_2 does not forward the multicast ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 9
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ICMPv6 Echo (ping) Request packet with site-local scope (address
|
||||
* ff05::…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 10: ROUTER sends an ICMPv6 Echo Request with global scope, encapsulated in an MPL packet.");
|
||||
|
||||
/**
|
||||
* Step 10
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request packet with global scope
|
||||
* (address ff0e::…) , encapsulated in an MPL packet.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(globalMcast, kEchoIdentifier, kEchoPayloadSize, 64, &routerGlobalAddr);
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 11: BR_1 automatically forwards the ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 11
|
||||
* - Device: BR_1
|
||||
* - Description: Automatically forwards the ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST forward the multicast ICMPv6 Echo (ping) Request packet with global scope (address ff0e::…)
|
||||
* to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 12: BR_2 does not forward the multicast ping request packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 12
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping request packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ICMPv6 Echo (ping) Request packet with global scope (address
|
||||
* ff0e::…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 13: ROUTER sends an ICMPv6 Echo (ping) Request packet with link-local scope.");
|
||||
|
||||
/**
|
||||
* Step 13
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request packet with link-local scope
|
||||
* (address ff02::…).
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(linkLocalMcast, kEchoIdentifier, kEchoPayloadSize, 64, &routerGlobalAddr);
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 14: BR_1 does not forward the multicast ping packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 14
|
||||
* - Device: BR_1
|
||||
* - Description: Does not forward the multicast ping packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST NOT forward the multicast ping packet with link-local scope (address ff02:…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 15: BR_2 does not forward the multicast ping packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 15
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ping packet with link-local scope (address ff02:…) to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 16: ROUTER sends an ICMPv6 Echo Request with global scope and ML-EID as source.");
|
||||
|
||||
/**
|
||||
* Step 16
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request with global scope (address
|
||||
* ff0e::…) , encapsulated in an MPL packet. The source address is chosen as the ML-EID. This implies that the
|
||||
* packet has to stay on the mesh. Note: this can be implemented in OT CLI using ping -I <srcaddr>
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(globalMcast, kEchoIdentifier, kEchoPayloadSize, 64,
|
||||
&router.Get<Mle::Mle>().GetMeshLocalEid());
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 17: BR_1 does not forward the multicast ping packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 17
|
||||
* - Device: BR_1
|
||||
* - Description: Does not forward the multicast ping packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST NOT forward the multicast ping packet with global scope to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 18: BR_2 does not forward the multicast ping packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 18
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ping packet with global scope to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 19: ROUTER sends an ICMPv6 Echo Request with global scope and link-local address as source.");
|
||||
|
||||
/**
|
||||
* Step 19
|
||||
* - Device: ROUTER
|
||||
* - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request with global scope (address
|
||||
* ff0e::…) , encapsulated in an MPL packet. The source address is chosen as the link-local address (fe80::...).
|
||||
* This implies that the encapsulated packet must never be forwarded. Note: this can be implemented in OT CLI
|
||||
* using ping -I <srcaddr>
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
router.SendEchoRequest(globalMcast, kEchoIdentifier, kEchoPayloadSize, 64,
|
||||
&router.Get<Mle::Mle>().GetLinkLocalAddress());
|
||||
nexus.AdvanceTime(kStabilizationTime);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 20: BR_1 does not forward the multicast ping packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 20
|
||||
* - Device: BR_1
|
||||
* - Description: Does not forward the multicast ping packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_1:
|
||||
* - The DUT MUST NOT forward the multicast ping packet with global scope to the LAN.
|
||||
*/
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
Log("Step 21: BR_2 does not forward the multicast ping packet to the LAN.");
|
||||
|
||||
/**
|
||||
* Step 21
|
||||
* - Device: BR_2
|
||||
* - Description: Does not forward the multicast ping packet to the LAN.
|
||||
* - Pass Criteria:
|
||||
* - For DUT = BR_2:
|
||||
* - The DUT MUST NOT forward the multicast ping packet with global scope to the LAN.
|
||||
*/
|
||||
|
||||
nexus.SaveTestInfo("test_1_2_MATN_TC_7.json");
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::Nexus::TestMatnTc7();
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2026, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add the current directory to sys.path to find verify_utils
|
||||
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(CUR_DIR)
|
||||
|
||||
import verify_utils
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
|
||||
def verify(pv):
|
||||
# 5.10.6 MATN-TC-07: Default BR multicast forwarding
|
||||
#
|
||||
# 5.10.6.1 Topology
|
||||
# - BR_1
|
||||
# - BR_2
|
||||
# - ROUTER
|
||||
#
|
||||
# 5.10.6.2 Purpose & Description
|
||||
# Verify if the default forwarding of multicast on a Primary BBR is correct. Note: this can be changed by
|
||||
# forwarding flags of the BBR; however, this is application specific and change is not tested. This test case
|
||||
# also verifies that a Secondary BBR does not forward multicast packets to the backbone link.
|
||||
#
|
||||
# Spec Reference | V1.2 Section | V1.3.0 Section
|
||||
# -----------------|--------------|---------------
|
||||
# Multicast | 5.10.6 | N/A
|
||||
|
||||
pkts = pv.pkts
|
||||
vars = pv.vars
|
||||
|
||||
# Step 0
|
||||
# - Device: N/A
|
||||
# - Description: Topology formation - BR_1, BR_2, ROUTER
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 0: Topology formation - BR_1, BR_2, ROUTER")
|
||||
|
||||
# Step 1
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to send an ICMPv6 Echo (ping) Request packet with realm-local scope
|
||||
# MA5.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 1: ROUTER sends an ICMPv6 Echo (ping) Request packet with realm-local scope MA5.")
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['MA5']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 2 & 3
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: Does not forward the multicast ping request packet to the LAN.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST NOT forward the multicast ICMPv6 Echo (ping) Request packet with realm-local scope address
|
||||
# MA5 to the LAN.
|
||||
print("Step 2 & 3: BR_1 and BR_2 do not forward the multicast ping request packet to the LAN.")
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['MA5']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
# Step 4
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to sends an ICMPv6 Echo (ping) Request packet with admin-local scope
|
||||
# (address ff04::…), encapsulated in an MPL packet.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 4: ROUTER sends an ICMPv6 Echo Request with admin-local scope, encapsulated in an MPL packet.")
|
||||
pkts_copy = pkts.copy()
|
||||
pkts_copy.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['ADMIN_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 5 & 6
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: BR_1 automatically forwards the ping request packet to the LAN. BR_2 does not.
|
||||
# - Pass Criteria:
|
||||
# - BR_1 MUST forward the multicast ICMPv6 Echo (ping) Request packet with admin-local scope to the LAN.
|
||||
# - BR_2 MUST NOT forward it.
|
||||
print("Step 5 & 6: BR_1 forwards the ping request to the LAN; BR_2 does not.")
|
||||
# Check that it is forwarded to the LAN by BR_1.
|
||||
# Note: MPL retransmissions may cause multiple copies on the LAN from the same BR.
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.eth.src == vars['BR_1_ETH']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['ADMIN_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Check that BR_2 does NOT forward it.
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.eth.src == vars['BR_2_ETH']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['ADMIN_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
if pkts.index < pkts_copy.index:
|
||||
pkts.index = pkts_copy.index
|
||||
|
||||
# Step 7
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request packet with site-local scope
|
||||
# (address ff05::…), encapsulated in an MPL packet.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 7: ROUTER sends an ICMPv6 Echo Request with site-local scope, encapsulated in an MPL packet.")
|
||||
pkts_copy = pkts.copy()
|
||||
pkts_copy.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['SITE_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 8 & 9
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: BR_1 automatically forwards the ping request packet to the LAN. BR_2 does not.
|
||||
print("Step 8 & 9: BR_1 forwards the ping request to the LAN; BR_2 does not.")
|
||||
# Check that it is forwarded to the LAN by BR_1.
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.eth.src == vars['BR_1_ETH']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['SITE_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Check that BR_2 does NOT forward it.
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.eth.src == vars['BR_2_ETH']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['SITE_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
if pkts.index < pkts_copy.index:
|
||||
pkts.index = pkts_copy.index
|
||||
|
||||
# Step 10
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request packet with global scope
|
||||
# (address ff0e::…) , encapsulated in an MPL packet.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 10: ROUTER sends an ICMPv6 Echo Request with global scope, encapsulated in an MPL packet.")
|
||||
pkts_copy = pkts.copy()
|
||||
pkts_copy.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 11 & 12
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: BR_1 automatically forwards the ping request packet to the LAN. BR_2 does not.
|
||||
print("Step 11 & 12: BR_1 forwards the ping request to the LAN; BR_2 does not.")
|
||||
# Check that it is forwarded to the LAN by BR_1.
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.eth.src == vars['BR_1_ETH']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Check that BR_2 does NOT forward it.
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.eth.src == vars['BR_2_ETH']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
if pkts.index < pkts_copy.index:
|
||||
pkts.index = pkts_copy.index
|
||||
|
||||
# Step 13
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request packet with link-local scope
|
||||
# (address ff02::…).
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 13: ROUTER sends an ICMPv6 Echo (ping) Request packet with link-local scope.")
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['LINK_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 14 & 15
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: Does not forward the multicast ping packet to the LAN.
|
||||
print("Step 14 & 15: BR_1 and BR_2 do not forward the multicast ping packet to the LAN.")
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['LINK_LOCAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
# Step 16
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request with global scope (address
|
||||
# ff0e::…) , encapsulated in an MPL packet. The source address is chosen as the ML-EID.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 16: ROUTER sends an ICMPv6 Echo Request with global scope and ML-EID as source.")
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.src == vars['ROUTER_MLEID'] or p.ipv6inner.src == vars['ROUTER_MLEID']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 17 & 18
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: Does not forward the multicast ping packet to the LAN.
|
||||
print("Step 17 & 18: BR_1 and BR_2 do not forward the multicast ping packet to the LAN.")
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.ipv6.src == vars['ROUTER_MLEID'] or p.ipv6inner.src == vars['ROUTER_MLEID']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
# Step 19
|
||||
# - Device: ROUTER
|
||||
# - Description: Harness instructs the device to send a ICMPv6 Echo (ping) Request with global scope (address
|
||||
# ff0e::…) , encapsulated in an MPL packet. The source address is chosen as the link-local address (fe80::...).
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 19: ROUTER sends an ICMPv6 Echo Request with global scope and link-local address as source.")
|
||||
pkts.filter_ping_request().\
|
||||
filter(lambda p: p.wpan).\
|
||||
filter(lambda p: p.ipv6.src == vars['ROUTER_LLA'] or p.ipv6inner.src == vars['ROUTER_LLA']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_next()
|
||||
|
||||
# Step 20 & 21
|
||||
# - Device: BR_1, BR_2
|
||||
# - Description: Does not forward the multicast ping packet to the LAN.
|
||||
print("Step 20 & 21: BR_1 and BR_2 do not forward the multicast ping packet to the LAN.")
|
||||
pkts.copy().\
|
||||
filter_ping_request().\
|
||||
filter(lambda p: not p.wpan).\
|
||||
filter(lambda p: p.ipv6.src == vars['ROUTER_LLA'] or p.ipv6inner.src == vars['ROUTER_LLA']).\
|
||||
filter(lambda p: p.ipv6.dst == Ipv6Addr(vars['GLOBAL_MCAST']) or\
|
||||
p.ipv6.dst == 'ff03::fc').\
|
||||
must_not_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
verify_utils.run_main(verify)
|
||||
Reference in New Issue
Block a user