From cb7d8ff5caab418f785c897f394cec341d774516 Mon Sep 17 00:00:00 2001 From: Jing Ma Date: Sat, 28 Nov 2020 01:03:49 +0800 Subject: [PATCH] [thread-cert] refactor case 6.1.2 using pktverify (#5844) --- .../thread-cert/Cert_6_1_02_REEDAttach.py | 372 ++++++++++++++++++ .../thread-cert/Cert_6_1_02_REEDAttach_MED.py | 122 ------ .../thread-cert/Cert_6_1_02_REEDAttach_SED.py | 126 ------ tests/scripts/thread-cert/Makefile.am | 6 +- tests/scripts/thread-cert/pktverify/consts.py | 9 + .../thread-cert/pktverify/packet_filter.py | 4 + 6 files changed, 387 insertions(+), 252 deletions(-) create mode 100755 tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py delete mode 100755 tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_MED.py delete mode 100755 tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_SED.py diff --git a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py b/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py new file mode 100755 index 000000000..4bfacab2d --- /dev/null +++ b/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach.py @@ -0,0 +1,372 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2018, 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 thread_cert +import config +from pktverify.consts import WPAN_DATA_REQUEST, WPAN_ACK, MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MLE_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, TLV_REQUEST_TLV, SCAN_MASK_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, NL_STATUS_TLV, NL_ROUTER_MASK_TLV, COAP_CODE_ACK +from pktverify.packet_verifier import PacketVerifier +from pktverify.null_field import nullField + +LEADER = 1 +REED = 2 +MTD = 3 + +# Test Purpose and Description: +# ----------------------------- +# The purpose of this test case is to validate that the DUT is able to successfully +# attach to a network as an End Device through a REED. +# +# Test Topology: +# ------------- +# Leader +# | +# REED +# | +# DUT +# +# DUT Types: +# ---------- +# ED +# SED + + +class Cert_6_1_2_REEDAttach_Base(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + + TOPOLOGY = { + LEADER: { + 'name': 'LEADER', + 'mode': 'rdn', + 'panid': 0xface, + 'allowlist': [REED] + }, + REED: { + 'name': 'REED', + 'mode': 'rdn', + 'panid': 0xface, + 'router_upgrade_threshold': 0, + 'router_selection_jitter': 1, + 'allowlist': [LEADER, MTD] + }, + MTD: { + 'name': 'DUT', + 'is_mtd': True, + 'panid': 0xface, + 'timeout': config.DEFAULT_CHILD_TIMEOUT, + 'allowlist': [REED] + }, + } + + def test(self): + self.nodes[LEADER].start() + self.simulator.go(5) + self.assertEqual(self.nodes[LEADER].get_state(), 'leader') + + self.nodes[REED].start() + self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL) + self.assertEqual(self.nodes[REED].get_state(), 'child') + self.collect_rloc16s() + + self.nodes[MTD].start() + self.simulator.go(5) + self.assertEqual(self.nodes[MTD].get_state(), 'child') + self.assertEqual(self.nodes[REED].get_state(), 'router') + self.collect_ipaddrs() + self.collect_rlocs() + + self.simulator.go(config.DEFAULT_CHILD_TIMEOUT) + + dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL) + self.assertTrue(self.nodes[REED].ping(dut_addr)) + + def verify(self, pv): + pkts = pv.pkts + pv.summary.show() + + LEADER = pv.vars['LEADER'] + LEADER_RLOC = pv.vars['LEADER_RLOC'] + REED = pv.vars['REED'] + REED_RLOC = pv.vars['REED_RLOC'] + REED_LLA = pv.vars['REED_LLA'] + REED_RLOC16 = pv.vars['REED_RLOC16'] + DUT = pv.vars['DUT'] + DUT_RLOC = pv.vars['DUT_RLOC'] + DUT_LLA = pv.vars['DUT_LLA'] + + # Step 1: Ensure the Leader is sending MLE Advertisements and is connected to REED + + pkts.filter_wpan_src64(LEADER).\ + filter_mle_advertisement('Leader').\ + must_next() + + pv.verify_attached('REED', 'LEADER') + + # Step 2: DUT sends a MLE Parent Request with an IP hop limit of + # 255 to the Link-Local All Routers multicast address (FF02::2). + # The following TLVs MUST be present in the MLE Parent Request: + # - Challenge TLV + # - Mode TLV + # - Scan Mask TLV + # Verify that the first one is sent to routers only + # - Version TLV + # If the first MLE Parent Request was sent to all Routers and + # REEDS, the test fails. + # In securing the first three messages of the attaching process, + # the full four-byte key sequence number MUST be included in + # the Auxiliary Security Header used for MLE security. + # + # To send the full four-byte key sequence number, the Key + # Identifier Mode of the Security Control Field SHALL be set to + # ‘0x02’, indicating the presence of a four-byte Key Source, + # which SHALL contain the four-byte key sequence number in + # network byte order. + + pkts.filter_wpan_src64(DUT).\ + filter_LLARMA().\ + filter_mle_cmd(MLE_PARENT_REQUEST).\ + filter(lambda p: { + CHALLENGE_TLV, + MODE_TLV, + SCAN_MASK_TLV, + VERSION_TLV + } <= set(p.mle.tlv.type) and\ + p.ipv6.hlim == 255 and\ + p.mle.tlv.scan_mask.r == 1 and\ + p.mle.tlv.scan_mask.e == 0 and\ + p.wpan.aux_sec.key_id_mode == 0x2 + ).\ + must_next() + index1 = pkts.index + + # Step 4: DUT sends a MLE Parent Request with an IP hop limit of + # 255 to the Link-Local All Routers multicast address (FF02::2). + # The following TLVs MUST be present in the MLE Parent Request: + # - Challenge TLV + # - Mode TLV + # - Scan Mask TLV + # Verify that it is sent to Routers AND REEDs + # - Version TLV + # If request was not sent to all routers and REEDS, then the test + # has failed. + # In securing the first three messages of the attaching process, + # the full four-byte key sequence number MUST be included in + # the Auxiliary Security Header used for MLE security. + # To send the full four-byte key sequence number, the Key + # Identifier Mode of the Security Control Field SHALL be set to + # ‘0x02’, indicating the presence of a four-byte Key Source, + # which SHALL contain the four-byte key sequence number in + # network byte order. + + pkts.filter_wpan_src64(DUT).\ + filter_LLARMA().\ + filter_mle_cmd(MLE_PARENT_REQUEST).\ + filter(lambda p: { + CHALLENGE_TLV, + MODE_TLV, + SCAN_MASK_TLV, + VERSION_TLV + } <= set(p.mle.tlv.type) and\ + p.ipv6.hlim == 255 and\ + p.mle.tlv.scan_mask.r == 1 and\ + p.mle.tlv.scan_mask.e == 1 and\ + p.wpan.aux_sec.key_id_mode == 0x2 + ).\ + must_next() + index2 = pkts.index + + # Step 3: REED doesn't response to the first Parent Request + + pkts.range(index1, index2).\ + filter_wpan_src64(REED).\ + filter_wpan_dst64(DUT).\ + filter_mle_cmd(MLE_PARENT_RESPONSE).\ + must_not_next() + + # Step 5: REED responds with MLE Parent Response for the second Parent Request + + pkts.filter_wpan_src64(REED).\ + filter_wpan_dst64(DUT).\ + filter_mle_cmd(MLE_PARENT_RESPONSE).\ + filter(lambda p: { + CHALLENGE_TLV, + CONNECTIVITY_TLV, + LEADER_DATA_TLV, + LINK_LAYER_FRAME_COUNTER_TLV, + LINK_MARGIN_TLV, + RESPONSE_TLV, + SOURCE_ADDRESS_TLV, + VERSION_TLV + } <= set(p.mle.tlv.type)).\ + must_next() + + # Step 6: DUT sends a MLE Child ID Request. + # The following TLVs MUST be present in the MLE Child ID Request: + # - Address Registration TLV + # - Link-layer Frame Counter TLV + # - Mode TLV + # - Response TLV + # - Timeout TLV + # - TLV Request TLV + # - Version TLV + # - MLE Frame Counter TLV (optional) + + pkts.filter_wpan_src64(DUT).\ + filter_wpan_dst64(REED).\ + filter_mle_cmd(MLE_CHILD_ID_REQUEST).\ + filter(lambda p: { + ADDRESS_REGISTRATION_TLV, + LINK_LAYER_FRAME_COUNTER_TLV, + MODE_TLV, + RESPONSE_TLV, + TIMEOUT_TLV, + TLV_REQUEST_TLV, + VERSION_TLV + } <= set(p.mle.tlv.type) and\ + p.wpan.aux_sec.key_id_mode == 0x2 + ).\ + must_next() + + # Step 7: REED sends an Address Solicit Request to Leader; + # Leader responds with an Address Solicit Response and REED + # becomes active router; + # REED sends Child ID Response with DUT’s new 16-bit Address. + + _pkt = pkts.filter_wpan_src64(REED).\ + filter_ipv6_dst(LEADER_RLOC).\ + filter_coap_request(ADDR_SOL_URI).\ + filter(lambda p: { + NL_MAC_EXTENDED_ADDRESS_TLV, + NL_STATUS_TLV + } <= set(p.coap.tlv.type) + ).\ + must_next() + pkts.filter_wpan_src64(LEADER).\ + filter_wpan_dst16(_pkt.wpan.src16).\ + filter_coap_ack(ADDR_SOL_URI).\ + filter(lambda p: { + NL_STATUS_TLV, + NL_RLOC16_TLV, + NL_ROUTER_MASK_TLV + } == set(p.coap.tlv.type) and\ + p.coap.code == COAP_CODE_ACK and\ + p.thread_address.tlv.status == 0\ + ).\ + must_next() + _pkt = pkts.filter_wpan_src64(REED).\ + filter_wpan_dst64(DUT).\ + filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\ + filter(lambda p: { + ADDRESS16_TLV, + LEADER_DATA_TLV, + NETWORK_DATA_TLV, + SOURCE_ADDRESS_TLV + } <= set(p.mle.tlv.type) and\ + p.mle.tlv.source_addr != REED_RLOC16 + ).\ + must_next() + + if self.TOPOLOGY[MTD]['mode'] == 'rn': + # Step 8: DUT sends periodic Child Update messages as part of the + # keep-alive message + # The DUT MUST send MLE Child Update messages containing + # the following TLVs: + # - Leader Data TLV + # - Mode TLV + # - Source Address TLV + pkts.filter_wpan_src64(DUT).\ + filter_wpan_dst64(REED).\ + filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\ + filter(lambda p: { + SOURCE_ADDRESS_TLV, + MODE_TLV, + LEADER_DATA_TLV + } < set(p.mle.tlv.type) + ).\ + must_next() + + # Step 9: REED Respond to Child Update messages with a MLE Update + # Response. + pkts.filter_wpan_src64(REED).\ + filter_wpan_dst64(DUT).\ + filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\ + filter(lambda p: { + SOURCE_ADDRESS_TLV, + MODE_TLV, + LEADER_DATA_TLV + } < set(p.mle.tlv.type) + ).\ + must_next() + + # Step 10: Go to Step 12 + + else: + # Step 11: DUT sends periodic 802.15.4 Data Request messages as part + # of the keep-alive message + # The DUT must send a 802.15.4 Data Request command to the + # parent device and receive an ACK message in response + _pkt2 = pkts.filter_wpan_src64(DUT).\ + filter_wpan_dst16(_pkt.mle.tlv.source_addr).\ + filter_wpan_cmd(WPAN_DATA_REQUEST).\ + must_next() + + pkts.filter(lambda p: + p.wpan.seq_no == _pkt2.wpan.seq_no and\ + p.wpan.frame_type == WPAN_ACK + ).\ + must_next() + + # Step 12: REED verifies connectivity by sending an ICMPv6 Echo Request + # to the DUT link local address + # DUT responds with ICMPv6 Echo Reply + + _pkt = pkts.filter_ping_request().\ + filter_ipv6_src_dst(REED_LLA, DUT_LLA).\ + must_next() + pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ + filter_ipv6_src_dst(DUT_LLA, REED_LLA).\ + must_next() + + +class Cert_6_1_2_REEDAttach_ED(Cert_6_1_2_REEDAttach_Base): + TOPOLOGY = copy.deepcopy(Cert_6_1_2_REEDAttach_Base.TOPOLOGY) + TOPOLOGY[MTD]['mode'] = 'rn' + + +class Cert_6_1_2_REEDAttach_SED(Cert_6_1_2_REEDAttach_Base): + TOPOLOGY = copy.deepcopy(Cert_6_1_2_REEDAttach_Base.TOPOLOGY) + TOPOLOGY[MTD]['mode'] = '-' + + +del (Cert_6_1_2_REEDAttach_Base) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_MED.py b/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_MED.py deleted file mode 100755 index 5b85f61b3..000000000 --- a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_MED.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2018, 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 command import check_parent_request -from command import check_child_id_request -from command import check_child_update_request_from_child -from command import CheckType -import config -import mle - -LEADER = 1 -REED = 2 -MED = 3 - - -class Cert_6_1_2_REEDAttach_MED(thread_cert.TestCase): - TOPOLOGY = { - LEADER: { - 'mode': 'rdn', - 'panid': 0xface, - 'allowlist': [REED] - }, - REED: { - 'mode': 'rdn', - 'panid': 0xface, - 'router_upgrade_threshold': 0, - 'allowlist': [LEADER, MED] - }, - MED: { - 'is_mtd': True, - 'mode': 'rn', - 'panid': 0xface, - 'timeout': config.DEFAULT_CHILD_TIMEOUT, - 'allowlist': [REED] - }, - } - - def test(self): - self.nodes[LEADER].start() - self.simulator.go(5) - self.assertEqual(self.nodes[LEADER].get_state(), 'leader') - - self.nodes[REED].start() - self.simulator.go(5) - self.assertEqual(self.nodes[REED].get_state(), 'child') - - self.nodes[MED].start() - - self.simulator.go(5) - self.assertEqual(self.nodes[MED].get_state(), 'child') - self.assertEqual(self.nodes[REED].get_state(), 'router') - med_messages = self.simulator.get_messages_sent_by(MED) - - # Step 2 - DUT sends MLE Parent Request - msg = med_messages.next_mle_message(mle.CommandType.PARENT_REQUEST) - check_parent_request(msg, is_first_request=True) - - # Step 4 - DUT sends MLE Parent Request again - msg = med_messages.next_mle_message(mle.CommandType.PARENT_REQUEST) - check_parent_request(msg, is_first_request=False) - - # Step 6 - DUT sends Child ID Request - msg = med_messages.next_mle_message(mle.CommandType.CHILD_ID_REQUEST, sent_to_node=self.nodes[REED]) - check_child_id_request( - msg, - address_registration=CheckType.CONTAIN, - tlv_request=CheckType.CONTAIN, - mle_frame_counter=CheckType.OPTIONAL, - route64=CheckType.OPTIONAL, - ) - - # Wait additional DEFAULT_CHILD_TIMEOUT to ensure the keep-alive - # message (child update request from MED) happens. - self.simulator.go(config.DEFAULT_CHILD_TIMEOUT) - med_messages = self.simulator.get_messages_sent_by(MED) - - # Step 8 - DUT sends Child Update messages - msg = med_messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST) - check_child_update_request_from_child( - msg, - source_address=CheckType.CONTAIN, - leader_data=CheckType.CONTAIN, - ) - - # Step 10 - Leader sends ICMPv6 echo request, to DUT link local address - med_addrs = self.nodes[MED].get_addrs() - for addr in med_addrs: - if addr[0:4] == 'fe80': - self.assertTrue(self.nodes[REED].ping(addr)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_SED.py b/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_SED.py deleted file mode 100755 index 2d74c07d7..000000000 --- a/tests/scripts/thread-cert/Cert_6_1_02_REEDAttach_SED.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2018, 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 command import check_parent_request -from command import check_child_id_request -from command import CheckType -import config -import mac802154 -import message -import mle - -LEADER = 1 -REED = 2 -SED = 3 - - -class Cert_6_1_2_REEDAttach_SED(thread_cert.TestCase): - TOPOLOGY = { - LEADER: { - 'mode': 'rdn', - 'panid': 0xface, - 'allowlist': [REED] - }, - REED: { - 'mode': 'rdn', - 'panid': 0xface, - 'router_upgrade_threshold': 0, - 'allowlist': [LEADER, SED] - }, - SED: { - 'is_mtd': True, - 'mode': '-', - 'panid': 0xface, - 'timeout': config.DEFAULT_CHILD_TIMEOUT, - 'allowlist': [REED] - }, - } - - def test(self): - self.nodes[LEADER].start() - self.simulator.go(5) - self.assertEqual(self.nodes[LEADER].get_state(), 'leader') - - self.nodes[REED].start() - self.simulator.go(5) - self.assertEqual(self.nodes[REED].get_state(), 'child') - - self.nodes[SED].start() - self.simulator.go(5) - self.assertEqual(self.nodes[SED].get_state(), 'child') - self.assertEqual(self.nodes[REED].get_state(), 'router') - - sed_messages = self.simulator.get_messages_sent_by(SED) - - # Step 2 - DUT sends MLE Parent Request - msg = sed_messages.next_mle_message(mle.CommandType.PARENT_REQUEST) - check_parent_request(msg, is_first_request=True) - - # Step 4 - DUT sends MLE Parent Request again - msg = sed_messages.next_mle_message(mle.CommandType.PARENT_REQUEST) - check_parent_request(msg, is_first_request=False) - - # Step 6 - DUT sends Child ID Request - msg = sed_messages.next_mle_message(mle.CommandType.CHILD_ID_REQUEST, sent_to_node=self.nodes[REED]) - check_child_id_request( - msg, - address_registration=CheckType.CONTAIN, - tlv_request=CheckType.CONTAIN, - mle_frame_counter=CheckType.OPTIONAL, - route64=CheckType.OPTIONAL, - ) - - # Wait DEFAULT_CHILD_TIMEOUT seconds, - # ensure SED has received the CHILD_ID_RESPONSE, - # and the next data requests would be keep-alive messages - self.simulator.go(config.DEFAULT_CHILD_TIMEOUT) - sed_messages = self.simulator.get_messages_sent_by(SED) - - # Step 11 - SED sends periodic 802.15.4 Data Request messages - msg = sed_messages.next_message() - self.assertEqual( - False, msg.isMacAddressTypeLong()) # Extra check, keep-alive messages are of short types of mac address - self.assertEqual(msg.type, message.MessageType.COMMAND) - self.assertEqual( - msg.mac_header.command_type, - mac802154.MacHeader.CommandIdentifier.DATA_REQUEST, - ) - - # Step 12 - REED sends ICMPv6 echo request, to DUT link local address - sed_addrs = self.nodes[SED].get_addrs() - for addr in sed_addrs: - if addr[0:4] == 'fe80': - self.assertTrue(self.nodes[REED].ping(addr)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/scripts/thread-cert/Makefile.am b/tests/scripts/thread-cert/Makefile.am index 5154e9eed..18118ef5c 100644 --- a/tests/scripts/thread-cert/Makefile.am +++ b/tests/scripts/thread-cert/Makefile.am @@ -80,8 +80,7 @@ EXTRA_DIST = \ Cert_5_8_02_KeyIncrement.py \ Cert_5_8_03_KeyIncrementRollOver.py \ Cert_6_1_01_RouterAttach.py \ - Cert_6_1_02_REEDAttach_MED.py \ - Cert_6_1_02_REEDAttach_SED.py \ + Cert_6_1_02_REEDAttach.py \ Cert_6_1_03_RouterAttachConnectivity.py \ Cert_6_1_05_REEDAttachConnectivity.py \ Cert_6_1_07_RouterAttachLinkQuality.py \ @@ -258,8 +257,7 @@ check_SCRIPTS = \ Cert_5_8_02_KeyIncrement.py \ Cert_5_8_03_KeyIncrementRollOver.py \ Cert_6_1_01_RouterAttach.py \ - Cert_6_1_02_REEDAttach_MED.py \ - Cert_6_1_02_REEDAttach_SED.py \ + Cert_6_1_02_REEDAttach.py \ Cert_6_1_03_RouterAttachConnectivity.py \ Cert_6_1_05_REEDAttachConnectivity.py \ Cert_6_1_07_RouterAttachLinkQuality.py \ diff --git a/tests/scripts/thread-cert/pktverify/consts.py b/tests/scripts/thread-cert/pktverify/consts.py index 675231653..e16187913 100644 --- a/tests/scripts/thread-cert/pktverify/consts.py +++ b/tests/scripts/thread-cert/pktverify/consts.py @@ -57,6 +57,15 @@ ALL_MPL_FORWARDERS_MA = Ipv6Addr('ff03::fc') LINK_LOCAL_PREFIX = Bytes("fe80") DEFAULT_MESH_LOCAL_PREFIX = Bytes("fd00:0db8:0000:0000") +# WPAN CMDs +WPAN_DATA_REQUEST = 4 + +# WPAN Frame Types +WPAN_BEACON = 0 +WPAN_DATA = 1 +WPAN_ACK = 2 +WPAN_CMD = 3 + # COAP methods COAP_CODE_POST = 2 COAP_CODE_ACK = 68 diff --git a/tests/scripts/thread-cert/pktverify/packet_filter.py b/tests/scripts/thread-cert/pktverify/packet_filter.py index 681139140..85cd2db4e 100644 --- a/tests/scripts/thread-cert/pktverify/packet_filter.py +++ b/tests/scripts/thread-cert/pktverify/packet_filter.py @@ -528,6 +528,10 @@ class PacketFilter(object): def filter_mle(self, **kwargs): return self.filter(attrgetter('mle'), **kwargs) + def filter_wpan_cmd(self, cmd, **kwargs): + assert isinstance(cmd, int), cmd + return self.filter(lambda p: p.wpan.cmd == cmd, **kwargs) + def filter_mle_cmd(self, cmd, **kwargs): assert isinstance(cmd, int), cmd return self.filter(lambda p: p.mle.cmd == cmd, **kwargs)