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# 29import logging 30import unittest 31from ipaddress import IPv6Network 32 33import config 34import thread_cert 35 36# Test description: 37# This test verifies on-link prefix configuration. 38# 39# Topology: 40# -------------(eth)---------------------------- 41# | | | 42# BR1 BR2 HOST 43# | | 44# ROUTER1 ROUTER2 45# 46# Thread Net1 Thread Net2 47# 48 49BR1 = 1 50ROUTER1 = 2 51BR2 = 3 52ROUTER2 = 4 53HOST = 5 54 55CHANNEL1 = 18 56CHANNEL2 = 19 57 58 59class MultiThreadNetworks(thread_cert.TestCase): 60 USE_MESSAGE_FACTORY = False 61 62 TOPOLOGY = { 63 BR1: { 64 'name': 'BR_1', 65 'allowlist': [ROUTER1], 66 'is_otbr': True, 67 'version': '1.2', 68 'channel': CHANNEL1, 69 'router_selection_jitter': 1, 70 'extended_panid': '0001020304050607' 71 }, 72 ROUTER1: { 73 'name': 'Router_1', 74 'allowlist': [BR1], 75 'version': '1.2', 76 'channel': CHANNEL1, 77 'router_selection_jitter': 1, 78 'extended_panid': '0001020304050607' 79 }, 80 BR2: { 81 'name': 'BR_2', 82 'allowlist': [ROUTER2], 83 'is_otbr': True, 84 'version': '1.2', 85 'channel': CHANNEL2, 86 'router_selection_jitter': 1, 87 'extended_panid': '08090a0b0c0d0e0f' 88 }, 89 ROUTER2: { 90 'name': 'Router_2', 91 'allowlist': [BR2], 92 'version': '1.2', 93 'channel': CHANNEL2, 94 'router_selection_jitter': 1, 95 'extended_panid': '08090a0b0c0d0e0f' 96 }, 97 HOST: { 98 'name': 'Host', 99 'is_host': True 100 }, 101 } 102 103 def test(self): 104 ON_LINK_PREFIX = 'fd00::/64' 105 br1 = self.nodes[BR1] 106 router1 = self.nodes[ROUTER1] 107 br2 = self.nodes[BR2] 108 router2 = self.nodes[ROUTER2] 109 host = self.nodes[HOST] 110 111 host.start(start_radvd=True, prefix=ON_LINK_PREFIX, slaac=True) 112 self.simulator.go(5) 113 114 br1.start() 115 self.simulator.go(config.LEADER_STARTUP_DELAY) 116 self.assertEqual('leader', br1.get_state()) 117 118 router1.start() 119 self.simulator.go(config.ROUTER_STARTUP_DELAY) 120 self.assertEqual('router', router1.get_state()) 121 122 self.simulator.go(10) 123 self.collect_ipaddrs() 124 125 logging.info("BR1 addrs: %r", br1.get_addrs()) 126 logging.info("ROUTER1 addrs: %r", router1.get_addrs()) 127 logging.info("HOST addrs: %r", host.get_addrs()) 128 129 self.assertEqual(len(br1.get_netdata_non_nat64_routes()), 1) 130 131 host_on_link_addr = host.get_matched_ula_addresses(ON_LINK_PREFIX)[0] 132 self.assertTrue(router1.ping(host_on_link_addr)) 133 self.assertTrue( 134 host.ping(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True, interface=host_on_link_addr)) 135 136 # Force kill the radvd host so that BR2 will start advertising its own on-link prefix. 137 host.kill_radvd_service() 138 139 br2.start() 140 self.simulator.go(config.LEADER_STARTUP_DELAY) 141 self.assertEqual('leader', br2.get_state()) 142 143 router2.start() 144 self.simulator.go(5) 145 self.assertEqual('router', router2.get_state()) 146 147 self.simulator.go(25) 148 self.collect_ipaddrs() 149 150 logging.info("BR1 addrs: %r", br1.get_addrs()) 151 logging.info("ROUTER1 addrs: %r", router1.get_addrs()) 152 logging.info("BR2 addrs: %r", br2.get_addrs()) 153 logging.info("ROUTER2 addrs: %r", router2.get_addrs()) 154 logging.info("HOST addrs: %r", host.get_addrs()) 155 156 self.assertTrue(len(br1.get_netdata_omr_prefixes()) == 1) 157 self.assertTrue(len(router1.get_netdata_omr_prefixes()) == 1) 158 self.assertTrue(len(br2.get_netdata_omr_prefixes()) == 1) 159 self.assertTrue(len(router2.get_netdata_omr_prefixes()) == 1) 160 161 br1_omr_prefix = br1.get_br_omr_prefix() 162 br2_omr_prefix = br2.get_br_omr_prefix() 163 self.assertNotEqual(br1_omr_prefix, br2_omr_prefix) 164 165 # Verify that the Border Routers starts advertising new on-link prefix 166 # but don't remove the external routes for the radvd on-link prefix 167 # immediately, because the SLAAC addresses are still valid. 168 169 self.assertEqual(len(br1.get_netdata_non_nat64_routes()), 1) 170 self.assertEqual(len(router1.get_netdata_non_nat64_routes()), 1) 171 self.assertEqual(len(br2.get_netdata_non_nat64_routes()), 1) 172 self.assertEqual(len(router2.get_netdata_non_nat64_routes()), 1) 173 174 br2_on_link_prefix = br2.get_br_on_link_prefix() 175 176 router1_omr_addr = router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0] 177 router2_omr_addr = router2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0] 178 179 # Make sure that addresses of both the deprecated radvd `ON_LINK_PREFIX` 180 # and preferred Border Router on-link prefix can be reached by Thread 181 # devices in network of Border Router 1. 182 for host_on_link_addr in [ 183 host.get_matched_ula_addresses(br2_on_link_prefix)[0], 184 host.get_matched_ula_addresses(ON_LINK_PREFIX)[0] 185 ]: 186 self.assertTrue(router1.ping(host_on_link_addr)) 187 self.assertTrue(host.ping(router1_omr_addr, backbone=True, interface=host_on_link_addr)) 188 189 host_on_link_addr = host.get_matched_ula_addresses(ON_LINK_PREFIX)[0] 190 191 192if __name__ == '__main__': 193 unittest.main() 194