• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#  Copyright (c) 2022, 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#
39# This test verifies behavior of Border Routers (which provide IP connectivity) requesting router role within Thread
40# mesh.
41
42# Topology:
43#
44#  5 FTD nodes, all connected.
45#
46#  Topology is expected to change during execution of test.
47#
48
49LEADER = 1
50ROUTER = 2
51BR1 = 3
52BR2 = 4
53BR3 = 5
54
55
56class BrUpgradeRouterRole(thread_cert.TestCase):
57    USE_MESSAGE_FACTORY = False
58    SUPPORT_NCP = False
59
60    TOPOLOGY = {
61        LEADER: {
62            'name': 'leader',
63            'mode': 'rdn',
64        },
65        ROUTER: {
66            'name': 'reader',
67            'mode': 'rdn',
68        },
69        BR1: {
70            'name': 'br-1',
71            'mode': 'rdn',
72        },
73        BR2: {
74            'name': 'br-2',
75            'mode': 'rdn',
76        },
77        BR3: {
78            'name': 'br-3',
79            'mode': 'rdn',
80        },
81    }
82
83    def test(self):
84        leader = self.nodes[LEADER]
85        router = self.nodes[ROUTER]
86        br1 = self.nodes[BR1]
87        br2 = self.nodes[BR2]
88        br3 = self.nodes[BR3]
89
90        #-------------------------------------------------------------------------------------
91        # Set the router upgrade threshold to 2 on all nodes.
92
93        for node in [leader, router, br1, br2, br3]:
94            node.set_router_upgrade_threshold(2)
95
96        #-------------------------------------------------------------------------------------
97        # Start the leader and router.
98
99        leader.start()
100        self.simulator.go(config.LEADER_STARTUP_DELAY)
101        self.assertEqual(leader.get_state(), 'leader')
102
103        router.start()
104        self.simulator.go(125)
105        self.assertEqual(router.get_state(), 'router')
106
107        #-------------------------------------------------------------------------------------
108        # Start all three BRs, we expect all to stay as child since there are already two
109        # routers in the Thread mesh.
110
111        br1.start()
112        br2.start()
113        br3.start()
114        self.simulator.go(125)
115        self.assertEqual(br1.get_state(), 'child')
116        self.assertEqual(br2.get_state(), 'child')
117        self.assertEqual(br3.get_state(), 'child')
118
119        #-------------------------------------------------------------------------------------
120        # Add an external route on `br1`, it should now try to become a router requesting
121        # with status BorderRouterRequest. Verify that leader allows it to become router.
122
123        br1.add_route('2001:dead:beef:cafe::/64', stable=True)
124        br1.register_netdata()
125        self.simulator.go(15)
126        self.assertEqual(br1.get_state(), 'router')
127
128        #-------------------------------------------------------------------------------------
129        # Add a prefix with default route on `br2`, it should also become a router.
130
131        br2.add_prefix('2001:dead:beef:2222::/64', 'paros')
132        br2.register_netdata()
133        self.simulator.go(15)
134        self.assertEqual(br2.get_state(), 'router')
135
136        #-------------------------------------------------------------------------------------
137        # Add an external route on `br3`, it should not become a router since we already have
138        # two that requested router role upgrade as border router reason.
139
140        br3.add_route('2001:dead:beef:cafe::/64', stable=True)
141        br3.register_netdata()
142        self.simulator.go(120)
143        self.assertEqual(br3.get_state(), 'child')
144
145        #-------------------------------------------------------------------------------------
146        # Remove the external route on `br1`. This should now trigger `br3` to request a
147        # router role upgrade since number of BRs acting as router in network data is now
148        # below the threshold of two.
149
150        br1.remove_route('2001:dead:beef:cafe::/64')
151        br1.register_netdata()
152        self.simulator.go(15)
153        self.assertEqual(br1.get_state(), 'router')
154        self.assertEqual(br3.get_state(), 'router')
155
156
157if __name__ == '__main__':
158    unittest.main()
159