1#!/usr/bin/env python3 2# 3# Copyright (c) 2020, 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# This script tests how node would handle duplicated Domain Unicast Address. 30# 31 32import unittest 33 34import config 35import thread_cert 36 37BBR_1 = 1 # Collapsed with Leader Role 38ROUTER = 2 39FED = 3 40MED = 4 41 42WAIT_ATTACH = 5 43WAIT_REDUNDANCE = 3 44BBR_REGISTRATION_JITTER = 5 45SED_POLL_PERIOD = 2000 # 2s 46MED_TIMEOUT = 20 # 20s 47""" 48 Topology 49 50 BBR_1 (Leader) 51 | 52 ROUTER_1---FED 53 | 54 MED 55""" 56 57WAIT_REDUNDANCE = 3 58REG_DELAY = 5 59 60 61class TestDomainUnicastAddress(thread_cert.TestCase): 62 TOPOLOGY = { 63 BBR_1: { 64 'version': '1.2', 65 'allowlist': [ROUTER], 66 'is_bbr': True 67 }, 68 ROUTER: { 69 'version': '1.2', 70 'allowlist': [BBR_1, FED, MED], 71 }, 72 FED: { 73 'version': '1.2', 74 'allowlist': [ROUTER], 75 'router_eligible': False, 76 'mode': 'rdn', 77 }, 78 MED: { 79 'version': '1.2', 80 'is_mtd': True, 81 'allowlist': [ROUTER], 82 'mode': 'rn', 83 }, 84 } 85 86 def test(self): 87 self.simulator.set_lowpan_context(1, config.DOMAIN_PREFIX) 88 89 # 1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain 90 # Prefix without `P_slaac`. 91 self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER) 92 self.nodes[BBR_1].set_backbone_router(seqno=1, reg_delay=REG_DELAY) 93 self.nodes[BBR_1].start() 94 95 self.simulator.go(WAIT_ATTACH * 2 + config.DEFAULT_ROUTER_SELECTION_JITTER) 96 self.assertEqual(self.nodes[BBR_1].get_state(), 'leader') 97 self.nodes[BBR_1].enable_backbone_router() 98 self.simulator.go(BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE) 99 self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(), 'Primary') 100 101 self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD') 102 self.simulator.go(WAIT_REDUNDANCE) 103 104 # 2) Bring up ROUTER_1 105 self.nodes[ROUTER].start() 106 self.simulator.go(WAIT_ATTACH + REG_DELAY + WAIT_REDUNDANCE) 107 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 108 109 # Bring up FED 110 self.nodes[FED].start() 111 self.simulator.go(WAIT_ATTACH + REG_DELAY + WAIT_REDUNDANCE) 112 self.assertEqual(self.nodes[FED].get_state(), 'child') 113 114 # Bring up MED 115 self.nodes[MED].start() 116 self.simulator.go(WAIT_ATTACH + config.PARENT_AGGREGATIOIN_DELAY + REG_DELAY + WAIT_REDUNDANCE) 117 self.assertEqual(self.nodes[MED].get_state(), 'child') 118 119 self._verify_dua_handle_address_error(ROUTER) 120 self._verify_dua_handle_address_error(FED) 121 self._verify_dua_handle_address_error(MED, is_med=True) 122 123 def _verify_dua_handle_address_error(self, nodeid, is_med=False): 124 dua = self.nodes[nodeid].get_addr(config.DOMAIN_PREFIX) 125 self.assertIsNotNone(dua) 126 127 # Ping the DUA to verify reachability, and also fill the EID cache on BBR_1 128 self.assertTrue(self.nodes[BBR_1].ping(dua)) 129 130 self.simulator.go(WAIT_REDUNDANCE) 131 132 # Send fake /a/an from ROUTER to BBR_1 for the node's DUA 133 pbbr_rloc = self.nodes[BBR_1].get_ip6_address(config.ADDRESS_TYPE.RLOC) 134 self.nodes[ROUTER].send_address_notification(pbbr_rloc, dua, f'000000000000{nodeid:04x}') 135 136 self.simulator.go(config.PARENT_AGGREGATIOIN_DELAY * is_med + REG_DELAY + WAIT_REDUNDANCE + 50) 137 138 # Make sure device handles /a/ae correctly by generating new DUA 139 new_dua = self.nodes[nodeid].get_addr(config.DOMAIN_PREFIX) 140 self.assertNotEqual(dua, new_dua) 141 self.assertTrue(self.nodes[BBR_1].ping(new_dua)) 142 self.assertFalse(self.nodes[BBR_1].ping(dua)) 143 144 self.simulator.go(3) 145 146 147if __name__ == '__main__': 148 unittest.main() 149