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 30import unittest 31 32import command 33import config 34import ipaddress 35import mle 36import thread_cert 37 38BBR_1 = 1 # Collapsed with Leader Role 39ROUTER_1_1 = 2 40ROUTER_1_2 = 3 41MED_1_2 = 4 42SED_1_2 = 5 43 44WAIT_ATTACH = 5 45WAIT_REDUNDANCE = 3 46ROUTER_SELECTION_JITTER = 1 47BBR_REGISTRATION_JITTER = 5 48SED_POLL_PERIOD = 2000 # 2s 49MED_TIMEOUT = 20 # 20s 50 51DUA_IID_MANUAL1 = '4444333322221111' 52DUA_IID_MANUAL2 = '5555444433332222' 53 54TEST_PREFIX1 = '2001:0:0:1::/64' 55TEST_PREFIX2 = '2001:0:0:2::/64' 56TEST_PREFIX3 = '2001:0:0:3::/64' 57""" 58 Topology 59 60 61 SED_1_2 62 | 63 | 64 ROUTER_1_1 MED_1_2 65 | | 66 | | 67 BBR_1 (LEADER) --- ROUTER_1_2 68 69 70 1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain 71 Prefix without `P_slaac`. 72 73 2) Bring up ROUTER_1_1, no DUA was added due to that `P_slaac` flag is not set. 74 75 3) Bring up ROUTER_1_2, verify that it has DUA generated. 76 77 4) Bring up MED_1_2 with DUA_IID_MANUAL1 set in advance, verify 78 a) DUA_IID_MANUAL1 is registered in Address Registration TLV via Child Update Request. 79 b) Remove DUA_IID_MANUAL1, a new DUA generated via SLAAC would be registered in Address 80 Registration TLV via Child Update Request. 81 c) Set DUA_IID_MANUAL2 which should override the generated one and be registered in Address 82 Registration TLV via Child Update Request. 83 d) Remove DUA_IID_MANUAL2, a new DUA generated via SLAAC, the same as in above b) would 84 be registered in Address Registration TLV via Child Update Request. 85 86 5) Change BBR_1 from config.DOMAIN_PREFIX to config.DOMAIN_PRFIX_ALTER. Verify that MED_1_2 87 generate a new Interface Identifier different from the one generated in 4d) due to the 88 Domain Prefix change. 89 90 6) Recover config.Domain_Prefix on BBR_1. Verify that MED_1_2 generates and registers the same 91 DUA as in step 4b). 92 93 7) Configure ROUTER_1_1 as Border Router with 3 SLAAC prefixes, verify MED_1_2 would register 94 its DUA in Address Registration TLV. 95 96 8) Bring up SED_1_2, verify it generates one DUA, and registers it to its parent, though the parent 97 is a Thread 1.1 device. 98 99""" 100 101 102class TestDomainUnicastAddress(thread_cert.TestCase): 103 TOPOLOGY = { 104 BBR_1: { 105 'version': '1.2', 106 'allowlist': [ROUTER_1_1, ROUTER_1_2], 107 'is_bbr': True 108 }, 109 ROUTER_1_1: { 110 'version': '1.1', 111 'allowlist': [BBR_1, SED_1_2] 112 }, 113 ROUTER_1_2: { 114 'version': '1.2', 115 'allowlist': [BBR_1, MED_1_2] 116 }, 117 MED_1_2: { 118 'mode': 'rn', 119 'version': '1.2', 120 'allowlist': [ROUTER_1_2], 121 }, 122 SED_1_2: { 123 'mode': 'n', 124 'version': '1.2', 125 'allowlist': [ROUTER_1_1], 126 }, 127 } 128 """All nodes are created with default configurations""" 129 130 def __get_iid(self, address): 131 ''' Get the interface identifier of an IPv6 address. 132 133 Args: 134 address (string): An IPv6 address; 135 ''' 136 return ''.join(ipaddress.ip_address(address).exploded.split(':')[4:]) 137 138 def __check_dua_registration(self, node, iid, dp_cid): 139 ''' Check whether or not the specified Domain Unicast Address is registered in Address 140 Registraion TLV. 141 142 Args: 143 node (int) : The device id 144 iid (string): The Interface Identifier 145 dp_cid (int): The context id of the domain prefix. 146 ''' 147 148 messages = self.simulator.get_messages_sent_by(node) 149 msg = messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST) 150 command.check_compressed_address_registration_tlv(msg, dp_cid, iid, cid_present_once=True) 151 152 def test(self): 153 # starting context id 154 context_id = 1 155 156 # 1) Bring up BBR_1, BBR_1 becomes Leader and Primary Backbone Router, with Domain 157 # Prefix without `P_slaac`. 158 self.nodes[BBR_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER) 159 self.nodes[BBR_1].set_bbr_registration_jitter(BBR_REGISTRATION_JITTER) 160 self.nodes[BBR_1].set_backbone_router(seqno=1) 161 self.nodes[BBR_1].start() 162 WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER 163 self.simulator.go(WAIT_TIME * 2) 164 self.assertEqual(self.nodes[BBR_1].get_state(), 'leader') 165 self.nodes[BBR_1].enable_backbone_router() 166 WAIT_TIME = BBR_REGISTRATION_JITTER + WAIT_REDUNDANCE 167 self.simulator.go(WAIT_TIME) 168 self.assertEqual(self.nodes[BBR_1].get_backbone_router_state(), 'Primary') 169 170 self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX, 'prosD') 171 WAIT_TIME = WAIT_REDUNDANCE 172 self.simulator.go(WAIT_TIME) 173 174 self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX) 175 domain_prefix_cid = context_id 176 177 # 2) Bring up ROUTER_1_1, no DUA was added due to that `P_slaac` flag is not set. 178 self.nodes[ROUTER_1_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER) 179 WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER 180 self.nodes[ROUTER_1_1].start() 181 self.simulator.go(WAIT_TIME) 182 self.assertEqual(self.nodes[ROUTER_1_1].get_state(), 'router') 183 dua = self.nodes[ROUTER_1_1].get_addr(config.DOMAIN_PREFIX) 184 assert not dua, 'Error: Unexpected DUA ({})'.format(dua) 185 186 # 3) Bring up ROUTER_1_2, verify that it has DUA generated. 187 self.nodes[ROUTER_1_2].set_router_selection_jitter(ROUTER_SELECTION_JITTER) 188 self.nodes[ROUTER_1_2].start() 189 WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER 190 self.simulator.go(WAIT_TIME) 191 self.assertEqual(self.nodes[ROUTER_1_2].get_state(), 'router') 192 dua = self.nodes[ROUTER_1_2].get_addr(config.DOMAIN_PREFIX) 193 assert dua, 'Error: Expected DUA not found' 194 self.assertTrue(self.nodes[BBR_1].ping(dua)) 195 196 # 4) Bring up MED_1_2 with DUA_IID_MANUAL1 set in advance 197 self.nodes[MED_1_2].set_dua_iid(DUA_IID_MANUAL1) 198 self.nodes[MED_1_2].set_timeout(MED_TIMEOUT) 199 self.nodes[MED_1_2].start() 200 WAIT_TIME = WAIT_ATTACH 201 self.simulator.go(WAIT_TIME) 202 self.assertEqual(self.nodes[MED_1_2].get_state(), 'child') 203 204 # 4a) DUA_IID_MANUAL1 is registered in Address Registration TLV via Child Update Request. 205 self.__check_dua_registration(MED_1_2, DUA_IID_MANUAL1, domain_prefix_cid) 206 207 # 4b) Remove DUA_IID_MANUAL1, a new DUA generated via SLAAC would be registered in Address 208 # Registration TLV via Child Update Request. 209 210 # Flush relative message queues. 211 messages = self.simulator.get_messages_sent_by(MED_1_2) 212 213 self.nodes[MED_1_2].clear_dua_iid() 214 WAIT_TIME = MED_TIMEOUT + WAIT_REDUNDANCE 215 self.simulator.go(WAIT_TIME) 216 217 med_1_2_dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX) 218 assert med_1_2_dua, 'Error: Expected DUA not found' 219 220 med_1_2_dua_iid = self.__get_iid(med_1_2_dua) 221 self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid) 222 223 # 4c) Set DUA_IID_MANUAL2 which should override the generated one and be registered in Address 224 # Registration TLV via Child Update Request. 225 226 # Flush relative message queues. 227 messages = self.simulator.get_messages_sent_by(MED_1_2) 228 self.nodes[MED_1_2].set_dua_iid(DUA_IID_MANUAL2) 229 WAIT_TIME = WAIT_REDUNDANCE 230 self.simulator.go(WAIT_TIME) 231 232 dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX) 233 234 self.__check_dua_registration(MED_1_2, DUA_IID_MANUAL2, domain_prefix_cid) 235 236 # 4d) Remove DUA_IID_MANUAL2, a new DUA generated via SLAAC, the same as in above b) would 237 # be registered in Address Registration TLV via Child Update Request. 238 239 # Flush relative message queues. 240 messages = self.simulator.get_messages_sent_by(MED_1_2) 241 self.nodes[MED_1_2].clear_dua_iid() 242 WAIT_TIME = WAIT_REDUNDANCE 243 self.simulator.go(WAIT_TIME) 244 dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX) 245 assert ipaddress.ip_address(dua) == ipaddress.ip_address( 246 med_1_2_dua), 'Error: Expected SLAAC DUA not generated' 247 assert ipaddress.ip_address(med_1_2_dua) == ipaddress.ip_address( 248 dua), 'Error: Expected same SLAAC DUA not generated' 249 250 self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid) 251 252 # 5) Change BBR_1 from config.DOMAIN_PREFIX to config.DOMAIN_PRFIX_ALTER. Verify that MED_1_2 253 # generates a new Interface Identifier different from the one generated in 4d) due to the 254 # Domain Prefix change. 255 context_id += 1 256 self.simulator.set_lowpan_context(context_id, config.DOMAIN_PREFIX_ALTER) 257 self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX_ALTER) 258 WAIT_TIME = WAIT_REDUNDANCE 259 self.simulator.go(WAIT_TIME) 260 261 med_1_2_dua2 = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX_ALTER) 262 med_1_2_dua2_iid = self.__get_iid(med_1_2_dua2) 263 self.__check_dua_registration(MED_1_2, med_1_2_dua2_iid, context_id) 264 265 #6) Recover config.Domain_Prefix on BBR_1. Verify that MED_1_2 generates and registers the same 266 # DUA as in step 4b). 267 self.nodes[BBR_1].set_domain_prefix(config.DOMAIN_PREFIX) 268 WAIT_TIME = WAIT_REDUNDANCE 269 self.simulator.go(WAIT_TIME) 270 dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX) 271 assert dua, 'Error: Expected DUA not found' 272 assert ipaddress.ip_address(med_1_2_dua) == ipaddress.ip_address( 273 dua), 'Error: Expected same SLAAC DUA not generated' 274 275 self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid) 276 277 #7) Configure ROUTER_1_1 as Border Router with 3 SLAAC prefixes, verify MED_1_2 would register 278 # its DUA in Address Registration TLV. 279 280 # Flush relative message queues. 281 messages = self.simulator.get_messages_sent_by(MED_1_2) 282 283 context_id += 1 284 self.simulator.set_lowpan_context(context_id, TEST_PREFIX1) 285 self.nodes[ROUTER_1_1].add_prefix(TEST_PREFIX1) 286 287 context_id += 1 288 self.simulator.set_lowpan_context(context_id, TEST_PREFIX2) 289 self.nodes[ROUTER_1_1].add_prefix(TEST_PREFIX2) 290 context_id += 1 291 self.simulator.set_lowpan_context(context_id, TEST_PREFIX3) 292 self.nodes[ROUTER_1_1].add_prefix(TEST_PREFIX3) 293 self.nodes[ROUTER_1_1].register_netdata() 294 295 WAIT_TIME = WAIT_REDUNDANCE 296 self.simulator.go(WAIT_TIME) 297 298 WAIT_TIME = MED_TIMEOUT 299 self.simulator.go(WAIT_TIME) 300 dua = self.nodes[MED_1_2].get_addr(config.DOMAIN_PREFIX) 301 assert dua, 'Error: Expected DUA not found' 302 assert ipaddress.ip_address(med_1_2_dua) == ipaddress.ip_address( 303 dua), 'Error: Expected same SLAAC DUA not generated' 304 305 self.__check_dua_registration(MED_1_2, med_1_2_dua_iid, domain_prefix_cid) 306 307 #8) Bring up SED_1_2, verify that it generates one DUA, and registers it to its parent, though the parent 308 # is a Thread 1.1 device. 309 self.nodes[SED_1_2].set_pollperiod(SED_POLL_PERIOD) 310 self.nodes[SED_1_2].start() 311 WAIT_TIME = WAIT_ATTACH 312 self.simulator.go(WAIT_TIME) 313 314 dua = self.nodes[SED_1_2].get_addr(config.DOMAIN_PREFIX) 315 assert dua, 'Error: Expected DUA not found' 316 317 dua_iid = self.__get_iid(dua) 318 self.__check_dua_registration(SED_1_2, dua_iid, domain_prefix_cid) 319 320 self.assertTrue(self.nodes[BBR_1].ping(dua)) 321 322 323if __name__ == '__main__': 324 unittest.main() 325