mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 01:47:47 +00:00
[nexus] add SRP-TC-11 for recovery after reboot (#12772)
This commit adds the Nexus test case 1_3_SRP_TC_11 which verifies that SRP registration and mDNS discovery are correctly recovered after various device reboots, as per the Thread 1.3 test specification. The implementation includes: - tests/nexus/test_1_3_SRP_TC_11.cpp: Executes the test sequence by simulating reboots of a Thread End Device (ED_1), a Border Router (BR_1), and an Infrastructure node (Eth_1). It ensures consistent network datasets across reboots and uses direct method calls for configuration. - tests/nexus/verify_1_3_SRP_TC_11.py: Performs automated verification of the captured traffic (PCAP). It uses specific MAC address filters to reliably identify mDNS queries and responses across multiple reboot scenarios where protocol exchanges may otherwise appear identical. - Integrated the new test into tests/nexus/CMakeLists.txt and tests/nexus/run_nexus_tests.sh. The test ensures that SRP clients automatically re-register after device or server reboots and that the BR correctly continues to respond to mDNS queries on the infrastructure interface.
This commit is contained in:
@@ -271,6 +271,7 @@ ot_nexus_test(1_3_SRP_TC_4 "cert;nexus")
|
||||
ot_nexus_test(1_3_SRP_TC_5 "cert;nexus")
|
||||
ot_nexus_test(1_3_SRP_TC_6 "cert;nexus")
|
||||
ot_nexus_test(1_3_SRP_TC_8 "cert;nexus")
|
||||
ot_nexus_test(1_3_SRP_TC_11 "cert;nexus")
|
||||
|
||||
# Misc tests
|
||||
ot_nexus_test(border_admitter "core;nexus")
|
||||
|
||||
@@ -206,6 +206,7 @@ DEFAULT_TESTS=(
|
||||
"1_3_SRP_TC_5"
|
||||
"1_3_SRP_TC_6"
|
||||
"1_3_SRP_TC_8"
|
||||
"1_3_SRP_TC_11"
|
||||
)
|
||||
|
||||
# Use provided arguments or the default test list
|
||||
|
||||
@@ -0,0 +1,530 @@
|
||||
/*
|
||||
* 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 <string.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 = 13 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for a node to join a network, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kJoinNetworkTime = 10 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for the BR to perform automatic actions (RA, Network Data), in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kBrActionTime = 20 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for SRP server information to be updated in Network Data.
|
||||
*/
|
||||
static constexpr uint32_t kSrpServerInfoUpdateTime = 20 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for SRP registration, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kSrpRegistrationTime = 10 * 1000;
|
||||
|
||||
/**
|
||||
* Time to advance for DNS query processing, in milliseconds.
|
||||
*/
|
||||
static constexpr uint32_t kDnsQueryTime = 5 * 1000;
|
||||
|
||||
/**
|
||||
* Infrastructure interface index.
|
||||
*/
|
||||
static constexpr uint32_t kInfraIfIndex = 1;
|
||||
|
||||
/**
|
||||
* SRP service registration parameters.
|
||||
*/
|
||||
static const char kSrpServiceType[] = "_thread-test._udp";
|
||||
static const char kSrpInstanceName[] = "service-test-1";
|
||||
static const char kSrpHostName[] = "host-test-1";
|
||||
static constexpr uint16_t kSrpServicePort = 1500;
|
||||
static constexpr uint8_t kSrpServicePriority = 8;
|
||||
static constexpr uint8_t kSrpServiceWeight = 8;
|
||||
static constexpr uint32_t kSrpLease = 300; // 5 minutes
|
||||
static constexpr uint32_t kSrpKeyLease = 600; // 10 minutes
|
||||
|
||||
void Test_1_3_SRP_TC_11(const char *aJsonFileName)
|
||||
{
|
||||
Srp::Client::Service service;
|
||||
|
||||
/**
|
||||
* 2.11. [1.3] [CERT] Recovery after reboot
|
||||
*
|
||||
* 2.11.1. Purpose
|
||||
* To test the following:
|
||||
* - 1. Handle SRP update after reboot of Thread device.
|
||||
* - 2. Handle SRP update after reboot of Border Router
|
||||
* - 3. Respond to mDNS queries on infrastructure interface after reboot of infrastructure device.
|
||||
*
|
||||
* 2.11.2. Topology
|
||||
* - 1. BR_1 (DUT) - Thread Border Router, and the Leader
|
||||
* - 2. ED 1-Test Bed device operating as a Thread End Device, attached to BR_1
|
||||
* - 3. Eth 1-Test Bed border router device on an Adjacent Infrastructure Link
|
||||
*
|
||||
* Spec Reference | V1.1 Section | V1.3.0 Section
|
||||
* -----------------|--------------|---------------
|
||||
* SRP Server | N/A | 1.3
|
||||
*/
|
||||
|
||||
Core nexus;
|
||||
|
||||
Node &br1 = nexus.CreateNode();
|
||||
Node &ed1 = nexus.CreateNode();
|
||||
Node ð1 = nexus.CreateNode();
|
||||
|
||||
br1.SetName("BR_1");
|
||||
ed1.SetName("ED_1");
|
||||
eth1.SetName("Eth_1");
|
||||
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
Instance::SetLogLevel(kLogLevelNote);
|
||||
|
||||
Log("---------------------------------------------------------------------------------------");
|
||||
|
||||
/**
|
||||
* Step 1
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Enable
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 1: BR 1 (DUT) Enable");
|
||||
SuccessOrQuit(br1.Get<Srp::Server>().SetAddressMode(Srp::Server::kAddressModeUnicast));
|
||||
br1.Get<Srp::Server>().SetEnabled(true);
|
||||
br1.Get<BorderRouter::InfraIf>().Init(kInfraIfIndex, true);
|
||||
br1.Get<BorderRouter::RoutingManager>().Init();
|
||||
SuccessOrQuit(br1.Get<BorderRouter::RoutingManager>().SetEnabled(true));
|
||||
br1.Form();
|
||||
nexus.AdvanceTime(kFormNetworkTime);
|
||||
|
||||
MeshCoP::Dataset::Info datasetInfo;
|
||||
SuccessOrQuit(br1.Get<MeshCoP::ActiveDatasetManager>().Read(datasetInfo));
|
||||
|
||||
/**
|
||||
* Step 2
|
||||
* - Device: Eth 1, ED 1
|
||||
* - Description (SRP-2.11): Enable
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 2: Eth 1, ED 1 Enable");
|
||||
ed1.Join(br1, Node::kAsFed);
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
// Wait for BR to advertise prefixes and ED to get an OMR address
|
||||
nexus.AdvanceTime(kBrActionTime);
|
||||
|
||||
/**
|
||||
* Step 3
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically adds SRP Server information in the Thread Network Data.
|
||||
* - Pass Criteria:
|
||||
* - The DUT's SRP Server information MUST appear in the Thread Network Data. This MUST be a
|
||||
* DNS/SRP Unicast Dataset, or a DNS/SRP Anycast Dataset, or both.
|
||||
* - In case of Anycast Dataset: record the SRP-SN value for later use.
|
||||
*/
|
||||
Log("Step 3: BR 1 (DUT) Automatically adds SRP Server information in the Thread Network Data.");
|
||||
nexus.AdvanceTime(kSrpServerInfoUpdateTime);
|
||||
|
||||
{
|
||||
String<10> srpPortString;
|
||||
srpPortString.Append("%u", br1.Get<Srp::Server>().GetPort());
|
||||
nexus.AddTestVar("BR_1_SRP_PORT_1", srpPortString.AsCString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 4
|
||||
* - Device: ED_1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send SRP Update: $ORIGIN
|
||||
* default.service.arpa. service-test-1._thread-test._udp ( SRV 8 1500 host-test-1 ) host-test-1
|
||||
* AAAA <OMR address of ED_1> KEY <public key of ED_1> with the following options: Update Lease
|
||||
* Option, Lease: 5 minutes, Key Lease: 10 minutes
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 4: ED_1 send SRP Update");
|
||||
{
|
||||
ed1.Get<Srp::Client>().EnableAutoStartMode(nullptr, nullptr);
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().SetHostName(kSrpHostName));
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().EnableAutoHostAddress());
|
||||
|
||||
ed1.Get<Srp::Client>().SetLeaseInterval(kSrpLease);
|
||||
ed1.Get<Srp::Client>().SetKeyLeaseInterval(kSrpKeyLease);
|
||||
|
||||
ClearAllBytes(service);
|
||||
service.mName = kSrpServiceType;
|
||||
service.mInstanceName = kSrpInstanceName;
|
||||
service.mPort = kSrpServicePort;
|
||||
service.mPriority = kSrpServicePriority;
|
||||
service.mWeight = kSrpServiceWeight;
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().AddService(service));
|
||||
}
|
||||
nexus.AdvanceTime(kSrpRegistrationTime);
|
||||
|
||||
/**
|
||||
* Step 5
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
*/
|
||||
Log("Step 5: BR 1 (DUT) Automatically sends SRP Update Response.");
|
||||
|
||||
/**
|
||||
* Step 6
|
||||
* - Device: Eth_1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send mDNS query QType SRV for
|
||||
* "service-test-1. thread-test, udp.local.".
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 6: Eth_1 send mDNS query QType SRV");
|
||||
{
|
||||
eth1.Reset();
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
Dns::Multicast::Core::SrvResolver resolver;
|
||||
ClearAllBytes(resolver);
|
||||
resolver.mCallback = [](otInstance *, const otPlatDnssdSrvResult *) {};
|
||||
resolver.mServiceInstance = kSrpInstanceName;
|
||||
resolver.mServiceType = kSrpServiceType;
|
||||
resolver.mInfraIfIndex = kInfraIfIndex;
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StartSrvResolver(resolver));
|
||||
nexus.AdvanceTime(kDnsQueryTime);
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StopSrvResolver(resolver));
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 7
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
* service-test-1 answer record: SORIGIN local. service-test-1. thread-test._udp ( SRV 8 8 1500
|
||||
* host-test-1 )
|
||||
*/
|
||||
Log("Step 7: BR 1 (DUT) Automatically sends mDNS Response.");
|
||||
|
||||
/**
|
||||
* Step 8
|
||||
* - Device: ED 1
|
||||
* - Description (SRP-2.11): Harness instructs the device to reboot/reset. Note: ED 1 MUST
|
||||
* persist its public/private keypair that is used for signing SRP Updates. So it is not a
|
||||
* factory-reset.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 8: ED 1 reboot/reset");
|
||||
ed1.Reset();
|
||||
ed1.Join(br1, Node::kAsFed);
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
/**
|
||||
* Step 9
|
||||
* - Device: ED 1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send SRP Update, as in step 4.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 9: ED 1 send SRP Update");
|
||||
{
|
||||
ed1.Get<Srp::Client>().EnableAutoStartMode(nullptr, nullptr);
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().SetHostName(kSrpHostName));
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().EnableAutoHostAddress());
|
||||
|
||||
ed1.Get<Srp::Client>().SetLeaseInterval(kSrpLease);
|
||||
ed1.Get<Srp::Client>().SetKeyLeaseInterval(kSrpKeyLease);
|
||||
|
||||
ClearAllBytes(service);
|
||||
service.mName = kSrpServiceType;
|
||||
service.mInstanceName = kSrpInstanceName;
|
||||
service.mPort = kSrpServicePort;
|
||||
service.mPriority = kSrpServicePriority;
|
||||
service.mWeight = kSrpServiceWeight;
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().AddService(service));
|
||||
}
|
||||
nexus.AdvanceTime(kSrpRegistrationTime);
|
||||
|
||||
/**
|
||||
* Step 10
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
*/
|
||||
Log("Step 10: BR 1 (DUT) Automatically sends SRP Update Response.");
|
||||
|
||||
/**
|
||||
* Step 11
|
||||
* - Device: Eth_1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send mDNS query QType=SRV for
|
||||
* "service-test-1._thread-test_udp.local.".
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 11: Eth_1 send mDNS query QType=SRV");
|
||||
{
|
||||
eth1.Reset();
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
Dns::Multicast::Core::SrvResolver resolver;
|
||||
ClearAllBytes(resolver);
|
||||
resolver.mCallback = [](otInstance *, const otPlatDnssdSrvResult *) {};
|
||||
resolver.mServiceInstance = kSrpInstanceName;
|
||||
resolver.mServiceType = kSrpServiceType;
|
||||
resolver.mInfraIfIndex = kInfraIfIndex;
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StartSrvResolver(resolver));
|
||||
nexus.AdvanceTime(kDnsQueryTime);
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StopSrvResolver(resolver));
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 12
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
* service-test-1 answer record: SORIGIN local. service-test-1. thread-test._udp ( SRV 1500
|
||||
* host-test-1 )
|
||||
*/
|
||||
Log("Step 12: BR 1 (DUT) Automatically sends mDNS Response.");
|
||||
|
||||
/**
|
||||
* Step 13
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): User is instructed to reboot the border router (DUT). Note: In case
|
||||
* DUT uses an Anycast Dataset, this will include a different SRP-SN (compared to the previous
|
||||
* SRP-SN recorded in step 3). This will then trigger re-registration in the next step. In
|
||||
* case DUT uses a Unicast Dataset, this will include a different port number (compared to the
|
||||
* previous port value used in step 3). This will then trigger re-registration.
|
||||
* - Pass Criteria:
|
||||
* - After reboot, the DUT's SRP Server information MUST appear in the Thread Network Data.
|
||||
* This MUST be a DNS/SRP Unicast Dataset, or DNS/SRP Anycast Dataset, or both.
|
||||
* - For an Anycast Dataset, the SRP-SN SHOULD be different but MAY be equal (in case DUT
|
||||
* persistently stores data, only).
|
||||
* - For a Unicast Dataset, the port number MUST differ.
|
||||
*/
|
||||
Log("Step 13: BR 1 (DUT) reboot");
|
||||
{
|
||||
br1.Reset();
|
||||
br1.Get<MeshCoP::ActiveDatasetManager>().SaveLocal(datasetInfo);
|
||||
br1.Get<ThreadNetif>().Up();
|
||||
SuccessOrQuit(br1.Get<Mle::Mle>().Start());
|
||||
SuccessOrQuit(br1.Get<Srp::Server>().SetAddressMode(Srp::Server::kAddressModeUnicast));
|
||||
br1.Get<Srp::Server>().SetEnabled(true);
|
||||
br1.Get<BorderRouter::InfraIf>().Init(kInfraIfIndex, true);
|
||||
br1.Get<BorderRouter::RoutingManager>().Init();
|
||||
SuccessOrQuit(br1.Get<BorderRouter::RoutingManager>().SetEnabled(true));
|
||||
nexus.AdvanceTime(kFormNetworkTime);
|
||||
nexus.AdvanceTime(kSrpServerInfoUpdateTime);
|
||||
|
||||
String<10> srpPortString;
|
||||
srpPortString.Append("%u", br1.Get<Srp::Server>().GetPort());
|
||||
nexus.AddTestVar("BR_1_SRP_PORT_2", srpPortString.AsCString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 14
|
||||
* - Device: ED_1
|
||||
* - Description (SRP-2.11): Automatically re-registers using SRP Update, as in step 4.
|
||||
* - Pass Criteria:
|
||||
* - MUST automatically re-register with SRP Update as in step 4.
|
||||
*/
|
||||
Log("Step 14: ED_1 Automatically re-registers using SRP Update");
|
||||
nexus.AdvanceTime(kSrpRegistrationTime);
|
||||
|
||||
/**
|
||||
* Step 15
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
*/
|
||||
Log("Step 15: BR 1 (DUT) Automatically sends SRP Update Response.");
|
||||
|
||||
/**
|
||||
* Step 16
|
||||
* - Device: Eth_1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send mDNS query QType SRV for
|
||||
* "service-test-1. thread-test_udp.local.".
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 16: Eth_1 send mDNS query QType SRV");
|
||||
{
|
||||
eth1.Reset();
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
Dns::Multicast::Core::SrvResolver resolver;
|
||||
ClearAllBytes(resolver);
|
||||
resolver.mCallback = [](otInstance *, const otPlatDnssdSrvResult *) {};
|
||||
resolver.mServiceInstance = kSrpInstanceName;
|
||||
resolver.mServiceType = kSrpServiceType;
|
||||
resolver.mInfraIfIndex = kInfraIfIndex;
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StartSrvResolver(resolver));
|
||||
nexus.AdvanceTime(kDnsQueryTime);
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StopSrvResolver(resolver));
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 17
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
* service-test-1 answer record: SORIGIN local. service-test-1._thread-test._udp ( SRV 8 8 1500
|
||||
* host-test-1 )
|
||||
*/
|
||||
Log("Step 17: BR 1 (DUT) Automatically sends mDNS Response.");
|
||||
|
||||
/**
|
||||
* Step 18
|
||||
* - Device: Eth 1
|
||||
* - Description (SRP-2.11): Harness instructs the device to reset
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 18: Eth 1 reset");
|
||||
eth1.Reset();
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
/**
|
||||
* Step 19
|
||||
* - Device: ED 1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send SRP Update, as in step 4.
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 19: ED 1 send SRP Update");
|
||||
{
|
||||
// ED_1 will automatically refresh when lease is close to expiry,
|
||||
// but here we manually trigger an update by clearing and re-adding if needed,
|
||||
// or just wait for next registration if the test implies another update.
|
||||
// The spec says "Harness instructs the device to send SRP Update, as in step 4".
|
||||
ed1.Get<Srp::Client>().ClearHostAndServices();
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().SetHostName(kSrpHostName));
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().EnableAutoHostAddress());
|
||||
|
||||
ed1.Get<Srp::Client>().SetLeaseInterval(kSrpLease);
|
||||
ed1.Get<Srp::Client>().SetKeyLeaseInterval(kSrpKeyLease);
|
||||
|
||||
ClearAllBytes(service);
|
||||
service.mName = kSrpServiceType;
|
||||
service.mInstanceName = kSrpInstanceName;
|
||||
service.mPort = kSrpServicePort;
|
||||
service.mPriority = kSrpServicePriority;
|
||||
service.mWeight = kSrpServiceWeight;
|
||||
SuccessOrQuit(ed1.Get<Srp::Client>().AddService(service));
|
||||
}
|
||||
nexus.AdvanceTime(kSrpRegistrationTime);
|
||||
|
||||
/**
|
||||
* Step 20
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
*/
|
||||
Log("Step 20: BR 1 (DUT) Automatically sends SRP Update Response.");
|
||||
|
||||
/**
|
||||
* Step 21
|
||||
* - Device: Eth 1
|
||||
* - Description (SRP-2.11): Harness instructs the device to send mDNS query QType SRV for
|
||||
* "service-test-1. thread-test._udp.local.".
|
||||
* - Pass Criteria:
|
||||
* - N/A
|
||||
*/
|
||||
Log("Step 21: Eth 1 send mDNS query QType SRV");
|
||||
{
|
||||
eth1.Reset();
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().SetEnabled(true, kInfraIfIndex));
|
||||
nexus.AdvanceTime(kJoinNetworkTime);
|
||||
|
||||
Dns::Multicast::Core::SrvResolver resolver;
|
||||
ClearAllBytes(resolver);
|
||||
resolver.mCallback = [](otInstance *, const otPlatDnssdSrvResult *) {};
|
||||
resolver.mServiceInstance = kSrpInstanceName;
|
||||
resolver.mServiceType = kSrpServiceType;
|
||||
resolver.mInfraIfIndex = kInfraIfIndex;
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StartSrvResolver(resolver));
|
||||
nexus.AdvanceTime(kDnsQueryTime);
|
||||
SuccessOrQuit(eth1.Get<Dns::Multicast::Core>().StopSrvResolver(resolver));
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 22
|
||||
* - Device: BR 1 (DUT)
|
||||
* - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
* - Pass Criteria:
|
||||
* - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
* service-test-1. SORIGIN local. service-test-1. thread-test._udp ( SRV 8 8 1500 host-test-1 )
|
||||
*/
|
||||
Log("Step 22: BR 1 (DUT) Automatically sends mDNS Response.");
|
||||
|
||||
Log("All steps completed.");
|
||||
|
||||
{
|
||||
Ip6::Prefix omrPrefix;
|
||||
SuccessOrQuit(br1.Get<BorderRouter::RoutingManager>().GetOmrPrefix(omrPrefix));
|
||||
nexus.AddTestVar("ED_1_OMR", ed1.FindMatchingAddress(omrPrefix.ToString().AsCString()).ToString().AsCString());
|
||||
}
|
||||
|
||||
nexus.SaveTestInfo(aJsonFileName);
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
} // namespace ot
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ot::Nexus::Test_1_3_SRP_TC_11((argc > 2) ? argv[2] : "test_1_3_SRP_TC_11.json");
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
#!/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):
|
||||
# 2.11. [1.3] [CERT] Recovery after reboot
|
||||
#
|
||||
# 2.11.1. Purpose
|
||||
# To test the following:
|
||||
# - 1. Handle SRP update after reboot of Thread device.
|
||||
# - 2. Handle SRP update after reboot of Border Router
|
||||
# - 3. Respond to mDNS queries on infrastructure interface after reboot of infrastructure device.
|
||||
#
|
||||
# 2.11.2. Topology
|
||||
# - 1. BR_1 (DUT) - Thread Border Router, and the Leader
|
||||
# - 2. ED 1-Test Bed device operating as a Thread End Device, attached to BR_1
|
||||
# - 3. Eth 1-Test Bed border router device on an Adjacent Infrastructure Link
|
||||
#
|
||||
# Spec Reference | V1.1 Section | V1.3.0 Section
|
||||
# ---------------|--------------|---------------
|
||||
# SRP Server | N/A | 1.3
|
||||
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
BR_1_MLEID = pv.vars['BR_1_MLEID']
|
||||
ED_1_MLEID = pv.vars['ED_1_MLEID']
|
||||
BR_1_SRP_PORT_1 = int(pv.vars['BR_1_SRP_PORT_1'])
|
||||
BR_1_SRP_PORT_2 = int(pv.vars['BR_1_SRP_PORT_2'])
|
||||
BR_1_ETH = pv.vars['BR_1_ETH']
|
||||
ETH_1_ETH = pv.vars['Eth_1_ETH']
|
||||
|
||||
SRP_SERVICE_NAME = '_thread-test._udp.default.service.arpa'
|
||||
SRP_INSTANCE_NAME = 'service-test-1.' + SRP_SERVICE_NAME
|
||||
SRP_HOST_NAME = 'host-test-1.default.service.arpa'
|
||||
MDNS_SERVICE_NAME = '_thread-test._udp.local'
|
||||
MDNS_INSTANCE_NAME = 'service-test-1.' + MDNS_SERVICE_NAME
|
||||
|
||||
SRP_SERVICE_PORT = 1500
|
||||
SRP_SERVICE_PRIORITY = 8
|
||||
SRP_SERVICE_WEIGHT = 8
|
||||
|
||||
DNS_TYPE_SRV = 33
|
||||
SERVICE_ID_SRP_UNICAST_DNS = 93
|
||||
|
||||
# Step 1
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Enable
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 1: BR 1 (DUT) Enable")
|
||||
|
||||
# Step 2
|
||||
# - Device: Eth 1, ED 1
|
||||
# - Description (SRP-2.11): Enable
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 2: Eth 1, ED 1 Enable")
|
||||
|
||||
# Step 3
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically adds SRP Server information in the Thread Network Data.
|
||||
# - Pass Criteria:
|
||||
# - The DUT's SRP Server information MUST appear in the Thread Network Data. This MUST be a
|
||||
# DNS/SRP Unicast Dataset, or a DNS/SRP Anycast Dataset, or both.
|
||||
# - In case of Anycast Dataset: record the SRP-SN value for later use.
|
||||
print("Step 3: BR 1 (DUT) Automatically adds SRP Server information in the Thread Network Data.")
|
||||
pkts.\
|
||||
filter_mle_cmd(consts.MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: SERVICE_ID_SRP_UNICAST_DNS in verify_utils.as_list(p.thread_nwd.tlv.service.srp_dataset_identifier)).\
|
||||
must_next()
|
||||
|
||||
# Step 4
|
||||
# - Device: ED_1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send SRP Update: $ORIGIN
|
||||
# default.service.arpa. service-test-1._thread-test._udp ( SRV 8 1500 host-test-1 ) host-test-1
|
||||
# AAAA <OMR address of ED_1> KEY <public key of ED_1> with the following options: Update Lease
|
||||
# Option, Lease: 5 minutes, Key Lease: 10 minutes
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 4: ED_1 sends SRP Update")
|
||||
pkts.\
|
||||
filter_ipv6_dst(BR_1_MLEID).\
|
||||
filter_ipv6_src(ED_1_MLEID).\
|
||||
filter(lambda p: p.udp.dstport == BR_1_SRP_PORT_1).\
|
||||
filter(lambda p: p.dns.flags.opcode == consts.DNS_OPCODE_UPDATE).\
|
||||
filter(lambda p: SRP_INSTANCE_NAME in verify_utils.as_list(p.dns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.dns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.dns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.dns.srv.weight)).\
|
||||
filter(lambda p: SRP_HOST_NAME in verify_utils.as_list(p.dns.srv.target)).\
|
||||
must_next()
|
||||
|
||||
# Step 5
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
print("Step 5: BR 1 (DUT) Automatically sends SRP Update Response.")
|
||||
pkts.\
|
||||
filter_ipv6_dst(ED_1_MLEID).\
|
||||
filter_ipv6_src(BR_1_MLEID).\
|
||||
filter(lambda p: p.udp.srcport == BR_1_SRP_PORT_1).\
|
||||
filter(lambda p: p.dns.flags.response == 1).\
|
||||
filter(lambda p: p.dns.flags.rcode == 0).\
|
||||
must_next()
|
||||
|
||||
# Step 6
|
||||
# - Device: Eth_1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send mDNS query QType SRV for
|
||||
# "service-test-1. thread-test, udp.local.".
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 6: Eth_1 sends mDNS query QType SRV")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == ETH_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 0).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.qry.name)).\
|
||||
filter(lambda p: DNS_TYPE_SRV in verify_utils.as_list(p.mdns.qry.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 7
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
# service-test-1 answer record: SORIGIN local. service-test-1. thread-test._udp ( SRV 8 8 1500
|
||||
# host-test-1 )
|
||||
print("Step 7: BR 1 (DUT) Automatically sends mDNS Response.")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == BR_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 1).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.mdns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.mdns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.mdns.srv.weight)).\
|
||||
must_next()
|
||||
|
||||
# Step 8
|
||||
# - Device: ED 1
|
||||
# - Description (SRP-2.11): Harness instructs the device to reboot/reset. Note: ED 1 MUST
|
||||
# persist its public/private keypair that is used for signing SRP Updates. So it is not a
|
||||
# factory-reset.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 8: ED 1 reboot/reset")
|
||||
|
||||
# Step 9
|
||||
# - Device: ED 1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send SRP Update, as in step 4.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 9: ED 1 sends SRP Update")
|
||||
pkts.\
|
||||
filter_ipv6_dst(BR_1_MLEID).\
|
||||
filter_ipv6_src(ED_1_MLEID).\
|
||||
filter(lambda p: p.udp.dstport == BR_1_SRP_PORT_1).\
|
||||
filter(lambda p: p.dns.flags.opcode == consts.DNS_OPCODE_UPDATE).\
|
||||
filter(lambda p: SRP_INSTANCE_NAME in verify_utils.as_list(p.dns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.dns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.dns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.dns.srv.weight)).\
|
||||
filter(lambda p: SRP_HOST_NAME in verify_utils.as_list(p.dns.srv.target)).\
|
||||
must_next()
|
||||
|
||||
# Step 10
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
print("Step 10: BR 1 (DUT) Automatically sends SRP Update Response.")
|
||||
pkts.\
|
||||
filter_ipv6_dst(ED_1_MLEID).\
|
||||
filter_ipv6_src(BR_1_MLEID).\
|
||||
filter(lambda p: p.udp.srcport == BR_1_SRP_PORT_1).\
|
||||
filter(lambda p: p.dns.flags.response == 1).\
|
||||
filter(lambda p: p.dns.flags.rcode == 0).\
|
||||
must_next()
|
||||
|
||||
# Step 11
|
||||
# - Device: Eth_1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send mDNS query QType=SRV for
|
||||
# "service-test-1._thread-test_udp.local.".
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 11: Eth_1 sends mDNS query QType=SRV")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == ETH_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 0).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.qry.name)).\
|
||||
filter(lambda p: DNS_TYPE_SRV in verify_utils.as_list(p.mdns.qry.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 12
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
# service-test-1 answer record: SORIGIN local. service-test-1. thread-test._udp ( SRV 1500
|
||||
# host-test-1 )
|
||||
print("Step 12: BR 1 (DUT) Automatically sends mDNS Response.")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == BR_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 1).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.mdns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.mdns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.mdns.srv.weight)).\
|
||||
must_next()
|
||||
|
||||
# Step 13
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): User is instructed to reboot the border router (DUT). Note: In case
|
||||
# DUT uses an Anycast Dataset, this will include a different SRP-SN (compared to the previous
|
||||
# SRP-SN recorded in step 3). This will then trigger re-registration in the next step. In
|
||||
# case DUT uses a Unicast Dataset, this will include a different port number (compared to the
|
||||
# previous port value used in step 3). This will then trigger re-registration.
|
||||
# - Pass Criteria:
|
||||
# - After reboot, the DUT's SRP Server information MUST appear in the Thread Network Data.
|
||||
# This MUST be a DNS/SRP Unicast Dataset, or DNS/SRP Anycast Dataset, or both.
|
||||
# - For an Anycast Dataset, the SRP-SN SHOULD be different but MAY be equal (in case DUT
|
||||
# persistently stores data, only).
|
||||
# - For a Unicast Dataset, the port number MUST differ.
|
||||
print("Step 13: BR 1 (DUT) reboot")
|
||||
pkts.\
|
||||
filter_mle_cmd(consts.MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: SERVICE_ID_SRP_UNICAST_DNS in verify_utils.as_list(p.thread_nwd.tlv.service.srp_dataset_identifier)).\
|
||||
must_next()
|
||||
|
||||
# Verify that the SRP server port has changed after reboot
|
||||
print(f"Checking SRP port change: {BR_1_SRP_PORT_1} -> {BR_1_SRP_PORT_2}")
|
||||
assert BR_1_SRP_PORT_1 != BR_1_SRP_PORT_2, f"SRP port MUST differ after reboot (was {BR_1_SRP_PORT_1})"
|
||||
|
||||
# Step 14
|
||||
# - Device: ED_1
|
||||
# - Description (SRP-2.11): Automatically re-registers using SRP Update, as in step 4.
|
||||
# - Pass Criteria:
|
||||
# - MUST automatically re-register with SRP Update as in step 4.
|
||||
print("Step 14: ED_1 Automatically re-registers using SRP Update")
|
||||
pkts.\
|
||||
filter_ipv6_dst(BR_1_MLEID).\
|
||||
filter_ipv6_src(ED_1_MLEID).\
|
||||
filter(lambda p: p.udp.dstport == BR_1_SRP_PORT_2).\
|
||||
filter(lambda p: p.dns.flags.opcode == consts.DNS_OPCODE_UPDATE).\
|
||||
filter(lambda p: SRP_INSTANCE_NAME in verify_utils.as_list(p.dns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.dns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.dns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.dns.srv.weight)).\
|
||||
filter(lambda p: SRP_HOST_NAME in verify_utils.as_list(p.dns.srv.target)).\
|
||||
must_next()
|
||||
|
||||
# Step 15
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
print("Step 15: BR 1 (DUT) Automatically sends SRP Update Response.")
|
||||
pkts.\
|
||||
filter_ipv6_dst(ED_1_MLEID).\
|
||||
filter_ipv6_src(BR_1_MLEID).\
|
||||
filter(lambda p: p.udp.srcport == BR_1_SRP_PORT_2).\
|
||||
filter(lambda p: p.dns.flags.response == 1).\
|
||||
filter(lambda p: p.dns.flags.rcode == 0).\
|
||||
must_next()
|
||||
|
||||
# Step 16
|
||||
# - Device: Eth_1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send mDNS query QType SRV for
|
||||
# "service-test-1. thread-test_udp.local.".
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 16: Eth_1 sends mDNS query QType SRV")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == ETH_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 0).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.qry.name)).\
|
||||
filter(lambda p: DNS_TYPE_SRV in verify_utils.as_list(p.mdns.qry.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 17
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
# service-test-1 answer record: SORIGIN local. service-test-1._thread-test._udp ( SRV 8 1500
|
||||
# host-test-1 )
|
||||
print("Step 17: BR 1 (DUT) Automatically sends mDNS Response.")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == BR_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 1).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.mdns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.mdns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.mdns.srv.weight)).\
|
||||
must_next()
|
||||
|
||||
# Step 18
|
||||
# - Device: Eth 1
|
||||
# - Description (SRP-2.11): Harness instructs the device to reset
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 18: Eth 1 reset")
|
||||
|
||||
# Step 19
|
||||
# - Device: ED 1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send SRP Update, as in step 4.
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 19: ED 1 sends SRP Update")
|
||||
pkts.\
|
||||
filter_ipv6_dst(BR_1_MLEID).\
|
||||
filter_ipv6_src(ED_1_MLEID).\
|
||||
filter(lambda p: p.udp.dstport == BR_1_SRP_PORT_2).\
|
||||
filter(lambda p: p.dns.flags.opcode == consts.DNS_OPCODE_UPDATE).\
|
||||
filter(lambda p: SRP_INSTANCE_NAME in verify_utils.as_list(p.dns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.dns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.dns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.dns.srv.weight)).\
|
||||
filter(lambda p: SRP_HOST_NAME in verify_utils.as_list(p.dns.srv.target)).\
|
||||
must_next()
|
||||
|
||||
# Step 20
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends SRP Update Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid SRP Update Response, with RCODE=0 (NoError).
|
||||
print("Step 20: BR 1 (DUT) Automatically sends SRP Update Response.")
|
||||
pkts.\
|
||||
filter_ipv6_dst(ED_1_MLEID).\
|
||||
filter_ipv6_src(BR_1_MLEID).\
|
||||
filter(lambda p: p.udp.srcport == BR_1_SRP_PORT_2).\
|
||||
filter(lambda p: p.dns.flags.response == 1).\
|
||||
filter(lambda p: p.dns.flags.rcode == 0).\
|
||||
must_next()
|
||||
|
||||
# Step 21
|
||||
# - Device: Eth 1
|
||||
# - Description (SRP-2.11): Harness instructs the device to send mDNS query QType SRV for
|
||||
# "service-test-1. thread-test._udp.local.".
|
||||
# - Pass Criteria:
|
||||
# - N/A
|
||||
print("Step 21: Eth 1 sends mDNS query QType SRV")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == ETH_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 0).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.qry.name)).\
|
||||
filter(lambda p: DNS_TYPE_SRV in verify_utils.as_list(p.mdns.qry.type)).\
|
||||
must_next()
|
||||
|
||||
# Step 22
|
||||
# - Device: BR 1 (DUT)
|
||||
# - Description (SRP-2.11): Automatically sends mDNS Response.
|
||||
# - Pass Criteria:
|
||||
# - The DUT MUST send a valid mDNS Response, with RCODE=0 (NoError); and contains
|
||||
# service-test-1. SORIGIN local. service-test-1. thread-test._udp ( SRV 8 8 1500 host-test-1 )
|
||||
print("Step 22: BR 1 (DUT) Automatically sends mDNS Response.")
|
||||
pkts.\
|
||||
filter(lambda p: p.eth.src == BR_1_ETH).\
|
||||
filter(lambda p: p.udp.dstport == 5353).\
|
||||
filter(lambda p: p.mdns.flags.response == 1).\
|
||||
filter(lambda p: MDNS_INSTANCE_NAME in verify_utils.as_list(p.mdns.resp.name)).\
|
||||
filter(lambda p: SRP_SERVICE_PORT in verify_utils.as_list(p.mdns.srv.port)).\
|
||||
filter(lambda p: SRP_SERVICE_PRIORITY in verify_utils.as_list(p.mdns.srv.priority)).\
|
||||
filter(lambda p: SRP_SERVICE_WEIGHT in verify_utils.as_list(p.mdns.srv.weight)).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
verify_utils.run_main(verify)
|
||||
@@ -691,6 +691,8 @@ _LAYER_FIELDS = {
|
||||
'dns.resp.type': _list(_auto),
|
||||
'dns.aaaa': _list(_ipv6_addr),
|
||||
'dns.txt': _list(_bytes),
|
||||
'dns.srv.priority': _list(_auto),
|
||||
'dns.srv.weight': _list(_auto),
|
||||
'dns.srv.port': _list(_auto),
|
||||
'dns.srv.target': _list(_str),
|
||||
'dns.ptr.domain_name': _list(_str),
|
||||
@@ -707,6 +709,8 @@ _LAYER_FIELDS = {
|
||||
'mdns.resp.type': _list(_auto),
|
||||
'mdns.aaaa': _list(_ipv6_addr),
|
||||
'mdns.txt': _list(_bytes),
|
||||
'mdns.srv.priority': _list(_auto),
|
||||
'mdns.srv.weight': _list(_auto),
|
||||
'mdns.srv.port': _list(_auto),
|
||||
'mdns.srv.target': _list(_str),
|
||||
'mdns.ptr.domain_name': _list(_str),
|
||||
|
||||
Reference in New Issue
Block a user