mirror of
https://github.com/espressif/openthread.git
synced 2026-10-03 06:17:41 +00:00
[nexus] implement test 1.2.LP.5.3.3 for SSED unsynchronization (#12605)
This commit implements Nexus test 1.2.LP.5.3.3, which validates the behavior when a Synchronized Sleepy End Device (SSED) becomes unsynchronized. The test verifies that: - When a SSED is CSL synchronized, the parent (DUT) relays frames using CSL transmission. - When the SSED stops sending synchronization data polls and the CSL connection times out, the parent falls back to indirect transmission (buffering and waiting for a Data Request). - Once the SSED resumes synchronization, the parent returns to using CSL transmission. Changes: - Add test_1_2_LP_5_3_3.cpp to implement the test logic using the Nexus simulation platform. - Add verify_1_2_LP_5_3_3.py for automated packet verification, ensuring frames are sent via CSL or indirect transmission as appropriate. - Register the new test in tests/nexus/CMakeLists.txt. - Add the test to the default test list in tests/nexus/run_nexus_tests.sh.
This commit is contained in:
@@ -217,6 +217,7 @@ ot_nexus_test(1_1_9_2_18 "cert;nexus")
|
||||
ot_nexus_test(1_1_9_2_19 "cert;nexus")
|
||||
ot_nexus_test(1_2_LP_5_3_1 "cert;nexus")
|
||||
ot_nexus_test(1_2_LP_5_3_2 "cert;nexus")
|
||||
ot_nexus_test(1_2_LP_5_3_3 "cert;nexus")
|
||||
|
||||
# Misc tests
|
||||
ot_nexus_test(border_admitter "core;nexus")
|
||||
|
||||
@@ -152,6 +152,7 @@ DEFAULT_TESTS=(
|
||||
"1_1_9_2_19"
|
||||
"1_2_LP_5_3_1"
|
||||
"1_2_LP_5_3_2"
|
||||
"1_2_LP_5_3_3"
|
||||
)
|
||||
|
||||
# Use provided arguments or the default test list
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* 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 "mac/data_poll_sender.hpp"
|
||||
#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 = 13 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for a node to join as a child and upgrade to a router, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kAttachToRouterTime = 200 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for a node to join as a SSED.
|
||||
*/
|
||||
static constexpr uint32_t kAttachAsSsedTime = 20 * 1000;
|
||||
|
||||
/**
|
||||
* Time to wait for SSED CSL timeout at DUT, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kSsedUnsyncWaitTime = 25 * 1000;
|
||||
|
||||
/**
|
||||
* Time to wait for CSL synchronization to resume, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kWaitTime18s = 18 * 1000;
|
||||
|
||||
/**
|
||||
* CSL period in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kCslPeriodMs = 500;
|
||||
|
||||
/**
|
||||
* CSL timeout in seconds.
|
||||
*/
|
||||
static constexpr uint32_t kCslTimeout = 20;
|
||||
|
||||
/**
|
||||
* Time to advance for ICMPv6 Echo Request/Response, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kEchoWaitTime = kCslPeriodMs * 2;
|
||||
|
||||
/**
|
||||
* Time to advance for CSL synchronization to complete, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kCslSyncTime = 5 * 1000;
|
||||
|
||||
/**
|
||||
* ICMPv6 Echo Request Identifiers.
|
||||
*/
|
||||
static constexpr uint16_t kEchoId1 = 0x01;
|
||||
static constexpr uint16_t kEchoId2 = 0x02;
|
||||
static constexpr uint16_t kEchoId3 = 0x03;
|
||||
|
||||
/**
|
||||
* Time to advance for the final ICMPv6 Echo Request, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kFinalEchoWaitTime = kCslPeriodMs * 4;
|
||||
|
||||
/**
|
||||
* Payload size for ICMPv6 Echo Request.
|
||||
*/
|
||||
static constexpr uint16_t kEchoPayloadSize = 10;
|
||||
|
||||
void Test1_2_LP_5_3_3(void)
|
||||
{
|
||||
/**
|
||||
* 5.3.3 SSED Becomes Unsynchronized
|
||||
*
|
||||
* 5.3.3.1 Topology
|
||||
* - Leader (DUT)
|
||||
* - Router 1
|
||||
* - SSED 1
|
||||
*
|
||||
* 5.3.3.2 Purpose & Description
|
||||
* The purpose of this test is to validate that when the DUT considers the SSED unsynchronized, it does not use CSL
|
||||
* transmission to transmit any messages, but rather falls back to indirect transmission until the SSED is CSL
|
||||
* synchronized again.
|
||||
*
|
||||
* Spec Reference | V1.2 Section
|
||||
* ------------------------------|--------------
|
||||
* SSED Becomes Unsynchronized | 4.6.5.1.1
|
||||
*/
|
||||
|
||||
Core nexus;
|
||||
|
||||
Node &dut = nexus.CreateNode();
|
||||
Node &router1 = nexus.CreateNode();
|
||||
Node &ssed1 = nexus.CreateNode();
|
||||
|
||||
dut.SetName("DUT");
|
||||
router1.SetName("ROUTER_1");
|
||||
ssed1.SetName("SSED_1");
|
||||
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
Instance::SetLogLevel(kLogLevelNote);
|
||||
|
||||
/**
|
||||
* Step 0: SSED_1
|
||||
* - Description: Preconditions: Set CSL Synchronized Timeout = 20s. Set CSL Period = 500ms.
|
||||
* - Pass Criteria: N/A.
|
||||
*/
|
||||
Log("Step 0: SSED_1");
|
||||
|
||||
/**
|
||||
* Step 1: All
|
||||
* - Description: Topology formation: DUT, Router_1, SSED_1.
|
||||
* - Pass Criteria: N/A.
|
||||
*/
|
||||
Log("Step 1: All");
|
||||
|
||||
/**
|
||||
* Use AllowList to specify links between nodes. There is a link between the following node pairs:
|
||||
* - Leader (DUT) and Router 1
|
||||
* - Leader (DUT) and SSED 1
|
||||
*/
|
||||
dut.AllowList(router1);
|
||||
router1.AllowList(dut);
|
||||
|
||||
dut.AllowList(ssed1);
|
||||
ssed1.AllowList(dut);
|
||||
|
||||
dut.Form();
|
||||
nexus.AdvanceTime(kFormNetworkTime);
|
||||
VerifyOrQuit(dut.Get<Mle::Mle>().IsLeader());
|
||||
|
||||
router1.Join(dut);
|
||||
nexus.AdvanceTime(kAttachToRouterTime);
|
||||
VerifyOrQuit(router1.Get<Mle::Mle>().IsRouter());
|
||||
|
||||
/**
|
||||
* Step 2: SSED_1
|
||||
* - Description: Automatically attaches to the DUT and establishes CSL synchronization.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST sent MLE Child ID Response to SSED_1.
|
||||
* - The DUT MUST unicast MLE Child Update Response to SSED_1.
|
||||
*/
|
||||
Log("Step 2: SSED_1");
|
||||
|
||||
ssed1.Join(dut, Node::kAsSed);
|
||||
nexus.AdvanceTime(kAttachAsSsedTime);
|
||||
VerifyOrQuit(ssed1.Get<Mle::Mle>().IsAttached());
|
||||
|
||||
ssed1.Get<Mac::Mac>().SetCslPeriod(kCslPeriodMs * 1000 / OT_US_PER_TEN_SYMBOLS);
|
||||
ssed1.Get<Mle::Mle>().SetCslTimeout(kCslTimeout);
|
||||
|
||||
nexus.AdvanceTime(kCslSyncTime);
|
||||
VerifyOrQuit(ssed1.Get<Mac::Mac>().GetCslPeriod() > 0);
|
||||
|
||||
/**
|
||||
* Step 3: Router_1
|
||||
* - Description: Harness verifies connectivity by instructing the device to send an ICMPv6 Echo Request to SSED_1
|
||||
* mesh-local address.
|
||||
* - Pass Criteria: The DUT MUST buffer the ICMPv6 Echo Request frame and relay it to SSED_1 within a subsequent CSL
|
||||
* slot.
|
||||
*/
|
||||
Log("Step 3: Router_1");
|
||||
|
||||
router1.SendEchoRequest(ssed1.Get<Mle::Mle>().GetMeshLocalEid(), kEchoId1, kEchoPayloadSize);
|
||||
nexus.AdvanceTime(kEchoWaitTime);
|
||||
|
||||
/**
|
||||
* Step 4: SSED_1
|
||||
* - Description: Automatically replies with ICMPv6 Echo Reply.
|
||||
* - Pass Criteria: The DUT MUST forward the ICMPv6 Echo Reply from SSED_1.
|
||||
*/
|
||||
Log("Step 4: SSED_1");
|
||||
|
||||
nexus.AdvanceTime(kEchoWaitTime);
|
||||
|
||||
/**
|
||||
* Step 5: SSED_1
|
||||
* - Description: Harness instructs the device to stop sending periodic synchronization data poll frames.
|
||||
* - Pass Criteria: N/A.
|
||||
*/
|
||||
Log("Step 5: SSED_1");
|
||||
|
||||
ssed1.Get<DataPollSender>().StopPolling();
|
||||
|
||||
/**
|
||||
* Step 6: Harness
|
||||
* - Description: Harness waits 25 seconds to time out the SSED / CSL connection.
|
||||
* - Pass Criteria: N/A (Implicit).
|
||||
*/
|
||||
Log("Step 6: Harness");
|
||||
|
||||
nexus.AdvanceTime(kSsedUnsyncWaitTime);
|
||||
|
||||
/**
|
||||
* Step 7: Router_1
|
||||
* - Description: Harness verifies connectivity by instructing the device to send an ICMPv6 Echo Request to the
|
||||
* SSED_1 mesh-local address.
|
||||
* - Pass Criteria: N/A.
|
||||
*/
|
||||
Log("Step 7: Router_1");
|
||||
|
||||
router1.SendEchoRequest(ssed1.Get<Mle::Mle>().GetMeshLocalEid(), kEchoId2, kEchoPayloadSize);
|
||||
|
||||
/**
|
||||
* Step 8: Leader (DUT)
|
||||
* - Description: Automatically buffers the frame for SSED_1 in the indirect (SED) queue.
|
||||
* - Pass Criteria: The DUT MUST NOT relay the ICMPv6 Echo Request frame to SSED_1.
|
||||
*/
|
||||
Log("Step 8: Leader (DUT)");
|
||||
|
||||
nexus.AdvanceTime(kEchoWaitTime);
|
||||
|
||||
/**
|
||||
* Step 9: SSED_1
|
||||
* - Description: Harness instructs the device to resume sending synchronization messages containing CSL IEs.
|
||||
* - Pass Criteria: N/A.
|
||||
*/
|
||||
Log("Step 9: SSED_1");
|
||||
|
||||
ssed1.Get<DataPollSender>().StartPolling();
|
||||
|
||||
/**
|
||||
* Step 10: Harness
|
||||
* - Description: Harness waits 18 seconds for the SSED / CSL connection to resume.
|
||||
* - Pass Criteria: N/A (Implicit).
|
||||
*/
|
||||
Log("Step 10: Harness");
|
||||
|
||||
nexus.AdvanceTime(kWaitTime18s);
|
||||
|
||||
/**
|
||||
* Step 11: Leader (DUT)
|
||||
* - Description: Automatically sends MAC Acknowledgement then relays the message.
|
||||
* - Pass Criteria: The DUT MUST verify that the Frame Pending bit is set and successfully transmits the ICMPv6 Echo
|
||||
* Request.
|
||||
*/
|
||||
Log("Step 11: Leader (DUT)");
|
||||
|
||||
nexus.AdvanceTime(kEchoWaitTime);
|
||||
|
||||
/**
|
||||
* Step 12: SSED_1
|
||||
* - Description: Automatically responds with ICMPv6 Echo Reply.
|
||||
* - Pass Criteria:
|
||||
* - SSED_1 MUST respond with ICMPv6 Echo Reply.
|
||||
* - The DUT MUST relay the ICMPv6 Echo Reply to Router_1.
|
||||
*/
|
||||
Log("Step 12: SSED_1");
|
||||
|
||||
nexus.AdvanceTime(kEchoWaitTime);
|
||||
|
||||
/**
|
||||
* Step 12b: SSED_1
|
||||
* - Description: Harness instructs the device to stop sending periodic synchronization data poll frames.
|
||||
* - Pass Criteria: N/A.
|
||||
*/
|
||||
Log("Step 12b: SSED_1");
|
||||
|
||||
ssed1.Get<DataPollSender>().StopPolling();
|
||||
|
||||
/**
|
||||
* Step 13: Router_1
|
||||
* - Description: Harness verifies CSL synchronization by instructing the device to send an ICMPv6 Echo Request to
|
||||
* the SSED_1 mesh-local address.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST buffer the ICMPv6 Echo Request frame and relay it to SSED_1 within a subsequent CSL slot.
|
||||
* - SSED_1 MUST respond with ICMPv6 Echo Reply.
|
||||
* - The DUT MUST relay the ICMPv6 Echo Reply to Router_1.
|
||||
*/
|
||||
Log("Step 13: Router_1");
|
||||
|
||||
router1.SendEchoRequest(ssed1.Get<Mle::Mle>().GetMeshLocalEid(), kEchoId3, kEchoPayloadSize);
|
||||
nexus.AdvanceTime(kFinalEchoWaitTime);
|
||||
|
||||
nexus.SaveTestInfo("test_1_2_LP_5_3_3.json");
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::Nexus::Test1_2_LP_5_3_3();
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
#!/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 import consts
|
||||
|
||||
|
||||
def verify(pv):
|
||||
# 5.3.3 SSED Becomes Unsynchronized
|
||||
#
|
||||
# 5.3.3.1 Topology
|
||||
# - Leader (DUT)
|
||||
# - Router 1
|
||||
# - SSED 1
|
||||
#
|
||||
# 5.3.3.2 Purpose & Description
|
||||
# The purpose of this test is to validate that when the DUT considers the SSED unsynchronized, it does not use CSL
|
||||
# transmission to transmit any messages, but rather falls back to indirect transmission until the SSED is CSL
|
||||
# synchronized again.
|
||||
#
|
||||
# Spec Reference | V1.2 Section
|
||||
# ------------------------------|-------------
|
||||
# SSED Becomes Unsynchronized | 4.6.5.1.1
|
||||
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC16 = pv.vars['DUT_RLOC16']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16']
|
||||
SSED_1 = pv.vars['SSED_1']
|
||||
SSED_1_RLOC16 = pv.vars['SSED_1_RLOC16']
|
||||
|
||||
# Step 0: SSED_1
|
||||
# - Description: Preconditions: Set CSL Synchronized Timeout = 20s. Set CSL Period = 500ms.
|
||||
# - Pass Criteria: N/A.
|
||||
print("Step 0: SSED_1 configuration")
|
||||
|
||||
# Step 1: All
|
||||
# - Description: Topology formation: DUT, Router_1, SSED_1.
|
||||
# - Pass Criteria: N/A.
|
||||
print("Step 1: Topology formation")
|
||||
|
||||
# Step 2: SSED_1
|
||||
# - Description: Automatically attaches to the DUT and establishes CSL synchronization.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST sent MLE Child ID Response to SSED_1.
|
||||
# - The DUT MUST unicast MLE Child Update Response to SSED_1.
|
||||
print("Step 2: SSED_1 attaches to DUT and establishes CSL synchronization")
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(SSED_1).\
|
||||
filter_mle_cmd(consts.MLE_CHILD_ID_RESPONSE).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(SSED_1).\
|
||||
filter_wpan_dst64(DUT).\
|
||||
filter_mle_cmd(consts.MLE_CHILD_UPDATE_REQUEST).\
|
||||
filter(lambda p: p.wpan.version == 2).\
|
||||
filter(lambda p: p.wpan.header_ie.csl.period == 3125).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst64(SSED_1).\
|
||||
filter_mle_cmd(consts.MLE_CHILD_UPDATE_RESPONSE).\
|
||||
filter(lambda p: p.wpan.version == 2).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Router_1
|
||||
# - Description: Harness verifies connectivity by instructing the device to send an ICMPv6 Echo Request to SSED_1
|
||||
# mesh-local address.
|
||||
# - Pass Criteria: The DUT MUST buffer the ICMPv6 Echo Request frame and relay it to SSED_1 within a subsequent CSL
|
||||
# slot.
|
||||
print("Step 3: Router_1 sends ICMPv6 Echo Request to SSED_1")
|
||||
|
||||
# ICMPv6 Echo Request from Router_1 to SSED_1
|
||||
echo_req_1 = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
filter_ipv6_dst(pv.vars['SSED_1_MLEID']).\
|
||||
must_next()
|
||||
|
||||
# Relayed ICMPv6 Echo Request from DUT to SSED_1 using CSL (wpan.version == 2)
|
||||
pkts.filter_ping_request().\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(SSED_1_RLOC16).\
|
||||
filter(lambda p: p.wpan.version == 2).\
|
||||
must_next()
|
||||
|
||||
# Step 4: SSED_1
|
||||
# - Description: Automatically replies with ICMPv6 Echo Reply.
|
||||
# - Pass Criteria: The DUT MUST forward the ICMPv6 Echo Reply from SSED_1.
|
||||
print("Step 4: SSED_1 replies with ICMPv6 Echo Reply")
|
||||
|
||||
echo_rep_1 = pkts.filter_ping_reply(identifier=echo_req_1.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(SSED_1).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_ping_reply(identifier=echo_req_1.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(ROUTER_1_RLOC16).\
|
||||
must_next()
|
||||
|
||||
# Step 5: SSED_1
|
||||
# - Description: Harness instructs the device to stop sending periodic synchronization data poll frames.
|
||||
# - Pass Criteria: N/A.
|
||||
print("Step 5: SSED_1 stops periodic synchronization data poll frames")
|
||||
|
||||
# Step 6: Harness
|
||||
# - Description: Harness waits 25 seconds to time out the SSED / CSL connection.
|
||||
# - Pass Criteria: N/A (Implicit).
|
||||
print("Step 6: Harness waits 25 seconds")
|
||||
|
||||
# Step 7: Router_1
|
||||
# - Description: Harness verifies connectivity by instructing the device to send an ICMPv6 Echo Request to the
|
||||
# SSED_1 mesh-local address.
|
||||
# - Pass Criteria: N/A.
|
||||
print("Step 7: Router_1 sends ICMPv6 Echo Request to SSED_1")
|
||||
|
||||
echo_req_2 = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
filter_ipv6_dst(pv.vars['SSED_1_MLEID']).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader (DUT)
|
||||
# - Description: Automatically buffers the frame for SSED_1 in the indirect (SED) queue.
|
||||
# - Pass Criteria: The DUT MUST NOT relay the ICMPv6 Echo Request frame to SSED_1.
|
||||
print("Step 8: DUT buffers the frame and does NOT relay it via CSL")
|
||||
|
||||
# We will verify this by checking that no such packet exists before Step 11's Data Request.
|
||||
|
||||
# Step 9: SSED_1
|
||||
# - Description: Harness instructs the device to resume sending synchronization messages containing CSL IEs.
|
||||
# - Pass Criteria: N/A.
|
||||
print("Step 9: SSED_1 resumes synchronization messages")
|
||||
|
||||
# Step 10: Harness
|
||||
# - Description: Harness waits 18 seconds for the SSED / CSL connection to resume.
|
||||
# - Pass Criteria: N/A (Implicit).
|
||||
print("Step 10: Harness waits 18 seconds")
|
||||
|
||||
# Step 11: Leader (DUT)
|
||||
# - Description: Automatically sends MAC Acknowledgement then relays the message.
|
||||
# - Pass Criteria: The DUT MUST verify that the Frame Pending bit is set and successfully transmits the ICMPv6 Echo
|
||||
# Request.
|
||||
print("Step 11: DUT sends MAC Ack with Frame Pending and relays the message")
|
||||
|
||||
# SSED_1 sends a Data Request or MLE Child Update Request (re-sync) to DUT
|
||||
data_req = pkts.filter(lambda p: (p.wpan.src64 == SSED_1 or p.wpan.src16 == SSED_1_RLOC16)).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
filter(lambda p: (p.wpan.frame_type == consts.WPAN_CMD and p.wpan.cmd == consts.WPAN_DATA_REQUEST) or\
|
||||
(p.wpan.frame_type == consts.WPAN_DATA and hasattr(p, 'mle') and p.mle.cmd == consts.MLE_CHILD_UPDATE_REQUEST)).\
|
||||
must_next()
|
||||
|
||||
# Verify that the frame was NOT relayed before the Data Request/re-sync (Step 8 Pass Criteria)
|
||||
pkts.range((echo_req_2.number, 0), (data_req.number, 0)).\
|
||||
filter_ping_request().\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(SSED_1_RLOC16).\
|
||||
must_not_next()
|
||||
|
||||
# DUT responds with an ACK that has Frame Pending set (1)
|
||||
pkts.filter_wpan_ack().\
|
||||
filter(lambda p: p.wpan.seq_no == data_req.wpan.seq_no).\
|
||||
filter(lambda p: p.wpan.pending == 1).\
|
||||
must_next()
|
||||
|
||||
# Relayed ICMPv6 Echo Request from DUT to SSED_1 (indirect transmission)
|
||||
pkts.filter_ping_request().\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(SSED_1_RLOC16).\
|
||||
filter(lambda p: p.wpan.version == consts.MAC_FRAME_VERSION_2015).\
|
||||
must_next()
|
||||
|
||||
# Step 12: SSED_1
|
||||
# - Description: Automatically responds with ICMPv6 Echo Reply.
|
||||
# - Pass Criteria:
|
||||
# - SSED_1 MUST respond with ICMPv6 Echo Reply.
|
||||
# - The DUT MUST relay the ICMPv6 Echo Reply to Router_1.
|
||||
print("Step 12: SSED_1 responds with ICMPv6 Echo Reply")
|
||||
|
||||
echo_rep_2 = pkts.filter_ping_reply(identifier=echo_req_2.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(SSED_1).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_ping_reply(identifier=echo_req_2.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(ROUTER_1_RLOC16).\
|
||||
must_next()
|
||||
|
||||
# Step 12b: SSED_1
|
||||
# - Description: Harness instructs the device to stop sending periodic synchronization data poll frames.
|
||||
# - Pass Criteria: N/A.
|
||||
print("Step 12b: SSED_1 stops periodic synchronization data poll frames")
|
||||
|
||||
# Step 13: Router_1
|
||||
# - Description: Harness verifies CSL synchronization by instructing the device to send an ICMPv6 Echo Request to
|
||||
# the SSED_1 mesh-local address.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST buffer the ICMPv6 Echo Request frame and relay it to SSED_1 within a subsequent CSL slot.
|
||||
# - SSED_1 MUST respond with ICMPv6 Echo Reply.
|
||||
# - The DUT MUST relay the ICMPv6 Echo Reply to Router_1.
|
||||
print("Step 13: Router_1 sends ICMPv6 Echo Request to SSED_1 (CSL relay)")
|
||||
|
||||
echo_req_3 = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
filter_ipv6_dst(pv.vars['SSED_1_MLEID']).\
|
||||
must_next()
|
||||
|
||||
# Relayed ICMPv6 Echo Request from DUT to SSED_1 using CSL (wpan.version == 2)
|
||||
# We verify it is CSL by checking that no Data Request was sent by SSED_1 before this frame.
|
||||
relay_req_3 = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(SSED_1_RLOC16).\
|
||||
filter(lambda p: p.wpan.version == 2).\
|
||||
must_next()
|
||||
|
||||
pkts.range((echo_req_3.number, 0), (relay_req_3.number, 0)).\
|
||||
filter_wpan_src64(SSED_1).\
|
||||
filter_wpan_cmd(consts.WPAN_DATA_REQUEST).\
|
||||
must_not_next()
|
||||
|
||||
echo_rep_3 = pkts.filter_ping_reply(identifier=echo_req_3.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(SSED_1).\
|
||||
filter_wpan_dst16(DUT_RLOC16).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_ping_reply(identifier=echo_req_3.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(DUT).\
|
||||
filter_wpan_dst16(ROUTER_1_RLOC16).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
verify_utils.run_main(verify)
|
||||
Reference in New Issue
Block a user