From 3cb8c7b03d0e3c4aa2fdeed5113e348c8531a9d0 Mon Sep 17 00:00:00 2001 From: Jing Ma Date: Fri, 11 Dec 2020 23:35:44 +0800 Subject: [PATCH] [thread-cert] add case 8.3.1 CommissionerPetition using pktverify (#5904) Also fix wrong COMMISSIONING_DATA_TLV const in cases 5.6.6 and 5.6.9. --- .../Cert_5_6_06_NetworkDataExpiration.py | 6 +- .../Cert_5_6_09_NetworkDataForwarding.py | 32 +- .../Cert_8_3_01_CommissionerPetition.py | 370 ++++++++++++++++++ tests/scripts/thread-cert/node.py | 5 + tests/scripts/thread-cert/pktverify/consts.py | 15 +- 5 files changed, 407 insertions(+), 21 deletions(-) create mode 100755 tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py diff --git a/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py b/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py index b557f0296..d89b0c756 100755 --- a/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py +++ b/tests/scripts/thread-cert/Cert_5_6_06_NetworkDataExpiration.py @@ -31,7 +31,7 @@ import unittest import config import thread_cert -from pktverify.consts import MLE_ADVERTISEMENT, SVR_DATA_URI, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_SERVICE_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS +from pktverify.consts import MLE_ADVERTISEMENT, SVR_DATA_URI, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS from pktverify.packet_verifier import PacketVerifier from pktverify.addrs import Ipv6Addr @@ -166,7 +166,7 @@ class Cert_5_6_6_NetworkDataExpiration(thread_cert.TestCase): _lpkts_sed = _lpkts.copy() _lpkts.filter_LLANMA().filter_mle_cmd(MLE_DATA_RESPONSE).must_next().must_verify( lambda p: { - NWD_SERVICE_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, + NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV } == set(p.thread_nwd.tlv.type) and { Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::'), @@ -200,7 +200,7 @@ class Cert_5_6_6_NetworkDataExpiration(thread_cert.TestCase): LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS ).must_next().must_verify( lambda p: { - NWD_SERVICE_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, + NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV } == set(p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::'), diff --git a/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py b/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py index 20812d194..d3e834f0f 100755 --- a/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py +++ b/tests/scripts/thread-cert/Cert_5_6_09_NetworkDataForwarding.py @@ -31,7 +31,7 @@ import unittest import config import thread_cert -from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_SERVICE_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_HAS_ROUTER_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS +from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_HAS_ROUTER_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS from pktverify.packet_verifier import PacketVerifier from pktverify.addrs import Ipv6Addr @@ -181,15 +181,16 @@ class Cert_5_6_9_NetworkDataForwarding(thread_cert.TestCase): # Step 9: The DUT MUST send a multicast MLE Data Response with # the new network information - _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next( - ).must_verify(lambda p: { - NWD_SERVICE_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, - NWD_HAS_ROUTER_TLV - } == set(p.thread_nwd.tlv.type) and { - Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::') - } == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [0, 1] and p.thread_nwd.tlv. - border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p. - thread_nwd.tlv.border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 1, 1]) + _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst( + LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify( + lambda p: { + NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, + NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV + } == set(p.thread_nwd.tlv.type) and { + Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::') + } == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [0, 1] and p.thread_nwd. + tlv.border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd + .tlv.border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 1, 1]) # Step 10: The DUT MUST send a unicast MLE Child Update Request to SED_1 _rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next( @@ -207,11 +208,12 @@ class Cert_5_6_9_NetworkDataForwarding(thread_cert.TestCase): # Step 13: The DUT MUST send a multicast MLE Data Response with # the new network information _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst( - LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify(lambda p: { - NWD_SERVICE_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, - NWD_HAS_ROUTER_TLV - } == set(p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), - Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix)) + LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify( + lambda p: { + NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, + NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV + } == set(p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), + Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix)) # Step 14: The DUT MUST send a unicast MLE Child Update Request to SED_1 _rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next( diff --git a/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py b/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py new file mode 100755 index 000000000..4759d5807 --- /dev/null +++ b/tests/scripts/thread-cert/Cert_8_3_01_CommissionerPetition.py @@ -0,0 +1,370 @@ +#!/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 thread_cert +from pktverify.consts import MLE_DATA_RESPONSE, LEAD_PET_URI, LEAD_KA_URI, MGMT_COMMISSIONER_SET_URI, 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 +from pktverify.packet_verifier import PacketVerifier + +LEADER = 1 +COMMISSIONER = 2 +FAKE_JOINER = '166e0a0000000999' + +# Test Purpose and Description: +# ----------------------------- +# The purpose of this test case is to verify that a Commissioner Candidate is able +# to register itself to the network as a Commissioner, send periodic Commissioner +# keep-alive messages, update steering data and unregister itself as a Commissioner +# Leader accepts the Commissioner Candidate as a Commissioner in the network, responds +# to periodic Commissioner keep-alive messages, propagates Thread Network Data correctly +# in the network and unregisters the Commissioner on its request +# +# Test Topology: +# ------------- +# Commissioner +# | +# Leader +# +# DUT Types: +# ---------- +# Leader +# Commissioner + + +class Cert_8_3_01_CommissionerPetition(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + SUPPORT_NCP = False + + TOPOLOGY = { + LEADER: { + 'name': 'LEADER', + 'masterkey': '00112233445566778899aabbccddeeff', + 'mode': 'rdn', + 'panid': 0xface + }, + COMMISSIONER: { + 'name': 'COMMISSIONER', + 'masterkey': '00112233445566778899aabbccddeeff', + 'mode': 'rdn', + 'panid': 0xface, + 'router_selection_jitter': 1 + }, + } + + def test(self): + self.nodes[LEADER].start() + self.simulator.go(5) + self.assertEqual(self.nodes[LEADER].get_state(), 'leader') + self.nodes[COMMISSIONER].start() + self.simulator.go(5) + self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router') + + self.collect_rlocs() + self.collect_rloc16s() + self.collect_leader_aloc(LEADER) + + self.nodes[COMMISSIONER].commissioner_start() + self.simulator.go(60) + + self.nodes[COMMISSIONER].commissioner_add_joiner(FAKE_JOINER, 'PSKD01') + self.simulator.go(5) + + self.nodes[COMMISSIONER].commissioner_stop() + self.simulator.go(5) + self.nodes[COMMISSIONER].commissioner_start() + self.simulator.go(5) + + 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'] + LEADER_RLOC16 = pv.vars['LEADER_RLOC16'] + COMMISSIONER = pv.vars['COMMISSIONER'] + COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC'] + + # Step 2: Commissioner sends a petition request (LEAD_PET.req) to Leader: + # CoAP Request URI + # CON POST coap://:MM/c/lp + # CoAP Payload + # Commissioner ID TLV + pv.verify_attached('COMMISSIONER', 'LEADER') + _pkt = pkts.last() + pkts.filter_wpan_src64(COMMISSIONER).\ + filter_wpan_dst16(LEADER_RLOC16).\ + filter_coap_request(LEAD_PET_URI).\ + filter(lambda p: { + NM_COMMISSIONER_ID_TLV + } == set(p.coap.tlv.type)\ + ).\ + must_next() + + # Step 3: Leader accepts Commissioner to the network, sends a Leader Petition + # Response (LEAD_PET.rsp) to Commissioner: + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept) + # Commissioner ID TLV + # Commissioner Session ID TLV + # + # 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_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\ + filter_coap_ack(LEAD_PET_URI).\ + filter(lambda p: { + NM_STATE_TLV, + NM_COMMISSIONER_ID_TLV, + NM_COMMISSIONER_SESSION_ID_TLV + } <= set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_ACCEPT + ).\ + must_next() + _dr_pkt = 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.mle.tlv.leader_data.data_version == + (_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\ + p.thread_nwd.tlv.stable == [0] + ).\ + must_next() + + # Step 4: Commissioner sends a commissioner keep-alive request (LEAD_KA.req) to Leader: + # CoAP Request URI + # CON POST coap://:MM/c/la + # CoAP Payload + # State TLV (value = Accept) + # Commissioner Session ID TLV + pkts.filter_wpan_src64(COMMISSIONER).\ + filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\ + filter_coap_request(LEAD_KA_URI).\ + filter(lambda p: { + NM_STATE_TLV, + NM_COMMISSIONER_SESSION_ID_TLV + } == set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_ACCEPT + ).\ + must_next() + + # Step 5: Leader sends a commissioner keep-alive response (LEAD_KA.rsp) to Commissioner: + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept) + pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\ + filter_coap_ack(LEAD_KA_URI).\ + filter(lambda p: { + NM_STATE_TLV + } <= set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_ACCEPT + ).\ + must_next() + + # Step 6: Commissioner sends a Set Commissioner Dataset Request (MGMT_COMMISSIONER_SET.req) + # to Leader ALOC 0xFC00 or Leader RLOC: + # CoAP Request URI + # CON POST coap://:MM/c/cs + # CoAP Payload + # Commissioner Session ID TLV + # Steering Data TLV + 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, + NM_COMMISSIONER_SESSION_ID_TLV + } == set(p.coap.tlv.type) + ).\ + must_next() + + # Step 7: 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) + # + # 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_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\ + filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\ + filter(lambda p: { + NM_STATE_TLV + } <= set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_ACCEPT + ).\ + must_next() + + _dr_pkt2 = 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.mle.tlv.leader_data.data_version == + (_dr_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\ + p.thread_nwd.tlv.stable == [0] + ).\ + must_next() + + # Step 8: Commissioner sends a resign request via commissioner keep-alive request + # (LEAD_KA.req) to Leader: + # CoAP Request URI + # CON POST coap://:MM/c/la + # CoAP Payload + # State TLV (value = Reject) + # Commissioner Session ID TLV + pkts.filter_wpan_src64(COMMISSIONER).\ + filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\ + filter_coap_request(LEAD_KA_URI).\ + filter(lambda p: { + NM_STATE_TLV, + NM_COMMISSIONER_SESSION_ID_TLV + } == set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_REJECT + ).\ + must_next() + + # Step 9: Leader accepts the resignation by responding with ‘Reject’ in a commissioner keep-alive + # response (LEAD_KA.rsp) to Commissioner: + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Reject) + # + # 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_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\ + filter_coap_ack(LEAD_KA_URI).\ + filter(lambda p: { + NM_STATE_TLV + } == set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_REJECT + ).\ + must_next() + _dr_pkt3 = 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_COMMISSIONER_SESSION_ID_TLV + } == set(p.thread_meshcop.tlv.type) and\ + p.mle.tlv.leader_data.data_version >= + (_dr_pkt2.mle.tlv.leader_data.data_version + 1) % 256 and\ + p.thread_nwd.tlv.stable == [0] + ).\ + must_next() + + # Step 10: Commissioner sends a petition request (LEAD_PET.req) to Leader: + # CoAP Request URI + # CON POST coap://:MM/c/lp + # CoAP Payload + # Commissioner ID TLV + pkts.filter_wpan_src64(COMMISSIONER).\ + filter_ipv6_2dsts(LEADER_ALOC, LEADER_RLOC).\ + filter_coap_request(LEAD_PET_URI).\ + filter(lambda p: { + NM_COMMISSIONER_ID_TLV + } == set(p.coap.tlv.type)\ + ).\ + must_next() + + # Step 11: Leader accepts Commissioner to the network, sends a Leader Petition + # Response (LEAD_PET.rsp) to Commissioner: + # CoAP Response Code + # 2.04 Changed + # CoAP Payload + # State TLV (value = Accept) + # Commissioner ID TLV + # Commissioner Session ID TLV (contains higher Session ID number + # than in Step 9) + pkts.filter_ipv6_src_dst(LEADER_RLOC, COMMISSIONER_RLOC).\ + filter_coap_ack(LEAD_PET_URI).\ + filter(lambda p: { + NM_STATE_TLV, + NM_COMMISSIONER_ID_TLV, + NM_COMMISSIONER_SESSION_ID_TLV + } <= set(p.coap.tlv.type) and\ + p.thread_meshcop.tlv.state == MESHCOP_ACCEPT and\ + p.thread_meshcop.tlv.commissioner_sess_id == + (_dr_pkt3.thread_meshcop.tlv.commissioner_sess_id + 1) % 65536 + ).\ + must_next() + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index abbd026ff..3ab12236f 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -624,6 +624,11 @@ class NodeImpl: self.send_command(cmd) self._expect('Done') + def commissioner_stop(self): + cmd = 'commissioner stop' + self.send_command(cmd) + self._expect('Done') + def commissioner_state(self): states = [r'disabled', r'petitioning', r'active'] self.send_command('commissioner state') diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py index 9d2d3f142..bfb36a79d 100644 --- a/tests/scripts/thread-cert/pktverify/consts.py +++ b/tests/scripts/thread-cert/pktverify/consts.py @@ -109,6 +109,9 @@ MGMT_PENDING_SET_URI = '/c/ps' MGMT_DATASET_CHANGED_URI = '/c/dc' DIAG_GET_URI = '/d/dg' DIAG_RST_URI = '/d/dr' +MGMT_COMMISSIONER_SET_URI = '/c/cs' +LEAD_PET_URI = '/c/lp' +LEAD_KA_URI = '/c/la' # ADDR SOL Status ADDR_SOL_SUCCESS = 0 @@ -179,6 +182,7 @@ NM_COMMISSIONER_SESSION_ID_TLV = 11 NM_SECURITY_POLICY_TLV = 12 NM_ACTIVE_TIMESTAMP_TLV = 14 NM_COMMISSIONER_UDP_PORT_TLV = 15 +NM_STATE_TLV = 16 NM_JOINER_UDP_PORT_TLV = 18 NM_DELAY_TIMER_TLV = 52 NM_CHANNEL_MASK_TLV = 53 @@ -204,6 +208,11 @@ DG_CHANNEL_PAGES_TLV = 17 DG_TYPE_LIST_TLV = 18 DG_MAX_CHILD_TIMEOUT_TLV = 19 +# MeshCop State +MESHCOP_ACCEPT = 1 +MESHCOP_PENDING = 0 +MESHCOP_REJECT = -1 + # DTLS HANDSHAKE_HELLO_REQUEST = 0 HANDSHAKE_CLIENT_HELLO = 1 @@ -226,9 +235,9 @@ NWD_HAS_ROUTER_TLV = 0 NWD_PREFIX_TLV = 1 NWD_BORDER_ROUTER_TLV = 2 NWD_6LOWPAN_ID_TLV = 3 -NWD_SERVICE_TLV = 4 -NWD_SERVER_TLV = 5 -NWD_COMMISSIONING_DATA_TLV = 6 +NWD_COMMISSIONING_DATA_TLV = 4 +NWD_SERVICE_TLV = 5 +NWD_SERVER_TLV = 6 # Link Metrics TLVs LM_FORWARD_PROBING_REGISTRATION_SUB_TLV = 3