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# 29import logging 30import unittest 31 32import config 33import thread_cert 34 35# Test description: 36# This test verifies bi-directional connectivity across multiple Thread networks. 37# 38# Topology: 39# -------------(eth)---------------- 40# | | 41# BR1 BR2 42# | | 43# ROUTER1 ROUTER2 44# 45# Thread Net1 Thread Net2 46# 47 48BR1 = 1 49ROUTER1 = 2 50BR2 = 3 51ROUTER2 = 4 52 53CHANNEL1 = 18 54CHANNEL2 = 19 55 56 57class MultiThreadNetworks(thread_cert.TestCase): 58 USE_MESSAGE_FACTORY = False 59 60 TOPOLOGY = { 61 BR1: { 62 'name': 'BR_1', 63 'allowlist': [ROUTER1], 64 'is_otbr': True, 65 'version': '1.2', 66 'channel': CHANNEL1, 67 }, 68 ROUTER1: { 69 'name': 'Router_1', 70 'allowlist': [BR1], 71 'version': '1.2', 72 'channel': CHANNEL1, 73 }, 74 BR2: { 75 'name': 'BR_2', 76 'allowlist': [ROUTER2], 77 'is_otbr': True, 78 'version': '1.2', 79 'channel': CHANNEL2, 80 }, 81 ROUTER2: { 82 'name': 'Router_2', 83 'allowlist': [BR2], 84 'version': '1.2', 85 'channel': CHANNEL2, 86 }, 87 } 88 89 def test(self): 90 br1 = self.nodes[BR1] 91 router1 = self.nodes[ROUTER1] 92 br2 = self.nodes[BR2] 93 router2 = self.nodes[ROUTER2] 94 95 br1.start() 96 self.simulator.go(config.LEADER_STARTUP_DELAY) 97 self.assertEqual('leader', br1.get_state()) 98 99 router1.start() 100 self.simulator.go(config.ROUTER_STARTUP_DELAY) 101 self.assertEqual('router', router1.get_state()) 102 103 br2.start() 104 self.simulator.go(config.LEADER_STARTUP_DELAY) 105 self.assertEqual('leader', br2.get_state()) 106 107 router2.start() 108 self.simulator.go(config.ROUTER_STARTUP_DELAY) 109 self.assertEqual('router', router2.get_state()) 110 111 # Wait for network to stabilize 112 self.simulator.go(15) 113 114 self.collect_ipaddrs() 115 116 logging.info("BR1 addrs: %r", br1.get_addrs()) 117 logging.info("ROUTER1 addrs: %r", router1.get_addrs()) 118 logging.info("BR2 addrs: %r", br2.get_addrs()) 119 logging.info("ROUTER2 addrs: %r", router2.get_addrs()) 120 121 self.assertTrue(len(br1.get_netdata_omr_prefixes()) == 1) 122 self.assertTrue(len(router1.get_netdata_omr_prefixes()) == 1) 123 self.assertTrue(len(br2.get_netdata_omr_prefixes()) == 1) 124 self.assertTrue(len(router2.get_netdata_omr_prefixes()) == 1) 125 126 br1_omr_prefix = br1.get_br_omr_prefix() 127 br2_omr_prefix = br2.get_br_omr_prefix() 128 129 self.assertNotEqual(br1_omr_prefix, br2_omr_prefix) 130 131 # Each BR should independently register an external route for the on-link prefix 132 # and OMR prefix in another Thread Network. 133 self.assertEqual(br1.get_netdata_non_nat64_routes(), ['fc00::/7']) 134 self.assertEqual(router1.get_netdata_non_nat64_routes(), ['fc00::/7']) 135 self.assertEqual(br2.get_netdata_non_nat64_routes(), ['fc00::/7']) 136 self.assertEqual(router2.get_netdata_non_nat64_routes(), ['fc00::/7']) 137 138 self.assertTrue(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1) 139 self.assertTrue(len(router2.get_ip6_address(config.ADDRESS_TYPE.OMR)) == 1) 140 141 self.assertTrue(router1.ping(router2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0])) 142 self.verify_border_routing_counters(br1, {'inbound_unicast': 1, 'outbound_unicast': 1}) 143 self.verify_border_routing_counters(br2, {'inbound_unicast': 1, 'outbound_unicast': 1}) 144 self.assertTrue(router2.ping(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0])) 145 self.verify_border_routing_counters(br1, {'inbound_unicast': 1, 'outbound_unicast': 1}) 146 self.verify_border_routing_counters(br2, {'inbound_unicast': 1, 'outbound_unicast': 1}) 147 self.assertGreater(br1.get_border_routing_counters()['ra_rx'], 0) 148 self.assertGreater(br1.get_border_routing_counters()['ra_tx_success'], 0) 149 self.assertGreater(br1.get_border_routing_counters()['rs_tx_success'], 0) 150 151 def verify_border_routing_counters(self, br, expect_delta): 152 delta_counters = br.read_border_routing_counters_delta() 153 self.assertEqual(set(delta_counters.keys()), set(expect_delta.keys())) 154 for key in delta_counters: 155 self.assertEqual(delta_counters[key][0], expect_delta[key]) 156 self.assertGreater(delta_counters[key][1], 0) 157 158 159if __name__ == '__main__': 160 unittest.main() 161