1#!/usr/bin/env python3 2# 3# Copyright (c) 2024, 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: Service ALOC destination route lookup 36# 37# Test topology: 38# 39# r1---- r2 ---- r3 ---- r4 40# | 41# | 42# fed1 43# 44# The same service is added on `r4` and `fed1`. 45 46test_name = __file__[:-3] if __file__.endswith('.py') else __file__ 47print('-' * 120) 48print('Starting \'{}\''.format(test_name)) 49 50# ----------------------------------------------------------------------------------------------------------------------- 51# Creating `cli.Nodes` instances 52 53speedup = 40 54cli.Node.set_time_speedup_factor(speedup) 55 56r1 = cli.Node() 57r2 = cli.Node() 58r3 = cli.Node() 59r4 = cli.Node() 60fed1 = cli.Node() 61 62nodes = [r1, r2, r3, r4, fed1] 63 64# ----------------------------------------------------------------------------------------------------------------------- 65# Form topology 66 67r1.allowlist_node(r2) 68r1.allowlist_node(fed1) 69 70r2.allowlist_node(r1) 71r2.allowlist_node(r3) 72 73r3.allowlist_node(r2) 74r3.allowlist_node(r4) 75 76r4.allowlist_node(r3) 77 78fed1.allowlist_node(r1) 79 80r1.form("srv-aloc") 81r2.join(r1) 82r3.join(r2) 83r4.join(r3) 84fed1.join(r1, cli.JOIN_TYPE_REED) 85 86verify(r1.get_state() == 'leader') 87verify(r2.get_state() == 'router') 88verify(r3.get_state() == 'router') 89verify(r4.get_state() == 'router') 90verify(fed1.get_state() == 'child') 91 92# ----------------------------------------------------------------------------------------------------------------------- 93# Test Implementation 94 95# Wait till first router has either established a link or 96# has a valid "next hop" towards all other routers. 97 98r1_rloc16 = int(r1.get_rloc16(), 16) 99 100 101def check_r1_router_table(): 102 table = r1.get_router_table() 103 verify(len(table) == 4) 104 for entry in table: 105 verify(int(entry['RLOC16'], 0) == r1_rloc16 or int(entry['Link']) == 1 or int(entry['Next Hop']) != 63) 106 107 108verify_within(check_r1_router_table, 120) 109 110# Add the same service on `r4` and `fed1` 111 112r4.cli('service add 44970 11 00') 113r4.register_netdata() 114 115fed1.cli('service add 44970 11 00') 116fed1.register_netdata() 117 118 119def check_netdata_services(expected_num_services): 120 # Check that all nodes see the `expected_num_services` service 121 # entries in network data. 122 for node in nodes: 123 verify(len(node.get_netdata_services()) == expected_num_services) 124 125 126verify_within(check_netdata_services, 100, 2) 127 128# Determine the ALOC address of the added service. 129 130aloc = r4.get_mesh_local_prefix().split('/')[0] + 'ff:fe00:fc10' 131 132# Ping ALOC address from `r3` and verify that `r4` responds. 133# `r4` should be chosen due to its shorter path cost from `r3`. 134 135old_counters = r4.get_ip_counters() 136r3.ping(aloc) 137new_counters = r4.get_ip_counters() 138 139verify(int(new_counters['RxSuccess']) > int(old_counters['RxSuccess'])) 140verify(int(new_counters['TxSuccess']) > int(old_counters['TxSuccess'])) 141 142# Ping ALOC address from `r1` and verify that `fed1` responds. 143# `fed1` should be chosen due to its shorter path cost from `r1`. 144 145old_counters = fed1.get_ip_counters() 146r1.ping(aloc) 147new_counters = fed1.get_ip_counters() 148 149verify(int(new_counters['RxSuccess']) > int(old_counters['RxSuccess'])) 150verify(int(new_counters['TxSuccess']) > int(old_counters['TxSuccess'])) 151 152# Ping ALOC address from `r2` and verify that `r4` responds. 153# Both `r4` and `fed1` have the same path cost, but `r4` is 154# preferred because it is acting as a router. 155 156old_counters = r4.get_ip_counters() 157r2.ping(aloc) 158new_counters = r4.get_ip_counters() 159 160verify(int(new_counters['RxSuccess']) > int(old_counters['RxSuccess'])) 161verify(int(new_counters['TxSuccess']) > int(old_counters['TxSuccess'])) 162 163# ----------------------------------------------------------------------------------------------------------------------- 164# Test finished 165 166cli.Node.finalize_all_nodes() 167 168print('\'{}\' passed.'.format(test_name)) 169