| #!/usr/bin/env python3 |
| # |
| # Copyright (c) 2023, The OpenThread Authors. |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # 3. Neither the name of the copyright holder nor the |
| # names of its contributors may be used to endorse or promote products |
| # derived from this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| # POSSIBILITY OF SUCH DAMAGE. |
| |
| from cli import verify |
| from cli import verify_within |
| import cli |
| import time |
| |
| # ----------------------------------------------------------------------------------------------------------------------- |
| # Test description: BR published route preference. |
| # |
| # |
| |
| test_name = __file__[:-3] if __file__.endswith('.py') else __file__ |
| print('-' * 120) |
| print('Starting \'{}\''.format(test_name)) |
| |
| # ----------------------------------------------------------------------------------------------------------------------- |
| # Creating `cli.Node` instances |
| |
| speedup = 40 |
| cli.Node.set_time_speedup_factor(speedup) |
| |
| leader = cli.Node() |
| br = cli.Node() |
| |
| # ----------------------------------------------------------------------------------------------------------------------- |
| # Form topology |
| |
| leader.set_macfilter_lqi_to_node(br, 2) |
| br.set_macfilter_lqi_to_node(leader, 2) |
| |
| leader.form('br-route-prf') |
| br.join(leader) |
| |
| verify(leader.get_state() == 'leader') |
| verify(br.get_state() == 'router') |
| |
| # ----------------------------------------------------------------------------------------------------------------------- |
| # Test Implementation |
| |
| verify(br.br_get_state() == 'uninitialized') |
| |
| br.br_init(1, 1) |
| |
| verify(br.br_get_state() == 'disabled') |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Check the default route preference while BR is disabled |
| |
| verify(br.br_get_routeprf() == 'med') |
| |
| br.br_set_routeprf('low') |
| verify(br.br_get_routeprf() == 'low') |
| |
| br.br_set_routeprf('med') |
| verify(br.br_get_routeprf() == 'med') |
| |
| br.br_set_routeprf('high') |
| verify(br.br_get_routeprf() == 'high') |
| |
| br.br_clear_routeprf() |
| verify(br.br_get_routeprf() == 'med') |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Enable BR and check the published route and its preference |
| |
| br.br_enable() |
| |
| |
| def check_published_route_1(): |
| verify(br.br_get_state() == 'running') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa med')) |
| verify(br.br_get_routeprf() == 'med') |
| |
| |
| verify_within(check_published_route_1, 5) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Force `br` to become an end-device. Check that the published |
| # route is now using `low` (since link quality to parent is |
| # configured as 2) |
| |
| br.set_router_eligible('disable') |
| |
| parent_info = br.get_parent_info() |
| verify(parent_info['Link Quality In'] == '2') |
| |
| |
| def check_published_route_2(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa low')) |
| verify(br.br_get_routeprf() == 'low') |
| |
| |
| verify_within(check_published_route_2, 5) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Manually set the route prf to 'high` and validated that network |
| # data gets updated. Repeat setting route prf to `med`. |
| |
| br.br_set_routeprf('high') |
| |
| |
| def check_published_route_3(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa high')) |
| verify(br.br_get_routeprf() == 'high') |
| |
| |
| verify_within(check_published_route_3, 5) |
| |
| br.br_set_routeprf('med') |
| |
| |
| def check_published_route_4(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa med')) |
| verify(br.br_get_routeprf() == 'med') |
| |
| |
| verify_within(check_published_route_4, 5) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Clear the manually set route prf and validate that we go back |
| # to `low`. |
| |
| br.br_clear_routeprf() |
| verify(br.br_get_routeprf() == 'low') |
| |
| |
| def check_published_route_5(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa low')) |
| verify(br.br_get_routeprf() == 'low') |
| |
| |
| verify_within(check_published_route_5, 5) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Allow `br` to take `router` role, validate that the route |
| # prf of `med` is used. |
| |
| br.set_router_eligible('enable') |
| |
| |
| def check_published_route_6(): |
| verify(br.get_state() == 'router') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa med')) |
| verify(br.br_get_routeprf() == 'med') |
| |
| |
| verify_within(check_published_route_6, 15) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Update RSS MAC filter to use link quality 3 between `br` and |
| # `leader`. Again force `br` to become `child` and validate |
| # that now it still continues to use `med` prf. |
| |
| leader.set_macfilter_lqi_to_node(br, 3) |
| br.set_macfilter_lqi_to_node(leader, 3) |
| |
| br.set_router_eligible('disable') |
| |
| |
| def check_published_route_7(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa med')) |
| verify(br.br_get_routeprf() == 'med') |
| |
| |
| verify_within(check_published_route_7, 5) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Update RSS MAC filter to use link quality 1 between `br` and |
| # `leader`. Validate that route prf is updated quickly to `low`. |
| |
| br.set_macfilter_lqi_to_node(leader, 1) |
| br.ping(leader.get_mleid_ip_addr()) |
| parent_info = br.get_parent_info() |
| verify(parent_info['Link Quality In'] == '1') |
| |
| |
| def check_published_route_8(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa low')) |
| verify(br.br_get_routeprf() == 'low') |
| |
| |
| verify_within(check_published_route_8, 15) |
| |
| # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| # Update RSS MAC filter to go back to link quality 3. |
| # Make sure the published route prf is not immediately |
| # updated and only updated after ~5 minutes. |
| |
| br.set_macfilter_lqi_to_node(leader, 3) |
| br.ping(leader.get_mleid_ip_addr()) |
| parent_info = br.get_parent_info() |
| verify(parent_info['Link Quality In'] == '3') |
| |
| verify(br.br_get_routeprf() == 'low') |
| |
| |
| def check_published_route_9(): |
| verify(br.get_state() == 'child') |
| routes = br.get_netdata_routes() |
| verify(len(routes) == 1) |
| verify(routes[0].startswith('fc00::/7 sa med')) |
| verify(br.br_get_routeprf() == 'med') |
| |
| |
| # Wait for 5 minutes |
| |
| verify_within(check_published_route_9, (5 * 60 / speedup) + 5) |
| |
| # ----------------------------------------------------------------------------------------------------------------------- |
| # Test finished |
| |
| cli.Node.finalize_all_nodes() |
| |
| print('\'{}\' passed.'.format(test_name)) |