/* * 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 #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 = 20 * 1000; /** * Time to advance for a node to join as a child and upgrade to a router, in milliseconds. */ static constexpr uint32_t kJoinNetworkTime = 300 * 1000; /** * Time to advance for the BR to perform automatic actions (RA, Network Data), in milliseconds. */ static constexpr uint32_t kBrActionTime = 100 * 1000; /** * Longer time to advance for network stabilization and address configuration. */ static constexpr uint32_t kLongActionTime = 500 * 1000; /** * Time to advance for the ping response, in milliseconds. */ static constexpr uint32_t kPingResponseTime = 100 * 1000; /** * Default Hop Limit for Echo Request. */ static constexpr uint8_t kDefaultHopLimit = 64; /** * Infrastructure interface index. */ static constexpr uint32_t kInfraIfIndex = 1; /** * Echo Request identifier. */ static constexpr uint16_t kEchoIdentifier = 0x1234; /** * Echo Request payload size. */ static constexpr uint16_t kEchoPayloadSize = 10; /** * Max number of seconds to wait for a condition. */ static constexpr uint32_t kMaxWaitTime = 120; /** * OMR prefix 3 string (numerically very low to be "winning"). */ static constexpr char kOmr3PrefixStr[] = "fd00:3::/64"; /** * OMR prefix 4 string (numerically very high to be "losing" if same preference). */ static constexpr char kOmr4PrefixStr[] = "fdff:4::/64"; /** * Infrastructure GUA address string for Eth_1. */ static constexpr char kEth1GuaAddrStr[] = "2001:db8:1::1"; /** * Infrastructure GUA prefix string. */ static constexpr char kGua1PrefixStr[] = "2001:db8:1::/64"; static void DumpNetworkData(Node &aNode) { NetworkData::Iterator iterator = NetworkData::kIteratorInit; NetworkData::OnMeshPrefixConfig prefixConfig; NetworkData::ExternalRouteConfig routeConfig; Log("Network Data for %s (Version: %d):", aNode.GetName(), aNode.Get().GetVersion(NetworkData::kFullSet)); while (aNode.Get().GetNext(iterator, prefixConfig) == kErrorNone) { Log(" Prefix: %s (pref:%d, preferred:%s)", prefixConfig.GetPrefix().ToString().AsCString(), prefixConfig.mPreference, ToYesNo(prefixConfig.mPreferred)); } iterator = NetworkData::kIteratorInit; while (aNode.Get().GetNext(iterator, routeConfig) == kErrorNone) { Log(" Route: %s (pref:%d)", routeConfig.GetPrefix().ToString().AsCString(), routeConfig.mPreference); } } static bool HasNetDataPrefix(Node &aNode, const Ip6::Prefix &aPrefix) { return aNode.Get().ContainsOmrPrefix(aPrefix); } static bool HasNetDataRoute(Node &aNode, const char *aPrefixStr) { bool hasRoute = false; NetworkData::Iterator iterator = NetworkData::kIteratorInit; NetworkData::ExternalRouteConfig routeConfig; Ip6::Prefix target; SuccessOrQuit(target.FromString(aPrefixStr)); while (aNode.Get().GetNext(iterator, routeConfig) == kErrorNone) { if (AsCoreType(&routeConfig.mPrefix) == target) { hasRoute = true; break; } } return hasRoute; } static void WaitForPrefix(Core &aNexus, Node &aNode, const Ip6::Prefix &aPrefix, bool aPresent) { for (uint32_t i = 0; i < kMaxWaitTime; i++) { if (HasNetDataPrefix(aNode, aPrefix) == aPresent) { break; } aNexus.AdvanceTime(1000); } VerifyOrQuit(HasNetDataPrefix(aNode, aPrefix) == aPresent); } static void WaitForRoute(Core &aNexus, Node &aNode, const char *aPrefixStr, bool aPresent) { for (uint32_t i = 0; i < kMaxWaitTime; i++) { if (HasNetDataRoute(aNode, aPrefixStr) == aPresent) { break; } aNexus.AdvanceTime(1000); } VerifyOrQuit(HasNetDataRoute(aNode, aPrefixStr) == aPresent); } static void PublishOmrPrefix(Node &aNode, const Ip6::Prefix &aPrefix, NetworkData::RoutePreference aPreference, bool aIsPreferred) { NetworkData::OnMeshPrefixConfig config; config.Clear(); config.GetPrefix() = aPrefix; config.mPreference = aPreference; config.mSlaac = true; config.mOnMesh = true; config.mStable = true; config.mPreferred = aIsPreferred; SuccessOrQuit(aNode.Get().PublishOnMeshPrefix(config, NetworkData::Publisher::kFromUser)); } void Test_1_3_DBR_TC_8(void) { /** * 1.8. [1.3] [CERT] Reachability - Multiple BRs - Single Thread / Single IPv6 Infrastructure - OMR prefix selection * * 1.8.1. Purpose * - To test the following: * - Maintain bi-directional reachability between Thread devices and infrastructure devices during prefix changes * - DUT BR should observe proper OMR prefix selection when testbed-BR advertises various other prefixes: * - Testbed advertises a winning prefix with equal preference, DUT should withdraw or deprecate its OMR prefix * - Testbed advertises a numerically higher, non-winning prefix with equal preference, DUT should not change * behavior. * - Testbed advertises a numerically higher prefix with higher preference, i.e. winning OMR prefix, DUT should * withdraw its OMR prefix. * - Testbed withdraws winning OMR prefix, DUT should advertise its prefix with 'Low' preference again * - Testbed OMR prefix becomes deprecated, DUT should advertise its prefix with 'Low' preference again * * 1.8.2. Topology * - Eth_1 - Adjacent Infrastructure Link Reference Device * - BR_1 (DUT) - Border Router * - BR_2 - Border Router Reference Device and Leader * - ED_1 - Thread Reference Device (End Device) attached to BR_1 * * Spec Reference | V1.1 Section | V1.3.0 Section * -----------------|--------------|--------------- * Reachability | N/A | 1.3 */ Core nexus; Node ð1 = nexus.CreateNode(); Node &br1 = nexus.CreateNode(); Node &br2 = nexus.CreateNode(); Node &ed1 = nexus.CreateNode(); eth1.SetName("Eth_1"); br1.SetName("BR_1"); br2.SetName("BR_2"); ed1.SetName("ED_1"); nexus.AdvanceTime(0); SuccessOrQuit(Instance::SetGlobalLogLevel(kLogLevelNote)); Log("---------------------------------------------------------------------------------------"); /** * Step 0 * - Device: Eth_1 * - Description (DBR-1.8): * - Harness configures Ethernet link with an on-link IPv6 GUA prefix GUA_1. Eth_1 is configured to multicast ND * RAs. * - Automatically configures a global address “Eth_1 GUA”. * - Pass Criteria * - N/A */ Log("Step 0: Eth_1 configured with GUA_1."); Ip6::Address eth1Gua; SuccessOrQuit(eth1Gua.FromString(kEth1GuaAddrStr)); eth1.mInfraIf.AddAddress(eth1Gua); Ip6::Prefix gua1; SuccessOrQuit(gua1.FromString(kGua1PrefixStr)); eth1.mInfraIf.StartRouterAdvertisement(gua1); nexus.AddTestVar("ETH_1_GUA_ADDR", kEth1GuaAddrStr); Log("---------------------------------------------------------------------------------------"); /** * Step 1 * - Device: Eth_1, BR_2, ED_1, ED_2 * - Description (DBR-1.8): * - Enable; BR_2 automatically configures an OMR prefix for the mesh, OMR_1. Harness records the value of OMR_1 * and saves it for verification use. * - Note: the OT command ‘br omrprefix’ should provide the prefix from BR_2. * - Form topology. Wait for BR_2 to: * - Become Leader * - Register as border router in Thread Network Data with its OMR prefix OMR_1 * - Send multicast ND RAs on AIL * - Automatically advertise a route to GUA_1 in the Thread Network Data, using a Prefix TLV: * - Prefix = ::/0 * - Domain ID = * - Has Route sub-TLV * - Pass Criteria * - N/A */ Log("Step 1: BR_2 becomes Leader and registers OMR_1."); AllowLinkBetween(br1, br2); AllowLinkBetween(br1, ed1); br2.Form(); nexus.AdvanceTime(kFormNetworkTime); br2.Get().Init(kInfraIfIndex, true); br2.Get().Init(); SuccessOrQuit(br2.Get().SetEnabled(true)); nexus.AdvanceTime(kBrActionTime); WaitForRoute(nexus, br2, "::/0", true); Ip6::Prefix omr1; SuccessOrQuit(br2.Get().GetOmrPrefix(omr1)); nexus.AddTestVar("OMR_1_PREFIX", omr1.ToString().AsCString()); Log("OMR_1_PREFIX: %s", omr1.ToString().AsCString()); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 2 * - Device: BR_1 (DUT) * - Description (DBR-1.8): Enable: switch on. * - Pass Criteria * - N/A */ Log("Step 2: Enable BR_1 (DUT)."); br1.Join(br2); nexus.AdvanceTime(kJoinNetworkTime); br1.Get().Init(kInfraIfIndex, true); br1.Get().Init(); SuccessOrQuit(br1.Get().SetEnabled(true)); Log("---------------------------------------------------------------------------------------"); /** * Step 3 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically registers itself as a border router in the Thread Network Data. * - Pass Criteria: * - The DUT MUST register a route to GUA_1 in the Thread Network Data as follows: * - Prefix TLV: Prefix = ::/0 * - Domain ID = * - Has Route sub-TLV * - R_preference = 00 (medium) or 11 (low) * - DUT MUST NOT register an OMR prefix (e.g. OMR_1, or other) in Thread Network Data. */ Log("Step 3: BR_1 (DUT) registers route to GUA_1."); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 4 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically announces the route to OMR_1 on the AIL. * - Pass Criteria: * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST contain a Route Information Option (RIO) with OMR_1. * - "Prf" bits MUST be 00 (medium) or 11 (low) */ Log("Step 4: BR_1 (DUT) announces OMR_1 on AIL."); nexus.AdvanceTime(kBrActionTime); Log("---------------------------------------------------------------------------------------"); /** * Step 5 * - Device: BR_2 * - Description (DBR-1.8): * - Harness instructs device to remove the existing OMR prefix (OMR_1) being advertised and send out new network * data without any prefix. * - Note: for 1.3.x cert, this could be implemented by 'br disable' or 'netdata unpublish ' on BR_2. * - Pass Criteria: * - N/A */ Log("Step 5: BR_2 removes OMR_1."); SuccessOrQuit(br2.Get().SetEnabled(false)); WaitForPrefix(nexus, br2, omr1, false); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 6 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically chooses a new OMR prefix OMR_2 and includes it in the Network Data. * - Pass Criteria: * - The DUT MUST register a new OMR prefix (OMR_2) in the Thread Network Data using Prefix TLV as follows: * - Prefix = OMR_2 * - Border Router sub-TLV * - P_preference = 11 (Low) * - P_default = true * - P_stable = true * - P_on_mesh = true * - P_preferred = true * - P_slaac = true * - P_dhcp = false * - P_dp = false * - OMR_2 MUST be 64 bits long and start with 0xFD. * - OMR_2 MUST differ from OMR_1. * - Also MUST contain a Prefix TLV as follows: * - Prefix = ::/0 * - Domain ID * - Has Route TLV * - R_preference = 00 (medium) or 11 (low) * - Note: one possible way to check this is to verify the contents of the SVR_DATA.ntf message sent by DUT to * Leader. */ Log("Step 6: BR_1 (DUT) chooses OMR_2 and registers in Network Data."); nexus.AdvanceTime(kBrActionTime); Ip6::Prefix omr2; SuccessOrQuit(br1.Get().GetOmrPrefix(omr2)); VerifyOrQuit(omr2 != omr1); nexus.AddTestVar("OMR_2_PREFIX", omr2.ToString().AsCString()); Log("OMR_2_PREFIX: %s", omr2.ToString().AsCString()); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 7 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically multicasts ND RAs on Adjacent Infrastructure Link. * - Pass Criteria: * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST contain a Route Information Option (RIO) with OMR_2. * - "Prf" bits MUST be 00 (medium) or 11 (low). * - MUST NOT contain a Route Information Option (RIO) with OMR_1. */ Log("Step 7: BR_1 (DUT) multicasts ND RA with OMR_2, no OMR_1."); nexus.AdvanceTime(kBrActionTime); Log("---------------------------------------------------------------------------------------"); /** * Step 8 * - Device: Eth_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to ED_1 via either one of BR_1 or BR_2. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_2) * - Pass Criteria: * - Eth_1 receives an ICMPv6 Echo Reply from ED_1. * - IPv6 Source: ED_1 OMR (using prefix OMR_2) * - IPv6 Destination: Eth_1 GUA */ Log("Step 8: Eth_1 pings ED_1 OMR_2."); ed1.Join(br1, Node::kAsFed); nexus.AdvanceTime(kJoinNetworkTime); const Ip6::Address &ed1Omr2 = ed1.FindMatchingAddress(omr2.ToString().AsCString()); nexus.AddTestVar("ED_1_OMR_2_ADDR", ed1Omr2.ToString().AsCString()); eth1.mInfraIf.SendEchoRequest(eth1Gua, ed1Omr2, kEchoIdentifier, kEchoPayloadSize); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 9 * - Device: ED_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to Eth_1. * - IPv6 Source: ED_1 OMR address (using prefix OMR_2) * - IPv6 Destination: Eth_1 GUA * - Pass Criteria: * - ED_1 receives an ICMPv6 Echo Reply from Eth_1. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_2) */ Log("Step 9: ED_1 OMR_2 pings Eth_1 GUA."); ed1.SendEchoRequest(eth1Gua, kEchoIdentifier, kEchoPayloadSize, kDefaultHopLimit, &ed1Omr2); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 10 * - Device: BR_2 * - Description (DBR-1.8): * - Harness instructs BR_2 to add an OMR prefix OMR_3 numerically lower than OMR_2, but with same preference * "Low". * - Note: can use OT command 'netdata publish prefix' for this. * - Pass Criteria: * - N/A */ Log("Step 10: BR_2 adds OMR_3."); Ip6::Prefix omr3; SuccessOrQuit(omr3.FromString(kOmr3PrefixStr)); PublishOmrPrefix(br2, omr3, NetworkData::kRoutePreferenceLow, true); nexus.AdvanceTime(kLongActionTime); WaitForPrefix(nexus, br2, omr3, true); DumpNetworkData(br2); nexus.AddTestVar("OMR_3_PREFIX", kOmr3PrefixStr); Log("OMR_3_PREFIX: %s", kOmr3PrefixStr); Log("---------------------------------------------------------------------------------------"); /** * Step 11 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically withdraws its own OMR prefix OMR_2 from the Thread Network Data. * - Pass Criteria: * - The DUT MUST register new Network Data: * - MUST NOT contain any of the OMR prefixes OMR_1, OMR_2, or OMR_3 in a Prefix TLV. * - MUST contain a Prefix TLV: * - Prefix = ::/0 * - Domain ID * - Has Route TLV * - R_preference = 00 (medium) or 11 (low) */ Log("Step 11: BR_1 (DUT) withdraws OMR_2 from Network Data."); WaitForPrefix(nexus, br2, omr2, false); nexus.AdvanceTime(kLongActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 12 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically multicasts ND RAs on Adjacent Infrastructure Link including OMR_2/OMR_3. * - Note: the reason that OMR_2 is still included initially, is that OMR_2 has been created by BR_1 originally * and as seen by BR_1, it stays in a deprecated state for at most OMR_ADDR_DEPRECATION_TIME * - Pass Criteria: * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST NOT contain a Route Information Option (RIO) with OMR_1. * - MUST contain a Route Information Option (RIO) with OMR_2. * - "Prf" bits MUST be 00 (medium) or 11 (low) * - MUST contain a Route Information Option (RIO) with OMR_3. * - "Prf" bits MUST be 00 (medium) or 11 (low) */ Log("Step 12: BR_1 (DUT) multicasts ND RA with OMR_2 and OMR_3."); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br1); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 13 * - Device: Eth_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to ED_1 via BR_1 or BR_2. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_3) * - Pass Criteria: * - Eth_1 receives an ICMPv6 Echo Reply from ED_1. * - IPv6 Source: ED_1 OMR (using prefix OMR_3) * - IPv6 Destination: Eth_1 GUA */ Log("Step 13: Eth_1 pings ED_1 OMR_3."); const Ip6::Address &ed1Omr3 = ed1.FindMatchingAddress(kOmr3PrefixStr); nexus.AddTestVar("ED_1_OMR_3_ADDR", ed1Omr3.ToString().AsCString()); eth1.mInfraIf.SendEchoRequest(eth1Gua, ed1Omr3, kEchoIdentifier, kEchoPayloadSize); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 14 * - Device: ED_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to Eth_1. * - IPv6 Source: ED_1 OMR address (using prefix OMR_3) * - IPv6 Destination: Eth_1 GUA * - Pass Criteria: * - ED_1 receives an ICMPv6 Echo Reply from Eth_1. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_3) */ Log("Step 14: ED_1 OMR_3 pings Eth_1 GUA."); ed1.SendEchoRequest(eth1Gua, kEchoIdentifier, kEchoPayloadSize, kDefaultHopLimit, &ed1Omr3); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 15 * - Device: BR_2 * - Description (DBR-1.8): * - Harness instructs device to remove existing OMR prefix (OMR_3) that is being advertised and sends out new * network data without the prefix OMR_3. * - Note: can use OT command 'netdata unpublish ' for this. * - Pass Criteria: * - N/A */ Log("Step 15: BR_2 removes OMR_3."); SuccessOrQuit(br2.Get().UnpublishPrefix(omr3)); WaitForPrefix(nexus, br2, omr3, false); nexus.AdvanceTime(kLongActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 16 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically starts advertising its own OMR prefix OMR_2 again. * - Pass Criteria: * - The DUT MUST register its OMR prefix OMR_2 in the Thread Network Data. Flags in the Border Router sub-TLV * MUST be: * - P_preference = 11 (Low) * - P_default = true * - P_stable = true * - P_on_mesh = true * - P_preferred = true * - P_slaac = true * - P_dhcp = false * - P_dp = false * - OMR_2 MUST be 64 bits long and start with 0xFD. * - OMR_2 MUST be equal to the OMR_2 values as used in previous test steps. */ Log("Step 16: BR_1 (DUT) re-registers OMR_2."); WaitForPrefix(nexus, br2, omr2, true); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 17 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically multicasts ND RAs on Adjacent Infrastructure Link with OMR_2. * - Note: the reason that OMR_3 is not advertised, is that OMR_3 was withdrawn and was not originally created by * BR_1. So BR_1 has no responsibility to advertise this deprecated prefix. * - Pass Criteria: * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST NOT contain a Route Information Option (RIO) with OMR_1. * - MUST contain a Route Information Option (RIO) with OMR_2. * - "Prf" bits MUST be 00 (medium) or 11 (low) * - MUST NOT contain a Route Information Option (RIO) with OMR_3. */ Log("Step 17: BR_1 (DUT) multicasts ND RA with OMR_2, no OMR_3."); nexus.AdvanceTime(kBrActionTime); Log("---------------------------------------------------------------------------------------"); /** * Step 18 * - Device: BR_2 * - Description (DBR-1.8): * - Harness instructs the device to add new OMR prefix (OMR_4) numerically higher than OMR_2, but with same * preference "Low". * - Pass Criteria: * - N/A */ Log("Step 18: BR_2 adds OMR_4."); Ip6::Prefix omr4; SuccessOrQuit(omr4.FromString(kOmr4PrefixStr)); PublishOmrPrefix(br2, omr4, NetworkData::kRoutePreferenceLow, true); WaitForPrefix(nexus, br2, omr4, true); nexus.AdvanceTime(kLongActionTime); nexus.AddTestVar("OMR_4_PREFIX", kOmr4PrefixStr); Log("OMR_4_PREFIX: %s", kOmr4PrefixStr); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 19 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - No change in behavior for advertising its OMR prefix, OMR_2. * - Automatically starts advertising a route for the new OMR_4 prefix. * - Pass Criteria: * - The DUT MUST NOT send a Network Data update with any one of the following prefixes in a Prefix TLV: * - OMR_1, OMR_2, OMR_3, OMR_4 * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST contain a Route Information Option (RIO) with OMR_2. * - "Prf" bits MUST be 00 (medium) or 11 (low). * - MUST contain a Route Information Option (RIO) with OMR_4. * - "Prf" bits MUST be 00 (medium) or 11 (low). * - MUST NOT contain RIO with any one of OMR_1, OMR_3. */ Log("Step 19: BR_1 (DUT) continues OMR_2, adds OMR_4 on AIL."); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 20 * - Device: BR_2 * - Description (DBR-1.8): * - Harness instructs the device to update the numerically higher OMR_4 with a higher preference value 00 * ('Medium'). * - Pass Criteria: * - N/A */ Log("Step 20: BR_2 updates OMR_4 to Medium pref."); PublishOmrPrefix(br2, omr4, NetworkData::kRoutePreferenceMedium, true); nexus.AdvanceTime(kLongActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 21 * - Device: BR_1 (DUT) * - Description (DBR-1.8): Automatically withdraws its current OMR prefix OMR_2. * - Pass Criteria: * - The DUT MUST send a Network Data update. In the new network data: * - the following prefixes MUST NOT be present in a Prefix TLV: OMR_1, OMR_2, OMR_3 * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST contain a Route Information Option (RIO) with OMR_2: * - "Prf" bits MUST be 00 (medium) or 11 (low). * - MUST contain a Route Information Option (RIO) with OMR_4: * - "Prf" bits MUST be 00 (medium) or 11 (low). * - MUST NOT contain a Route Information Option (RIO) with OMR_1 or OMR_3. */ Log("Step 21: BR_1 (DUT) withdraws OMR_2."); WaitForPrefix(nexus, br2, omr2, false); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 22 * - Device: BR_2 * - Description (DBR-1.8): * - Harness instructs the device to update the prefix OMR_4 to a deprecated state by setting P_preferred = * 'false'. * - Note: can use OT command 'netdata publish prefix' for this where the flags do not contain the 'p' (Preferred) * flag. * - Pass Criteria: * - N/A */ Log("Step 22: BR_2 deprecates OMR_4."); PublishOmrPrefix(br2, omr4, NetworkData::kRoutePreferenceMedium, false); nexus.AdvanceTime(kLongActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 23 * - Device: BR_1 (DUT) * - Description (DBR-1.8): Automatically starts advertising its own OMR prefix OMR_2 again. * - Pass Criteria: * - The DUT MUST register its OMR prefix OMR_2 in the Thread Network Data. Flags in the Border Router sub-TLV * MUST be: * - P_preference = 11 (Low) * - P_default = true * - P_stable = true * - P_on_mesh = true * - P_preferred = true * - P_slaac = true * - P_dhcp = false * - P_dp = false * - OMR_2 MUST be 64 bits long and start with 0xFD. * - OMR_2 MUST be equal to the OMR_2 values as used in previous test steps. */ Log("Step 23: BR_1 (DUT) re-registers OMR_2."); WaitForPrefix(nexus, br2, omr2, true); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 24 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically multicasts ND RAs on Adjacent Infrastructure Link. * - Note: even though OMR_4 is deprecated, it is still valid so it is advertised on the AIL in a RIO. * - Pass Criteria: * - The DUT MUST multicast ND RAs on the infrastructure link: * - IPv6 destination MUST be ff02::1 * - MUST NOT contain a Prefix Information Option (PIO) with a ULA prefix. * - MUST NOT contain a Route Information Option (RIO) with OMR_1. * - MUST contain a Route Information Option (RIO) with OMR_2. * - "Prf" bits MUST be 00 (medium) or 11 (low) * - MUST NOT contain a Route Information Option (RIO) with OMR_3. * - MUST contain a Route Information Option (RIO) with OMR_4. * - "Prf" bits MUST be 00 (medium) or 11 (low) */ Log("Step 24: BR_1 (DUT) multicasts ND RA with OMR_2 and OMR_4."); nexus.AdvanceTime(kBrActionTime); Log("---------------------------------------------------------------------------------------"); /** * Step 25 * - Device: Eth_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to ED_1 via BR_1. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_2) * - Pass Criteria: * - Eth_1 receives an ICMPv6 Echo Reply from ED_1. * - IPv6 Source: ED_1 OMR (using prefix OMR_2) * - IPv6 Destination: Eth_1 GUA */ Log("Step 25: Eth_1 pings ED_1 OMR_2."); eth1.mInfraIf.SendEchoRequest(eth1Gua, ed1Omr2, kEchoIdentifier, kEchoPayloadSize); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 26 * - Device: ED_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to Eth_1. * - IPv6 Source: ED_1 OMR address (using prefix OMR_2) * - IPv6 Destination: Eth_1 GUA * - Pass Criteria: * - ED_1 receives an ICMPv6 Echo Reply from Eth_1. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_2) */ Log("Step 26: ED_1 OMR_2 pings Eth_1 GUA."); ed1.SendEchoRequest(eth1Gua, kEchoIdentifier, kEchoPayloadSize, kDefaultHopLimit, &ed1Omr2); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 27 * - Device: BR_2 * - Description (DBR-1.8): * - Harness disables the BR function of the device. Or if that is not possible, switch it off. * - Note: disabling BR may use 'br disable' CLI command. * - Note: in case of switching off BR_2, the OMR prefix OMR_4 that was advertised by BR_2 remains active for some * time. The Leader timeout of Leader BR_2 does not happen yet during the below steps of this test. * - Pass Criteria: * - N/A */ Log("Step 27: BR_2 disabled."); SuccessOrQuit(br2.Get().SetEnabled(false)); nexus.AdvanceTime(kBrActionTime); DumpNetworkData(br2); Log("---------------------------------------------------------------------------------------"); /** * Step 28 * - Device: Eth_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to ED_1 via BR_1. * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_2) * - Pass Criteria: * - Eth_1 receives an ICMPv6 Echo Reply from ED_1. * - IPv6 Source: ED_1 OMR (using prefix OMR_2) * - IPv6 Destination: Eth_1 GUA */ Log("Step 28: Eth_1 pings ED_1 OMR_2."); eth1.mInfraIf.SendEchoRequest(eth1Gua, ed1Omr2, kEchoIdentifier, kEchoPayloadSize); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 29 * - Device: ED_1 * - Description (DBR-1.8): * - Harness instructs the device to send an ICMPv6 Echo Request to Eth_1. * - IPv6 Source: ED_1 OMR address (using prefix OMR_4) * - IPv6 Destination: Eth_1 GUA. * - Note: ED_1 is forced here to use a source address based on prefix OMR_4, even though that prefix is * deprecated. In OT CLI this can most likely be achieved using the command: * - ping -I * - Pass Criteria: * - N/A */ Log("Step 29: ED_1 pings Eth_1 using OMR_4."); const Ip6::Address &ed1Omr4 = ed1.FindMatchingAddress(kOmr4PrefixStr); nexus.AddTestVar("ED_1_OMR_4_ADDR", ed1Omr4.ToString().AsCString()); ed1.SendEchoRequest(eth1Gua, kEchoIdentifier, kEchoPayloadSize, kDefaultHopLimit, &ed1Omr4); Log("---------------------------------------------------------------------------------------"); /** * Step 30 * - Device: Eth_1 * - Description (DBR-1.8): * - Automatically replies to the ICMPv6 Echo Request with Echo Reply, that is sent to BR_1. * - Pass Criteria: * - N/A */ Log("Step 30: Eth_1 replies to OMR_4."); nexus.AdvanceTime(kPingResponseTime); Log("---------------------------------------------------------------------------------------"); /** * Step 31 * - Device: BR_1 (DUT) * - Description (DBR-1.8): * - Automatically attempts to deliver the Echo Reply to a node on the mesh. * - Pass Criteria: * - The DUT MUST attempt to deliver the packet to a node on the mesh, either: * - 1. BR_1 sends a multicast Address Query for ED_1 OMR_4 based address into the mesh; * - 2. or ED_1 receives the Echo Reply from Eth_1 as follows: * - IPv6 Source: Eth_1 GUA * - IPv6 Destination: ED_1 OMR address (using prefix OMR_4) */ Log("Step 31: BR_1 delivers Echo Reply for OMR_4."); nexus.AdvanceTime(kPingResponseTime); nexus.SaveTestInfo("test_1_3_DBR_TC_8.json"); } } // namespace Nexus } // namespace ot int main(void) { ot::Nexus::Test_1_3_DBR_TC_8(); printf("All tests passed\n"); return 0; }