1#!/usr/bin/env python3 2# 3# Copyright (c) 2021, 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 ipaddress 31import unittest 32 33import command 34import config 35import thread_cert 36 37# Test description: 38# This test verifies network data publisher behavior with DNS/SRP service entries and on-mesh prefix and external 39# route entries. 40# 41# Topology: 42# 43# 1 leader, 5 routers and 5 end-devices all connected. 44# 45 46LEADER = 1 47ROUTER1 = 2 48ROUTER2 = 3 49ROUTER3 = 4 50ROUTER4 = 5 51ROUTER5 = 6 52END_DEV1 = 7 53END_DEV2 = 8 54END_DEV3 = 9 55END_DEV4 = 10 56END_DEV5 = 11 57 58WAIT_TIME = 55 59 60ON_MESH_PREFIX = 'fd00:1234:0:0::/64' 61ON_MESH_FLAGS = 'paso' 62 63EXTERNAL_ROUTE = 'fd00:abce:0:0::/64' 64EXTERNAL_FLAGS = 's' 65 66ANYCAST_SEQ_NUM = 4 67 68DNSSRP_ADDRESS = 'fd00::cdef' 69DNSSRP_PORT = 49152 70 71# The desired number of entries (based on related config). 72DESIRED_NUM_DNSSRP_ANYCAST = 8 73DESIRED_NUM_DNSSRP_UNICAST = 2 74DESIRED_NUM_ON_MESH_PREFIX = 3 75DESIRED_NUM_EXTERNAL_ROUTE = 10 76 77THREAD_ENTERPRISE_NUMBER = 44970 78ANYCAST_SERVICE_NUM = 0x5c 79UNICAST_SERVICE_NUM = 0x5d 80 81 82class NetDataPublisher(thread_cert.TestCase): 83 USE_MESSAGE_FACTORY = False 84 SUPPORT_NCP = False 85 86 TOPOLOGY = { 87 LEADER: { 88 'name': 'LEADER', 89 'mode': 'rdn', 90 }, 91 ROUTER1: { 92 'name': 'ROUTER1', 93 'mode': 'rdn', 94 }, 95 ROUTER2: { 96 'name': 'ROUTER2', 97 'mode': 'rdn', 98 }, 99 ROUTER3: { 100 'name': 'ROUTER3', 101 'mode': 'rdn', 102 }, 103 ROUTER4: { 104 'name': 'ROUTER4', 105 'mode': 'rdn', 106 }, 107 ROUTER5: { 108 'name': 'ROUTER5', 109 'mode': 'rdn', 110 }, 111 END_DEV1: { 112 'name': 'END_DEV1', 113 'mode': 'rn', 114 }, 115 END_DEV2: { 116 'name': 'END_DEV2', 117 'mode': 'rn', 118 }, 119 END_DEV3: { 120 'name': 'END_DEV3', 121 'mode': 'rn', 122 }, 123 END_DEV4: { 124 'name': 'END_DEV4', 125 'mode': 'rn', 126 }, 127 END_DEV5: { 128 'name': 'END_DEV5', 129 'mode': 'rn', 130 }, 131 } 132 133 def verify_anycast_service(self, service): 134 # Verify the data in a single anycast `service` from `get_services()` 135 # Example of `service`: ['44970', '5c04', '', 's', 'bc00'] 136 self.assertEqual(int(service[0]), THREAD_ENTERPRISE_NUMBER) 137 # Check service data 138 service_data = bytes.fromhex(service[1]) 139 self.assertTrue(len(service_data) >= 2) 140 self.assertEqual(service_data[0], ANYCAST_SERVICE_NUM) 141 self.assertEqual(service_data[1], int(ANYCAST_SEQ_NUM)) 142 # Verify that it stable 143 self.assertEqual(service[3], 's') 144 145 def verify_anycast_services(self, services): 146 # Verify a list of anycast `services` from `get_services()` 147 for service in services: 148 self.verify_anycast_service(service) 149 150 def verify_unicast_service(self, service): 151 # Verify the data in a single unicast `service` from `get_services()` 152 # Example of `service`: ['44970', '5d', 'fd000db800000000c6b0e5ee81f940e8223d', 's', '7000'] 153 self.assertEqual(int(service[0]), THREAD_ENTERPRISE_NUMBER) 154 # Check service data 155 service_data = bytes.fromhex(service[1]) 156 self.assertTrue(len(service_data) >= 1) 157 self.assertEqual(service_data[0], UNICAST_SERVICE_NUM) 158 # Verify that it stable 159 self.assertEqual(service[3], 's') 160 161 def verify_unicast_services(self, services): 162 # Verify a list of unicast `services` from `get_services()` 163 for service in services: 164 self.verify_unicast_service(service) 165 166 def check_num_of_prefixes(self, prefixes, num_low, num_med, num_high): 167 # Check and validate the prefix entries in network data (from 168 # `prefixes`) based on number of published prefix entries at 169 # different preference levels given by `num_low`, `num_med`, 170 # `num_high`. Prefixes is a list of the format 171 # 'fd00:1234:0:0::/64 paos low a802'. 172 self.assertEqual(len(prefixes), min(num_high + num_med + num_low, DESIRED_NUM_ON_MESH_PREFIX)) 173 prfs = [prefix.split(' ')[2] for prefix in prefixes] 174 self.assertEqual(prfs.count('high'), min(num_high, DESIRED_NUM_ON_MESH_PREFIX)) 175 self.assertEqual(prfs.count('med'), min(num_med, max(0, DESIRED_NUM_ON_MESH_PREFIX - num_high))) 176 self.assertEqual(prfs.count('low'), min(num_low, max(0, DESIRED_NUM_ON_MESH_PREFIX - num_high - num_med))) 177 178 def check_num_of_routes(self, routes, num_low, num_med, num_high): 179 # Check and validate the prefix entries in network data (from 180 # `routes`) based on number of published prefix entries at 181 # different preference levels given by `num_low`, `num_med`, 182 # `num_high`. Prefixes is a list of the format 183 # 'fd00:abce:0:0::/64 s med 6c01'. 184 self.assertEqual(len(routes), min(num_high + num_med + num_low, DESIRED_NUM_EXTERNAL_ROUTE)) 185 prfs = [route.split(' ')[2] for route in routes] 186 self.assertEqual(prfs.count('high'), min(num_high, DESIRED_NUM_EXTERNAL_ROUTE)) 187 self.assertEqual(prfs.count('med'), min(num_med, max(0, DESIRED_NUM_EXTERNAL_ROUTE - num_high))) 188 self.assertEqual(prfs.count('low'), min(num_low, max(0, DESIRED_NUM_EXTERNAL_ROUTE - num_high - num_med))) 189 190 def test(self): 191 leader = self.nodes[LEADER] 192 router1 = self.nodes[ROUTER1] 193 router2 = self.nodes[ROUTER2] 194 router3 = self.nodes[ROUTER3] 195 router4 = self.nodes[ROUTER4] 196 router5 = self.nodes[ROUTER5] 197 end_dev1 = self.nodes[END_DEV1] 198 end_dev2 = self.nodes[END_DEV2] 199 end_dev3 = self.nodes[END_DEV3] 200 end_dev4 = self.nodes[END_DEV4] 201 end_dev5 = self.nodes[END_DEV5] 202 203 nodes = self.nodes.values() 204 routers = [router1, router2, router3, router4, router5] 205 end_devs = [end_dev1, end_dev2, end_dev3, end_dev4, end_dev5] 206 207 # Start the nodes 208 209 leader.start() 210 self.simulator.go(config.LEADER_STARTUP_DELAY) 211 self.assertEqual(leader.get_state(), 'leader') 212 213 for router in routers: 214 router.start() 215 self.simulator.go(config.ROUTER_STARTUP_DELAY) 216 self.assertEqual(router.get_state(), 'router') 217 218 for end_dev in end_devs: 219 end_dev.start() 220 self.simulator.go(5) 221 self.assertEqual(end_dev.get_state(), 'child') 222 223 #--------------------------------------------------------------------------------- 224 # DNS/SRP anycast entries - equal version number 225 226 # Publish DNS/SRP anycast on leader and all routers (6 nodes). 227 228 leader.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM) 229 for node in routers: 230 node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM) 231 self.simulator.go(WAIT_TIME) 232 233 # Check all entries are present in the network data 234 235 services = leader.get_services() 236 self.assertEqual(len(services), min(1 + len(routers), DESIRED_NUM_DNSSRP_ANYCAST)) 237 self.verify_anycast_services(services) 238 239 # Publish same entry on all end-devices (5 nodes). 240 241 for node in end_devs: 242 node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM) 243 print(node.name) 244 self.simulator.go(WAIT_TIME) 245 246 # Check number of entries in the network data is limited to 247 # the desired number (8 entries). 248 249 services = leader.get_services() 250 self.assertEqual(len(leader.get_services()), min(len(nodes), DESIRED_NUM_DNSSRP_ANYCAST)) 251 self.verify_anycast_services(services) 252 253 # Unpublish the entry from nodes one by one starting from leader 254 # and check that number of entries is correct in each step. 255 256 num = len(nodes) 257 for node in nodes: 258 node.netdata_unpublish_dnssrp() 259 self.simulator.go(WAIT_TIME) 260 num -= 1 261 services = leader.get_services() 262 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_ANYCAST)) 263 self.verify_anycast_services(services) 264 265 #--------------------------------------------------------------------------------- 266 # DNS/SRP anycast entries - different version numbers 267 268 # Publish DNS/SRP anycast on leader and all routers (6 nodes). 269 270 version = 0 271 leader.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM, version) 272 num = 1 273 274 for node in routers: 275 version += 1 276 node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM, version) 277 num += 1 278 279 self.simulator.go(WAIT_TIME) 280 281 # Check all entries are present in the network data 282 283 services = leader.get_services() 284 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_ANYCAST)) 285 self.verify_anycast_services(services) 286 287 # Publish same entry with same version on all end-devices (5 nodes). 288 289 for node in end_devs: 290 node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM, version) 291 num += 1 292 print(node.name) 293 self.simulator.go(WAIT_TIME) 294 # Check number of entries in the network data is limited 295 # to the desired number (8 entries). All new entries use 296 # higher version and should be preferred. Validate that 297 # the 'services' list contains the new services. 298 services = leader.get_services() 299 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_ANYCAST)) 300 self.verify_anycast_services(services) 301 node_rloc16 = node.get_addr16() 302 self.assertTrue(any(int(service[4], 16) == node_rloc16 for service in services)) 303 304 # Unpublish the entry from nodes one by one starting from leader 305 # and check that number of entries is correct in each step. 306 307 for node in nodes: 308 node.netdata_unpublish_dnssrp() 309 self.simulator.go(WAIT_TIME) 310 num -= 1 311 services = leader.get_services() 312 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_ANYCAST)) 313 self.verify_anycast_services(services) 314 315 #--------------------------------------------------------------------------------- 316 # DNS/SRP service data unicast entries - equal version number 317 318 num = 0 319 for node in routers: 320 node.netdata_publish_dnssrp_unicast(DNSSRP_ADDRESS, DNSSRP_PORT) 321 self.simulator.go(WAIT_TIME) 322 num += 1 323 services = leader.get_services() 324 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 325 self.verify_unicast_services(services) 326 327 for node in routers: 328 node.srp_server_set_enabled(True) 329 self.simulator.go(WAIT_TIME) 330 331 self.assertEqual(sum(node.srp_server_get_state() == 'running' for node in routers), 332 min(len(routers), DESIRED_NUM_DNSSRP_UNICAST)) 333 self.assertEqual(sum(node.srp_server_get_state() == 'stopped' for node in routers), 334 max(len(routers) - DESIRED_NUM_DNSSRP_UNICAST, 0)) 335 336 for node in routers: 337 node.netdata_unpublish_dnssrp() 338 self.simulator.go(WAIT_TIME) 339 num -= 1 340 services = leader.get_services() 341 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 342 self.verify_unicast_services(services) 343 for node in routers: 344 node.srp_server_set_enabled(False) 345 self.assertEqual(node.srp_server_get_state(), 'disabled') 346 347 #--------------------------------------------------------------------------------- 348 # DNS/SRP service data unicast entries - different version numbers 349 350 num = 0 351 for node in routers: 352 # Use `num` as version. 353 node.netdata_publish_dnssrp_unicast(DNSSRP_ADDRESS, DNSSRP_PORT, num) 354 self.simulator.go(WAIT_TIME) 355 num += 1 356 services = leader.get_services() 357 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 358 self.verify_unicast_services(services) 359 # The most recent service should win as it uses a higher version 360 # number. Validate that the 'services' list contains the service 361 # from this node by checking the service RLOC16. 362 node_rloc16 = node.get_addr16() 363 self.assertTrue(any(int(service[4], 16) == node_rloc16 for service in services)) 364 365 for node in reversed(routers): 366 node.netdata_unpublish_dnssrp() 367 self.simulator.go(WAIT_TIME) 368 num -= 1 369 services = leader.get_services() 370 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 371 self.verify_unicast_services(services) 372 373 #--------------------------------------------------------------------------------- 374 # DNS/SRP server data unicast entries - equal version number 375 376 num = 0 377 for node in routers: 378 node.netdata_publish_dnssrp_unicast_mleid(DNSSRP_PORT) 379 self.simulator.go(WAIT_TIME) 380 num += 1 381 services = leader.get_services() 382 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 383 self.verify_unicast_services(services) 384 385 for node in routers: 386 node.srp_server_set_enabled(True) 387 self.simulator.go(WAIT_TIME) 388 self.assertEqual(sum(node.srp_server_get_state() == 'running' for node in routers), 389 min(len(routers), DESIRED_NUM_DNSSRP_UNICAST)) 390 self.assertEqual(sum(node.srp_server_get_state() == 'stopped' for node in routers), 391 max(len(routers) - DESIRED_NUM_DNSSRP_UNICAST, 0)) 392 393 for node in routers: 394 node.netdata_unpublish_dnssrp() 395 self.simulator.go(WAIT_TIME) 396 num -= 1 397 services = leader.get_services() 398 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 399 self.verify_unicast_services(services) 400 for node in routers: 401 node.srp_server_set_enabled(False) 402 self.assertEqual(node.srp_server_get_state(), 'disabled') 403 404 #--------------------------------------------------------------------------------- 405 # DNS/SRP server data unicast entries - different version numbers 406 407 num = 0 408 for node in routers: 409 node.netdata_publish_dnssrp_unicast_mleid(DNSSRP_PORT, num) 410 self.simulator.go(WAIT_TIME) 411 num += 1 412 services = leader.get_services() 413 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 414 self.verify_unicast_services(services) 415 # The most recent service should win as it uses a higher version 416 # number. Validate that the 'services' list contains the service 417 # from this node by checking the service RLOC16. 418 node_rloc16 = node.get_addr16() 419 self.assertTrue(any(int(service[4], 16) == node_rloc16 for service in services)) 420 421 for node in reversed(routers): 422 node.netdata_unpublish_dnssrp() 423 self.simulator.go(WAIT_TIME) 424 num -= 1 425 services = leader.get_services() 426 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 427 self.verify_unicast_services(services) 428 429 # Repeat the same test steps, but start with larger version 430 # numbers first. 431 432 num = 0 433 for node in routers: 434 node.netdata_publish_dnssrp_unicast_mleid(DNSSRP_PORT, 20 - num) 435 self.simulator.go(WAIT_TIME) 436 num += 1 437 services = leader.get_services() 438 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 439 self.verify_unicast_services(services) 440 # The service from first router should win as it uses the highest 441 # version number. 442 first_router_rloc16 = routers[0].get_addr16() 443 self.assertTrue(any(int(service[4], 16) == first_router_rloc16 for service in services)) 444 445 for node in routers: 446 node.netdata_unpublish_dnssrp() 447 self.simulator.go(WAIT_TIME) 448 num -= 1 449 services = leader.get_services() 450 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 451 self.verify_unicast_services(services) 452 453 #--------------------------------------------------------------------------------- 454 # DNS/SRP server data unicast vs anycast 455 456 num = 0 457 for node in routers: 458 node.netdata_publish_dnssrp_unicast_mleid(DNSSRP_PORT) 459 self.simulator.go(WAIT_TIME) 460 num += 1 461 services = leader.get_services() 462 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 463 self.verify_unicast_services(services) 464 465 # Verify that publishing an anycast entry will update the 466 # limit for the server data unicast address entry and all are 467 # removed. 468 469 leader.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM) 470 self.simulator.go(WAIT_TIME) 471 services = leader.get_services() 472 self.assertEqual(len(services), 1) 473 self.verify_anycast_services(services) 474 475 # Removing the anycast entry will cause the lower priority 476 # server data unicast entries to be added again. 477 478 leader.netdata_unpublish_dnssrp() 479 self.simulator.go(WAIT_TIME) 480 481 services = leader.get_services() 482 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 483 self.verify_unicast_services(services) 484 485 #--------------------------------------------------------------------------------- 486 # DNS/SRP server data unicast vs service data unicast 487 488 leader.netdata_publish_dnssrp_unicast(DNSSRP_ADDRESS, DNSSRP_PORT) 489 self.simulator.go(WAIT_TIME) 490 services = leader.get_services() 491 self.assertEqual(len(services), 1) 492 self.verify_unicast_services(services) 493 494 # Removing the service data unicast entry will cause the lower 495 # priority server data unicast entries to be added again. 496 497 leader.netdata_unpublish_dnssrp() 498 self.simulator.go(WAIT_TIME) 499 500 services = leader.get_services() 501 self.assertEqual(len(services), min(num, DESIRED_NUM_DNSSRP_UNICAST)) 502 self.verify_unicast_services(services) 503 504 for node in routers: 505 node.netdata_unpublish_dnssrp() 506 507 #--------------------------------------------------------------------------------- 508 # DNS/SRP entries: Verify publisher preference when removing 509 # entries. 510 # 511 # Publish DNS/SRP anycast on 8 nodes: leader, router1, 512 # router2, and all 5 end-devices. Afterwards, manually add 513 # the same service entry in Network Data on router3, router4, 514 # and router5 and at each step check that entry from one of 515 # the end-devices is removed (publisher prefers 516 # entries from routers over the ones from end-devices). 517 518 num = 0 519 test_routers = [leader, router1, router2] 520 for node in test_routers + end_devs: 521 node.netdata_publish_dnssrp_anycast(ANYCAST_SEQ_NUM) 522 self.simulator.go(WAIT_TIME) 523 num += 1 524 services = leader.get_services() 525 self.assertEqual(len(services), num) 526 self.verify_anycast_services(services) 527 528 self.assertEqual(num, DESIRED_NUM_DNSSRP_ANYCAST) 529 530 service_data = '%02x%02x' % (ANYCAST_SERVICE_NUM, int(ANYCAST_SEQ_NUM)) 531 for node in [router3, router4, router5]: 532 node.add_service(str(THREAD_ENTERPRISE_NUMBER), service_data, '00') 533 node.register_netdata() 534 self.simulator.go(WAIT_TIME) 535 536 services = leader.get_services() 537 self.assertEqual(len(services), num) 538 self.verify_anycast_services(services) 539 540 service_rlocs = [int(service[4], 16) for service in services] 541 test_routers.append(node) 542 543 for router in test_routers: 544 self.assertIn(router.get_addr16(), service_rlocs) 545 546 #--------------------------------------------------------------------------------- 547 # On-mesh prefix 548 549 # Publish the same on-mesh prefix on different nodes (low 550 # preference on end-devices, medium preference on routers, and 551 # high on leader) one by one and then unpublish them one by one. 552 # Verify that at each step the entries in the network data are 553 # correct. Particularly verify that that higher preference 554 # entries replace lower preference ones even when there are 555 # already desired number in network data. 556 557 num_low = 0 558 num_med = 0 559 num_high = 0 560 561 for node in end_devs: 562 node.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'low') 563 self.simulator.go(WAIT_TIME) 564 num_low += 1 565 prefixes = leader.get_prefixes() 566 self.check_num_of_prefixes(prefixes, num_low, num_med, num_high) 567 568 # Now add the entry as 'med' on routers and check that we see those in the list. 569 for node in routers: 570 node.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'med') 571 self.simulator.go(WAIT_TIME) 572 num_med += 1 573 prefixes = leader.get_prefixes() 574 self.check_num_of_prefixes(prefixes, num_low, num_med, num_high) 575 576 leader.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'high') 577 self.simulator.go(WAIT_TIME) 578 num_high += 1 579 prefixes = leader.get_prefixes() 580 self.check_num_of_prefixes(prefixes, num_low, num_med, num_high) 581 582 for node in routers: 583 node.netdata_unpublish_prefix(ON_MESH_PREFIX) 584 self.simulator.go(WAIT_TIME) 585 num_med -= 1 586 prefixes = leader.get_prefixes() 587 self.check_num_of_prefixes(prefixes, num_low, num_med, num_high) 588 589 leader.netdata_unpublish_prefix(ON_MESH_PREFIX) 590 self.simulator.go(WAIT_TIME) 591 num_high -= 1 592 prefixes = leader.get_prefixes() 593 self.check_num_of_prefixes(prefixes, num_low, num_med, num_high) 594 595 for node in end_devs: 596 node.netdata_unpublish_prefix(ON_MESH_PREFIX) 597 self.simulator.go(WAIT_TIME) 598 num_low -= 1 599 prefixes = leader.get_prefixes() 600 self.check_num_of_prefixes(prefixes, num_low, num_med, num_high) 601 602 #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 603 # Verify that when removing extra entries, non-preferred entries 604 # are removed first over preferred ones. Entries from routers are 605 # preferred over similar entries from end-devices. 606 607 # Publish prefix entry on `end_dev1` and verify that it is added. 608 609 end_dev1.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'med') 610 self.simulator.go(WAIT_TIME) 611 prefixes = leader.get_prefixes() 612 self.check_num_of_prefixes(prefixes, 0, 1, 0) 613 614 # Publish same prefix on all routers (again as `med` preference). 615 # Verify that we reach the desired number of prefix entries in network 616 # data and that the entry from `end_dev1` is present in network data. 617 618 for node in routers: 619 node.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'med') 620 self.simulator.go(WAIT_TIME) 621 prefixes = leader.get_prefixes() 622 self.check_num_of_prefixes(prefixes, 0, 1 + len(routers), 0) 623 self.assertTrue(1 + len(routers) >= DESIRED_NUM_ON_MESH_PREFIX) 624 # `prefixes` is a list of format 'fd00:1234:0:0::/64 paos low a802' 625 rlocs = [int(prefix.split(' ')[3], 16) for prefix in prefixes] 626 self.assertTrue(rlocs.count(end_dev1.get_addr16()) == 1) 627 628 # Publish same prefix now with `high` preference on leader. 629 # Since it is `high` preference, it is added to network data 630 # which leads to total number of entries to go above the desired 631 # number temporarily and trigger other nodes to try to remove 632 # their entry. The entries from routers should be preferred over 633 # the one from `end_dev1` so that is the one we expect to be 634 # removed. We check that this is the case (i.e., the entry from 635 # `end_dev1` is no longer present in network data). 636 637 leader.netdata_publish_prefix(ON_MESH_PREFIX, ON_MESH_FLAGS, 'high') 638 self.simulator.go(WAIT_TIME) 639 prefixes = leader.get_prefixes() 640 self.check_num_of_prefixes(prefixes, 0, 1 + len(routers), 1) 641 rlocs = [int(prefix.split(' ')[3], 16) for prefix in prefixes] 642 self.assertTrue(rlocs.count(end_dev1.get_addr16()) == 0) 643 644 #--------------------------------------------------------------------------------- 645 # External route 646 647 # Publish same external route on all nodes with low preference. 648 649 num = 0 650 for node in nodes: 651 node.netdata_publish_route(EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'low') 652 self.simulator.go(WAIT_TIME) 653 num += 1 654 routes = leader.get_routes() 655 self.check_num_of_routes(routes, num, 0, 0) 656 657 # Change the preference level of the existing entry on leader to high. 658 659 leader.netdata_publish_route(EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'high') 660 self.simulator.go(WAIT_TIME) 661 routes = leader.get_routes() 662 self.check_num_of_routes(routes, num - 1, 0, 1) 663 664 # Replace the published route on leader with '::/0'. 665 leader.netdata_publish_replace(EXTERNAL_ROUTE, '::/0', EXTERNAL_FLAGS, 'med') 666 self.simulator.go(1) 667 routes = leader.get_routes() 668 self.assertEqual([route.split(' ')[0] == '::/0' for route in routes].count(True), 1) 669 670 # Replace it back to the original route. 671 leader.netdata_publish_replace('::/0', EXTERNAL_ROUTE, EXTERNAL_FLAGS, 'high') 672 self.simulator.go(WAIT_TIME) 673 routes = leader.get_routes() 674 self.assertEqual([route.split(' ')[0] == '::/0' for route in routes].count(True), 0) 675 self.check_num_of_routes(routes, num - 1, 0, 1) 676 677 # Publish the same prefix on leader as an on-mesh prefix. Make 678 # sure it is removed from external routes and now seen in the 679 # prefix list. 680 681 leader.netdata_publish_prefix(EXTERNAL_ROUTE, ON_MESH_FLAGS, 'low') 682 self.simulator.go(WAIT_TIME) 683 routes = leader.get_routes() 684 self.check_num_of_routes(routes, num - 1, 0, 0) 685 686 prefixes = leader.get_prefixes() 687 print(prefixes) 688 self.assertIn(EXTERNAL_ROUTE, [prefix.split()[0] for prefix in prefixes]) 689 690 691if __name__ == '__main__': 692 unittest.main() 693