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