1#!/usr/bin/env python3 2# 3# Copyright (c) 2016, 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 mle 34import network_layer 35import thread_cert 36from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_RESPONSE, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ADDRESS16_TLV, ROUTE64_TLV, LEADER_DATA_TLV, NETWORK_DATA_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, ADDR_SOL_NA, ADDR_SOL_SUCCESS 37from pktverify.packet_verifier import PacketVerifier 38from pktverify.null_field import nullField 39 40DUT_LEADER = 1 41ROUTER_1 = 2 42ROUTER_31 = 32 43ROUTER_32 = 33 44 45# Test Purpose and Description: 46# ----------------------------- 47# The purpose of this test case is to show that the DUT will 48# only allow 32 active routers on the network and reject the 49# Address Solicit Request from a 33rd router - that is 50# 2-hops away - with a No Address Available status. 51# 52# Test Topology: 53# ------------- 54# Leader[DUT] 55# / \ 56# Router_1 --- Router_31 57# | 58# | 59# Router_32 60# 61# DUT Types: 62# ---------- 63# Leader 64 65 66class Cert_5_2_3_LeaderReject2Hops(thread_cert.TestCase): 67 USE_MESSAGE_FACTORY = False 68 69 TOPOLOGY = { 70 DUT_LEADER: { 71 'name': 72 'LEADER', 73 'mode': 74 'rdn', 75 'panid': 76 0xface, 77 'router_downgrade_threshold': 78 33, 79 'router_upgrade_threshold': 80 32, 81 'allowlist': [ 82 ROUTER_1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 83 28, 29, 30, 31, ROUTER_31 84 ] 85 }, 86 ROUTER_1: { 87 'name': 'ROUTER_1', 88 'mode': 'rdn', 89 'router_downgrade_threshold': 33, 90 'router_upgrade_threshold': 33, 91 'allowlist': [DUT_LEADER, ROUTER_32] 92 }, 93 3: { 94 'name': 'ROUTER_2', 95 'mode': 'rdn', 96 'router_downgrade_threshold': 33, 97 'router_upgrade_threshold': 33, 98 'allowlist': [DUT_LEADER] 99 }, 100 4: { 101 'name': 'ROUTER_3', 102 'mode': 'rdn', 103 'router_downgrade_threshold': 33, 104 'router_upgrade_threshold': 33, 105 'allowlist': [DUT_LEADER] 106 }, 107 5: { 108 'name': 'ROUTER_4', 109 'mode': 'rdn', 110 'router_downgrade_threshold': 33, 111 'router_upgrade_threshold': 33, 112 'allowlist': [DUT_LEADER] 113 }, 114 6: { 115 'name': 'ROUTER_5', 116 'mode': 'rdn', 117 'router_downgrade_threshold': 33, 118 'router_upgrade_threshold': 33, 119 'allowlist': [DUT_LEADER] 120 }, 121 7: { 122 'name': 'ROUTER_6', 123 'mode': 'rdn', 124 'router_downgrade_threshold': 33, 125 'router_upgrade_threshold': 33, 126 'allowlist': [DUT_LEADER] 127 }, 128 8: { 129 'name': 'ROUTER_7', 130 'mode': 'rdn', 131 'router_downgrade_threshold': 33, 132 'router_upgrade_threshold': 33, 133 'allowlist': [DUT_LEADER] 134 }, 135 9: { 136 'name': 'ROUTER_8', 137 'mode': 'rdn', 138 'router_downgrade_threshold': 33, 139 'router_upgrade_threshold': 33, 140 'allowlist': [DUT_LEADER] 141 }, 142 10: { 143 'name': 'ROUTER_9', 144 'mode': 'rdn', 145 'router_downgrade_threshold': 33, 146 'router_upgrade_threshold': 33, 147 'allowlist': [DUT_LEADER] 148 }, 149 11: { 150 'name': 'ROUTER_10', 151 'mode': 'rdn', 152 'router_downgrade_threshold': 33, 153 'router_upgrade_threshold': 33, 154 'allowlist': [DUT_LEADER] 155 }, 156 12: { 157 'name': 'ROUTER_11', 158 'mode': 'rdn', 159 'router_downgrade_threshold': 33, 160 'router_upgrade_threshold': 33, 161 'allowlist': [DUT_LEADER] 162 }, 163 13: { 164 'name': 'ROUTER_12', 165 'mode': 'rdn', 166 'router_downgrade_threshold': 33, 167 'router_upgrade_threshold': 33, 168 'allowlist': [DUT_LEADER] 169 }, 170 14: { 171 'name': 'ROUTER_13', 172 'mode': 'rdn', 173 'router_downgrade_threshold': 33, 174 'router_upgrade_threshold': 33, 175 'allowlist': [DUT_LEADER] 176 }, 177 15: { 178 'name': 'ROUTER_14', 179 'mode': 'rdn', 180 'router_downgrade_threshold': 33, 181 'router_upgrade_threshold': 33, 182 'allowlist': [DUT_LEADER] 183 }, 184 16: { 185 'name': 'ROUTER_15', 186 'mode': 'rdn', 187 'router_downgrade_threshold': 33, 188 'router_upgrade_threshold': 33, 189 'allowlist': [DUT_LEADER] 190 }, 191 17: { 192 'name': 'ROUTER_16', 193 'mode': 'rdn', 194 'router_downgrade_threshold': 33, 195 'router_upgrade_threshold': 33, 196 'allowlist': [DUT_LEADER] 197 }, 198 18: { 199 'name': 'ROUTER_17', 200 'mode': 'rdn', 201 'router_downgrade_threshold': 33, 202 'router_upgrade_threshold': 33, 203 'allowlist': [DUT_LEADER] 204 }, 205 19: { 206 'name': 'ROUTER_18', 207 'mode': 'rdn', 208 'router_downgrade_threshold': 33, 209 'router_upgrade_threshold': 33, 210 'allowlist': [DUT_LEADER] 211 }, 212 20: { 213 'name': 'ROUTER_19', 214 'mode': 'rdn', 215 'router_downgrade_threshold': 33, 216 'router_upgrade_threshold': 33, 217 'allowlist': [DUT_LEADER] 218 }, 219 21: { 220 'name': 'ROUTER_20', 221 'mode': 'rdn', 222 'router_downgrade_threshold': 33, 223 'router_upgrade_threshold': 33, 224 'allowlist': [DUT_LEADER] 225 }, 226 22: { 227 'name': 'ROUTER_21', 228 'mode': 'rdn', 229 'router_downgrade_threshold': 33, 230 'router_upgrade_threshold': 33, 231 'allowlist': [DUT_LEADER] 232 }, 233 23: { 234 'name': 'ROUTER_22', 235 'mode': 'rdn', 236 'router_downgrade_threshold': 33, 237 'router_upgrade_threshold': 33, 238 'allowlist': [DUT_LEADER] 239 }, 240 24: { 241 'name': 'ROUTER_23', 242 'mode': 'rdn', 243 'router_downgrade_threshold': 33, 244 'router_upgrade_threshold': 33, 245 'allowlist': [DUT_LEADER] 246 }, 247 25: { 248 'name': 'ROUTER_24', 249 'mode': 'rdn', 250 'router_downgrade_threshold': 33, 251 'router_upgrade_threshold': 33, 252 'allowlist': [DUT_LEADER] 253 }, 254 26: { 255 'name': 'ROUTER_25', 256 'mode': 'rdn', 257 'router_downgrade_threshold': 33, 258 'router_upgrade_threshold': 33, 259 'allowlist': [DUT_LEADER] 260 }, 261 27: { 262 'name': 'ROUTER_26', 263 'mode': 'rdn', 264 'router_downgrade_threshold': 33, 265 'router_upgrade_threshold': 33, 266 'allowlist': [DUT_LEADER] 267 }, 268 28: { 269 'name': 'ROUTER_27', 270 'mode': 'rdn', 271 'router_downgrade_threshold': 33, 272 'router_upgrade_threshold': 33, 273 'allowlist': [DUT_LEADER] 274 }, 275 29: { 276 'name': 'ROUTER_28', 277 'mode': 'rdn', 278 'router_downgrade_threshold': 33, 279 'router_upgrade_threshold': 33, 280 'allowlist': [DUT_LEADER] 281 }, 282 30: { 283 'name': 'ROUTER_29', 284 'mode': 'rdn', 285 'router_downgrade_threshold': 33, 286 'router_upgrade_threshold': 33, 287 'allowlist': [DUT_LEADER] 288 }, 289 31: { 290 'name': 'ROUTER_30', 291 'mode': 'rdn', 292 'router_downgrade_threshold': 33, 293 'router_upgrade_threshold': 33, 294 'allowlist': [DUT_LEADER] 295 }, 296 ROUTER_31: { 297 'name': 'ROUTER_31', 298 'mode': 'rdn', 299 'router_downgrade_threshold': 33, 300 'router_upgrade_threshold': 33, 301 'allowlist': [DUT_LEADER] 302 }, 303 ROUTER_32: { 304 'name': 'ROUTER_32', 305 'mode': 'rdn', 306 'router_downgrade_threshold': 33, 307 'router_upgrade_threshold': 33, 308 'allowlist': [ROUTER_1] 309 }, 310 } 311 312 def test(self): 313 self.nodes[DUT_LEADER].start() 314 self.simulator.go(config.LEADER_STARTUP_DELAY) 315 self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader') 316 317 for i in range(2, 32): 318 self.nodes[i].start() 319 self.simulator.go(config.ROUTER_STARTUP_DELAY) 320 self.assertEqual(self.nodes[i].get_state(), 'router') 321 self.collect_rlocs() 322 323 self.nodes[ROUTER_31].start() 324 self.simulator.go(config.ROUTER_STARTUP_DELAY) 325 self.assertEqual(self.nodes[ROUTER_31].get_state(), 'router') 326 327 self.nodes[ROUTER_32].start() 328 self.simulator.go(config.ROUTER_STARTUP_DELAY) 329 330 def verify(self, pv: PacketVerifier): 331 pkts = pv.pkts 332 pv.summary.show() 333 334 LEADER = pv.vars['LEADER'] 335 LEADER_RLOC = pv.vars['LEADER_RLOC'] 336 ROUTER_31 = pv.vars['ROUTER_31'] 337 ROUTER_32 = pv.vars['ROUTER_32'] 338 339 # Step 1: Topology is created, the DUT is the Leader of the network 340 # and there is a total of 32 active routers, including the Leader. 341 for i in range(1, 32): 342 pv.verify_attached('ROUTER_%d' % i) 343 344 # Step 2: Router_31 to attaches to the network and sends an Address 345 # Solicit Request to become an active router. 346 347 _pkt = pkts.filter_wpan_src64(ROUTER_31).\ 348 filter_ipv6_dst(LEADER_RLOC).\ 349 filter_coap_request(ADDR_SOL_URI).\ 350 filter(lambda p: { 351 NL_MAC_EXTENDED_ADDRESS_TLV, 352 NL_STATUS_TLV 353 } == set(p.coap.tlv.type) 354 ).\ 355 must_next() 356 357 # Step 3: Leader sends an Address Solicit Response. 358 # Ensure the Address Solicit Response is properly formatted: 359 # CoAP Response Code 360 # 2.04 Changed 361 # CoAP Payload 362 # - Status TLV (value = Success) 363 # - RLOC16 TLV 364 # - Router Mask TLV 365 366 pkts.filter_wpan_src64(LEADER).\ 367 filter_ipv6_dst(_pkt.ipv6.src).\ 368 filter_coap_ack(ADDR_SOL_URI).\ 369 filter(lambda p: { 370 NL_STATUS_TLV, 371 NL_RLOC16_TLV, 372 NL_ROUTER_MASK_TLV 373 } == set(p.coap.tlv.type) and\ 374 p.coap.code == COAP_CODE_ACK and\ 375 p.thread_address.tlv.status == ADDR_SOL_SUCCESS\ 376 ).\ 377 must_next() 378 379 # Step 4: Leader The DUT sends MLE Advertisements. 380 # The MLE Advertisements from the Leader MUST contain 381 # the Route64 TLV with 32 assigned Router IDs. 382 383 pkts.filter_wpan_src64(LEADER).\ 384 filter_LLANMA().\ 385 filter_mle_cmd(MLE_ADVERTISEMENT).\ 386 filter(lambda p: { 387 LEADER_DATA_TLV, 388 ROUTE64_TLV, 389 SOURCE_ADDRESS_TLV 390 } == set(p.mle.tlv.type) and\ 391 len(p.mle.tlv.route64.cost) == 32 and\ 392 p.ipv6.hlim == 255 393 ).\ 394 must_next() 395 396 # Step 5: Router_32 to attach to any of the active routers, 2-hops 397 # from the leader, and to send an Address Solicit Request 398 # to become an active router. 399 400 _pkt = pkts.filter_wpan_src64(ROUTER_32).\ 401 filter_ipv6_dst(LEADER_RLOC).\ 402 filter_coap_request(ADDR_SOL_URI).\ 403 filter(lambda p: { 404 NL_MAC_EXTENDED_ADDRESS_TLV, 405 NL_STATUS_TLV 406 } == set(p.coap.tlv.type) 407 ).\ 408 must_next() 409 410 # Step 6: Leader sends an Address Solicit Response. 411 # Ensure the Address Solicit Response is properly formatted: 412 # CoAP Response Code 413 # 2.04 Changed 414 # CoAP Payload 415 # - Status TLV (value = No Address Available) 416 417 pkts.filter_wpan_src64(LEADER).\ 418 filter_ipv6_dst(_pkt.ipv6.src).\ 419 filter_coap_ack(ADDR_SOL_URI).\ 420 filter(lambda p: 421 p.coap.code == COAP_CODE_ACK and\ 422 p.thread_address.tlv.status == ADDR_SOL_NA 423 ).\ 424 must_next() 425 426 427if __name__ == '__main__': 428 unittest.main() 429