mirror of
https://github.com/espressif/openthread.git
synced 2026-08-17 16:09:51 +00:00
[tests] remove migrated thread-cert scripts (#12566)
This commit removes the certification test scripts in tests/scripts/thread-cert/ that have been successfully migrated to the Nexus test framework. The following tests were migrated and are now available as Nexus tests under tests/nexus/: - 5.8.2, 5.8.3, 5.8.4 - 9.2.1 through 9.2.19 Migrating these tests to Nexus provides faster execution, better reliability, and easier debugging compared to the old simulation-based scripts.
This commit is contained in:
@@ -1,131 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_RESPONSE
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
|
||||
|
||||
class Cert_5_8_2_KeyIncrement(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), "leader")
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), "router")
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ROUTER].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
key_sequence_counter = self.nodes[LEADER].get_key_sequence_counter()
|
||||
self.nodes[LEADER].set_key_sequence_counter(key_sequence_counter + 1)
|
||||
|
||||
addrs = self.nodes[ROUTER].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
router_pkts = pkts.filter_wpan_src64(ROUTER)
|
||||
|
||||
# Step 1: The DUT must start the network using
|
||||
# thrKeySequenceCounter = 0
|
||||
leader_pkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next().must_verify(lambda p: p.wpan.aux_sec.key_source == 0)
|
||||
|
||||
# Step 2: Verify that the topology described above is created.
|
||||
# MLE Auxiliary security header shall contain Key Source = 0,
|
||||
# KeyIndex = 1, KeyID Mode = 2
|
||||
leader_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
_lpkts = leader_pkts.copy()
|
||||
_rpkts = router_pkts.range(leader_pkts.index)
|
||||
|
||||
_rpkts.filter_mle_cmd(
|
||||
MLE_ADVERTISEMENT).must_next().must_verify(lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.
|
||||
key_id_mode == 2 and p.wpan.aux_sec.key_source == 0)
|
||||
|
||||
# Step 3: Leader send an ICMPv6 Echo Request to Router_1.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
leader_mleid = pv.vars['LEADER_MLEID']
|
||||
router_mleid = pv.vars['ROUTER_MLEID']
|
||||
_lpkts.filter(lambda p: p.ipv6.dst == router_mleid).filter_ping_request().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 4: Router_1 send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
_rpkts.filter(lambda p: p.ipv6.dst == leader_mleid).filter_ping_reply().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 5: The DUT MUST set incoming frame counters to 0 for all existing devices.
|
||||
# Step 6: Leader Send an ICMPv6 Echo Request to Router_1.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 2, KeyID Mode = 1
|
||||
_lpkts.filter(lambda p: p.ipv6.dst == router_mleid).filter_ping_request().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 2 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 7: Router_1 send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 2, KeyID Mode = 1
|
||||
_rpkts.filter(lambda p: p.ipv6.dst == leader_mleid).filter_ping_reply().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 2 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,134 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_CHILD_ID_RESPONSE
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER = 1
|
||||
ROUTER = 2
|
||||
|
||||
|
||||
class Cert_5_8_3_KeyIncrementRollOver(thread_cert.TestCase):
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'key_sequence_counter': 127,
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.collect_ipaddrs()
|
||||
addrs = self.nodes[ROUTER].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
key_sequence_counter = self.nodes[LEADER].get_key_sequence_counter()
|
||||
self.nodes[LEADER].set_key_sequence_counter(key_sequence_counter + 1)
|
||||
|
||||
addrs = self.nodes[ROUTER].get_addrs()
|
||||
for addr in addrs:
|
||||
if addr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER].ping(addr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
leader_pkts = pkts.filter_wpan_src64(LEADER)
|
||||
router_pkts = pkts.filter_wpan_src64(ROUTER)
|
||||
|
||||
# Step 1: The DUT must start the network using
|
||||
# thrKeySequenceCounter = 127
|
||||
_lpkts = leader_pkts.filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
self.assertTrue(_lpkts.wpan.aux_sec.key_source == 127)
|
||||
|
||||
# Step 2: Verify that the topology described above is created.
|
||||
# MLE Auxiliary security header shall contain Key Source = 127,
|
||||
# KeyIndex = 128, KeyID Mode = 2
|
||||
leader_pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
_lpkts = leader_pkts.copy()
|
||||
_rpkts = router_pkts.range(leader_pkts.index)
|
||||
|
||||
_rpkts.filter_mle_cmd(
|
||||
MLE_ADVERTISEMENT).must_next().must_verify(lambda p: p.wpan.aux_sec.key_index == 128 and p.wpan.aux_sec.
|
||||
key_id_mode == 2 and p.wpan.aux_sec.key_source == 127)
|
||||
|
||||
# Step 3: Leader send an ICMPv6 Echo Request to Router_1.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 128, KeyID Mode = 1
|
||||
leader_mleid = pv.vars['LEADER_MLEID']
|
||||
router_mleid = pv.vars['ROUTER_MLEID']
|
||||
_lpkts.filter(lambda p: p.ipv6.dst == router_mleid).filter_ping_request().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 128 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 4: Router_1 send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 128, KeyID Mode = 1
|
||||
_rpkts.filter(lambda p: p.ipv6.dst == leader_mleid).filter_ping_reply().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 128 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 5: The DUT MUST implementation specific means increment
|
||||
# thrKeySequenceCounter by 1 to force a key switch
|
||||
# Step 6: Leader Send an ICMPv6 Echo Request to Router_1.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
_lpkts.filter(lambda p: p.ipv6.dst == router_mleid).filter_ping_request().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
# Step 7: Router_1 send an ICMPv6 Echo Reply to Leader.
|
||||
# The MAC Auxiliary security header must contain
|
||||
# KeyIndex = 1, KeyID Mode = 1
|
||||
_rpkts.filter(lambda p: p.ipv6.dst == leader_mleid).filter_ping_reply().must_next().must_verify(
|
||||
lambda p: p.wpan.aux_sec.key_index == 1 and p.wpan.aux_sec.key_id_mode == 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,415 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, 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 unittest
|
||||
|
||||
from mesh_cop import TlvType
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, LEADER_ALOC, NM_COMMISSIONER_SESSION_ID_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_SECURITY_POLICY_TLV, NM_NETWORK_KEY_TLV, MLE_DISCOVERY_RESPONSE
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.layer_fields import nullField
|
||||
from pktverify.bytes import Bytes
|
||||
|
||||
LEADER = 1
|
||||
COMMISSIONER_1 = 2
|
||||
COMMISSIONER_2 = 3
|
||||
THREAD_NODE = 4
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify network behavior when Security
|
||||
# Policy TLV “O”,”N”,”R”,”B” bits are disabled. “C” bit is not tested as it
|
||||
# requires an External Commissioner which is currently not part of Thread
|
||||
# Certification.
|
||||
#
|
||||
# Notes: Due to the packet parsing compatible issue for supporting Thread 1.2
|
||||
# and 1.1, the security policy values can be fetched only in the unknown
|
||||
# field.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Leader ---- Commissioner_2
|
||||
# Thread_Node |
|
||||
# Commissioner_1
|
||||
#
|
||||
# Notes: Commissioner_2 is introduced in Step 10 and powoff
|
||||
# Thread_Node sends scan beacon
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_5_8_04_SecurityPolicyTLV(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'channel': 19,
|
||||
'network_key': '00112233445566778899aabbccddeeff',
|
||||
'security_policy': [3600, 'onrc']
|
||||
},
|
||||
'mode': 'rdn',
|
||||
},
|
||||
COMMISSIONER_1: {
|
||||
'name': 'COMMISSIONER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'channel': 19,
|
||||
'network_key': '00112233445566778899aabbccddeeff',
|
||||
'security_policy': [3600, 'onrc']
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
COMMISSIONER_2: {
|
||||
'name': 'COMMISSIONER_2',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
THREAD_NODE: {
|
||||
'name': 'THREAD_NODE',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'channel': 19,
|
||||
'network_key': '00112233445566778899aabbccddeeff',
|
||||
'security_policy': [3600, 'onrc']
|
||||
},
|
||||
'mode': 'rdn',
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER_1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER_1].get_state(), 'router')
|
||||
|
||||
self.nodes[COMMISSIONER_1].commissioner_start()
|
||||
self.simulator.go(5)
|
||||
self.nodes[COMMISSIONER_1].commissioner_add_joiner('*', 'PSKD01')
|
||||
|
||||
self.collect_rlocs()
|
||||
leader_rloc = self.nodes[LEADER].get_rloc()
|
||||
|
||||
# Step 2
|
||||
self.nodes[COMMISSIONER_1].send_mgmt_active_get()
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 5
|
||||
# Disabling O-Bit security_policy = [3600, 0b01110000]
|
||||
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
|
||||
active_timestamp=15,
|
||||
security_policy=[3600, 'nrc'],
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 7
|
||||
# Get NetworkKey
|
||||
self.nodes[COMMISSIONER_1].send_mgmt_active_get(leader_rloc, [TlvType.NETWORK_KEY])
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 9
|
||||
# Disabling N-Bit security_policy = [3600, 0b10110000]
|
||||
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
|
||||
active_timestamp=20,
|
||||
security_policy=[3600, 'orc'],
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 10
|
||||
# Add Native Commissioner
|
||||
self.nodes[COMMISSIONER_2].interface_up()
|
||||
self.nodes[COMMISSIONER_2].joiner_start('10DKSP')
|
||||
self.simulator.go(5)
|
||||
self.nodes[COMMISSIONER_2].reset()
|
||||
|
||||
# Step 13
|
||||
# Disabling B-Bit security_policy = [3600, 0b11110000]
|
||||
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
|
||||
active_timestamp=25,
|
||||
security_policy=[3600, 'onrc'],
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 15
|
||||
# send beacons
|
||||
self.nodes[THREAD_NODE].start()
|
||||
self.simulator.go(2)
|
||||
self.nodes[THREAD_NODE].scan(result=0)
|
||||
self.simulator.go(20)
|
||||
|
||||
# Step 17
|
||||
# Disabling R-Bit security_policy = [3600, 0b11010000]
|
||||
self.nodes[COMMISSIONER_1].send_mgmt_active_set(
|
||||
active_timestamp=30,
|
||||
security_policy=[3600, 'onc'],
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
COMMISSIONER_1 = pv.vars['COMMISSIONER_1']
|
||||
COMMISSIONER_1_RLOC = pv.vars['COMMISSIONER_1_RLOC']
|
||||
COMMISSIONER_2 = pv.vars['COMMISSIONER_2']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pv.verify_attached('COMMISSIONER_1', 'LEADER')
|
||||
|
||||
# Step 2: Commissioner_1 sends MGMT_ACTIVE_GET.req to Leader
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/ag
|
||||
# CoAP Payload
|
||||
# <empty>
|
||||
pkts.filter_wpan_src64(COMMISSIONER_1).\
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).\
|
||||
filter_coap_request(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader MUST send MGMT_ACTIVE_GET.rsp to the Commissioner_1
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Security Policy TLV
|
||||
# Bits “O”,”N”,”R”,”C” should be set to 1
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: (p.thread_meshcop.tlv.sec_policy_rot == 3600 and
|
||||
p.thread_meshcop.tlv.sec_policy_o == 1 and
|
||||
p.thread_meshcop.tlv.sec_policy_n == 1 and
|
||||
p.thread_meshcop.tlv.sec_policy_r == 1 and
|
||||
p.thread_meshcop.tlv.sec_policy_c == 1) or
|
||||
(p.thread_meshcop.tlv.unknown == '0e10f7')).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/as
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Active Timestamp TLV > stored value in step 4
|
||||
# Security Policy TLV with “O” bit disabled
|
||||
pkts.filter_wpan_src64(COMMISSIONER_1). \
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \
|
||||
filter_coap_request(MGMT_ACTIVE_SET_URI). \
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 15 and\
|
||||
(p.thread_meshcop.tlv.sec_policy_o == 0 or
|
||||
p.thread_meshcop.tlv.unknown == '0e1077')).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (0x01))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == 1).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Commissioner_1 sends MGMT_ACTIVE_GET.req to Leader
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/ag
|
||||
# CoAP Payload
|
||||
# Network Key TLV
|
||||
pkts.filter_wpan_src64(COMMISSIONER_1).\
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).\
|
||||
filter_coap_request(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: NM_NETWORK_KEY_TLV in p.thread_meshcop.tlv.type).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader MUST send MGMT_ACTIVE_GET.rsp to the Commissioner_1
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Network Key TLV MUST NOT be included
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 9: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/as
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Active Timestamp TLV > stored value in step 5
|
||||
# Security Policy TLV with “N” bit disabled
|
||||
pkts.filter_wpan_src64(COMMISSIONER_1). \
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \
|
||||
filter_coap_request(MGMT_ACTIVE_SET_URI). \
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 20 and\
|
||||
(p.thread_meshcop.tlv.sec_policy_n == 0 or
|
||||
p.thread_meshcop.tlv.unknown == '0e10b7')).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (0x01))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == 1).\
|
||||
must_next()
|
||||
|
||||
# Step 12: Leader MUST send a Discovery Response with Native Commissioning
|
||||
# bit set to “Not Allowed”
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_mle_cmd(MLE_DISCOVERY_RESPONSE).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.discovery_rsp_n == 0).\
|
||||
must_next()
|
||||
|
||||
# Step 13: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/as
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Active Timestamp TLV > stored value in step 9
|
||||
# Security Policy TLV with “B” bit disabled
|
||||
pkts.filter_wpan_src64(COMMISSIONER_1). \
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \
|
||||
filter_coap_request(MGMT_ACTIVE_SET_URI). \
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 25 and\
|
||||
(p.thread_meshcop.tlv.sec_policy_b == 0 or
|
||||
p.thread_meshcop.tlv.unknown == '0e10f7')).\
|
||||
must_next()
|
||||
|
||||
# Step 14: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (0x01))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == 1).\
|
||||
must_next()
|
||||
|
||||
# Step 16: The DUT MUST send beacon response frames.The beacon payload MUST
|
||||
# either be empty OR the payload format MUST be different from the
|
||||
# Thread Beacon payload The Protocol ID and Version field values
|
||||
# MUST be different from the values specified for the Thread beacon
|
||||
# (Protocol ID= 3, Version = 2)
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_beacon().\
|
||||
filter(lambda p:
|
||||
(p.thread_bcn.protocol is nullField or\
|
||||
p.thread_bcn.protocol != 3) and\
|
||||
(p.thread_bcn.version is nullField or\
|
||||
p.thread_bcn.version != 2)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 17: Commissioner_1 sends MGMT_ACTIVE_SET.req to Leader
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/as
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Active Timestamp TLV > stored value in step 9
|
||||
# Security Policy TLV with “R” bit disabled
|
||||
pkts.filter_wpan_src64(COMMISSIONER_1). \
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC). \
|
||||
filter_coap_request(MGMT_ACTIVE_SET_URI). \
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 30 and\
|
||||
(p.thread_meshcop.tlv.sec_policy_r == 0 or
|
||||
p.thread_meshcop.tlv.unknown == '0e10d7')).\
|
||||
must_next()
|
||||
|
||||
# Step 18: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner_1
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (0x01))
|
||||
# Leader MUST multicast MLE Data Response to the Link-Local All Nodes
|
||||
# multicast address (FF02::1) with active timestamp value as set in
|
||||
# Step 17.
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_1_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == 1).\
|
||||
must_next()
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == 30).\
|
||||
must_next()
|
||||
|
||||
# Step 20: The DUT MUST send a unicast MLE Data Response to Commissioner_1.
|
||||
# The Active Operational Set MUST contain a Security Policy TLV with
|
||||
# R bit set to 0.
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(COMMISSIONER_1). \
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p:
|
||||
p.mle.tlv.active_tstamp == 30 and\
|
||||
(p.thread_meshcop.tlv.sec_policy_r == 0 or
|
||||
p.thread_meshcop.tlv.unknown == '0e10d7')).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,279 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_DATA_RESPONSE, MGMT_COMMISSIONER_GET_URI, NM_CHANNEL_TLV, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, SOURCE_ADDRESS_TLV, NWD_COMMISSIONING_DATA_TLV, NM_PAN_ID_TLV, NM_NETWORK_NAME_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify Leader's and active Commissioner's behavior via
|
||||
# MGMT_COMMISSIONER_GET request and response
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Commissioner
|
||||
|
||||
|
||||
class Cert_9_2_01_MGMTCommissionerGet(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
USE_MESSAGE_FACTORY = True
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
|
||||
self.collect_leader_aloc(LEADER)
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtget()
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtget('0b08')
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtget('0b01')
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtget('0903')
|
||||
self.simulator.go(5)
|
||||
|
||||
leader_rloc = self.nodes[LEADER].get_rloc()
|
||||
commissioner_rloc = self.nodes[COMMISSIONER].get_rloc()
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(leader_rloc))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].ping(commissioner_rloc))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_ALOC = pv.vars['LEADER_ALOC']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('COMMISSIONER', 'LEADER')
|
||||
|
||||
# Step 2: Commissioner sends a MGMT_COMMISSIONER_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cg
|
||||
# CoAP Payload
|
||||
# <empty> - get all Commissioner Dataset parameters
|
||||
_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: p.coap.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends a MGMT_COMMISSIONER_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# (entire Commissioner Dataset)
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
pkts.filter_ipv6_src_dst(_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.ba_locator is not nullField and\
|
||||
p.thread_meshcop.tlv.commissioner_sess_id is not nullField and\
|
||||
p.thread_meshcop.tlv.steering_data is not nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Commissioner sends a MGMT_COMMISSIONER_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cg
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
_mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends a MGMT_COMMISSIONER_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Encoded values for the requested Commissioner Dataset parameters
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.commissioner_sess_id is not nullField and\
|
||||
p.thread_meshcop.tlv.steering_data is not nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Commissioner sends a MGMT_COMMISSIONER_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cg
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# PAN ID TLV
|
||||
_mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_PAN_ID_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader sends a MGMT_COMMISSIONER_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Encoded values for the requested Commissioner Dataset parameters
|
||||
# Commissioner Session ID TLV
|
||||
# (PAN ID TLV in Get TLV is ignored)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.commissioner_sess_id is not nullField and\
|
||||
p.thread_meshcop.tlv.pan_id is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Commissioner sends a MGMT_COMMISSIONER_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cg
|
||||
# CoAP Payload
|
||||
# Border Agent Locator TLV
|
||||
# Network Name TLV
|
||||
_mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_NETWORK_NAME_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: Leader sends a MGMT_COMMISSIONER_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Encoded values for the requested Commissioner Dataset parameters
|
||||
# Border Agent Locator TLV
|
||||
# (Network Name TLV in Get TLV is ignored)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_BORDER_AGENT_LOCATOR_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.ba_locator is not nullField and\
|
||||
p.thread_meshcop.tlv.net_name is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Verify connectivity by sending an ICMPv6 Echo Request to the DUT mesh local address
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,385 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2019, 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 unittest
|
||||
|
||||
import command
|
||||
import config
|
||||
import mesh_cop
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_DATA_RESPONSE, LEAD_PET_URI, LEAD_KA_URI, MGMT_COMMISSIONER_SET_URI, NM_CHANNEL_TLV, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STATE_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, SOURCE_ADDRESS_TLV, NWD_COMMISSIONING_DATA_TLV, MESHCOP_ACCEPT, MESHCOP_REJECT, LEADER_ALOC
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.bytes import Bytes
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify Leader's and active Commissioner's behavior via
|
||||
# MGMT_COMMISSIONER_SET request and response
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Commissioner
|
||||
|
||||
|
||||
class Cert_9_2_02_MGMTCommissionerSet(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.simulator.get_messages_sent_by(LEADER)
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
leader_messages = self.simulator.get_messages_sent_by(LEADER)
|
||||
msg = leader_messages.next_coap_message('2.04', assert_enabled=True)
|
||||
commissioner_session_id_tlv = command.get_sub_tlv(msg.coap.payload, mesh_cop.CommissionerSessionId)
|
||||
|
||||
steering_data_tlv = mesh_cop.SteeringData(bytes([0xff]))
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs([steering_data_tlv])
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs([steering_data_tlv, commissioner_session_id_tlv])
|
||||
self.simulator.go(5)
|
||||
|
||||
border_agent_locator_tlv = mesh_cop.BorderAgentLocator(0x0400)
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs(
|
||||
[commissioner_session_id_tlv, border_agent_locator_tlv])
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs([
|
||||
steering_data_tlv,
|
||||
commissioner_session_id_tlv,
|
||||
border_agent_locator_tlv,
|
||||
])
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs(
|
||||
[mesh_cop.CommissionerSessionId(0xffff), steering_data_tlv])
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs([
|
||||
commissioner_session_id_tlv,
|
||||
steering_data_tlv,
|
||||
mesh_cop.Channel(0x0, 0x0),
|
||||
])
|
||||
self.simulator.go(5)
|
||||
|
||||
leader_rloc = self.nodes[LEADER].get_rloc()
|
||||
commissioner_rloc = self.nodes[COMMISSIONER].get_rloc()
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(leader_rloc))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].ping(commissioner_rloc))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
LEADER_RLOC16 = pv.vars['LEADER_RLOC16']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('COMMISSIONER', 'LEADER')
|
||||
|
||||
# Step 2: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req)
|
||||
# to Leader Anycast or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cs
|
||||
# CoAP Payload
|
||||
# (missing Commissioner Session ID TLV)
|
||||
# Steering Data TLV (0xFF)
|
||||
_mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STEERING_DATA_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.steering_data == Bytes('ff')
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends a Set Commissioner Dataset Response (MGMT_COMMISSIONER_SET.rsp) to
|
||||
# Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Reject)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STATE_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.state == MESHCOP_REJECT
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req)
|
||||
# to Leader Anycast or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cs
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV (0xFF)
|
||||
_mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.steering_data == Bytes('ff')
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends a Set Commissioner Dataset Response (MGMT_COMMISSIONER_SET.rsp) to
|
||||
# Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STATE_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.state == MESHCOP_ACCEPT
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader sends a MLE Data Response to the network with the
|
||||
# following TLVs:
|
||||
# - Active Timestamp TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - Source Address TLV
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
LEADER_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NWD_COMMISSIONING_DATA_TLV
|
||||
} <= set(p.thread_nwd.tlv.type) and\
|
||||
{
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_nwd.tlv.stable == [0]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req)
|
||||
# to Leader Anycast or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cs
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Border Agent Locator TLV (0x0400) (not allowed TLV)
|
||||
_mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.ba_locator == 0x0400
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader sends a Set Commissioner Dataset Response (MGMT_COMMISSIONER_SET.rsp) to
|
||||
# Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Reject)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STATE_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.state == MESHCOP_REJECT
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req)
|
||||
# to Leader Anycast or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cs
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV (0xFF)
|
||||
# Border Agent Locator TLV (0x0400) (not allowed TLV)
|
||||
_mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.ba_locator == 0x0400 and\
|
||||
p.thread_meshcop.tlv.steering_data == Bytes('ff')
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Leader sends a Set Commissioner Dataset Response (MGMT_COMMISSIONER_SET.rsp) to
|
||||
# Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Reject)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STATE_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.state == MESHCOP_REJECT
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 11: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req)
|
||||
# to Leader Anycast or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cs
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV (0xFFFF) (invalid value)
|
||||
# Steering Data TLV (0xFF)
|
||||
_mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.commissioner_sess_id == 0xFFFF and\
|
||||
p.thread_meshcop.tlv.steering_data == Bytes('ff')
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 12: Leader sends a Set Commissioner Dataset Response (MGMT_COMMISSIONER_SET.rsp) to
|
||||
# Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Reject)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STATE_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.state == MESHCOP_REJECT
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 13: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req)
|
||||
# to Leader Anycast or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/cs
|
||||
# CoAP Payload
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV (0xFF)
|
||||
# Channel TLV (not allowed TLV)
|
||||
_mgmt_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_STEERING_DATA_TLV,
|
||||
NM_CHANNEL_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.steering_data == Bytes('ff')
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 14: Leader sends a Set Commissioner Dataset Response (MGMT_COMMISSIONER_SET.rsp) to
|
||||
# Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter(lambda p:
|
||||
[NM_STATE_TLV] == p.coap.tlv.type and\
|
||||
p.thread_meshcop.tlv.state == MESHCOP_ACCEPT
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 15: Verify connectivity by sending an ICMPv6 Echo Request to the DUT mesh local address
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,265 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, 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 unittest
|
||||
|
||||
import config
|
||||
import mesh_cop
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_GET_URI, NM_CHANNEL_TLV, NM_COMMISSIONER_ID_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_STEERING_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PSKC_TLV, NM_SCAN_DURATION, NM_ENERGY_LIST_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV, NM_SECURITY_POLICY_TLV, LEADER_ALOC
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify Leader's and active Commissioner's behavior via
|
||||
# MGMT_ACTIVE_GET request and response
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Commissioner
|
||||
|
||||
|
||||
class Cert_9_2_03_ActiveDatasetGet(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
USE_MESSAGE_FACTORY = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
leader_rloc = self.nodes[LEADER].get_rloc()
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_get()
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_get(
|
||||
leader_rloc,
|
||||
[mesh_cop.TlvType.CHANNEL_MASK, mesh_cop.TlvType.NETWORK_MESH_LOCAL_PREFIX, mesh_cop.TlvType.NETWORK_NAME])
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_get(leader_rloc, [
|
||||
mesh_cop.TlvType.CHANNEL, mesh_cop.TlvType.NETWORK_MESH_LOCAL_PREFIX, mesh_cop.TlvType.NETWORK_NAME,
|
||||
mesh_cop.TlvType.SCAN_DURATION, mesh_cop.TlvType.ENERGY_LIST
|
||||
])
|
||||
self.simulator.go(5)
|
||||
|
||||
commissioner_rloc = self.nodes[COMMISSIONER].get_rloc()
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(leader_rloc))
|
||||
self.simulator.go(1)
|
||||
self.assertTrue(self.nodes[LEADER].ping(commissioner_rloc))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('COMMISSIONER', 'LEADER')
|
||||
|
||||
# Step 2: Commissioner sends a MGMT_ACTIVE_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/ag
|
||||
# CoAP Payload
|
||||
# <empty> - get all Active Operational Dataset parameters
|
||||
_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: p.coap.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends a MGMT_ACTIVE_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# (entire Active Operational Dataset)
|
||||
# Active Timestamp TLV
|
||||
# Channel TLV
|
||||
# Channel Mask TLV
|
||||
# Extended PAN ID TLV
|
||||
# Network Mesh-Local Prefix TLV
|
||||
# Network Key TLV
|
||||
# Network Name TLV
|
||||
# PAN ID TLV
|
||||
# PSKc TLV
|
||||
# Security Policy TLV
|
||||
pkts.filter_ipv6_src_dst(_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_CHANNEL_TLV,
|
||||
NM_CHANNEL_MASK_TLV,
|
||||
NM_EXTENDED_PAN_ID_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_KEY_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
NM_PAN_ID_TLV,
|
||||
NM_PSKC_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Commissioner sends a MGMT_ACTIVE_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/ag
|
||||
# CoAP Payload
|
||||
# Channel Mask TLV
|
||||
# Network Mesh-Local Prefix TLV
|
||||
# Network Name TLV
|
||||
pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_CHANNEL_MASK_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_NAME_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends a MGMT_ACTIVE_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Channel Mask TLV
|
||||
# Network Mesh-Local Prefix TLV
|
||||
# Network Name TLV
|
||||
pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_CHANNEL_MASK_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_NAME_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Commissioner sends a MGMT_ACTIVE_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/ag
|
||||
# CoAP Payload
|
||||
# Channel TLV
|
||||
# Network Mesh-Local Prefix TLV
|
||||
# Network Name TLV
|
||||
# Scan Duration TLV (not allowed TLV)
|
||||
# Energy List TLV (not allowed TLV)
|
||||
pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_CHANNEL_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
NM_SCAN_DURATION,
|
||||
NM_ENERGY_LIST_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader sends a MGMT_ACTIVE_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# Channel TLV
|
||||
# Network Mesh-Local Prefix TLV
|
||||
# Network Name TLV
|
||||
pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_CHANNEL_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Verify connectivity by sending an ICMPv6 Echo Request to the
|
||||
# DUT mesh local address
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,319 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.bytes import Bytes
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
|
||||
|
||||
class Cert_9_2_04_ActiveDataset(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': 10,
|
||||
'network_key': '00112233445566778899aabbccddeeff'
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 10,
|
||||
'network_key': '00112233445566778899aabbccddeeff'
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(5)
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_leader_aloc(LEADER)
|
||||
# Step 2
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=101,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_name='GRL',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_get()
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 6
|
||||
# Attempt to set Channel TLV
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=102,
|
||||
channel=18,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000001',
|
||||
network_name='threadcert',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
# Step 8
|
||||
# Attempt to set Mesh Local Prefix TLV
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=103,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
mesh_local='fd00:0db7::',
|
||||
network_name='UL',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
# Step 10
|
||||
# Attempt to set Network Key TLV
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=104,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_key='ffeeddccbbaa99887766554433221100',
|
||||
mesh_local='fd00:0db7::',
|
||||
network_name='GRL',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
# Step 12
|
||||
# Attempt to set PAN ID TLV
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=105,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_key='00112233445566778899aabbccddeeff',
|
||||
mesh_local='fd00:0db7::',
|
||||
network_name='UL',
|
||||
panid=0xafce,
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
# Step 14
|
||||
# Invalid Commissioner Session ID
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=106,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_name='UL',
|
||||
binary='0b02abcd',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
# Step 16
|
||||
# Old Active Timestamp
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=101,
|
||||
channel_mask=0x01fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_name='UL',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
# Step 18
|
||||
# Unexpected Steering Data TLV
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=107,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_name='UL',
|
||||
binary='0806113320440000',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'UL')
|
||||
|
||||
# Step 20
|
||||
# Undefined TLV
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=108,
|
||||
channel_mask=0x7fff800,
|
||||
extended_panid='000db70000000000',
|
||||
network_name='GRL',
|
||||
binary='8202aa55',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), 'GRL')
|
||||
|
||||
ipaddrs = self.nodes[COMMISSIONER].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
self.assertTrue(self.nodes[LEADER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
LEADER_ALOC = pv.vars['LEADER_ALOC']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pkts.filter_wpan_src64(LEADER).filter_wpan_dst64(COMMISSIONER).filter_mle_cmd(
|
||||
MLE_CHILD_ID_RESPONSE).must_next()
|
||||
|
||||
# Step 2: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).filter_coap_request(
|
||||
MGMT_ACTIVE_SET_URI).filter(lambda p: p.thread_meshcop.tlv.xpan_id == '000db70000000000' and p.
|
||||
thread_meshcop.tlv.net_name == ['GRL'] and p.thread_meshcop.tlv.chan_mask_mask
|
||||
== '001fffe0' and p.thread_meshcop.tlv.active_tstamp == 101).must_next()
|
||||
|
||||
# Step 3: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == 1).must_next()
|
||||
|
||||
# Step 4: Commissioner sends MGMT_ACTIVE_GET.req to Leader
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_GET_URI).must_next()
|
||||
|
||||
# Step 5: The Leader MUST send MGMT_ACTIVE_GET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(
|
||||
MGMT_ACTIVE_GET_URI).filter(lambda p: p.thread_meshcop.tlv.active_tstamp == 101 and p.thread_meshcop.tlv.
|
||||
xpan_id == '000db70000000000' and p.thread_meshcop.tlv.net_name == ['GRL'] and
|
||||
p.thread_meshcop.tlv.chan_mask_mask == '001fffe0').must_next()
|
||||
|
||||
# Step 6: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 102 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000001' and p.thread_meshcop.tlv.net_name == ['threadcert'] and p.thread_meshcop.tlv.
|
||||
chan_mask_mask == '001fffe0' and p.thread_meshcop.tlv.channel == [18]).must_next()
|
||||
|
||||
# Step 7: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == -1).must_next()
|
||||
|
||||
# Step 8: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 103 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000000' and p.thread_meshcop.tlv.net_name == ['UL'] and p.thread_meshcop.tlv.chan_mask_mask
|
||||
== '001fffe0' and p.thread_meshcop.tlv.ml_prefix == 'fd000db700000000').must_next()
|
||||
|
||||
# Step 9: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == -1).must_next()
|
||||
|
||||
# Step 10: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 104 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000000' and p.thread_meshcop.tlv.net_name == ['GRL'] and p.thread_meshcop.tlv.master_key ==
|
||||
'ffeeddccbbaa99887766554433221100' and p.thread_meshcop.tlv.chan_mask_mask == '001fffe0' and p.
|
||||
thread_meshcop.tlv.ml_prefix == 'fd000db700000000').must_next()
|
||||
|
||||
# Step 11: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == -1).must_next()
|
||||
|
||||
# Step 12: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 105 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000000' and p.thread_meshcop.tlv.net_name == ['UL'] and p.thread_meshcop.tlv.master_key ==
|
||||
'00112233445566778899aabbccddeeff' and p.thread_meshcop.tlv.pan_id == [0xafce] and p.thread_meshcop.tlv
|
||||
.chan_mask_mask == '001fffe0' and p.thread_meshcop.tlv.ml_prefix == 'fd000db700000000').must_next()
|
||||
|
||||
# Step 13: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == -1).must_next()
|
||||
|
||||
# Step 14: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 106 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000000' and p.thread_meshcop.tlv.net_name == ['UL'] and p.thread_meshcop.tlv.
|
||||
commissioner_sess_id == 0xabcd and p.thread_meshcop.tlv.chan_mask_mask == '001fffe0').must_next()
|
||||
|
||||
# Step 15: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == -1).must_next()
|
||||
|
||||
# Step 16: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).filter_coap_request(
|
||||
MGMT_ACTIVE_SET_URI).filter(lambda p: p.thread_meshcop.tlv.active_tstamp == 101 and p.thread_meshcop.tlv.
|
||||
xpan_id == '000db70000000000' and p.thread_meshcop.tlv.net_name == ['UL'] and p
|
||||
.thread_meshcop.tlv.chan_mask_mask == '001fff80').must_next()
|
||||
|
||||
# Step 17: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == -1).must_next()
|
||||
|
||||
# Step 18: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 107 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000000' and p.thread_meshcop.tlv.net_name == ['UL'] and p.thread_meshcop.tlv.steering_data
|
||||
== Bytes('113320440000') and p.thread_meshcop.tlv.chan_mask_mask == '001fffe0').must_next()
|
||||
|
||||
# Step 19: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == 1).must_next()
|
||||
|
||||
# Step 20: Commissioner sends MGMT_ACTIVE_SET.req to Leader RLOC or Leader Anycast Locator
|
||||
pkts.filter_wpan_src64(COMMISSIONER).filter_ipv6_2dsts(
|
||||
LEADER_RLOC, LEADER_ALOC).filter_coap_request(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.active_tstamp == 108 and p.thread_meshcop.tlv.xpan_id ==
|
||||
'000db70000000000' and p.thread_meshcop.tlv.net_name == ['GRL'] and p.thread_meshcop.tlv.unknown ==
|
||||
'aa55' and p.thread_meshcop.tlv.chan_mask_mask == '001fffe0').must_next()
|
||||
|
||||
# Step 21: Leader MUST send MGMT_ACTIVE_SET.rsp to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).filter(
|
||||
lambda p: p.thread_meshcop.tlv.state == 1).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,369 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, NETWORK_DATA_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
ROUTER = 1
|
||||
LEADER = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify the DUT’s behavior when receiving
|
||||
# MGMT_ACTIVE_SET.req from an active Thread node.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Router
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_9_2_05_ActiveDataset(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'channel': 11,
|
||||
'network_key': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'channel': 11,
|
||||
'network_key': '00112233445566778899aabbccddeeff',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER].commissioner_start()
|
||||
self.simulator.go(5)
|
||||
|
||||
self.collect_rlocs()
|
||||
# Step 2: new, valid Timestamp TLV
|
||||
# all valid Active Operational Dataset parameters,
|
||||
# with new values in the TLVs that don’t affect connectivity
|
||||
# binary = new pskc and security policy [3600, 0b11101111]
|
||||
self.nodes[ROUTER].send_mgmt_active_set(
|
||||
active_timestamp=100,
|
||||
channel_mask=0x3fff800,
|
||||
extended_panid='000db80000000001',
|
||||
mesh_local='fd00:0db8::',
|
||||
network_name='TEST_1',
|
||||
network_key='00112233445566778899aabbccddeeff',
|
||||
panid=0xface,
|
||||
channel=11,
|
||||
binary='0410d2aa9cd8dff7919122d77d37ec3c1b5f0c030e10ef',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 7: old, invalid Active Timestamp TLV
|
||||
# all valid Active Operational Dataset parameters, with
|
||||
# new values in the TLVs that don’t affect connectivity
|
||||
# binary = new pskc and security policy [3600, 0b11111111]
|
||||
self.nodes[ROUTER].send_mgmt_active_set(
|
||||
active_timestamp=100,
|
||||
channel_mask=0x1fff800,
|
||||
extended_panid='000db80000000002',
|
||||
mesh_local='fd00:0db8::',
|
||||
network_name='TEST_2',
|
||||
network_key='00112233445566778899aabbccddeeff',
|
||||
panid=0xface,
|
||||
channel=11,
|
||||
binary='041017d672be32b0c24a2f8385f2fbaf1d970c030e10ff',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 9: new, valid Active Timestamp TLV
|
||||
# all of valid Commissioner Dataset parameters plus one bogus TLV, and
|
||||
# new values in the TLVs that don’t affect connectivity
|
||||
# binary = new pskc and security policy [3600, 0b11111111] and BogusTLV=0x400
|
||||
self.nodes[ROUTER].send_mgmt_active_set(
|
||||
active_timestamp=101,
|
||||
channel_mask=0xfff800,
|
||||
extended_panid='000db80000000003',
|
||||
mesh_local='fd00:0db8::',
|
||||
network_name='TEST_3',
|
||||
network_key='00112233445566778899aabbccddeeff',
|
||||
panid=0xface,
|
||||
channel=11,
|
||||
binary='041008f4e9531e8efa8e852d5f4fb951b13e0c030e10ff8202aa55',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# Step 14: new, valid Active Timestamp TLV
|
||||
# attempt to set Channel TLV to an unsupported channel + all of other TLVs
|
||||
# binary = pskc and security policy step 9
|
||||
self.nodes[ROUTER].send_mgmt_active_set(
|
||||
active_timestamp=102,
|
||||
channel_mask=0x1fff800,
|
||||
extended_panid='000db80000000003',
|
||||
mesh_local='fd00:0db8::',
|
||||
network_name='TEST_3',
|
||||
network_key='00112233445566778899aabbccddeeff',
|
||||
panid=0xface,
|
||||
channel=63,
|
||||
binary='041008f4e9531e8efa8e852d5f4fb951b13e0c030e10f8',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
ipaddr = self.nodes[LEADER].get_rloc()
|
||||
self.assertTrue(self.nodes[ROUTER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_RLOC = pv.vars['ROUTER_RLOC']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pv.verify_attached('ROUTER', 'LEADER')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 3: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with
|
||||
# with the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (01))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == 1).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Leader MUST send a multicast MLE Data Response, including
|
||||
# the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version field [incremented]
|
||||
# Stable Version field [incremented]
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV [new value set in Step 9]
|
||||
_dr_pkt = pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == 100 and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader MUST send a unicast MLE Data Response to Router, including
|
||||
# the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Active Operational Dataset TLV
|
||||
# - Channel TLV
|
||||
# - Channel Mask TLV [new value set in Step 2]
|
||||
# - Extended PAN ID TLV [new value set in Step 2]
|
||||
# - Network Mesh-Local Prefix TLV
|
||||
# - Network Key TLV
|
||||
# - Network Name TLV [new value set in Step 2]
|
||||
# - PAN ID TLV
|
||||
# - PSKc TLV [new value set in Step 2]
|
||||
# - Security Policy TLV [new value set in Step 2]
|
||||
# - Active Timestamp TLV [new value set in Step 2]
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_OPERATION_DATASET_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NM_CHANNEL_TLV,
|
||||
NM_CHANNEL_MASK_TLV,
|
||||
NM_EXTENDED_PAN_ID_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_KEY_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
NM_PAN_ID_TLV,
|
||||
NM_PSKC_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == 100 and\
|
||||
p.thread_meshcop.tlv.chan_mask_mask == '001fffc0' and\
|
||||
p.thread_meshcop.tlv.xpan_id == '000db80000000001' and\
|
||||
p.thread_meshcop.tlv.net_name == ['TEST_1'] and\
|
||||
p.thread_meshcop.tlv.pskc == 'd2aa9cd8dff7919122d77d37ec3c1b5f'
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with
|
||||
# with the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Reject (ff))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == -1).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with
|
||||
# with the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (01))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == 1).\
|
||||
must_next()
|
||||
|
||||
# Step 11: Leader MUST send a multicast MLE Data Response, including
|
||||
# the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version field [incremented]
|
||||
# Stable Version field [incremented]
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV [new value set in Step 9]
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == 101 and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_dr_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_dr_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 13: Leader MUST send a unicast MLE Data Response to Router, including
|
||||
# the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Active Operational Dataset TLV
|
||||
# - Channel TLV
|
||||
# - Channel Mask TLV [new value set in Step 9]
|
||||
# - Extended PAN ID TLV [new value set in Step 9]
|
||||
# - Network Mesh-Local Prefix TLV
|
||||
# - Network Key TLV
|
||||
# - Network Name TLV [new value set in Step 9]
|
||||
# - PAN ID TLV
|
||||
# - PSKc TLV [new value set in Step 9]
|
||||
# - Security Policy TLV [new value set in Step 9]
|
||||
# - Active Timestamp TLV [new value set in Step 9]
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: {
|
||||
NETWORK_DATA_TLV,
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_OPERATION_DATASET_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
{
|
||||
NM_CHANNEL_TLV,
|
||||
NM_CHANNEL_MASK_TLV,
|
||||
NM_EXTENDED_PAN_ID_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_KEY_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
NM_PAN_ID_TLV,
|
||||
NM_PSKC_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == 101 and\
|
||||
p.thread_meshcop.tlv.chan_mask_mask == '001fff00' and\
|
||||
p.thread_meshcop.tlv.xpan_id == '000db80000000003' and\
|
||||
p.thread_meshcop.tlv.net_name == ['TEST_3'] and\
|
||||
p.thread_meshcop.tlv.pskc == '08f4e9531e8efa8e852d5f4fb951b13e'
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 15: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with
|
||||
# with the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Reject (ff)))
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_RLOC).\
|
||||
filter_coap_ack(MGMT_ACTIVE_SET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.state == -1).\
|
||||
must_next()
|
||||
|
||||
# Step 16: The DUT must respond with an ICMPv6 Echo Reply
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(ROUTER_RLOC, LEADER_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(LEADER_RLOC, ROUTER_RLOC).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,872 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, 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 unittest
|
||||
|
||||
import command
|
||||
import config
|
||||
import mesh_cop
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE, MLE_DATA_REQUEST, MGMT_COMMISSIONER_SET_URI, MGMT_ACTIVE_SET_URI, MGMT_PENDING_SET_URI, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, PENDING_OPERATION_DATASET_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_KEY_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV, NM_DELAY_TIMER_TLV, NM_STEERING_DATA_TLV, NWD_COMMISSIONING_DATA_TLV, LEADER_ALOC
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.layer_fields import nullField
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
TIMESTAMP_INIT = 10
|
||||
CHANNEL_SECOND = 21
|
||||
|
||||
COMM_ACTIVE_TIMESTAMP = 15
|
||||
COMM_ACTIVE_NET_NAME = 'Thread'
|
||||
COMM_ACTIVE_PSKC = '10b95765596ab9d0b86cebdd0fa24da3'
|
||||
|
||||
COMM_PENDING_TIMESTAMP = 30
|
||||
COMM_PENDING_ACTIVE_TIMESTAMP = 75
|
||||
COMM_DELAY_TIMER = 60000
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER = 3
|
||||
MED = 4
|
||||
SED = 5
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# DUT as Leader:
|
||||
# The purpose of this test case is to verify that the Leader device properly
|
||||
# collects and disseminates Operational Datasets through a Thread network.
|
||||
# DUT as Router:
|
||||
# The purpose of this test case is to show that the Router device correctly
|
||||
# sets the Commissioning information propagated by the Leader device and sends
|
||||
# it properly to devices already attached to it.
|
||||
# DUT as MED/SED:
|
||||
# MED - requires full network data
|
||||
# SED - requires only stable network data
|
||||
# Set on Leader: Active TimeStamp = 10s
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
# |
|
||||
# Router
|
||||
# / \
|
||||
# MED SED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Router
|
||||
# MED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_9_2_06_DatasetDissemination(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER, ROUTER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, MED, SED]
|
||||
},
|
||||
MED: {
|
||||
'name': 'MED',
|
||||
'channel': CHANNEL_INIT,
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'panid': PANID_INIT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
SED: {
|
||||
'name': 'SED',
|
||||
'channel': CHANNEL_INIT,
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'panid': PANID_INIT,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.simulator.get_messages_sent_by(LEADER)
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
leader_messages = self.simulator.get_messages_sent_by(LEADER)
|
||||
msg = leader_messages.next_coap_message('2.04', assert_enabled=True)
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[MED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
self.nodes[SED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED].get_state(), 'child')
|
||||
|
||||
commissioner_session_id_tlv = command.get_sub_tlv(msg.coap.payload, mesh_cop.CommissionerSessionId)
|
||||
steering_data_tlv = mesh_cop.SteeringData(bytes([0xff]))
|
||||
# Step 2
|
||||
self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs([steering_data_tlv, commissioner_session_id_tlv])
|
||||
self.simulator.go(10)
|
||||
|
||||
# Step 7
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(
|
||||
active_timestamp=COMM_ACTIVE_TIMESTAMP,
|
||||
network_name=COMM_ACTIVE_NET_NAME,
|
||||
binary='0410' + COMM_ACTIVE_PSKC,
|
||||
)
|
||||
self.simulator.go(10)
|
||||
|
||||
# Step 18
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=COMM_PENDING_TIMESTAMP,
|
||||
active_timestamp=COMM_PENDING_ACTIVE_TIMESTAMP,
|
||||
delay_timer=COMM_DELAY_TIMER,
|
||||
channel=CHANNEL_SECOND,
|
||||
)
|
||||
self.simulator.go(120)
|
||||
|
||||
self.collect_rlocs()
|
||||
ed_rloc = self.nodes[MED].get_rloc()
|
||||
sed_rloc = self.nodes[SED].get_rloc()
|
||||
leader_rloc = self.nodes[LEADER].get_rloc()
|
||||
router_rloc = self.nodes[ROUTER].get_rloc()
|
||||
for rloc in (leader_rloc, router_rloc, ed_rloc, sed_rloc):
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(rloc))
|
||||
self.simulator.go(10)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
ROUTER_RLOC = pv.vars['ROUTER_RLOC']
|
||||
MED_RLOC = pv.vars['MED_RLOC']
|
||||
SED_RLOC = pv.vars['SED_RLOC']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
for node in ('COMMISSIONER', 'ROUTER'):
|
||||
pv.verify_attached(node, 'LEADER')
|
||||
for node in ('MED', 'SED'):
|
||||
pv.verify_attached(node, 'ROUTER', 'MTD')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 3: Leader sends MGMT_COMMISSIONER_SET.rsp to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
pkts.filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC).\
|
||||
must_next().\
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 4: Leader MUST multicast MLE Data Response to the Link-Local
|
||||
# All Nodes multicast address (FF02::1) with the new information
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field NOT incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_LLANMA(). \
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == TIMESTAMP_INIT and \
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt.mle.tlv.leader_data.stable_data_version and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
idx_start = pkts.index
|
||||
|
||||
# Step 5: Router MUST multicast MLE Data Response to the Link-Local
|
||||
# All Nodes multicast address (FF02::1) with the new information
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field NOT incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_LLANMA(). \
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == TIMESTAMP_INIT and \
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt.mle.tlv.leader_data.stable_data_version and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 8: Leader sends MGMT_ACTIVE_SET.rsp to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
pkts.filter_coap_ack(MGMT_ACTIVE_SET_URI). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC). \
|
||||
must_next(). \
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
idx_end = pkts.index
|
||||
|
||||
# Step 6: Router MUST NOT send a unicast MLE Data Response or MLE Child
|
||||
# Update Request to SED_1
|
||||
pkts.range(idx_start, idx_end).\
|
||||
filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(SED).\
|
||||
must_not_next()
|
||||
|
||||
# Step 9: Leader MUST multicast MLE Data Response to the Link-Local
|
||||
# All Nodes multicast address (FF02::1) with the new information
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
_pkt9 = pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_LLANMA(). \
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and \
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 10: Router MUST send a unicast MLE Data Request to the Leader, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(ROUTER).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_DATA_REQUEST).\
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 11: Leader sends a MLE Data Response to Router_1 including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 9
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV: <new value>
|
||||
# - Active Operational Dataset TLV
|
||||
# - Network Name TLV <new value>
|
||||
# - Channel TLV
|
||||
# - PAN ID TLV
|
||||
# - PSKc TLV
|
||||
# MUST NOT contain the Active Timestamp TLV
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_wpan_dst64(ROUTER). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
ACTIVE_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
{
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt9.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt9.mle.tlv.leader_data.stable_data_version and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_ACTIVE_TIMESTAMP_TLV not in p.thread_meshcop.tlv.type and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_INIT] and \
|
||||
p.thread_meshcop.tlv.net_name == [COMM_ACTIVE_NET_NAME] and \
|
||||
p.thread_meshcop.tlv.pskc == COMM_ACTIVE_PSKC and \
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_INIT]
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 12: Router MUST multicast MLE Data Response to the Link-Local
|
||||
# All Nodes multicast address (FF02::1) with the new information
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 9
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
with pkts.save_index():
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_LLANMA(). \
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt9.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt9.mle.tlv.leader_data.stable_data_version and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 13: MED MUST send a unicast MLE Data Request to the Router, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV
|
||||
|
||||
# Step 14: Router sends a MLE Data Response to MED including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 9
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV: <new value>
|
||||
# - Active Operational Dataset TLV
|
||||
# - Network Name TLV <new value>
|
||||
# - Channel TLV
|
||||
# - PAN ID TLV
|
||||
# MUST NOT contain the Active Timestamp TLV
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(MED). \
|
||||
filter_wpan_dst64(ROUTER). \
|
||||
filter_mle_cmd(MLE_DATA_REQUEST). \
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
). \
|
||||
must_next()
|
||||
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(MED). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
ACTIVE_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
{
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt9.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt9.mle.tlv.leader_data.stable_data_version and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_ACTIVE_TIMESTAMP_TLV not in p.thread_meshcop.tlv.type and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_INIT] and \
|
||||
p.thread_meshcop.tlv.net_name == [COMM_ACTIVE_NET_NAME] and \
|
||||
p.thread_meshcop.tlv.pskc == COMM_ACTIVE_PSKC and \
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_INIT]
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 15: Router MUST send MLE Child Update Request or MLE Data Response
|
||||
# to SED, including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 9
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
pkts.filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(SED). \
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE). \
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt9.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt9.mle.tlv.leader_data.stable_data_version and \
|
||||
NETWORK_DATA_TLV in p.mle.tlv.type and\
|
||||
SOURCE_ADDRESS_TLV in p.mle.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 16: SED MUST send a unicast MLE Data Request to the Router, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(SED). \
|
||||
filter_wpan_dst64(ROUTER). \
|
||||
filter_mle_cmd(MLE_DATA_REQUEST). \
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 17: Router sends a MLE Data Response to SED including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 9
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV: <15s>
|
||||
# - Active Operational Dataset TLV
|
||||
# - Network Name TLV <new value>
|
||||
# - Channel TLV
|
||||
# - PAN ID TLV
|
||||
# MUST NOT contain the Active Timestamp TLV
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(SED). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
ACTIVE_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt9.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt9.mle.tlv.leader_data.stable_data_version and \
|
||||
NM_ACTIVE_TIMESTAMP_TLV not in p.thread_meshcop.tlv.type and \
|
||||
p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_INIT] and \
|
||||
p.thread_meshcop.tlv.net_name == [COMM_ACTIVE_NET_NAME] and \
|
||||
p.thread_meshcop.tlv.pskc == COMM_ACTIVE_PSKC and \
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_INIT]
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 19: Leader sends MGMT_PENDING_SET.rsp to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
pkts.filter_coap_ack(MGMT_PENDING_SET_URI). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC). \
|
||||
must_next(). \
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 20: Leader MUST multicast MLE Data Response to the Link-Local
|
||||
# All Nodes multicast address (FF02::1) with the new information
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV
|
||||
# - Pending Timestamp TLV
|
||||
_pkt20 = pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_LLANMA(). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
{
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and \
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt9.mle.tlv.leader_data.data_version) % 256 <= 127 and \
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt9.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 21: Router MUST send a unicast MLE Data Request to the Leader, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(LEADER). \
|
||||
filter_mle_cmd(MLE_DATA_REQUEST). \
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 22: Leader sends a MLE Data Response to Router including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV
|
||||
# - Pending Timestamp TLV
|
||||
# - Pending Operational Dataset TLV
|
||||
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(LEADER). \
|
||||
filter_wpan_dst64(ROUTER). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
{
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and \
|
||||
p.thread_meshcop.tlv.delay_timer < COMM_DELAY_TIMER and \
|
||||
p.thread_meshcop.tlv.active_tstamp == COMM_PENDING_ACTIVE_TIMESTAMP and \
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_SECOND] and \
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_INIT]
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 23: Router MUST multicast MLE Data Response to the Link-Local
|
||||
# All Nodes multicast address (FF02::1) with the new information
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 20
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
with pkts.save_index():
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_LLANMA(). \
|
||||
filter(lambda p: {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and \
|
||||
p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt20.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt20.mle.tlv.leader_data.stable_data_version and \
|
||||
p.thread_nwd.tlv.stable == [0] and \
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 24: MED MUST send a unicast MLE Data Request to the Router, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV
|
||||
|
||||
# Step 25: Router sends a MLE Data Response to MED including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 20
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# Steering Data TLV
|
||||
# - Active Timestamp TLV
|
||||
# - Pending Timestamp TLV
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Network Name TLV
|
||||
# - Channel TLV
|
||||
# - PAN ID TLV
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(MED). \
|
||||
filter_wpan_dst64(ROUTER). \
|
||||
filter_mle_cmd(MLE_DATA_REQUEST). \
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
). \
|
||||
must_next()
|
||||
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(MED). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
{
|
||||
NM_COMMISSIONER_SESSION_ID_TLV,
|
||||
NM_BORDER_AGENT_LOCATOR_TLV,
|
||||
NM_STEERING_DATA_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt20.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt20.mle.tlv.leader_data.stable_data_version and \
|
||||
p.thread_nwd.tlv.stable == [0]
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 26: Router MUST send MLE Child Update Request or MLE Data Response
|
||||
# to SED, including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 20
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
pkts.filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(SED). \
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE). \
|
||||
filter(lambda p: p.mle.tlv.active_tstamp ==
|
||||
COMM_ACTIVE_TIMESTAMP and \
|
||||
p.mle.tlv.pending_tstamp ==
|
||||
COMM_PENDING_TIMESTAMP and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt20.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt20.mle.tlv.leader_data.stable_data_version and \
|
||||
NETWORK_DATA_TLV in p.mle.tlv.type
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 27: SED MUST send a unicast MLE Data Request to the Router, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV
|
||||
pkts.filter_wpan_src64(SED). \
|
||||
filter_wpan_dst64(ROUTER). \
|
||||
filter_mle_cmd(MLE_DATA_REQUEST). \
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 28: Router sends a MLE Data Response to SED including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# Data version numbers should be
|
||||
# the same as the ones sent in the
|
||||
# multicast data response in step 20
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Network Name TLV
|
||||
# - Channel TLV
|
||||
# - PAN ID TLV
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
|
||||
filter_wpan_src64(ROUTER). \
|
||||
filter_wpan_dst64(SED). \
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and \
|
||||
p.mle.tlv.leader_data.data_version ==
|
||||
_pkt20.mle.tlv.leader_data.data_version and \
|
||||
p.mle.tlv.leader_data.stable_data_version ==
|
||||
_pkt20.mle.tlv.leader_data.stable_data_version and \
|
||||
p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP
|
||||
). \
|
||||
must_next()
|
||||
|
||||
# Step 30: The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
for DUT_RLOC in (LEADER_RLOC, ROUTER_RLOC, MED_RLOC, SED_RLOC):
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(COMMISSIONER_RLOC, DUT_RLOC).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(DUT_RLOC, COMMISSIONER_RLOC).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,228 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_DATA_RESPONSE, MGMT_PENDING_SET_URI, MGMT_ACTIVE_SET_URI, MGMT_DATASET_CHANGED_URI, COAP_CODE_ACK, ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, NETWORK_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_DELAY_TIMER_TLV, PENDING_OPERATION_DATASET_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
PANID_INIT = 0xface
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER = 3
|
||||
|
||||
LEADER_ACTIVE_TIMESTAMP = 10
|
||||
ROUTER_ACTIVE_TIMESTAMP = 20
|
||||
ROUTER_PENDING_TIMESTAMP = 30
|
||||
ROUTER_PENDING_ACTIVE_TIMESTAMP = 25
|
||||
ROUTER_DELAY_TIMER = 3600000
|
||||
|
||||
COMMISSIONER_PENDING_TIMESTAMP = 40
|
||||
COMMISSIONER_PENDING_ACTIVE_TIMESTAMP = 80
|
||||
COMMISSIONER_DELAY_TIMER = 60000
|
||||
COMMISSIONER_PENDING_CHANNEL = 20
|
||||
COMMISSIONER_PENDING_PANID = 0xafce
|
||||
|
||||
|
||||
class Cert_9_2_7_DelayTimer(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'partition_id': 0xffffffff,
|
||||
'allowlist': [COMMISSIONER]
|
||||
},
|
||||
ROUTER: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'partition_id': 1,
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(active_timestamp=LEADER_ACTIVE_TIMESTAMP,)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'leader')
|
||||
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER].get_addr64())
|
||||
self.nodes[ROUTER].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.simulator.go(35)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
self.nodes[ROUTER].send_mgmt_active_set(active_timestamp=ROUTER_ACTIVE_TIMESTAMP,)
|
||||
self.simulator.go(30)
|
||||
|
||||
self.nodes[ROUTER].send_mgmt_pending_set(
|
||||
pending_timestamp=ROUTER_PENDING_TIMESTAMP,
|
||||
active_timestamp=ROUTER_PENDING_ACTIVE_TIMESTAMP,
|
||||
delay_timer=ROUTER_DELAY_TIMER,
|
||||
)
|
||||
self.simulator.go(60)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=COMMISSIONER_PENDING_TIMESTAMP,
|
||||
active_timestamp=COMMISSIONER_PENDING_ACTIVE_TIMESTAMP,
|
||||
delay_timer=COMMISSIONER_DELAY_TIMER,
|
||||
channel=COMMISSIONER_PENDING_CHANNEL,
|
||||
panid=COMMISSIONER_PENDING_PANID,
|
||||
)
|
||||
self.simulator.go(120)
|
||||
|
||||
self.assertEqual(self.nodes[LEADER].get_panid(), COMMISSIONER_PENDING_PANID)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_panid(), COMMISSIONER_PENDING_PANID)
|
||||
self.assertEqual(self.nodes[ROUTER].get_panid(), COMMISSIONER_PENDING_PANID)
|
||||
|
||||
self.assertEqual(self.nodes[LEADER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
|
||||
self.assertEqual(
|
||||
self.nodes[COMMISSIONER].get_channel(),
|
||||
COMMISSIONER_PENDING_CHANNEL,
|
||||
)
|
||||
self.assertEqual(self.nodes[ROUTER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
|
||||
|
||||
self.collect_rloc16s()
|
||||
self.collect_rlocs()
|
||||
ipaddrs = self.nodes[ROUTER].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
self.assertTrue(self.nodes[LEADER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC16 = pv.vars['LEADER_RLOC16']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_RLOC = pv.vars['ROUTER_RLOC']
|
||||
ROUTER_RLOC16 = pv.vars['ROUTER_RLOC16']
|
||||
_lpkts = pkts.filter_wpan_src64(LEADER)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_lpkts.filter_wpan_dst64(COMMISSIONER).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
_lpkts_coap = _lpkts.copy()
|
||||
|
||||
# Step 4: Leader MUST send a unicast MLE Child ID Response to the Router
|
||||
_lpkts.filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next(
|
||||
).must_verify(lambda p: {ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type) and {
|
||||
NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and p.mle.tlv.active_tstamp == LEADER_ACTIVE_TIMESTAMP)
|
||||
|
||||
# Step 6: Leader automatically sends a MGMT_ACTIVE_SET.rsp to the Router
|
||||
_lpkts.filter_ipv6_dst(ROUTER_RLOC).filter_coap_ack(MGMT_ACTIVE_SET_URI).must_next().must_verify(
|
||||
lambda p: p.coap.code == COAP_CODE_ACK and p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 7: Leader multicasts a MLE Data Response with the new information
|
||||
_lpkts.filter_LLANMA().filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, NETWORK_DATA_TLV} <= set(
|
||||
p.mle.tlv.type) and {NM_BORDER_AGENT_LOCATOR_TLV, NM_COMMISSIONER_SESSION_ID_TLV} <= set(
|
||||
p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0] and p.mle.tlv.active_tstamp ==
|
||||
ROUTER_ACTIVE_TIMESTAMP)
|
||||
|
||||
# Step 10: Leader MUST send a unicast MLE Data Response to the Router
|
||||
_lpkts.filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_RESPONSE).must_next(
|
||||
).must_verify(lambda p: {ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type) and {
|
||||
NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and p.mle.tlv.active_tstamp == ROUTER_ACTIVE_TIMESTAMP)
|
||||
|
||||
# Step 12: Leader sends a MGMT_PENDING_SET.rsp to the Router with Status = Accept
|
||||
_lpkts_coap.filter_ipv6_dst(ROUTER_RLOC).filter_coap_ack(MGMT_PENDING_SET_URI).must_next().must_verify(
|
||||
lambda p: p.coap.code == COAP_CODE_ACK and p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 13: Leader sends a multicast MLE Data Response
|
||||
_lpkts.filter_LLANMA().filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, NETWORK_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and p.thread_nwd.tlv.stable == [0] and p.mle.tlv.active_tstamp ==
|
||||
ROUTER_ACTIVE_TIMESTAMP and p.mle.tlv.pending_tstamp == ROUTER_PENDING_TIMESTAMP)
|
||||
|
||||
# Step 14: The DUT MUST send MGMT_DATASET_CHANGED.ntf to the Router
|
||||
_lpkts_coap.filter_wpan_dst16(ROUTER_RLOC16).filter_coap_request(MGMT_DATASET_CHANGED_URI).must_next()
|
||||
|
||||
# Step 16: Leader MUST send a unicast MLE Data Response to the Router
|
||||
_lpkts.filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV} <= set(p.mle.tlv.type) and p.mle.tlv.active_tstamp
|
||||
== ROUTER_ACTIVE_TIMESTAMP and p.mle.tlv.pending_tstamp == ROUTER_PENDING_TIMESTAMP)
|
||||
|
||||
# Step 18: The DUT MUST send MGMT_PENDING_SET.rsp to the Commissioner
|
||||
_lpkts_coap.filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(MGMT_PENDING_SET_URI).must_next().must_verify(
|
||||
lambda p: p.coap.code == COAP_CODE_ACK and p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 19: Leader MUST send a unicast MLE Data Response to the Router
|
||||
_lpkts.filter_LLANMA().filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and p.thread_nwd.tlv.stable == [0] and p.mle.tlv.active_tstamp ==
|
||||
ROUTER_ACTIVE_TIMESTAMP and p.mle.tlv.pending_tstamp == COMMISSIONER_PENDING_TIMESTAMP)
|
||||
|
||||
# Step 20: Leader MUST send a unicast MLE Data Response to the Router
|
||||
_lpkts.filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_RESPONSE).must_next(
|
||||
).must_verify(lambda p: {ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, PENDING_OPERATION_DATASET_TLV} < set(
|
||||
p.mle.tlv.type) and {NM_CHANNEL_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV} <=
|
||||
set(p.thread_meshcop.tlv.type) and p.mle.tlv.active_tstamp == ROUTER_ACTIVE_TIMESTAMP and p.mle.
|
||||
tlv.pending_tstamp == COMMISSIONER_PENDING_TIMESTAMP and p.thread_meshcop.tlv.pan_id ==
|
||||
[COMMISSIONER_PENDING_PANID] and p.thread_meshcop.tlv.channel == [COMMISSIONER_PENDING_CHANNEL])
|
||||
|
||||
# Step 21: Router MUST respond with an ICMPv6 Echo Reply
|
||||
pkts.filter_wpan_src16_dst16(ROUTER_RLOC16, LEADER_RLOC16).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,353 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
import copy
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_DATA_RESPONSE, MLE_DATA_REQUEST, MLE_CHILD_UPDATE_REQUEST, MGMT_PENDING_SET_URI, ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, TLV_REQUEST_TLV, NETWORK_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_DELAY_TIMER_TLV, PENDING_OPERATION_DATASET_TLV, NWD_COMMISSIONING_DATA_TLV, LEADER_ALOC
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
DUT = 3
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
LEADER_ACTIVE_TIMESTAMP = 10
|
||||
|
||||
COMMISSIONER_PENDING_TIMESTAMP = 20
|
||||
COMMISSIONER_ACTIVE_TIMESTAMP = 70
|
||||
COMMISSIONER_DELAY_TIMER = 60000
|
||||
COMMISSIONER_PENDING_CHANNEL = 20
|
||||
COMMISSIONER_PENDING_PANID = 0xafce
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify that after a reset, the DUT
|
||||
# reattaches to the test network using parameters set in Active/Pending
|
||||
# Operational Datasets.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
# |
|
||||
# DUT
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Router
|
||||
# ED
|
||||
# SED
|
||||
|
||||
|
||||
class Cert_9_2_8_PersistentDatasets_Base(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': LEADER_ACTIVE_TIMESTAMP,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER, DUT]
|
||||
},
|
||||
DUT: {
|
||||
'name': 'DUT',
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpDUT(self):
|
||||
self.nodes[DUT].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[DUT].enable_allowlist()
|
||||
if self.TOPOLOGY[DUT]['mode'] == 'rdn':
|
||||
self.nodes[DUT].set_router_selection_jitter(1)
|
||||
else:
|
||||
self.nodes[DUT].set_timeout(config.DEFAULT_CHILD_TIMEOUT)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
|
||||
self.nodes[DUT].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
if self.TOPOLOGY[DUT]['mode'] == 'rdn':
|
||||
self.assertEqual(self.nodes[DUT].get_state(), 'router')
|
||||
else:
|
||||
self.assertEqual(self.nodes[DUT].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=COMMISSIONER_PENDING_TIMESTAMP,
|
||||
active_timestamp=COMMISSIONER_ACTIVE_TIMESTAMP,
|
||||
delay_timer=COMMISSIONER_DELAY_TIMER,
|
||||
channel=COMMISSIONER_PENDING_CHANNEL,
|
||||
panid=COMMISSIONER_PENDING_PANID,
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
# power down the DUT for 60 seconds
|
||||
self.nodes[DUT].reset()
|
||||
self.simulator.go(60)
|
||||
|
||||
# the network moves to COMMISSIONER_PENDING_PANID
|
||||
self.assertEqual(self.nodes[LEADER].get_panid(), COMMISSIONER_PENDING_PANID)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_panid(), COMMISSIONER_PENDING_PANID)
|
||||
self.assertEqual(self.nodes[LEADER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_channel(), COMMISSIONER_PENDING_CHANNEL)
|
||||
|
||||
# restart the DUT to attach to COMMISSIONER_PENDING_CHANNEL
|
||||
self.nodes[DUT].reset()
|
||||
self._setUpDUT()
|
||||
self.nodes[DUT].start()
|
||||
|
||||
self.assertEqual(self.nodes[DUT].get_panid(), PANID_INIT)
|
||||
self.assertEqual(self.nodes[DUT].get_channel(), CHANNEL_INIT)
|
||||
self.simulator.go(60)
|
||||
|
||||
self.assertEqual(self.nodes[DUT].get_panid(), COMMISSIONER_PENDING_PANID)
|
||||
self.assertEqual(self.nodes[DUT].get_channel(), COMMISSIONER_PENDING_CHANNEL)
|
||||
self.collect_ipaddrs()
|
||||
|
||||
ipaddr = self.nodes[DUT].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_MLEID = pv.vars['COMMISSIONER_MLEID']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
DUT_EXTADDR = pv.vars['DUT']
|
||||
DUT_MLEID = pv.vars['DUT_MLEID']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pv.verify_attached('COMMISSIONER', 'LEADER')
|
||||
if self.TOPOLOGY[DUT]['mode'] == 'rdn':
|
||||
pv.verify_attached('DUT', 'LEADER')
|
||||
else:
|
||||
pv.verify_attached('DUT', 'LEADER', 'MTD')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 2: Commissioner to send MGMT_PENDING_SET.req to the Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# coap://[<L>]:MM/c/ps
|
||||
# CoAP Payload
|
||||
# - valid Commissioner Session ID TLV
|
||||
# - Pending Timestamp TLV : 20s
|
||||
# - Active Timestamp TLV : 70s
|
||||
# - Delay Timer TLV : 60s
|
||||
# - Channel TLV : 20
|
||||
# - PAN ID TLV: 0xAFCE
|
||||
pkts.filter_coap_request(MGMT_PENDING_SET_URI).\
|
||||
filter_ipv6_2dsts(LEADER_RLOC, LEADER_ALOC).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.active_tstamp ==
|
||||
COMMISSIONER_ACTIVE_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.pending_tstamp ==
|
||||
COMMISSIONER_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.delay_timer ==
|
||||
COMMISSIONER_DELAY_TIMER and\
|
||||
p.thread_meshcop.tlv.channel ==
|
||||
[COMMISSIONER_PENDING_CHANNEL] and\
|
||||
p.thread_meshcop.tlv.pan_id ==
|
||||
[COMMISSIONER_PENDING_PANID] and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends MGMT_PENDING_SET.rsq to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
pkts.filter_coap_ack(MGMT_PENDING_SET_URI).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC).\
|
||||
must_next().\
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
if self.TOPOLOGY[DUT]['mode'] != '-':
|
||||
# Step 4: Leader sends a multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 70s
|
||||
# - Pending Timestamp TLV: 20s
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp ==
|
||||
LEADER_ACTIVE_TIMESTAMP and\
|
||||
p.mle.tlv.pending_tstamp ==
|
||||
COMMISSIONER_PENDING_TIMESTAMP and\
|
||||
p.mle.tlv.leader_data.data_version !=
|
||||
(_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version !=
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
else:
|
||||
# Step 5: Leader MUST send a MLE Child Update Request or MLE Data
|
||||
# Response to SED, including the following TLVs:
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Active Timestamp TLV: 70s
|
||||
# - Pending Timestamp TLV: 20s
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(DUT_EXTADDR).\
|
||||
filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp ==
|
||||
LEADER_ACTIVE_TIMESTAMP and\
|
||||
p.mle.tlv.pending_tstamp ==
|
||||
COMMISSIONER_PENDING_TIMESTAMP and\
|
||||
p.mle.tlv.leader_data.data_version !=
|
||||
(_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
|
||||
p.mle.tlv.leader_data.stable_data_version !=
|
||||
(_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256 and\
|
||||
NETWORK_DATA_TLV in p.mle.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: The DUT MUST send a MLE Data Request to the Leader and include its current
|
||||
# Active Timestamp
|
||||
pkts.filter_mle_cmd(MLE_DATA_REQUEST).\
|
||||
filter_wpan_src64(DUT_EXTADDR).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_nwd.tlv.type is nullField and\
|
||||
p.mle.tlv.active_tstamp == LEADER_ACTIVE_TIMESTAMP
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Leader sends a MLE Data Response including the following TLVs:
|
||||
# - Active Timestamp TLV
|
||||
# - Pending Timestamp TLV
|
||||
# - Pending Operational Dataset TLV
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(DUT_EXTADDR).\
|
||||
filter(lambda p: {
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: The DUT MUST attempt to reattach by sending Parent Request using the parameters
|
||||
# from Active Operational Dataset (Channel ='Primary', PANID: 0xFACE)
|
||||
# The DUT MUST then attach using the parameters from the Pending Operational
|
||||
# Dataset (Channel = 'Secondary', PANID:0xAFCE)
|
||||
for pan_id in (PANID_INIT, COMMISSIONER_PENDING_PANID):
|
||||
pkts.filter_mle_cmd(MLE_PARENT_REQUEST).\
|
||||
filter_wpan_src64(DUT_EXTADDR).\
|
||||
filter_LLARMA().\
|
||||
filter(lambda p: p.wpan.dst_pan == pan_id).\
|
||||
must_next()
|
||||
|
||||
# Step 10: The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_dst(DUT_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(DUT_EXTADDR).\
|
||||
filter_ipv6_dst(COMMISSIONER_MLEID).\
|
||||
must_next()
|
||||
|
||||
|
||||
class Cert_9_2_8_PersistentDatasets_ROUTER(Cert_9_2_8_PersistentDatasets_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_8_PersistentDatasets_Base.TOPOLOGY)
|
||||
TOPOLOGY[DUT]['mode'] = 'rdn'
|
||||
|
||||
|
||||
class Cert_9_2_8_PersistentDatasets_ED(Cert_9_2_8_PersistentDatasets_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_8_PersistentDatasets_Base.TOPOLOGY)
|
||||
TOPOLOGY[DUT]['mode'] = 'rn'
|
||||
TOPOLOGY[DUT]['is_mtd'] = True
|
||||
TOPOLOGY[DUT]['timeout'] = config.DEFAULT_CHILD_TIMEOUT
|
||||
|
||||
|
||||
class Cert_9_2_8_PersistentDatasets_SED(Cert_9_2_8_PersistentDatasets_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_8_PersistentDatasets_Base.TOPOLOGY)
|
||||
TOPOLOGY[DUT]['mode'] = '-'
|
||||
TOPOLOGY[DUT]['is_mtd'] = True
|
||||
TOPOLOGY[DUT]['timeout'] = config.DEFAULT_CHILD_TIMEOUT
|
||||
|
||||
|
||||
del (Cert_9_2_8_PersistentDatasets_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,762 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_DATA_RESPONSE, MLE_DATA_REQUEST, MGMT_PENDING_SET_URI, MGMT_ACTIVE_SET_URI, MGMT_DATASET_CHANGED_URI, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, TLV_REQUEST_TLV, NETWORK_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_DELAY_TIMER_TLV, PENDING_OPERATION_DATASET_TLV, NWD_COMMISSIONING_DATA_TLV, LEADER_ALOC, NM_ACTIVE_TIMESTAMP_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
TIMESTAMP_INIT = 10
|
||||
CHANNEL_SECOND = 20
|
||||
|
||||
CHANNEL_FINAL = 19
|
||||
PANID_FINAL = 0xabcd
|
||||
|
||||
ROUTER2_ACTIVE_TIMESTAMP = 15
|
||||
ROUTER2_PENDING_ACTIVE_TIMESTAMP = 410
|
||||
ROUTER2_PENDING_TIMESTAMP = 50
|
||||
ROUTER2_DELAY_TIMER = 200000
|
||||
ROUTER2_NET_NAME = 'TEST'
|
||||
|
||||
COMM_PENDING_ACTIVE_TIMESTAMP = 210
|
||||
COMM_PENDING_TIMESTAMP = 30
|
||||
COMM_DELAY_TIMER = 1000000
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ROUTER2 = 4
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify how Pending Operational Datasets
|
||||
# are synchronized when two partitions merge.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
# |
|
||||
# Router_1
|
||||
# |
|
||||
# Router_2
|
||||
#
|
||||
# Note: Router_1 and Router_2 will be in&out RF shield box
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Router
|
||||
|
||||
|
||||
class Cert_9_2_09_PendingPartition(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'partition_id': 0xffffffff,
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER2]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'active_dataset': {
|
||||
'timestamp': TIMESTAMP_INIT,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'network_id_timeout': 70,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=COMM_PENDING_TIMESTAMP,
|
||||
active_timestamp=COMM_PENDING_ACTIVE_TIMESTAMP,
|
||||
delay_timer=COMM_DELAY_TIMER,
|
||||
channel=CHANNEL_SECOND,
|
||||
panid=PANID_INIT,
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[LEADER].remove_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[ROUTER1].remove_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.nodes[ROUTER2].set_preferred_partition_id(1)
|
||||
self.simulator.go(250)
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'leader')
|
||||
|
||||
# Keeping network id timeout at 70 can result in ROUTER2
|
||||
# occasionally creating its own partition. Reset back to 120
|
||||
# here to avoid occasional test failures.
|
||||
self.nodes[ROUTER2].set_network_id_timeout(120)
|
||||
|
||||
self.nodes[ROUTER2].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
self.nodes[ROUTER2].send_mgmt_active_set(
|
||||
active_timestamp=ROUTER2_ACTIVE_TIMESTAMP,
|
||||
network_name=ROUTER2_NET_NAME,
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER2].send_mgmt_pending_set(
|
||||
pending_timestamp=ROUTER2_PENDING_TIMESTAMP,
|
||||
active_timestamp=ROUTER2_PENDING_ACTIVE_TIMESTAMP,
|
||||
delay_timer=ROUTER2_DELAY_TIMER,
|
||||
channel=CHANNEL_FINAL,
|
||||
panid=PANID_FINAL,
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.simulator.go(260)
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
self.collect_ipaddrs()
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[LEADER].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_panid(), PANID_FINAL)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_channel(), CHANNEL_FINAL)
|
||||
self.assertEqual(self.nodes[LEADER].get_channel(), CHANNEL_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_channel(), CHANNEL_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_channel(), CHANNEL_FINAL)
|
||||
|
||||
leader_addr = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
|
||||
router1_addr = self.nodes[ROUTER1].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
|
||||
self.assertTrue(self.nodes[ROUTER2].ping(leader_addr, timeout=10))
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(router1_addr, timeout=10))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
LEADER_MLEID = pv.vars['LEADER_MLEID']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_MLEID = pv.vars['COMMISSIONER_MLEID']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
COMMISSIONER_RLOC16 = pv.vars['COMMISSIONER_RLOC16']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_1_RLOC = pv.vars['ROUTER_1_RLOC']
|
||||
ROUTER_1_MLEID = pv.vars['ROUTER_1_MLEID']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
ROUTER_2_RLOC = pv.vars['ROUTER_2_RLOC']
|
||||
ROUTER_2_MLEID = pv.vars['ROUTER_2_MLEID']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
for node in ('COMMISSIONER', 'ROUTER_1'):
|
||||
pv.verify_attached(node, 'LEADER')
|
||||
pv.verify_attached('ROUTER_2', 'ROUTER_1')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 3: Leader sends MGMT_PENDING_SET.rsq to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
pkts.filter_coap_ack(MGMT_PENDING_SET_URI).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC).\
|
||||
must_next().\
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 4: Leader MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 10s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
#
|
||||
# Router_1 MUST send a unicast MLE Data Request to the Leader, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV (10s)
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
pkts.filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_DATA_REQUEST).\
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends a MLE Data Response to Router_1 including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 10s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Active Timestamp TLV <210s>
|
||||
# - Delay Timer TLV <~ 1000s>
|
||||
# - Channel TLV : ‘Secondary’
|
||||
# - PAN ID TLV : 0xAFCE
|
||||
_dr_pkt = pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER_1).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
|
||||
p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.delay_timer < COMM_DELAY_TIMER and\
|
||||
p.thread_meshcop.tlv.active_tstamp == COMM_PENDING_ACTIVE_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_SECOND] and\
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_INIT]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Router_1 MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 10s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
with pkts.save_index():
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Router_1 sends a MLE Data Response to Router_2 including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 10s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Active Timestamp TLV <210s>
|
||||
# - Delay Timer TLV <~ 1000s>
|
||||
# - Channel TLV : ‘Secondary’
|
||||
# - PAN ID TLV : 0xAFCE
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst64(ROUTER_2).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
|
||||
p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.delay_timer < COMM_DELAY_TIMER and\
|
||||
p.thread_meshcop.tlv.active_tstamp == COMM_PENDING_ACTIVE_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_SECOND] and\
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_INIT]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 10: Router_1 MUST attach to the new partition formed by Router_2
|
||||
pv.verify_attached('ROUTER_1', 'ROUTER_2')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 12: Router_1 MUST send a unicast MLE Data Request to the Router_2, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV (10s)
|
||||
# - Pending Timestamp TLV (30s)
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter_mle_cmd(MLE_DATA_REQUEST).\
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 14: Router_1 MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Pending Timestamp TLV: 30s
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 17: Router_1 MUST send a unicast MLE Data Request to the Router_2, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV (15s)
|
||||
# - Pending Timestamp TLV (30s)
|
||||
pkts.filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst64(ROUTER_2).\
|
||||
filter_mle_cmd(MLE_DATA_REQUEST).\
|
||||
filter(lambda p: {
|
||||
TLV_REQUEST_TLV,
|
||||
NETWORK_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.type is nullField
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 19: Router_1 MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Pending Timestamp TLV: 50s
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 21: Router_1 MUST go through the attachment process and send MLE Child ID
|
||||
# Request to the Leader, including the following TLV:
|
||||
# - Active Timestamp TLV: 15s
|
||||
pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).\
|
||||
filter_wpan_src64(ROUTER_1).\
|
||||
filter_wpan_dst64(LEADER).\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP).\
|
||||
must_next()
|
||||
|
||||
# Step 22: Leader MUST send MLE Child ID Response to Router_1, including its current
|
||||
# active timestamp and active configuration set:
|
||||
# - Active Timestamp TLV: 10s
|
||||
# - Active Operational Dataset TLV:
|
||||
# - Pending Timestamp TLV: 30s
|
||||
# - Pending Operational Dataset TLV:
|
||||
# - Active Timestamp TLV:210s
|
||||
_pkt = pkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER_1).\
|
||||
filter(lambda p:
|
||||
p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.active_tstamp == COMM_PENDING_ACTIVE_TIMESTAMP
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 23: Router_1 MUST send MGMT_ACTIVE_SET.req to the Leader RLOC or Anycast Locator:
|
||||
# CoAP Request URI
|
||||
# coap://[Leader]:MM/c/as
|
||||
# CoAP Payload
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Network Name TLV: “TEST”
|
||||
# - PAN ID TLV
|
||||
# - Channel TLV
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(ROUTER_1).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_ACTIVE_SET_URI) .\
|
||||
filter(lambda p: {
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_CHANNEL_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
NM_PAN_ID_TLV,
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.net_name == [ROUTER2_NET_NAME]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 24: Leader sends MGMT_ACTIVE_SET.rsp to the Router_1:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
# TODO: this ack can not be parsed by pktverify
|
||||
|
||||
# Step 25: Leader MUST send MGMT_DATASET_CHANGED.ntf to Commissioner:
|
||||
# CoAP Request URI
|
||||
# coap://[ Commissioner]:MM/c/dc
|
||||
# CoAP Payload
|
||||
# <empty>
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst16(COMMISSIONER_RLOC16).\
|
||||
filter_coap_request(MGMT_DATASET_CHANGED_URI) .\
|
||||
filter(lambda p: p.thread_meshcop.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 27: Router_1 MUST send MGMT_PENDING_SET.req to the Leader RLOC or Anycast Locator:
|
||||
# CoAP Request URI
|
||||
# coap://[Leader]:MM/c/ps
|
||||
# CoAP Payload
|
||||
# - Delay Timer TLV: ~200s
|
||||
# - Channel TLV : ‘Primary’
|
||||
# - PAN ID TLV : 0xABCD
|
||||
# - Network Name TLV: ‘TEST’
|
||||
# - Active Timestamp TLV: 410s
|
||||
# - Pending Timestamp TLV: 50s
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(ROUTER_1).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_PENDING_SET_URI) .\
|
||||
filter(lambda p:
|
||||
p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
|
||||
p.thread_meshcop.tlv.channel == [CHANNEL_FINAL] and\
|
||||
p.thread_meshcop.tlv.pan_id == [PANID_FINAL] and\
|
||||
p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
|
||||
p.thread_meshcop.tlv.net_name == [ROUTER2_NET_NAME]
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 28: Leader sends MGMT_PENDING_SET.rsq to the Router_1:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
# TODO: this ack can not be parsed by pktverify
|
||||
|
||||
# Step 29: Leader MUST send MGMT_DATASET_CHANGED.ntf to Commissioner:
|
||||
# CoAP Request URI
|
||||
# coap://[ Commissioner]:MM/c/dc
|
||||
# CoAP Payload
|
||||
# <empty>
|
||||
pkts.filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst16(COMMISSIONER_RLOC16).\
|
||||
filter_coap_request(MGMT_DATASET_CHANGED_URI) .\
|
||||
filter(lambda p: p.thread_meshcop.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 30: Leader MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Pending Timestamp TLV: 50s
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
#
|
||||
# Disable steps 32, 33, and 34 until a solution is
|
||||
# found. Depending on timing, there may be one MLE Data
|
||||
# Request/Response exchange for both Active and Pending
|
||||
# Operational Datasets or individual MLE Data Request/Response
|
||||
# exchange for each Active and Pending Operational Dataset
|
||||
# separately.
|
||||
#
|
||||
|
||||
# Step 32: Leader sends a MLE Data Response to Commissioner including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Active Operational Dataset TLV:
|
||||
# - Network Name TLV : ‘TEST’
|
||||
# - Pending Timestamp TLV: 50s
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Active Timestamp TLV <410s>
|
||||
# - Delay Timer TLV <~ 200s>
|
||||
# - Channel TLV : ‘Primary’
|
||||
# - PAN ID TLV : 0xABCD
|
||||
# - Network Name TLV : 'TEST'
|
||||
#with pkts.save_index():
|
||||
# pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
# filter_wpan_src64(LEADER).\
|
||||
# filter_wpan_dst64(COMMISSIONER).\
|
||||
# filter(lambda p: {
|
||||
# SOURCE_ADDRESS_TLV,
|
||||
# LEADER_DATA_TLV,
|
||||
# ACTIVE_TIMESTAMP_TLV,
|
||||
# PENDING_TIMESTAMP_TLV,
|
||||
# PENDING_OPERATION_DATASET_TLV
|
||||
# } <= set(p.mle.tlv.type) and\
|
||||
# p.thread_nwd.tlv.stable == [0] and\
|
||||
# NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
# NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
# NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
|
||||
# p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
# p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
|
||||
# p.thread_meshcop.tlv.net_name == [ROUTER2_NET_NAME, ROUTER2_NET_NAME] and\
|
||||
# p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
|
||||
# p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
|
||||
# p.thread_meshcop.tlv.channel == [CHANNEL_INIT, CHANNEL_FINAL] and\
|
||||
# p.thread_meshcop.tlv.pan_id == [PANID_INIT, PANID_FINAL]
|
||||
# ).\
|
||||
# must_next()
|
||||
|
||||
# Step 33: Router_1 MUST send a unicast MLE Data Request to the Leader, including the
|
||||
# following TLVs:
|
||||
# - TLV Request TLV:
|
||||
# - Network Data TLV
|
||||
# - Active Timestamp TLV (10s)
|
||||
# - Pending Timestamp TLV (30s)
|
||||
#pkts.filter_wpan_src64(ROUTER_1).\
|
||||
# filter_wpan_dst64(LEADER).\
|
||||
# filter_mle_cmd(MLE_DATA_REQUEST).\
|
||||
# filter(lambda p: {
|
||||
# TLV_REQUEST_TLV,
|
||||
# NETWORK_DATA_TLV,
|
||||
# ACTIVE_TIMESTAMP_TLV
|
||||
# } <= set(p.mle.tlv.type) and\
|
||||
# p.mle.tlv.active_tstamp == TIMESTAMP_INIT and\
|
||||
# p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and\
|
||||
# p.thread_meshcop.tlv.type is nullField
|
||||
# ).\
|
||||
# must_next()
|
||||
|
||||
# Step 34: Leader sends a MLE Data Response to Router_1 including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Active Timestamp TLV: 15s
|
||||
# - Active Operational Dataset TLV:
|
||||
# - Network Name TLV : ‘TEST’
|
||||
# - Pending Timestamp TLV: 50s
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Active Timestamp TLV <410s>
|
||||
# - Delay Timer TLV <~ 200s>
|
||||
# - Channel TLV : ‘Primary’
|
||||
# - PAN ID TLV : 0xABCD
|
||||
#pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
# filter_wpan_src64(LEADER).\
|
||||
# filter_wpan_dst64(ROUTER_1).\
|
||||
# filter(lambda p: {
|
||||
# SOURCE_ADDRESS_TLV,
|
||||
# LEADER_DATA_TLV,
|
||||
# ACTIVE_TIMESTAMP_TLV,
|
||||
# PENDING_TIMESTAMP_TLV,
|
||||
# PENDING_OPERATION_DATASET_TLV
|
||||
# } <= set(p.mle.tlv.type) and\
|
||||
# p.mle.tlv.active_tstamp == ROUTER2_ACTIVE_TIMESTAMP and\
|
||||
# p.mle.tlv.pending_tstamp == ROUTER2_PENDING_TIMESTAMP and\
|
||||
# p.thread_meshcop.tlv.delay_timer < ROUTER2_DELAY_TIMER and\
|
||||
# p.thread_meshcop.tlv.active_tstamp == ROUTER2_PENDING_ACTIVE_TIMESTAMP and\
|
||||
# p.thread_meshcop.tlv.channel == [CHANNEL_INIT, CHANNEL_FINAL] and\
|
||||
# p.thread_meshcop.tlv.pan_id == [PANID_INIT, PANID_FINAL]
|
||||
# ).\
|
||||
# must_next()
|
||||
|
||||
# Step 36: The DUT MUST respond with an ICMPv6 Echo Reply
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(ROUTER_2_MLEID, LEADER_MLEID).\
|
||||
filter_ipv6_dst(LEADER_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(LEADER_MLEID, ROUTER_2_MLEID).\
|
||||
must_next()
|
||||
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_ipv6_src_dst(COMMISSIONER_MLEID, ROUTER_1_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_ipv6_src_dst(ROUTER_1_MLEID, COMMISSIONER_MLEID).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,242 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_DATA_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, VERSION_TLV, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, CHALLENGE_TLV, LINK_MARGIN_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, PENDING_OPERATION_DATASET_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS, LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS, NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV, NM_ACTIVE_TIMESTAMP_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
|
||||
CHANNEL_FINAL = 16
|
||||
PANID_FINAL = 0xafce
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ED1 = 4
|
||||
SED1 = 5
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_9_2_10_PendingPartition(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'channel': 19
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'channel': 19
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'partition_id': 0xffffffff,
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'channel': 19
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED1, SED1]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'MED',
|
||||
'channel': 19,
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'channel': 19,
|
||||
'is_mtd': True,
|
||||
'mode': '-',
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=30,
|
||||
active_timestamp=165,
|
||||
delay_timer=250,
|
||||
channel=CHANNEL_FINAL,
|
||||
panid=PANID_FINAL,
|
||||
)
|
||||
self.simulator.go(260)
|
||||
|
||||
self.nodes[LEADER].remove_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[ROUTER1].remove_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.simulator.go(300)
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ED1].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[SED1].get_panid(), PANID_FINAL)
|
||||
|
||||
self.assertEqual(self.nodes[ROUTER1].get_channel(), CHANNEL_FINAL)
|
||||
self.assertEqual(self.nodes[ED1].get_channel(), CHANNEL_FINAL)
|
||||
self.assertEqual(self.nodes[SED1].get_channel(), CHANNEL_FINAL)
|
||||
|
||||
self.nodes[LEADER].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64())
|
||||
self.simulator.go(60)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
ipaddrs = self.nodes[ED1].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
|
||||
self.assertTrue(self.nodes[LEADER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
MED = pv.vars['MED']
|
||||
SED = pv.vars['SED']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER, cascade=False)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_rpkts.filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
|
||||
# Step 5: Router MUST send a unicast MLE Data Request to the Leader
|
||||
_rpkts.filter_wpan_dst64(LEADER).filter_mle_cmd(MLE_DATA_REQUEST).must_next().must_verify(
|
||||
lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
|
||||
_rpkts_med = _rpkts.copy()
|
||||
|
||||
# Step 7: Router MUST multicast a MLE Data Response
|
||||
_rpkts.filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).filter_mle_cmd(
|
||||
MLE_DATA_RESPONSE).must_next().must_verify(lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and {NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV} <= set(
|
||||
p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
|
||||
|
||||
# Step 8: MED MUST send a unicast MLE Data Request to Router_1,
|
||||
with pkts.save_index():
|
||||
pkts.filter_wpan_src64(MED).filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_REQUEST).must_next(
|
||||
).must_verify(lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 9: Router MUST send a unicast MLE Data Response to MED_1
|
||||
_rpkts_med.filter_wpan_dst64(MED).filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify(lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and {
|
||||
NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
|
||||
|
||||
# Step 10: Router MUST send MLE Child Update Request to SED_1
|
||||
_rpkts.range(pkts.index).filter_wpan_dst64(SED).filter_mle_cmd(
|
||||
MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 11: SED MUST send a unicast MLE Data Request to Router_1
|
||||
pkts.filter_wpan_src64(SED).filter_wpan_dst64(ROUTER).filter_mle_cmd(MLE_DATA_REQUEST).must_next().must_verify(
|
||||
lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 12: Router MUST send a unicast MLE Data Response to SED_1
|
||||
_pkt = _rpkts.filter_wpan_dst64(SED).filter_mle_cmd(MLE_DATA_RESPONSE).must_next()
|
||||
_pkt.must_verify(lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and {
|
||||
NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type))
|
||||
|
||||
# Step 14: After NETWORK_ID_TIMEOUT, Router MUST start a new partition
|
||||
_rpkts.filter_ipv6_dst(LINK_LOCAL_ALL_ROUTERS_MULTICAST_ADDRESS).filter_mle_cmd(
|
||||
MLE_PARENT_REQUEST).must_next().must_verify(lambda p: p.sniff_timestamp - _pkt.sniff_timestamp > 300)
|
||||
_rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter(lambda p: p.wpan.dst_pan == PANID_FINAL).must_next()
|
||||
|
||||
# Step 16: After the Delay Timer expires, Router MUST move to the Secondary channel
|
||||
_rpkts.filter_mle_cmd(MLE_ADVERTISEMENT).filter(lambda p: p.wpan.dst_pan == PANID_FINAL).must_next()
|
||||
|
||||
# Step 19: Router MUST reattach to the Leader and the partitions MUST merge
|
||||
pkts.filter_wpan_src64(LEADER).filter_wpan_dst64(ROUTER).filter_mle_cmd(
|
||||
MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.mle.tlv.leader_data.partition_id == 0xffffffff)
|
||||
|
||||
# Step 20: MED MUST respond with an ICMPv6 Echo Reply
|
||||
p = pkts.filter_ping_request().filter_wpan_src64(LEADER).must_next()
|
||||
pkts.filter_ping_reply(identifier=p.icmpv6.echo.identifier).filter_wpan_src64(MED).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,390 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_PARENT_REQUEST, MLE_DATA_RESPONSE, MLE_DATA_REQUEST, MGMT_PENDING_SET_URI, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_OPERATION_DATASET_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, TLV_REQUEST_TLV, NETWORK_DATA_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_DELAY_TIMER_TLV, PENDING_OPERATION_DATASET_TLV, NWD_COMMISSIONING_DATA_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
KEY1 = '00112233445566778899aabbccddeeff'
|
||||
KEY2 = 'ffeeddccbbaa99887766554433221100'
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ED1 = 4
|
||||
SED1 = 5
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to confirm the DUT correctly applies
|
||||
# DELAY_TIMER_DEFAULT when the network key is changed.
|
||||
# The Commissioner first tries to set a network 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.
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
# |
|
||||
# Router
|
||||
# / \
|
||||
# ED SED
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
|
||||
|
||||
class Cert_9_2_11_NetworkKey(thread_cert.TestCase):
|
||||
USE_MESSAGE_FACTORY = False
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': 10,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'network_key': KEY1
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 10,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'network_key': KEY1
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER',
|
||||
'active_dataset': {
|
||||
'timestamp': 10,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'network_key': KEY1
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED1, SED1]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'ED',
|
||||
'channel': CHANNEL_INIT,
|
||||
'is_mtd': True,
|
||||
'network_key': KEY1,
|
||||
'mode': 'rn',
|
||||
'panid': PANID_INIT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'channel': CHANNEL_INIT,
|
||||
'is_mtd': True,
|
||||
'network_key': KEY1,
|
||||
'mode': '-',
|
||||
'panid': PANID_INIT,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_ipaddrs()
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=10,
|
||||
active_timestamp=70,
|
||||
delay_timer=60000,
|
||||
network_key=KEY2,
|
||||
)
|
||||
self.simulator.go(310)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[LEADER].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[ED1].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[SED1].get_networkkey(), KEY2)
|
||||
|
||||
ipaddr = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(ipaddr))
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=20,
|
||||
active_timestamp=30,
|
||||
delay_timer=500000,
|
||||
network_key=KEY1,
|
||||
)
|
||||
self.simulator.go(510)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_networkkey(), KEY1)
|
||||
self.assertEqual(self.nodes[LEADER].get_networkkey(), KEY1)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_networkkey(), KEY1)
|
||||
self.assertEqual(self.nodes[ED1].get_networkkey(), KEY1)
|
||||
self.assertEqual(self.nodes[SED1].get_networkkey(), KEY1)
|
||||
|
||||
ipaddr = self.nodes[LEADER].get_ip6_address(config.ADDRESS_TYPE.ML_EID)
|
||||
self.assertTrue(self.nodes[ROUTER1].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_MLEID = pv.vars['LEADER_MLEID']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
ROUTER_MLEID = pv.vars['ROUTER_MLEID']
|
||||
ED = pv.vars['ED']
|
||||
SED = pv.vars['SED']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
for node in ('COMMISSIONER', 'ROUTER'):
|
||||
pv.verify_attached(node, 'LEADER')
|
||||
for node in ('ED', 'SED'):
|
||||
pv.verify_attached(node, 'ROUTER', 'MTD')
|
||||
_pkt = pkts.last()
|
||||
|
||||
# Step 3: Leader sends MGMT_PENDING_SET.rsq to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
#
|
||||
# Leader MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 10s
|
||||
# - Pending Timestamp TLV: 20s
|
||||
pkts.filter_coap_ack(MGMT_PENDING_SET_URI).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC).\
|
||||
must_next().\
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == 10 and\
|
||||
p.mle.tlv.pending_tstamp == 10 and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends a MLE Data Response to Router including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV
|
||||
# - Pending Timestamp TLV
|
||||
# - Pending Operational Dataset TLV
|
||||
# - Delay Timer TLV <greater than 200s>
|
||||
# - Network Key TLV: New Network Key
|
||||
# - Active Timestamp TLV <70s>
|
||||
_dr_pkt = pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
|
||||
p.thread_meshcop.tlv.delay_timer > 200000 and\
|
||||
p.thread_meshcop.tlv.master_key == KEY2 and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 70
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Verify all devices now use New Network key.
|
||||
# checked in test()
|
||||
|
||||
# Step 9: Verify new MAC key is generated and used when sending ICMPv6 Echo Reply
|
||||
# is received.
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(ROUTER).\
|
||||
filter_ipv6_dst(LEADER_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_MLEID).\
|
||||
must_next()
|
||||
|
||||
# Step 11: Leader sends MGMT_PENDING_SET.rsq to the Commissioner:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# - State TLV (value = Accept)
|
||||
#
|
||||
# Leader MUST multicast MLE Data Response with the new network data,
|
||||
# including the following TLVs:
|
||||
# - Leader Data TLV:
|
||||
# Data Version field incremented
|
||||
# Stable Version field incremented
|
||||
# - Network Data TLV:
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# Border Agent Locator TLV
|
||||
# Commissioner Session ID TLV
|
||||
# - Active Timestamp TLV: 70s
|
||||
# - Pending Timestamp TLV: 20s
|
||||
pkts.filter_coap_ack(MGMT_PENDING_SET_URI).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(COMMISSIONER_RLOC).\
|
||||
must_next().\
|
||||
must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_LLANMA().\
|
||||
filter(lambda p: p.mle.tlv.active_tstamp == 70 and\
|
||||
p.mle.tlv.pending_tstamp == 20 and\
|
||||
(p.mle.tlv.leader_data.data_version -
|
||||
_dr_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\
|
||||
(p.mle.tlv.leader_data.stable_data_version -
|
||||
_dr_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 13: Leader sends a MLE Data Response to Router including the following TLVs:
|
||||
# - Source Address TLV
|
||||
# - Leader Data TLV
|
||||
# - Network Data TLV
|
||||
# - Commissioner Data TLV:
|
||||
# Stable flag set to 0
|
||||
# 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 <greater than 300s>
|
||||
# - Network Key TLV: New Network Key
|
||||
pkts.filter_mle_cmd(MLE_DATA_RESPONSE).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_wpan_dst64(ROUTER).\
|
||||
filter(lambda p: {
|
||||
SOURCE_ADDRESS_TLV,
|
||||
LEADER_DATA_TLV,
|
||||
ACTIVE_TIMESTAMP_TLV,
|
||||
PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and\
|
||||
p.thread_nwd.tlv.stable == [0] and\
|
||||
NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and\
|
||||
NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and\
|
||||
NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type and\
|
||||
p.mle.tlv.active_tstamp == 70 and\
|
||||
p.mle.tlv.pending_tstamp == 20 and\
|
||||
p.thread_meshcop.tlv.delay_timer > 300000 and\
|
||||
p.thread_meshcop.tlv.master_key == KEY1 and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 30
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 17: The DUT MUST send an ICMPv6 Echo Reply using the new Network key
|
||||
_pkt = pkts.filter_ping_request().\
|
||||
filter_wpan_src64(ROUTER).\
|
||||
filter_ipv6_dst(LEADER_MLEID).\
|
||||
must_next()
|
||||
pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
|
||||
filter_wpan_src64(LEADER).\
|
||||
filter_ipv6_dst(ROUTER_MLEID).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,174 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_ANNOUNCE, CHANNEL_TLV, PAN_ID_TLV, ACTIVE_TIMESTAMP_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
LEADER1 = 1
|
||||
ROUTER1 = 2
|
||||
LEADER2 = 3
|
||||
MED = 4
|
||||
|
||||
DATASET1_TIMESTAMP = 20
|
||||
DATASET1_CHANNEL = 11
|
||||
DATASET1_PANID = 0xface
|
||||
|
||||
DATASET2_TIMESTAMP = 10
|
||||
DATASET2_CHANNEL = 12
|
||||
DATASET2_PANID = 0xafce
|
||||
|
||||
|
||||
class Cert_9_2_12_Announce(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER1: {
|
||||
'name': 'LEADER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': DATASET1_TIMESTAMP,
|
||||
'panid': DATASET1_PANID,
|
||||
'channel': DATASET1_CHANNEL
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': DATASET1_TIMESTAMP,
|
||||
'panid': DATASET1_PANID,
|
||||
'channel': DATASET1_CHANNEL
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER1, LEADER2]
|
||||
},
|
||||
LEADER2: {
|
||||
'name': 'LEADER_2',
|
||||
'active_dataset': {
|
||||
'timestamp': DATASET2_TIMESTAMP,
|
||||
'panid': DATASET2_PANID,
|
||||
'channel': DATASET2_CHANNEL
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [MED, ROUTER1]
|
||||
},
|
||||
MED: {
|
||||
'name': 'MED',
|
||||
'channel': DATASET2_CHANNEL,
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'panid': DATASET2_PANID,
|
||||
'allowlist': [LEADER2]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER1].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
|
||||
self.nodes[LEADER1].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[LEADER2].start()
|
||||
self.nodes[LEADER2].set_state('leader')
|
||||
self.assertEqual(self.nodes[LEADER2].get_state(), 'leader')
|
||||
|
||||
self.nodes[MED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
ipaddrs = self.nodes[ROUTER1].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
|
||||
self.nodes[LEADER1].announce_begin(0x1000, 1, 1000, ipaddr)
|
||||
self.simulator.go(30)
|
||||
self.assertEqual(self.nodes[LEADER2].get_state(), 'router')
|
||||
self.assertEqual(self.nodes[MED].get_state(), 'child')
|
||||
|
||||
self.collect_rlocs()
|
||||
ipaddrs = self.nodes[MED].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
self.assertTrue(self.nodes[LEADER1].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER_1 = pv.vars['LEADER_1']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
LEADER_2 = pv.vars['LEADER_2']
|
||||
LEADER_1_RLOC = pv.vars['LEADER_1_RLOC']
|
||||
MED = pv.vars['MED']
|
||||
MED_RLOC = pv.vars['MED_RLOC']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pkts.filter_wpan_src64(LEADER_1).filter_wpan_dst64(ROUTER_1).filter_mle_cmd(
|
||||
MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst_pan == DATASET1_PANID)
|
||||
pkts.copy().filter_wpan_src64(LEADER_2).filter_wpan_dst64(MED).filter_mle_cmd(
|
||||
MLE_CHILD_ID_RESPONSE).must_next().must_verify(lambda p: p.wpan.dst_pan == DATASET2_PANID)
|
||||
|
||||
# Step 4: Leader_2 MUST send a MLE Child ID Request on its new channel to Router_1
|
||||
# LEADER_2 MUST send a MLE Announce Message
|
||||
# The Destination PAN ID (0xFFFF) in the IEEE 802.15.4 MAC and MUST be secured using Key ID Mode 2.
|
||||
pkts.filter_wpan_src64(LEADER_2).filter_wpan_dst64(ROUTER_1).filter_mle_cmd(
|
||||
MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: p.wpan.dst_pan == DATASET1_PANID)
|
||||
|
||||
pkts.filter_wpan_src64(LEADER_2).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).filter_mle_cmd(
|
||||
MLE_ANNOUNCE).must_next().must_verify(
|
||||
lambda p: {CHANNEL_TLV, PAN_ID_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type) and p.wpan.dst_pan ==
|
||||
0xffff and p.wpan.aux_sec.key_id_mode == 0x2 and p.wpan.aux_sec.key_source == 0x00000000ffffffff)
|
||||
|
||||
# Step 5: MED MUST send a MLE Child ID Request on its new channel
|
||||
# MED MUST send a MLE Announce Message
|
||||
# The Destination PAN ID (0xFFFF) in the IEEE 802.15.4 MAC and MUST be secured using Key ID Mode 2.
|
||||
pkts.filter_wpan_src64(MED).filter_wpan_dst64(LEADER_2).filter_mle_cmd(
|
||||
MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: p.wpan.dst_pan == DATASET1_PANID)
|
||||
|
||||
pkts.filter_wpan_src64(MED).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).filter_mle_cmd(
|
||||
MLE_ANNOUNCE).must_next().must_verify(
|
||||
lambda p: {CHANNEL_TLV, PAN_ID_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type) and p.wpan.dst_pan ==
|
||||
0xffff and p.wpan.aux_sec.key_id_mode == 0x2 and p.wpan.aux_sec.key_source == 0x00000000ffffffff)
|
||||
|
||||
# Step 6: MED MUST respond with an ICMPv6 Echo Reply
|
||||
pkts.filter_ping_reply().filter_ipv6_src_dst(MED_RLOC, LEADER_1_RLOC).must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,162 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 copy
|
||||
import unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MGMT_ED_SCAN, MGMT_ED_REPORT, NM_CHANNEL_MASK_TLV, NM_ENERGY_LIST_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ED = 4
|
||||
|
||||
|
||||
class Cert_9_2_13_EnergyScan_Base(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED]
|
||||
},
|
||||
ED: {
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ED].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED].get_state(), 'child')
|
||||
self.collect_rlocs()
|
||||
|
||||
if self.TOPOLOGY[ED]['name'] == 'DUT':
|
||||
ipaddrs = self.nodes[ED].get_addrs()
|
||||
else:
|
||||
ipaddrs = self.nodes[ROUTER1].get_addrs()
|
||||
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
|
||||
self.nodes[COMMISSIONER].energy_scan(0x50000, 0x02, 0x20, 0xc8, ipaddr)
|
||||
self.simulator.go(3)
|
||||
self.nodes[COMMISSIONER].energy_scan(0x50000, 0x02, 0x20, 0xc8, 'ff33:0040:fd00:db8:0:0:0:1')
|
||||
self.simulator.go(3)
|
||||
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
DUT = pv.vars['DUT']
|
||||
DUT_RLOC = pv.vars['DUT_RLOC']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
_pkts = pkts.filter_wpan_src64(DUT)
|
||||
|
||||
# Step 3: The DUT MUST send MGMT_ED_REPORT.ans to the Commissioner and report energy measurements
|
||||
_pkts.filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_request(MGMT_ED_REPORT).must_next().must_verify(
|
||||
lambda p: {NM_CHANNEL_MASK_TLV, NM_ENERGY_LIST_TLV} <= set(p.thread_meshcop.tlv.type) and p.thread_meshcop.
|
||||
tlv.chan_mask_mask == '0000a000' and len(p.thread_meshcop.tlv.energy_list) == 2)
|
||||
|
||||
# Step 5: The DUT MUST send MGMT_ED_REPORT.ans to the Commissioner and report energy measurements
|
||||
_pkts.filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_request(MGMT_ED_REPORT).must_next().must_verify(
|
||||
lambda p: {NM_CHANNEL_MASK_TLV, NM_ENERGY_LIST_TLV} <= set(p.thread_meshcop.tlv.type) and p.thread_meshcop.
|
||||
tlv.chan_mask_mask == '0000a000' and len(p.thread_meshcop.tlv.energy_list) == 2)
|
||||
|
||||
# Step 6: The DUT MUST respond with ICMPv6 Echo Reply
|
||||
_pkts.filter_ping_reply().filter_ipv6_src_dst(DUT_RLOC, COMMISSIONER_RLOC).must_next()
|
||||
|
||||
|
||||
class Cert_9_2_13_EnergyScan_FED(Cert_9_2_13_EnergyScan_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
|
||||
TOPOLOGY[ED]['name'] = 'DUT'
|
||||
TOPOLOGY[ED]['router_upgrade_threshold'] = 0
|
||||
|
||||
|
||||
class Cert_9_2_13_EnergyScan_MED(Cert_9_2_13_EnergyScan_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
|
||||
TOPOLOGY[ED]['name'] = 'DUT'
|
||||
TOPOLOGY[ED]['mode'] = 'rn'
|
||||
TOPOLOGY[ED]['is_mtd'] = True
|
||||
|
||||
|
||||
class Cert_9_2_13_EnergyScan_ROUTER(Cert_9_2_13_EnergyScan_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'DUT'
|
||||
TOPOLOGY[ED]['name'] = 'ED'
|
||||
TOPOLOGY[ED]['mode'] = 'rn'
|
||||
TOPOLOGY[ED]['is_mtd'] = True
|
||||
|
||||
|
||||
class Cert_9_2_13_EnergyScan_SED(Cert_9_2_13_EnergyScan_Base):
|
||||
TOPOLOGY = copy.deepcopy(Cert_9_2_13_EnergyScan_Base.TOPOLOGY)
|
||||
TOPOLOGY[ROUTER1]['name'] = 'ROUTER'
|
||||
TOPOLOGY[ED]['name'] = 'DUT'
|
||||
TOPOLOGY[ED]['mode'] = '-'
|
||||
TOPOLOGY[ED]['is_mtd'] = True
|
||||
TOPOLOGY[ED]['timeout'] = config.DEFAULT_CHILD_TIMEOUT
|
||||
|
||||
|
||||
del (Cert_9_2_13_EnergyScan_Base)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,141 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_REQUEST, MGMT_PANID_QUERY, MGMT_PANID_CONFLICT, MGMT_ED_REPORT, NM_COMMISSIONER_SESSION_ID_TLV, NM_CHANNEL_MASK_TLV, NM_PAN_ID_TLV, REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER1 = 2
|
||||
ROUTER1 = 3
|
||||
LEADER2 = 4
|
||||
|
||||
|
||||
class Cert_9_2_14_PanIdQuery(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER1]
|
||||
},
|
||||
LEADER1: {
|
||||
'name': 'LEADER_1',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER1, LEADER2]
|
||||
},
|
||||
LEADER2: {
|
||||
'name': 'LEADER_2',
|
||||
'mode': 'rdn',
|
||||
'panid': 0xdead,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER1].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[LEADER2].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER2].get_state(), 'leader')
|
||||
|
||||
self.collect_rlocs()
|
||||
ipaddrs = self.nodes[ROUTER1].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
|
||||
self.nodes[COMMISSIONER].panid_query(0xdead, 0xffffffff, ipaddr)
|
||||
|
||||
self.nodes[COMMISSIONER].panid_query(0xdead, 0xffffffff, 'ff33:0040:fd00:db8:0:0:0:1')
|
||||
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
ROUTER = pv.vars['ROUTER']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
ROUTER_RLOC = pv.vars['ROUTER_RLOC']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
_rpkts = pkts.filter_wpan_src64(ROUTER)
|
||||
_cpkts = pkts.filter_wpan_src64(COMMISSIONER)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
_rpkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next()
|
||||
|
||||
# Step 2: Commissioner MUST send a unicast MGMT_PANID_QUERY.qry unicast to Router_1
|
||||
_cpkts.filter_ipv6_dst(ROUTER_RLOC).filter_coap_request(MGMT_PANID_QUERY).must_next().must_verify(
|
||||
lambda p: {NM_COMMISSIONER_SESSION_ID_TLV, NM_CHANNEL_MASK_TLV, NM_PAN_ID_TLV} <= set(p.thread_meshcop.tlv.
|
||||
type))
|
||||
|
||||
# Step 3: Router MUST send MGMT_ED_REPORT.ans to the Commissioner
|
||||
_rpkts.range(
|
||||
_cpkts.index).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_request(MGMT_PANID_CONFLICT).must_next(
|
||||
).must_verify(lambda p: {NM_CHANNEL_MASK_TLV, NM_PAN_ID_TLV} <= set(p.thread_meshcop.tlv.type))
|
||||
|
||||
# Step 4: Commissioner MUST send a multicast MGMT_PANID_QUERY.qry
|
||||
_cpkts.filter_ipv6_dst(REALM_LOCAL_ALL_THREAD_NODES_MULTICAST_ADDRESS).filter_coap_request(
|
||||
MGMT_PANID_QUERY).must_next().must_verify(
|
||||
lambda p: {NM_COMMISSIONER_SESSION_ID_TLV, NM_CHANNEL_MASK_TLV, NM_PAN_ID_TLV} <= set(p.thread_meshcop.
|
||||
tlv.type))
|
||||
|
||||
# Step 5: Router MUST send MGMT_PANID_CONFLICT.ans to the Commissioner
|
||||
_rpkts.range(
|
||||
_cpkts.index).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_request(MGMT_PANID_CONFLICT).must_next(
|
||||
).must_verify(lambda p: {NM_CHANNEL_MASK_TLV, NM_PAN_ID_TLV} <= set(p.thread_meshcop.tlv.type))
|
||||
|
||||
# Step 6: Router MUST respond with an ICMPv6 Echo Reply
|
||||
_rpkts.filter_ipv6_dst(COMMISSIONER_RLOC).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,198 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_CHILD_ID_REQUEST, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, ADDRESS_REGISTRATION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
|
||||
PANID_FINAL = 0xabcd
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ROUTER2 = 4
|
||||
|
||||
|
||||
class Cert_9_2_15_PendingPartition(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'partition_id': 0xffffffff,
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER2]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'active_dataset': {
|
||||
'timestamp': 15,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpRouter2(self):
|
||||
self.nodes[ROUTER2].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[ROUTER2].enable_allowlist()
|
||||
self.nodes[ROUTER2].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=10,
|
||||
active_timestamp=70,
|
||||
delay_timer=600000,
|
||||
mesh_local='fd00:0db9::',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].reset()
|
||||
self._setUpRouter2()
|
||||
self.simulator.go(100)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=20,
|
||||
active_timestamp=80,
|
||||
delay_timer=200000,
|
||||
mesh_local='fd00:0db7::',
|
||||
panid=PANID_FINAL,
|
||||
)
|
||||
self.simulator.go(100)
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_RESET_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
self.simulator.go(100)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[LEADER].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_panid(), PANID_FINAL)
|
||||
|
||||
ipaddrs = self.nodes[ROUTER2].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
self.assertTrue(self.nodes[LEADER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
_router2_pkts = pkts.filter_wpan_src64(ROUTER_2)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
# Verify Commissioner, Leader and Router_1 are sending MLE advertisements
|
||||
pkts.copy().filter_wpan_src64(LEADER).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
pkts.filter_wpan_dst64(COMMISSIONER).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
pkts.copy().filter_wpan_src64(COMMISSIONER).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
pkts.filter_wpan_dst64(ROUTER_1).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
pkts.copy().filter_wpan_src64(ROUTER_1).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
|
||||
# Step 5: Router_2 begins attach process by sending a multicast MLE Parent Request
|
||||
# The first MLE Parent Request sent MUST NOT be sent to all routers and REEDS
|
||||
_router2_pkts.range(pkts.index).filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0)
|
||||
|
||||
# Step 7: Router_2 MUST send a MLE Child ID Request to Router_1
|
||||
_router2_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type) and ADDRESS_REGISTRATION_TLV not in p.mle.tlv.type)
|
||||
|
||||
# Step 14: Router_2 begins attach process by sending a multicast MLE Parent Request
|
||||
# The first MLE Parent Request sent MUST NOT be sent to all routers and REEDS
|
||||
_router2_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0)
|
||||
|
||||
# Step 16: Router_2 MUST send a MLE Child ID Request to Router_1
|
||||
_router2_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type) and ADDRESS_REGISTRATION_TLV not in p.mle.tlv.type)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,208 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_CHILD_ID_REQUEST, MGMT_ACTIVE_SET_URI, MGMT_ACTIVE_GET_URI, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, ADDRESS_REGISTRATION_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
|
||||
NETWORK_NAME_FINAL = 'threadCert'
|
||||
PANID_FINAL = 0xabcd
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ROUTER2 = 4
|
||||
|
||||
|
||||
class Cert_9_2_16_ActivePendingPartition(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'partition_id': 0xffffffff,
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ROUTER2]
|
||||
},
|
||||
ROUTER2: {
|
||||
'name': 'ROUTER_2',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def _setUpRouter2(self):
|
||||
self.nodes[ROUTER2].add_allowlist(self.nodes[ROUTER1].get_addr64())
|
||||
self.nodes[ROUTER2].enable_allowlist()
|
||||
self.nodes[ROUTER2].set_router_selection_jitter(1)
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=10,
|
||||
active_timestamp=10,
|
||||
delay_timer=600000,
|
||||
mesh_local='fd00:0db9::',
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.nodes[ROUTER2].reset()
|
||||
self._setUpRouter2()
|
||||
self.simulator.go(100)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=20,
|
||||
active_timestamp=20,
|
||||
delay_timer=200000,
|
||||
mesh_local='fd00:0db7::',
|
||||
panid=PANID_FINAL,
|
||||
)
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(active_timestamp=15, network_name='threadCert')
|
||||
self.simulator.go(100)
|
||||
|
||||
self.nodes[ROUTER2].start()
|
||||
self.simulator.go(config.ROUTER_RESET_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_state(), 'router')
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_network_name(), NETWORK_NAME_FINAL)
|
||||
self.assertEqual(self.nodes[LEADER].get_network_name(), NETWORK_NAME_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_network_name(), NETWORK_NAME_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_network_name(), NETWORK_NAME_FINAL)
|
||||
|
||||
self.simulator.go(100)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[LEADER].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_panid(), PANID_FINAL)
|
||||
self.assertEqual(self.nodes[ROUTER2].get_panid(), PANID_FINAL)
|
||||
|
||||
ipaddrs = self.nodes[ROUTER2].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
if ipaddr[0:4] != 'fe80':
|
||||
break
|
||||
self.assertTrue(self.nodes[LEADER].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
ROUTER_2 = pv.vars['ROUTER_2']
|
||||
_router2_pkts = pkts.filter_wpan_src64(ROUTER_2)
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
# Verify Commissioner, Leader and Router_1 are sending MLE advertisements
|
||||
pkts.copy().filter_wpan_src64(LEADER).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
pkts.filter_wpan_dst64(COMMISSIONER).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
pkts.copy().filter_wpan_src64(COMMISSIONER).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
pkts.filter_wpan_dst64(ROUTER_1).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
pkts.copy().filter_wpan_src64(ROUTER_1).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
|
||||
# Step 5: Router_2 begins attach process by sending a multicast MLE Parent Request
|
||||
# The first MLE Parent Request sent MUST NOT be sent to all routers and REEDS
|
||||
_router2_pkts.range(pkts.index).filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0)
|
||||
|
||||
# Step 7: Router_2 MUST send a MLE Child ID Request to Router_1
|
||||
_router2_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type) and ADDRESS_REGISTRATION_TLV not in p.mle.tlv.type)
|
||||
|
||||
# Step 14: Router_2 begins attach process by sending a multicast MLE Parent Request
|
||||
# The first MLE Parent Request sent MUST NOT be sent to all routers and REEDS
|
||||
_router2_pkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next().must_verify(
|
||||
lambda p: {MODE_TLV, CHALLENGE_TLV, SCAN_MASK_TLV, VERSION_TLV} <= set(
|
||||
p.mle.tlv.type) and p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0)
|
||||
|
||||
# Step 16: Router_2 MUST send a MLE Child ID Request to Router_1
|
||||
_router2_pkts.filter_mle_cmd(MLE_CHILD_ID_REQUEST).must_next().must_verify(lambda p: {
|
||||
RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV
|
||||
} <= set(p.mle.tlv.type) and ADDRESS_REGISTRATION_TLV not in p.mle.tlv.type)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,147 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_REQUEST, MLE_CHILD_ID_RESPONSE, MLE_ANNOUNCE, CHANNEL_TLV, PAN_ID_TLV, ACTIVE_TIMESTAMP_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
|
||||
CHANNEL1 = 11
|
||||
CHANNEL2 = 18
|
||||
CHANNEL_MASK = 1 << 18
|
||||
PANID_INIT = 0xface
|
||||
|
||||
LEADER1 = 1
|
||||
LEADER2 = 2
|
||||
ED1 = 3
|
||||
|
||||
|
||||
class Cert_9_2_17_Orphan(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
LEADER1: {
|
||||
'name': 'LEADER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': 10,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL1,
|
||||
'channel_mask': CHANNEL_MASK
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [ED1]
|
||||
},
|
||||
LEADER2: {
|
||||
'name': 'LEADER_2',
|
||||
'active_dataset': {
|
||||
'timestamp': 20,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL2,
|
||||
'channel_mask': CHANNEL_MASK
|
||||
},
|
||||
'mode': 'rdn',
|
||||
},
|
||||
ED1: {
|
||||
'name': 'ED',
|
||||
'channel': CHANNEL1,
|
||||
'is_mtd': True,
|
||||
'mode': 'rn',
|
||||
'panid': PANID_INIT,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [LEADER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER1].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER1].get_state(), 'leader')
|
||||
|
||||
self.nodes[LEADER2].start()
|
||||
self.nodes[LEADER2].set_state('leader')
|
||||
self.assertEqual(self.nodes[LEADER2].get_state(), 'leader')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[LEADER1].stop()
|
||||
self.nodes[LEADER2].add_allowlist(self.nodes[ED1].get_addr64())
|
||||
self.nodes[ED1].add_allowlist(self.nodes[LEADER2].get_addr64())
|
||||
self.simulator.go(20)
|
||||
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
self.assertEqual(self.nodes[ED1].get_channel(), CHANNEL2)
|
||||
|
||||
self.collect_ipaddrs()
|
||||
ipaddrs = self.nodes[ED1].get_addrs()
|
||||
for ipaddr in ipaddrs:
|
||||
self.assertTrue(self.nodes[LEADER2].ping(ipaddr))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER_1 = pv.vars['LEADER_1']
|
||||
LEADER_2 = pv.vars['LEADER_2']
|
||||
ED = pv.vars['ED']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
# Verify that Leader_1 & Leader_2 are sending MLE Advertisements on separate channels.
|
||||
pkts.copy().filter_wpan_src64(LEADER_1).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
pkts.copy().filter_wpan_src64(LEADER_2).filter_mle_cmd(MLE_ADVERTISEMENT).must_next()
|
||||
pkts.filter_wpan_src64(LEADER_1).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next().must_verify(
|
||||
lambda p: p.wpan.dst64 == ED and p.thread_meshcop.tlv.channel == [CHANNEL1])
|
||||
|
||||
# Step 4: powers-down Leader_1 and enables connectivity between the ED and Leader_2
|
||||
# ED MUST send a MLE Parent Request
|
||||
_epkts = pkts.filter_wpan_src64(ED)
|
||||
_epkts.filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
|
||||
|
||||
# Step 6: ED MUST send a MLE Announce Message
|
||||
# The Destination PAN ID (0xFFFF) in the IEEE 802.15.4 MAC and MUST be secured using Key ID Mode 2.
|
||||
_epkts.filter_mle_cmd(MLE_ANNOUNCE).must_next().must_verify(
|
||||
lambda p: {CHANNEL_TLV, PAN_ID_TLV, ACTIVE_TIMESTAMP_TLV} <= set(
|
||||
p.mle.tlv.type) and p.wpan.dst_pan == 0xffff and p.wpan.aux_sec.key_id_mode == 0x2)
|
||||
|
||||
# Step 8: ED MUST attempt to attach on the Secondary channel,
|
||||
# with the new PAN ID it received in the MLE Announce message from Leader_2
|
||||
pkts.range(_epkts.index).filter_mle_cmd(MLE_ANNOUNCE).filter_wpan_src64(LEADER_2).filter_wpan_dst64(
|
||||
ED).must_next().must_verify(lambda p: p.mle.tlv.channel == CHANNEL2)
|
||||
_epkts.range(pkts.index).filter_mle_cmd(MLE_PARENT_REQUEST).must_next()
|
||||
|
||||
# Step 9: ED MUST respond with an ICMPv6 Echo Reply
|
||||
_epkts.filter('ipv6.dst == {LEADER_2_MLEID} and ipv6.src == {ED_MLEID}',
|
||||
**pv.vars).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,258 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2016, 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 unittest
|
||||
|
||||
import config
|
||||
import thread_cert
|
||||
from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE, MLE_DATA_REQUEST, MGMT_ACTIVE_SET_URI, MGMT_PENDING_SET_URI, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, PENDING_OPERATION_DATASET_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_KEY_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV, NM_DELAY_TIMER_TLV
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.addrs import Ipv6Addr
|
||||
|
||||
KEY1 = '00112233445566778899aabbccddeeff'
|
||||
KEY2 = 'ffeeddccbbaa99887766554433221100'
|
||||
|
||||
CHANNEL_INIT = 19
|
||||
PANID_INIT = 0xface
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
ROUTER1 = 3
|
||||
ED1 = 4
|
||||
SED1 = 5
|
||||
|
||||
MTDS = [ED1, SED1]
|
||||
|
||||
|
||||
class Cert_9_2_18_RollBackActiveTimestamp(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'network_key': KEY1
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'network_key': KEY1
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'partition_id': 0xffffffff,
|
||||
'allowlist': [COMMISSIONER, ROUTER1]
|
||||
},
|
||||
ROUTER1: {
|
||||
'name': 'ROUTER_1',
|
||||
'active_dataset': {
|
||||
'timestamp': 1,
|
||||
'panid': PANID_INIT,
|
||||
'channel': CHANNEL_INIT,
|
||||
'network_key': KEY1
|
||||
},
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER, ED1, SED1]
|
||||
},
|
||||
ED1: {
|
||||
'name': 'ED',
|
||||
'channel': CHANNEL_INIT,
|
||||
'is_mtd': True,
|
||||
'network_key': KEY1,
|
||||
'mode': 'rn',
|
||||
'panid': PANID_INIT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
SED1: {
|
||||
'name': 'SED',
|
||||
'channel': CHANNEL_INIT,
|
||||
'is_mtd': True,
|
||||
'network_key': KEY1,
|
||||
'mode': '-',
|
||||
'panid': PANID_INIT,
|
||||
'timeout': config.DEFAULT_CHILD_TIMEOUT,
|
||||
'allowlist': [ROUTER1]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[ROUTER1].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
|
||||
|
||||
self.nodes[ED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[ED1].get_state(), 'child')
|
||||
|
||||
self.nodes[SED1].start()
|
||||
self.simulator.go(5)
|
||||
self.assertEqual(self.nodes[SED1].get_state(), 'child')
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_active_set(active_timestamp=20000, network_name='GRL')
|
||||
self.simulator.go(5)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=20,
|
||||
active_timestamp=20,
|
||||
delay_timer=20,
|
||||
network_name='Shouldnotbe',
|
||||
)
|
||||
self.simulator.go(30)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
pending_timestamp=20,
|
||||
active_timestamp=20,
|
||||
delay_timer=300,
|
||||
network_name='MyHouse',
|
||||
network_key=KEY2,
|
||||
)
|
||||
self.simulator.go(310)
|
||||
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[LEADER].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[ROUTER1].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[ED1].get_networkkey(), KEY2)
|
||||
self.assertEqual(self.nodes[SED1].get_networkkey(), KEY2)
|
||||
|
||||
self.collect_rlocs()
|
||||
ed_rloc = self.nodes[ED1].get_rloc()
|
||||
sed_rloc = self.nodes[SED1].get_rloc()
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(ed_rloc))
|
||||
self.assertTrue(self.nodes[COMMISSIONER].ping(sed_rloc))
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
ROUTER_1 = pv.vars['ROUTER_1']
|
||||
SED = pv.vars['SED']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
ED_RLOC = pv.vars['ED_RLOC']
|
||||
SED_RLOC = pv.vars['SED_RLOC']
|
||||
|
||||
# Step 1: Ensure the topology is formed correctly
|
||||
pkts.filter_wpan_src64(ROUTER_1).filter_wpan_dst64(SED).filter_mle_cmd(MLE_CHILD_ID_RESPONSE).must_next()
|
||||
|
||||
# Step 3: Leader MUST send MGMT_ACTIVE_SET.rsp (Accept) to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(
|
||||
MGMT_ACTIVE_SET_URI).must_next().must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 5: Leader MUST send MGMT_PENDING_SET.rsp (Reject) to the Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(
|
||||
MGMT_PENDING_SET_URI).must_next().must_verify(lambda p: p.thread_meshcop.tlv.state == -1)
|
||||
|
||||
# Step 7: Leader MUST send MGMT_PENDING_SET.rsp (Accept) to Commissioner
|
||||
pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(COMMISSIONER_RLOC).filter_coap_ack(
|
||||
MGMT_PENDING_SET_URI).must_next().must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
|
||||
|
||||
# Step 8: Leader MUST multicast a MLE Data Response to the Link-Local All Nodes multicast address
|
||||
_pkt = pkts.filter_wpan_src64(LEADER).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).filter_mle_cmd(
|
||||
MLE_DATA_RESPONSE).must_next()
|
||||
_pkt.must_verify(lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and {NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV} <= set(
|
||||
p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
|
||||
|
||||
# Step 9: Router MUST send a unicast MLE Data Request to the Leader
|
||||
pkts.filter_wpan_src64(ROUTER_1).filter_wpan_dst64(LEADER).filter_mle_cmd(MLE_DATA_REQUEST).must_next(
|
||||
).must_verify(lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 10: Leader MUST send a unicast MLE Data Response to Router_1
|
||||
pkts.filter_wpan_src64(LEADER).filter_wpan_dst64(ROUTER_1).filter_mle_cmd(
|
||||
MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and {
|
||||
NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_NETWORK_NAME_TLV, NM_NETWORK_KEY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
|
||||
|
||||
# Copy a pv.pkts here to filter SED related packets for potential sequence packets disorder
|
||||
_pkts_sed = pkts.copy()
|
||||
|
||||
# Step 11: Router MUST multicast a MLE Data Response with the new information
|
||||
pkts.filter_wpan_src64(ROUTER_1).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).filter_mle_cmd(
|
||||
MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and p.mle.tlv.leader_data.data_version == _pkt.mle.tlv.leader_data.
|
||||
data_version and p.mle.tlv.leader_data.stable_data_version == _pkt.mle.tlv.leader_data.
|
||||
stable_data_version and {NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV} <= set(
|
||||
p.thread_meshcop.tlv.type) and p.thread_nwd.tlv.stable == [0])
|
||||
|
||||
# Step 12: Router MUST send MLE Child Update Request to SED_1
|
||||
pkts.filter_wpan_src64(ROUTER_1).filter_wpan_dst64(SED).filter_mle_cmd(
|
||||
MLE_CHILD_UPDATE_REQUEST).must_next().must_verify(lambda p: {
|
||||
SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV
|
||||
} <= set(p.mle.tlv.type) and p.mle.tlv.leader_data.data_version == _pkt.mle.tlv.leader_data.data_version)
|
||||
|
||||
# Step 13: SED MUST send a unicast MLE Data Request to Router_1
|
||||
_pkts_sed.filter_wpan_src64(SED).filter_wpan_dst64(ROUTER_1).filter_mle_cmd(MLE_DATA_REQUEST).must_next(
|
||||
).must_verify(lambda p: {TLV_REQUEST_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set(p.mle.tlv.type))
|
||||
|
||||
# Step 14: Router MUST send a unicast MLE Data Response to SED_1
|
||||
_pkts_sed.filter_wpan_src64(ROUTER_1).filter_wpan_dst64(SED).filter_mle_cmd(
|
||||
MLE_DATA_RESPONSE).must_next().must_verify(
|
||||
lambda p: {
|
||||
SOURCE_ADDRESS_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV,
|
||||
PENDING_OPERATION_DATASET_TLV
|
||||
} <= set(p.mle.tlv.type) and {
|
||||
NM_CHANNEL_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_DELAY_TIMER_TLV,
|
||||
NM_ACTIVE_TIMESTAMP_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_KEY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and p.thread_meshcop.tlv.net_name == ["MyHouse"] and p.
|
||||
thread_meshcop.tlv.master_key == KEY2)
|
||||
|
||||
# Step 17: MED and SED MUST respond with an ICMPv6 Echo Reply
|
||||
pkts.filter_ipv6_src_dst(ED_RLOC, COMMISSIONER_RLOC).filter_ping_reply().must_next()
|
||||
pkts.filter_ipv6_src_dst(SED_RLOC, COMMISSIONER_RLOC).filter_ping_reply().must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -1,293 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Copyright (c) 2020, 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 unittest
|
||||
|
||||
import config
|
||||
import mesh_cop
|
||||
import thread_cert
|
||||
from pktverify.consts import MGMT_PENDING_GET_URI, MGMT_PENDING_SET_URI, NM_CHANNEL_TLV, NM_PAN_ID_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PSKC_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_KEY_TLV, NM_SECURITY_POLICY_TLV, NM_PENDING_TIMESTAMP_TLV, NM_DELAY_TIMER_TLV, LEADER_ALOC
|
||||
from pktverify.packet_verifier import PacketVerifier
|
||||
from pktverify.null_field import nullField
|
||||
|
||||
COMMISSIONER = 1
|
||||
LEADER = 2
|
||||
|
||||
# Test Purpose and Description:
|
||||
# -----------------------------
|
||||
# The purpose of this test case is to verify Leader's and active Commissioner's behavior via
|
||||
# MGMT_PENDING_GET request and response
|
||||
#
|
||||
# Test Topology:
|
||||
# -------------
|
||||
# Commissioner
|
||||
# |
|
||||
# Leader
|
||||
#
|
||||
# DUT Types:
|
||||
# ----------
|
||||
# Leader
|
||||
# Commissioner
|
||||
|
||||
|
||||
class Cert_9_2_19_PendingDatasetGet(thread_cert.TestCase):
|
||||
SUPPORT_NCP = False
|
||||
|
||||
TOPOLOGY = {
|
||||
COMMISSIONER: {
|
||||
'name': 'COMMISSIONER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [LEADER]
|
||||
},
|
||||
LEADER: {
|
||||
'name': 'LEADER',
|
||||
'mode': 'rdn',
|
||||
'allowlist': [COMMISSIONER]
|
||||
},
|
||||
}
|
||||
|
||||
def test(self):
|
||||
self.nodes[LEADER].start()
|
||||
self.simulator.go(config.LEADER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
|
||||
|
||||
self.nodes[COMMISSIONER].start()
|
||||
self.simulator.go(config.ROUTER_STARTUP_DELAY)
|
||||
self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
|
||||
self.simulator.get_messages_sent_by(LEADER)
|
||||
|
||||
self.collect_rlocs()
|
||||
self.collect_rloc16s()
|
||||
|
||||
leader_rloc = self.nodes[LEADER].get_rloc()
|
||||
|
||||
self.nodes[COMMISSIONER].commissioner_start()
|
||||
self.simulator.go(3)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_get()
|
||||
self.simulator.go(2)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_set(
|
||||
active_timestamp=60,
|
||||
delay_timer=60000,
|
||||
panid=0xAFCE,
|
||||
pending_timestamp=30,
|
||||
)
|
||||
self.simulator.go(2)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_get()
|
||||
self.simulator.go(2)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_get(leader_rloc, [mesh_cop.TlvType.PAN_ID])
|
||||
self.simulator.go(92)
|
||||
|
||||
self.nodes[COMMISSIONER].send_mgmt_pending_get()
|
||||
self.simulator.go(2)
|
||||
|
||||
def verify(self, pv):
|
||||
pkts = pv.pkts
|
||||
pv.summary.show()
|
||||
|
||||
LEADER = pv.vars['LEADER']
|
||||
LEADER_RLOC = pv.vars['LEADER_RLOC']
|
||||
COMMISSIONER = pv.vars['COMMISSIONER']
|
||||
COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
|
||||
|
||||
# Step 1: Ensure topology is formed correctly
|
||||
pv.verify_attached('COMMISSIONER', 'LEADER')
|
||||
|
||||
# Step 2: Commissioner sends a MGMT_PENDING_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/pg
|
||||
# CoAP Payload
|
||||
# <empty> - get all Active Operational Dataset parameters
|
||||
_mgmt_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: p.coap.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 3: Leader sends a MGMT_PENDING_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# <empty> - (no Pending Operational Dataset)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: p.coap.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 4: Commissioner sends a MGMT_PENDING_SET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/ps
|
||||
# CoAP Payload
|
||||
# Active Timestamp TLV: 60s
|
||||
# Commissioner Session ID TLV (valid)
|
||||
# Delay Timer TLV: 1 minute
|
||||
# Pending Timestamp TLV: 30s
|
||||
# PAN ID TLV: 0xAFCE (new value)
|
||||
_mgmt_pending_set_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_PENDING_SET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_PENDING_TIMESTAMP_TLV,
|
||||
NM_DELAY_TIMER_TLV,
|
||||
NM_PAN_ID_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type) and\
|
||||
p.thread_meshcop.tlv.active_tstamp == 60 and\
|
||||
p.thread_meshcop.tlv.pan_id == [0xafce] and\
|
||||
p.thread_meshcop.tlv.delay_timer == 60000
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 5: Leader sends a MGMT_PENDING_SET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# State TLV (value = Accept (01))
|
||||
pkts.filter_ipv6_src_dst(_mgmt_pending_set_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_PENDING_SET_URI).\
|
||||
filter(lambda p:
|
||||
p.thread_meshcop.tlv.state == 1
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 6: Commissioner sends a MGMT_PENDING_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/pg
|
||||
# CoAP Payload
|
||||
# <empty> - get all Active Operational Dataset parameters
|
||||
_mgmt_pending_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: p.coap.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 7: Leader sends a MGMT_PENDING_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# (entire Active Operational Dataset)
|
||||
# Active Timestamp TLV
|
||||
# Channel TLV
|
||||
# Channel Mask TLV
|
||||
# Delay Timer TLV
|
||||
# Extended PAN ID TLV
|
||||
# Network Mesh-Local Prefix TLV
|
||||
# Network Key TLV
|
||||
# Network Name TLV
|
||||
# PAN ID TLV
|
||||
# Pending Timestamp TLV
|
||||
# PSKc TLV
|
||||
# Security Policy TLV
|
||||
pkts.filter_ipv6_src_dst(_mgmt_pending_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_ACTIVE_TIMESTAMP_TLV,
|
||||
NM_CHANNEL_TLV,
|
||||
NM_CHANNEL_MASK_TLV,
|
||||
NM_DELAY_TIMER_TLV,
|
||||
NM_EXTENDED_PAN_ID_TLV,
|
||||
NM_NETWORK_MESH_LOCAL_PREFIX_TLV,
|
||||
NM_NETWORK_KEY_TLV,
|
||||
NM_NETWORK_NAME_TLV,
|
||||
NM_PAN_ID_TLV,
|
||||
NM_PENDING_TIMESTAMP_TLV,
|
||||
NM_PSKC_TLV,
|
||||
NM_SECURITY_POLICY_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 8: Commissioner sends a MGMT_PENDING_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/pg
|
||||
# CoAP Payload
|
||||
# PAN ID TLV
|
||||
_mgmt_pending_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_PAN_ID_TLV
|
||||
} <= set(p.thread_meshcop.tlv.type)
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 9: Leader sends a MGMT_PENDING_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# PAN ID TLV
|
||||
# Delay Timer TLV
|
||||
pkts.filter_ipv6_src_dst(_mgmt_pending_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: {
|
||||
NM_DELAY_TIMER_TLV,
|
||||
NM_PAN_ID_TLV
|
||||
} <= set(p.coap.tlv.type) and\
|
||||
p.thread_meshcop.tlv.pan_id == [0xafce] and\
|
||||
p.thread_meshcop.tlv.delay_timer < 60000
|
||||
).\
|
||||
must_next()
|
||||
|
||||
# Step 11: Commissioner sends a MGMT_PENDING_GET.req to Leader Anycast
|
||||
# or Routing Locator:
|
||||
# CoAP Request URI
|
||||
# CON POST coap://<L>:MM/c/pg
|
||||
# CoAP Payload
|
||||
# <empty> - get all Active Operational Dataset parameters
|
||||
_mgmt_pending_get_pkt = pkts.filter_wpan_src64(COMMISSIONER).\
|
||||
filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\
|
||||
filter_coap_request(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: p.coap.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
# Step 12: Leader sends a MGMT_PENDING_GET.rsp to Commissioner with
|
||||
# the following format:
|
||||
# CoAP Response Code
|
||||
# 2.04 Changed
|
||||
# CoAP Payload
|
||||
# <empty> - (no Pending Operational Dataset)
|
||||
pkts.filter_ipv6_src_dst(_mgmt_pending_get_pkt.ipv6.dst, COMMISSIONER_RLOC).\
|
||||
filter_coap_ack(MGMT_PENDING_GET_URI).\
|
||||
filter(lambda p: p.thread_meshcop.tlv.type is nullField).\
|
||||
must_next()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user