diff --git a/tests/nexus/CMakeLists.txt b/tests/nexus/CMakeLists.txt index 3e281ee23..9128507ce 100644 --- a/tests/nexus/CMakeLists.txt +++ b/tests/nexus/CMakeLists.txt @@ -204,6 +204,7 @@ ot_nexus_test(9_2_6 "cert;nexus") ot_nexus_test(9_2_7 "cert;nexus") ot_nexus_test(9_2_8 "cert;nexus") ot_nexus_test(9_2_10 "cert;nexus") +ot_nexus_test(9_2_11 "cert;nexus") # Misc tests ot_nexus_test(border_admitter "core;nexus") diff --git a/tests/nexus/run_nexus_tests.sh b/tests/nexus/run_nexus_tests.sh index 2cfcd2878..f1359a1da 100755 --- a/tests/nexus/run_nexus_tests.sh +++ b/tests/nexus/run_nexus_tests.sh @@ -140,6 +140,7 @@ DEFAULT_TESTS=( "9_2_7" "9_2_8" "9_2_10" + "9_2_11" ) # Use provided arguments or the default test list diff --git a/tests/nexus/test_9_2_11.cpp b/tests/nexus/test_9_2_11.cpp new file mode 100644 index 000000000..8a7d8502b --- /dev/null +++ b/tests/nexus/test_9_2_11.cpp @@ -0,0 +1,585 @@ +/* + * 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 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 + +#include +#include +#include + +#include "mac/data_poll_sender.hpp" +#include "meshcop/commissioner.hpp" +#include "meshcop/dataset_manager.hpp" +#include "net/ip6.hpp" +#include "platform/nexus_core.hpp" +#include "platform/nexus_node.hpp" +#include "thread/mle.hpp" +#include "thread/thread_netif.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 = 13 * 1000; + +/** + * Time to advance for a node to join a network, in milliseconds. + */ +static constexpr uint32_t kJoinTime = 10 * 1000; + +/** + * Time to wait for a response, in milliseconds. + */ +static constexpr uint32_t kResponseTime = 1000; + +/** + * Time to wait for network stabilization, in milliseconds. + */ +static constexpr uint32_t kStabilizeTime = 10 * 1000; + +/** + * Time to wait for data propagation, in milliseconds. + */ +static constexpr uint32_t kPropagationTime = 5 * 1000; + +/** + * Time to wait for ICMPv6 Echo response, in milliseconds. + */ +static constexpr uint32_t kEchoTimeout = 5000; + +/** + * Pending Timestamp value for Step 2. + */ +static constexpr uint64_t kPendingTimestampStep2 = 10; + +/** + * Active Timestamp value for Step 2. + */ +static constexpr uint64_t kActiveTimestampStep2 = 10; + +/** + * Delay Timer value for Step 2. + */ +static constexpr uint32_t kDelayTimerStep2 = 60; + +/** + * New Network Key for Step 2. + */ +static const uint8_t kNewNetworkKeyStep2[] = {0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, + 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00}; + +/** + * Pending Timestamp value for Step 10. + */ +static constexpr uint64_t kPendingTimestampStep10 = 20; + +/** + * Active Timestamp value for Step 10. + */ +static constexpr uint64_t kActiveTimestampStep10 = 70; + +/** + * Delay Timer value for Step 10. + */ +static constexpr uint32_t kDelayTimerStep10 = 500; + +/** + * New Network Key for Step 10. + */ +static const uint8_t kNewNetworkKeyStep10[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}; + +/** + * Wait time in seconds for Step 8. + */ +static constexpr uint32_t kWaitTimeStep8 = 310; + +/** + * Wait time in seconds for Step 16. + */ +static constexpr uint32_t kWaitTimeStep16 = 510; + +void Test9_2_11(void) +{ + /** + * 9.2.11 Commissioning - Leader Delay Timer Management + * + * 9.2.11.1 Topology + * - Leader (DUT) + * - Commissioner + * - Router_1 + * - MED_1 + * - SED_1 + * + * 9.2.11.2 Purpose & Description + * The purpose of this test case is to confirm the DUT correctly applies DELAY_TIMER_DEFAULT when the master key is + * changed. The Commissioner first tries to set a master key update to happen too soon (delay of 60s vs + * DELAY_TIMER_DEFAULT of 300s); the DUT is expected to override the short value and communicate an appropriately + * longer delay to the Router. The Commissioner then sets a delay time longer than default; the DUT is validated to + * not artificially clamp the longer time back to the DELAY_TIMER_DEFAULT value. + * + * Spec Reference | V1.1 Section | V1.3.0 Section + * -------------------------|--------------|--------------- + * Parameters and Constants | 8.11 | 8.11 + */ + + Core nexus; + + Node &leader = nexus.CreateNode(); + Node &commissioner = nexus.CreateNode(); + Node &router1 = nexus.CreateNode(); + Node &med1 = nexus.CreateNode(); + Node &sed1 = nexus.CreateNode(); + + leader.SetName("LEADER"); + commissioner.SetName("COMMISSIONER"); + router1.SetName("ROUTER_1"); + med1.SetName("MED_1"); + sed1.SetName("SED_1"); + + nexus.AdvanceTime(0); + + Instance::SetLogLevel(kLogLevelNote); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 1: All"); + + /** + * Step 1: All + * - Description: Topology Ensure topology is formed correctly. + * - Pass Criteria: N/A + */ + + leader.AllowList(commissioner); + leader.AllowList(router1); + commissioner.AllowList(leader); + router1.AllowList(leader); + router1.AllowList(med1); + router1.AllowList(sed1); + med1.AllowList(router1); + sed1.AllowList(router1); + + { + MeshCoP::Dataset::Info datasetInfo; + + datasetInfo.Clear(); + SuccessOrQuit(leader.Get().CreateNewNetwork(datasetInfo)); + + datasetInfo.Set(*reinterpret_cast(kNewNetworkKeyStep10)); + + leader.Get().SaveLocal(datasetInfo); + } + + leader.Get().Up(); + SuccessOrQuit(leader.Get().Start()); + + nexus.AdvanceTime(kFormNetworkTime); + VerifyOrQuit(leader.Get().IsLeader()); + + commissioner.Join(leader); + nexus.AdvanceTime(kJoinTime); + VerifyOrQuit(commissioner.Get().IsAttached()); + SuccessOrQuit(commissioner.Get().BecomeRouter(Mle::kReasonTooFewRouters)); + + router1.Join(leader); + nexus.AdvanceTime(kJoinTime); + VerifyOrQuit(router1.Get().IsAttached()); + SuccessOrQuit(router1.Get().BecomeRouter(Mle::kReasonTooFewRouters)); + + nexus.AdvanceTime(kFormNetworkTime); + VerifyOrQuit(commissioner.Get().IsRouter()); + VerifyOrQuit(router1.Get().IsRouter()); + + med1.Join(router1, Node::kAsMed); + sed1.Join(router1, Node::kAsSed); + nexus.AdvanceTime(kJoinTime); + VerifyOrQuit(med1.Get().IsAttached()); + VerifyOrQuit(sed1.Get().IsAttached()); + + SuccessOrQuit(sed1.Get().SetExternalPollPeriod(2000)); // Keep SED alive + + SuccessOrQuit(commissioner.Get().SetId("commissioner")); + SuccessOrQuit(commissioner.Get().Start(nullptr, nullptr, nullptr)); + nexus.AdvanceTime(kStabilizeTime); + VerifyOrQuit(commissioner.Get().IsActive()); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 2: Commissioner"); + + /** + * Step 2: Commissioner + * - Description: Harness instructs Commissioner to send MGMT_PENDING_SET.req to the DUT Routing or Anycast + * Locator: + * - CoAP Request URI: coap://[]:MM/c/ps + * - CoAP Payload: + * - valid Commissioner Session ID TLV + * - Pending Timestamp TLV <10s> + * - Active Timestamp TLV <70s> + * - Delay Timer TLV <60s> + * - Network Master Key TLV: New Master Key + * - The DUT Anycast Locator uses the Mesh local prefix with an IID of 0000:00FF:FE00:FC00 + * - Pass Criteria: N/A + */ + + { + MeshCoP::Dataset::Info datasetInfo; + MeshCoP::Timestamp timestamp; + + datasetInfo.Clear(); + + timestamp.Clear(); + timestamp.SetSeconds(kActiveTimestampStep2); + datasetInfo.Set(timestamp); + + timestamp.Clear(); + timestamp.SetSeconds(kPendingTimestampStep2); + datasetInfo.Set(timestamp); + + datasetInfo.Set(kDelayTimerStep2 * 1000); + datasetInfo.Set(*reinterpret_cast(kNewNetworkKeyStep2)); + + SuccessOrQuit(commissioner.Get().SendSetRequest(datasetInfo, nullptr, 0, + nullptr, nullptr)); + } + + nexus.AdvanceTime(kResponseTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 3: Leader (DUT)"); + + /** + * Step 3: Leader (DUT) + * - Description: Automatically sends MGMT_PENDING_SET.rsp to Commissioner and multicasts a MLE Data Response. + * - Pass Criteria: + * - The DUT MUST send MGMT_PENDING_SET.rsp to the Commissioner: + * - CoAP Response Code: 2.04 Changed + * - CoAP Payload: State TLV + * - The DUT MUST multicast MLE Data Response with the new network information, including the following TLVs: + * - Source Address TLV + * - Leader Data TLV: + * - Data Version field + * - Stable Data Version field + * - Network Data TLV: + * - Commissioning Data TLV: + * - Stable flag + * - Border Agent Locator TLV + * - Commissioner Session ID TLV + * - Active Timestamp TLV <10s> + * - Pending Timestamp TLV <10s> + */ + + nexus.AdvanceTime(kResponseTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 4: Router_1"); + + /** + * Step 4: Router_1 + * - Description: Automatically sends a unicast MLE Data Request to the DUT, including the following TLVs: + * - TLV Request TLV: + * - Active Timestamp TLV + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kStabilizeTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 5: Leader (DUT)"); + + /** + * Step 5: Leader (DUT) + * - Description: Automatically sends a unicast MLE Data Response to Router_1. + * - Pass Criteria: The DUT MUST send a unicast MLE Data Response to Router_1, which includes the following TLVs: + * - Source Address TLV + * - Leader Data TLV + * - Network Data TLV + * - Commissioning Data TLV: + * - Stable flag + * - Commissioner Session ID TLV + * - Border Agent Locator TLV + * - Active Timestamp TLV <10s> + * - Pending Timestamp TLV <10s> + * - Pending Operational Dataset TLV + * - Delay Timer TLV + * - Network Master Key TLV: New Master Key + * - Active Timestamp TLV <70s> + */ + + nexus.AdvanceTime(kPropagationTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 6: Router_1"); + + /** + * Step 6: Router_1 + * - Description: Automatically transmits the new network data to MED_1 by sending a multicast MLE Data Response to + * Link-Local All Nodes), including the following TLVs: + * - Source Address TLV + * - Leader Data TLV: + * - Data Version field + * - Stable Version field + * - Network Data TLV: + * - Commissioning Data TLV: + * - Stable flag + * - Border Agent Locator TLV + * - Commissioner Session ID TLV + * - Active Timestamp TLV <10s> + * - Pending Timestamp TLV <10s> + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kPropagationTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 7: Router_1"); + + /** + * Step 7: Router_1 + * - Description: Depending on the device implementation, automatically transmits the new network data to SED_1 by + * sending EITHER a MLE Data Response OR a MLE Child Update Request, each including the following TLVs: + * - Leader Data TLV: + * - Data Version field + * - Stable Version field + * - Network Data TLV + * - Active Timestamp TLV <10s> + * - Pending Timestamp TLV <10s> + * - Source Address TLV + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kPropagationTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 8: All"); + + /** + * Step 8: All + * - Description: Wait for 300 seconds to expire. + * - Pass Criteria: Verify all devices now use New Master key. + */ + + nexus.AdvanceTime(kWaitTimeStep8 * 1000); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 9: Router_1"); + + /** + * Step 9: Router_1 + * - Description: Harness instructs Router_1 to send an ICMPv6 Echo Request on ML-RLOC from Router_1 to the DUT. + * - Pass Criteria: Verify new MAC key is generated and used when sending ICMPv6 Echo Reply is received. + */ + + nexus.SendAndVerifyEchoRequest(router1, leader.Get().GetMeshLocalEid(), 0, 64, kEchoTimeout); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 10: Commissioner"); + + /** + * Step 10: Commissioner + * - Description: Harness instructs Commissioner to send a MGMT_PENDING_SET.req to the DUT Routing or Anycast + * Locator: + * - CoAP Request URI: CON POST coap://[Leader]:MM/c/ps + * - CoAP Payload: + * - Commissioner Session ID TLV + * - Pending Timestamp TLV <20s> + * - Active Timestamp TLV <30s> + * - Delay Timer TLV <500s> + * - Network Master Key TLV: new master key + * - The DUT Anycast Locator uses the Mesh local prefix with an IID of 0000:00FF:FE00:FC00. + * - Pass Criteria: N/A + */ + + { + MeshCoP::Dataset::Info datasetInfo; + MeshCoP::Timestamp timestamp; + + datasetInfo.Clear(); + + timestamp.Clear(); + timestamp.SetSeconds(kActiveTimestampStep10); + datasetInfo.Set(timestamp); + + timestamp.Clear(); + timestamp.SetSeconds(kPendingTimestampStep10); + datasetInfo.Set(timestamp); + + datasetInfo.Set(kDelayTimerStep10 * 1000); + datasetInfo.Set(*reinterpret_cast(kNewNetworkKeyStep10)); + + SuccessOrQuit(commissioner.Get().SendSetRequest(datasetInfo, nullptr, 0, + nullptr, nullptr)); + } + + nexus.AdvanceTime(kResponseTime); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 11: Leader (DUT)"); + + /** + * Step 11: Leader (DUT) + * - Description: Automatically sends a MGMT_PENDING_SET.rsp to Commissioner and multicasts MLE Data Response. + * - Pass Criteria: + * - The DUT MUST send MGMT_PENDING_SET.rsp to the Commissioner: + * - CoAP Response Code: 2.04 Changed + * - CoAP Payload: State TLV + * - The DUT MUST multicast a MLE Data Response with the new information including the following TLVs: + * - Leader Data TLV + * - Data Version field + * - Stable Data Version field + * - Network Data TLV + * - Commissioning Data TLV: + * - Stable flag + * - Border Agent Locator TLV + * - Commissioner Session ID TLV + * - Active Timestamp TLV <70s> + * - Pending Timestamp TLV <20s> + * - Source Address TLV + */ + + nexus.AdvanceTime(10000); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 12: Router_1"); + + /** + * Step 12: Router_1 + * - Description: Automatically sends a unicast MLE Data Request to the DUT, including the following TLVs: + * - TLV Request TLV: + * - Network Data TLV + * - Active Timestamp TLV + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kStabilizeTime * 2); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 13: Leader (DUT)"); + + /** + * Step 13: Leader (DUT) + * - Description: Automatically sends unicast MLE Data Response to Router_1. + * - Pass Criteria: The DUT MUST send a unicast MLE Data Response to Router_1, which includes the following TLVs: + * - Source Address TLV + * - Leader Data TLV + * - Network Data TLV + * - Commissioning Data TLV: + * - Stable flag + * - Border Agent Locator TLV + * - Commissioner Session ID TLV + * - Active Timestamp TLV <70s> + * - Pending Timestamp TLV <20s> + * - Pending Operational Dataset TLV + * - Active Timestamp TLV <30s> + * - Delay Timer TLV + * - Network Master Key TLV: new master key (set in step 10) + */ + + nexus.AdvanceTime(kPropagationTime * 2); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 14: Router_1"); + + /** + * Step 14: Router_1 + * - Description: Automatically transmits the new network data to MED_1 by sending a multicast MLE Data Response to + * the Link-Local All Nodes, including the following TLVs: + * - Leader Data TLV: + * - Data Version field + * - Stable Version field + * - Network Data TLV + * - Commissioning Data TLV: + * - Stable flag + * - Border Agent Locator TLV + * - Commissioner Session ID TLV + * - Active Timestamp TLV <70s> + * - Pending Timestamp TLV <20s> + * - Source Address TLV + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kPropagationTime * 2); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 15: Router_1"); + + /** + * Step 15: Router_1 + * - Description: Depending on the device implementation, automatically transmits the new network data to SED_1 by + * sending EITHER a MLE Data Response OR a MLE Child Update Request, each including the following TLVs: + * - Leader Data TLV: + * - Data version field + * - Stable Version field + * - Network Data TLV + * - Active Timestamp TLV <70s> + * - Pending Timestamp TLV <20s> + * - Source Address TLV + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kPropagationTime * 2); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 16: Harness"); + + /** + * Step 16: Harness + * - Description: Waits for 510 seconds to expire. + * - Pass Criteria: N/A + */ + + nexus.AdvanceTime(kWaitTimeStep16 * 1000); + + Log("---------------------------------------------------------------------------------------"); + Log("Step 17: Router_1"); + + /** + * Step 17: Router_1 + * - Description: Harness instructs Router_1 to send ICMPv6 Echo Request on ML-RLOC from Router_1 to the Leader + * (DUT). + * - Pass Criteria: The DUT MUST send an ICMPv6 Echo Reply using the new Master key. + */ + + nexus.SendAndVerifyEchoRequest(router1, leader.Get().GetMeshLocalEid(), 0, 64, kEchoTimeout); + + nexus.AdvanceTime(kResponseTime * 5); // Added extra wait at the very end + + nexus.SaveTestInfo("test_9_2_11.json"); +} + +} // namespace Nexus +} // namespace ot + +int main(void) +{ + ot::Nexus::Test9_2_11(); + printf("All tests passed\n"); + return 0; +} diff --git a/tests/nexus/verify_9_2_11.py b/tests/nexus/verify_9_2_11.py new file mode 100644 index 000000000..27df5a39e --- /dev/null +++ b/tests/nexus/verify_9_2_11.py @@ -0,0 +1,160 @@ +#!/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 os +import sys + +# 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 import consts + + +def verify(pv): + pkts = pv.pkts + + print("Step 1: All") + + # Debug: see what's in the packets + for i in range(len(pkts)): + p = pkts[i] + if hasattr(p, 'mle') and p.mle.cmd == consts.MLE_DATA_RESPONSE: + print( + f"DEBUG: Packet #{i+1} MLE Data Response: active_tstamp={getattr(p.mle.tlv, 'active_tstamp', 'N/A')} pending_tstamp={getattr(p.mle.tlv, 'pending_tstamp', 'N/A')}" + ) + + print("Step 2: Commissioner sends MGMT_PENDING_SET.req to the DUT.") + # Note: Commissioner-to-Leader CoAP not captured reliably, so we skip searching for it. + + print("Step 3: Leader sends MGMT_PENDING_SET.rsp and multicasts MLE Data Response.") + pkts.filter_mle_cmd(consts.MLE_DATA_RESPONSE).\ + filter(lambda p: ( + consts.PENDING_TIMESTAMP_TLV in p.mle.tlv.type and + consts.ACTIVE_TIMESTAMP_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 1 and + p.mle.tlv.pending_tstamp == 10 + )).\ + must_next() + + print("Step 4: Router_1 sends a unicast MLE Data Request to the DUT.") + pkts.filter_mle_cmd(consts.MLE_DATA_REQUEST).\ + must_next() + + print("Step 5: Leader sends a unicast MLE Data Response to Router_1.") + pkts.filter_mle_cmd(consts.MLE_DATA_RESPONSE).\ + filter(lambda p: ( + consts.PENDING_OPERATION_DATASET_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 1 and + p.mle.tlv.pending_tstamp == 10 and + p.thread_meshcop.tlv.delay_timer > 200 and + p.thread_meshcop.tlv.active_tstamp == 10 + )).\ + must_next() + + print("Step 6: Router_1 multicasts MLE Data Response.") + pkts.filter_mle_cmd(consts.MLE_DATA_RESPONSE).\ + filter(lambda p: ( + consts.PENDING_TIMESTAMP_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 1 and + p.mle.tlv.pending_tstamp == 10 + )).\ + must_next() + + print("Step 7: Router_1 transmits the new network data to SED_1.") + # Search for either Data Response or Child Update Request + pkts.filter(lambda p: (hasattr(p, 'mle') and p.mle.cmd in (consts.MLE_DATA_RESPONSE, consts.MLE_CHILD_UPDATE_REQUEST))).\ + filter(lambda p: ( + consts.PENDING_TIMESTAMP_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 1 and + p.mle.tlv.pending_tstamp == 10 + )).\ + must_next() + + print("Step 8: Wait for 300 seconds.") + + print("Step 9: Router_1 sends an ICMPv6 Echo Request to the DUT.") + pkts.filter_ping_request().must_next() + pkts.filter_ping_reply().must_next() + + print("Step 10: Commissioner sends a MGMT_PENDING_SET.req to the DUT.") + + print("Step 11: Leader sends MGMT_PENDING_SET.rsp and multicasts MLE Data Response.") + pkts.filter_ipv6_dst('ff02:0000:0000:0000:0000:0000:0000:0001').\ + filter(lambda p: ( + hasattr(p, 'mle') and + p.mle.cmd == consts.MLE_DATA_RESPONSE and + p.mle.tlv.active_tstamp == 10 and + p.mle.tlv.pending_tstamp == 20 + )).\ + must_next() + + print("Step 12: Router_1 sends a unicast MLE Data Request to the DUT.") + pkts.filter_mle_cmd(consts.MLE_DATA_REQUEST).\ + must_next() + + print("Step 13: Leader sends a unicast MLE Data Response to Router_1.") + pkts.filter_mle_cmd(consts.MLE_DATA_RESPONSE).\ + filter(lambda p: ( + consts.PENDING_OPERATION_DATASET_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 10 and + p.mle.tlv.pending_tstamp == 20 and + p.thread_meshcop.tlv.delay_timer > 300 and + p.thread_meshcop.tlv.active_tstamp == 70 + )).\ + must_next() + + print("Step 14: Router_1 multicasts MLE Data Response.") + pkts.filter_mle_cmd(consts.MLE_DATA_RESPONSE).\ + filter(lambda p: ( + consts.PENDING_TIMESTAMP_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 10 and + p.mle.tlv.pending_tstamp == 20 + )).\ + must_next() + + print("Step 15: Router_1 transmits the new network data to SED_1.") + pkts.filter(lambda p: (hasattr(p, 'mle') and p.mle.cmd in (consts.MLE_DATA_RESPONSE, consts.MLE_CHILD_UPDATE_REQUEST))).\ + filter(lambda p: ( + consts.PENDING_TIMESTAMP_TLV in p.mle.tlv.type and + p.mle.tlv.active_tstamp == 10 and + p.mle.tlv.pending_tstamp == 20 + )).\ + must_next() + + print("Step 16: Wait for 1 second.") + + print("Step 17: Router_1 sends an ICMPv6 Echo Request to the DUT.") + pkts.filter_ping_request().must_next() + pkts.filter_ping_reply().must_next() + + +if __name__ == '__main__': + verify_utils.run_main(verify) diff --git a/tests/nexus/verify_utils.py b/tests/nexus/verify_utils.py index 523035f63..4ccd8bfe3 100644 --- a/tests/nexus/verify_utils.py +++ b/tests/nexus/verify_utils.py @@ -279,7 +279,13 @@ def run_main(verify_func): network_key = data.get('network_key') if network_key: - wireshark_prefs['uat:ieee802154_keys'] = f'"{network_key}","1","Thread hash"' + existing_keys = wireshark_prefs.get('uat:ieee802154_keys', '') + new_key = f'"{network_key}","1","Thread hash"' + if network_key not in existing_keys: + if existing_keys: + wireshark_prefs['uat:ieee802154_keys'] = existing_keys + '\n' + new_key + else: + wireshark_prefs['uat:ieee802154_keys'] = new_key mesh_local_prefix = data.get('extra_vars', {}).get('mesh_local_prefix') if mesh_local_prefix: