xref: /aosp_15_r20/external/openthread/tests/toranj/cli/test-021-br-route-prf.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1#!/usr/bin/env python3
2#
3#  Copyright (c) 2023, 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
29from cli import verify
30from cli import verify_within
31import cli
32import time
33
34# -----------------------------------------------------------------------------------------------------------------------
35# Test description: BR published route preference.
36#
37#
38
39test_name = __file__[:-3] if __file__.endswith('.py') else __file__
40print('-' * 120)
41print('Starting \'{}\''.format(test_name))
42
43# -----------------------------------------------------------------------------------------------------------------------
44# Creating `cli.Node` instances
45
46speedup = 40
47cli.Node.set_time_speedup_factor(speedup)
48
49leader = cli.Node()
50br = cli.Node()
51
52# -----------------------------------------------------------------------------------------------------------------------
53# Form topology
54
55leader.set_macfilter_lqi_to_node(br, 2)
56br.set_macfilter_lqi_to_node(leader, 2)
57
58leader.form('br-route-prf')
59br.join(leader)
60
61verify(leader.get_state() == 'leader')
62verify(br.get_state() == 'router')
63
64# -----------------------------------------------------------------------------------------------------------------------
65# Test Implementation
66
67verify(br.br_get_state() == 'uninitialized')
68
69br.br_init(1, 1)
70
71verify(br.br_get_state() == 'disabled')
72
73# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
74# Check the default route preference while BR is disabled
75
76verify(br.br_get_routeprf() == 'med')
77
78br.br_set_routeprf('low')
79verify(br.br_get_routeprf() == 'low')
80
81br.br_set_routeprf('med')
82verify(br.br_get_routeprf() == 'med')
83
84br.br_set_routeprf('high')
85verify(br.br_get_routeprf() == 'high')
86
87br.br_clear_routeprf()
88verify(br.br_get_routeprf() == 'med')
89
90# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
91# Enable BR and check the published route and its preference
92
93br.br_enable()
94
95
96def check_published_route_1():
97    verify(br.br_get_state() == 'running')
98    routes = br.get_netdata_routes()
99    verify(len(routes) == 1)
100    verify(routes[0].startswith('fc00::/7 sa med'))
101    verify(br.br_get_routeprf() == 'med')
102
103
104verify_within(check_published_route_1, 5)
105
106# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107# Force `br` to become an end-device. Check that the published
108# route is now using `low` (since link quality to parent is
109# configured as 2)
110
111br.set_router_eligible('disable')
112
113parent_info = br.get_parent_info()
114verify(parent_info['Link Quality In'] == '2')
115
116
117def check_published_route_2():
118    verify(br.get_state() == 'child')
119    routes = br.get_netdata_routes()
120    verify(len(routes) == 1)
121    verify(routes[0].startswith('fc00::/7 sa low'))
122    verify(br.br_get_routeprf() == 'low')
123
124
125verify_within(check_published_route_2, 5)
126
127# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128# Manually set the route prf to 'high` and validated that network
129# data gets updated. Repeat setting route prf to `med`.
130
131br.br_set_routeprf('high')
132
133
134def check_published_route_3():
135    verify(br.get_state() == 'child')
136    routes = br.get_netdata_routes()
137    verify(len(routes) == 1)
138    verify(routes[0].startswith('fc00::/7 sa high'))
139    verify(br.br_get_routeprf() == 'high')
140
141
142verify_within(check_published_route_3, 5)
143
144br.br_set_routeprf('med')
145
146
147def check_published_route_4():
148    verify(br.get_state() == 'child')
149    routes = br.get_netdata_routes()
150    verify(len(routes) == 1)
151    verify(routes[0].startswith('fc00::/7 sa med'))
152    verify(br.br_get_routeprf() == 'med')
153
154
155verify_within(check_published_route_4, 5)
156
157# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158# Clear the manually set route prf and validate that we go back
159# to `low`.
160
161br.br_clear_routeprf()
162verify(br.br_get_routeprf() == 'low')
163
164
165def check_published_route_5():
166    verify(br.get_state() == 'child')
167    routes = br.get_netdata_routes()
168    verify(len(routes) == 1)
169    verify(routes[0].startswith('fc00::/7 sa low'))
170    verify(br.br_get_routeprf() == 'low')
171
172
173verify_within(check_published_route_5, 5)
174
175# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
176# Allow `br` to take `router` role, validate that the route
177# prf of `med` is used.
178
179br.set_router_eligible('enable')
180
181
182def check_published_route_6():
183    verify(br.get_state() == 'router')
184    routes = br.get_netdata_routes()
185    verify(len(routes) == 1)
186    verify(routes[0].startswith('fc00::/7 sa med'))
187    verify(br.br_get_routeprf() == 'med')
188
189
190verify_within(check_published_route_6, 15)
191
192# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
193# Update RSS MAC filter to use link quality 3 between `br` and
194# `leader`. Again force `br` to become `child` and validate
195# that now it still continues to use `med` prf.
196
197leader.set_macfilter_lqi_to_node(br, 3)
198br.set_macfilter_lqi_to_node(leader, 3)
199
200br.set_router_eligible('disable')
201
202
203def check_published_route_7():
204    verify(br.get_state() == 'child')
205    routes = br.get_netdata_routes()
206    verify(len(routes) == 1)
207    verify(routes[0].startswith('fc00::/7 sa med'))
208    verify(br.br_get_routeprf() == 'med')
209
210
211verify_within(check_published_route_7, 5)
212
213# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
214# Update RSS MAC filter to use link quality 1 between `br` and
215# `leader`. Validate that route prf is updated quickly to `low`.
216
217br.set_macfilter_lqi_to_node(leader, 1)
218br.ping(leader.get_mleid_ip_addr())
219parent_info = br.get_parent_info()
220verify(parent_info['Link Quality In'] == '1')
221
222
223def check_published_route_8():
224    verify(br.get_state() == 'child')
225    routes = br.get_netdata_routes()
226    verify(len(routes) == 1)
227    verify(routes[0].startswith('fc00::/7 sa low'))
228    verify(br.br_get_routeprf() == 'low')
229
230
231verify_within(check_published_route_8, 15)
232
233# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234# Update RSS MAC filter to go back to link quality 3.
235# Make sure the published route prf is not immediately
236# updated and only updated after ~5 minutes.
237
238br.set_macfilter_lqi_to_node(leader, 3)
239br.ping(leader.get_mleid_ip_addr())
240parent_info = br.get_parent_info()
241verify(parent_info['Link Quality In'] == '3')
242
243verify(br.br_get_routeprf() == 'low')
244
245
246def check_published_route_9():
247    verify(br.get_state() == 'child')
248    routes = br.get_netdata_routes()
249    verify(len(routes) == 1)
250    verify(routes[0].startswith('fc00::/7 sa med'))
251    verify(br.br_get_routeprf() == 'med')
252
253
254# Wait for 5 minutes
255
256verify_within(check_published_route_9, (5 * 60 / speedup) + 5)
257
258# -----------------------------------------------------------------------------------------------------------------------
259# Test finished
260
261cli.Node.finalize_all_nodes()
262
263print('\'{}\' passed.'.format(test_name))
264