1#!/usr/bin/env python3 2# 3# Copyright (c) 2019, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30import unittest 31 32import config 33import copy 34import mle 35import thread_cert 36from pktverify.consts import MLE_PARENT_REQUEST, MLE_PARENT_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, 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 37from pktverify.packet_verifier import PacketVerifier 38 39LEADER = 1 40REED = 2 41ROUTER = 3 42MTD = 4 43 44# Test Purpose and Description: 45# ----------------------------- 46# The purpose of this test is to verify that the DUT sends a second Parent Request 47# to the all-routers and all-reeds multicast address if it gets a reply from the 48# first Parent Request to the all-routers address with a bad link quality. 49# 50# Test Topology: 51# ------------- 52# Leader 53# / \ 54# REED ROUTER 55# \ / 56# DUT 57# 58# DUT Types: 59# ---------- 60# ED 61# SED 62 63 64class Cert_6_1_6_REEDAttachLinkQuality_Base(thread_cert.TestCase): 65 USE_MESSAGE_FACTORY = False 66 67 TOPOLOGY = { 68 LEADER: { 69 'name': 'LEADER', 70 'mode': 'rdn', 71 'allowlist': [REED, ROUTER] 72 }, 73 REED: { 74 'name': 'REED', 75 'mode': 'rdn', 76 'router_upgrade_threshold': 0, 77 'allowlist': [LEADER, MTD] 78 }, 79 ROUTER: { 80 'name': 'ROUTER', 81 'mode': 'rdn', 82 'allowlist': [LEADER, (MTD, -85)] 83 }, 84 MTD: { 85 'name': 'DUT', 86 'is_mtd': True, 87 'timeout': config.DEFAULT_CHILD_TIMEOUT, 88 'allowlist': [REED, ROUTER] 89 }, 90 } 91 92 def test(self): 93 self.nodes[LEADER].start() 94 self.simulator.go(config.LEADER_STARTUP_DELAY) 95 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 96 97 self.nodes[REED].start() 98 self.simulator.go(5) 99 self.assertEqual(self.nodes[REED].get_state(), 'child') 100 101 self.nodes[ROUTER].start() 102 self.simulator.go(config.ROUTER_STARTUP_DELAY) 103 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 104 105 self.nodes[MTD].start() 106 self.simulator.go(10) 107 self.assertEqual(self.nodes[MTD].get_state(), 'child') 108 self.assertEqual(self.nodes[REED].get_state(), 'router') 109 110 self.collect_ipaddrs() 111 self.collect_rlocs() 112 113 def verify(self, pv): 114 pkts = pv.pkts 115 pv.summary.show() 116 117 LEADER = pv.vars['LEADER'] 118 REED = pv.vars['REED'] 119 ROUTER = pv.vars['ROUTER'] 120 DUT = pv.vars['DUT'] 121 122 # Step 1: Setup the topology without the DUT. Ensure all routers and leader 123 # are sending MLE advertisements 124 pkts.filter_wpan_src64(LEADER).\ 125 filter_mle_advertisement('Leader').\ 126 must_next() 127 128 pv.verify_attached('REED', 'LEADER') 129 pv.verify_attached('ROUTER', 'LEADER') 130 131 # Step 3: DUT sends a MLE Parent Request with an IP hop limit of 132 # 255 to the Link-Local All Routers multicast address (FF02::2). 133 # The following TLVs MUST be present in the MLE Parent Request: 134 # - Challenge TLV 135 # - Mode TLV 136 # - Scan Mask TLV 137 # Verify sent to routers only 138 # - Version TLV 139 # If the first Request was sent to all routers and REEDS, then 140 # the test has failed. 141 pkts.filter_wpan_src64(DUT).\ 142 filter_LLARMA().\ 143 filter_mle_cmd(MLE_PARENT_REQUEST).\ 144 filter(lambda p: { 145 CHALLENGE_TLV, 146 MODE_TLV, 147 SCAN_MASK_TLV, 148 VERSION_TLV 149 } <= set(p.mle.tlv.type) and\ 150 p.ipv6.hlim == 255 and\ 151 p.mle.tlv.scan_mask.r == 1 and\ 152 p.mle.tlv.scan_mask.e == 0 and\ 153 p.wpan.aux_sec.key_id_mode == 0x2 154 ).\ 155 must_next() 156 157 # Step 4: Router responds with MLE Parent Response 158 pkts.filter_wpan_src64(ROUTER).\ 159 filter_wpan_dst64(DUT).\ 160 filter_mle_cmd(MLE_PARENT_RESPONSE).\ 161 filter(lambda p: { 162 CHALLENGE_TLV, 163 CONNECTIVITY_TLV, 164 LEADER_DATA_TLV, 165 LINK_LAYER_FRAME_COUNTER_TLV, 166 LINK_MARGIN_TLV, 167 RESPONSE_TLV, 168 SOURCE_ADDRESS_TLV, 169 VERSION_TLV 170 } <= set(p.mle.tlv.type)).\ 171 must_next() 172 173 # Step 5: DUT sends a MLE Parent Request with an IP hop limit of 174 # 255 to the Link-Local All Routers multicast address (FF02::2). 175 # The following TLVs MUST be present in the MLE Parent Request: 176 # - Challenge TLV 177 # - Mode TLV 178 # - Scan Mask TLV 179 # Verify that it is sent to Routers AND REEDs 180 # - Version TLV 181 pkts.filter_wpan_src64(DUT).\ 182 filter_LLARMA().\ 183 filter_mle_cmd(MLE_PARENT_REQUEST).\ 184 filter(lambda p: { 185 CHALLENGE_TLV, 186 MODE_TLV, 187 SCAN_MASK_TLV, 188 VERSION_TLV 189 } <= set(p.mle.tlv.type) and\ 190 p.ipv6.hlim == 255 and\ 191 p.mle.tlv.scan_mask.r == 1 and\ 192 p.mle.tlv.scan_mask.e == 1 and\ 193 p.wpan.aux_sec.key_id_mode == 0x2 194 ).\ 195 must_next() 196 index2 = pkts.index 197 198 # Step 6: REED sends MLE Parent Response to DUT 199 pkts.filter_wpan_src64(REED).\ 200 filter_wpan_dst64(DUT).\ 201 filter_mle_cmd(MLE_PARENT_RESPONSE).\ 202 filter(lambda p: { 203 CHALLENGE_TLV, 204 CONNECTIVITY_TLV, 205 LEADER_DATA_TLV, 206 LINK_LAYER_FRAME_COUNTER_TLV, 207 LINK_MARGIN_TLV, 208 RESPONSE_TLV, 209 SOURCE_ADDRESS_TLV, 210 VERSION_TLV 211 } <= set(p.mle.tlv.type)).\ 212 must_next() 213 214 # Step 6: DUT sends a MLE Child ID Request to REED 215 # The following TLVs MUST be present in the MLE Child ID Request: 216 # - Address Registration TLV 217 # - Link-layer Frame Counter TLV 218 # - Mode TLV 219 # - Response TLV 220 # - Timeout TLV 221 # - TLV Request TLV 222 # - Version TLV 223 # - MLE Frame Counter TLV (optional) 224 pkts.filter_wpan_src64(DUT).\ 225 filter_wpan_dst64(REED).\ 226 filter_mle_cmd(MLE_CHILD_ID_REQUEST).\ 227 filter(lambda p: { 228 ADDRESS_REGISTRATION_TLV, 229 LINK_LAYER_FRAME_COUNTER_TLV, 230 MODE_TLV, 231 RESPONSE_TLV, 232 TIMEOUT_TLV, 233 TLV_REQUEST_TLV, 234 VERSION_TLV 235 } <= set(p.mle.tlv.type) and\ 236 p.wpan.aux_sec.key_id_mode == 0x2 237 ).\ 238 must_next() 239 240 241class Cert_6_1_6_REEDAttachLinkQuality_ED(Cert_6_1_6_REEDAttachLinkQuality_Base): 242 TOPOLOGY = copy.deepcopy(Cert_6_1_6_REEDAttachLinkQuality_Base.TOPOLOGY) 243 TOPOLOGY[MTD]['mode'] = 'rn' 244 245 246class Cert_6_1_6_REEDAttachLinkQuality_SED(Cert_6_1_6_REEDAttachLinkQuality_Base): 247 TOPOLOGY = copy.deepcopy(Cert_6_1_6_REEDAttachLinkQuality_Base.TOPOLOGY) 248 TOPOLOGY[MTD]['mode'] = '-' 249 250 251del (Cert_6_1_6_REEDAttachLinkQuality_Base) 252 253if __name__ == '__main__': 254 unittest.main() 255