1#!/usr/bin/env python3 2# 3# Copyright (c) 2020, 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 29import time 30import wpan 31from wpan import verify 32 33# ----------------------------------------------------------------------------------------------------------------------- 34# Test description: This test covers behavior of device after TREL network is temporarily disabled 35# and rediscovery of TREL by receiving message over that radio from the neighbor. 36# 37# r1 ---------- r2 38# (15.4+trel) (15.4+trel) 39# 40# On r2 we disable trel temporarily. 41# 42 43test_name = __file__[:-3] if __file__.endswith('.py') else __file__ 44print('-' * 120) 45print('Starting \'{}\''.format(test_name)) 46 47# ----------------------------------------------------------------------------------------------------------------------- 48# Creating `wpan.Nodes` instances 49 50speedup = 4 51wpan.Node.set_time_speedup_factor(speedup) 52 53r1 = wpan.Node(wpan.NODE_15_4_TREL) 54r2 = wpan.Node(wpan.NODE_15_4_TREL) 55c2 = wpan.Node(wpan.NODE_15_4) 56 57# ----------------------------------------------------------------------------------------------------------------------- 58# Init all nodes 59 60wpan.Node.init_all_nodes() 61 62# ----------------------------------------------------------------------------------------------------------------------- 63# Build network topology 64# 65 66r1.allowlist_node(r2) 67r2.allowlist_node(r1) 68 69r2.allowlist_node(c2) 70c2.allowlist_node(r2) 71 72r1.form("discover-by-rx") 73 74r2.join_node(r1, wpan.JOIN_TYPE_ROUTER) 75c2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE) 76 77# ----------------------------------------------------------------------------------------------------------------------- 78# Test implementation 79 80WAIT_TIME = 5 81HIGH_PREFERENCE_THRESHOLD = 220 82MIN_PREFERENCE_THRESHOLD = 0 83 84r1_ext_address = r1.get(wpan.WPAN_EXT_ADDRESS)[1:-1] 85r1_rloc = int(r1.get(wpan.WPAN_THREAD_RLOC16), 16) 86r1_ml_address = r1.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1] 87r2_ext_address = r2.get(wpan.WPAN_EXT_ADDRESS)[1:-1] 88r2_rloc = int(r2.get(wpan.WPAN_THREAD_RLOC16), 16) 89r2_ml_address = r2.get(wpan.WPAN_IP6_MESH_LOCAL_ADDRESS)[1:-1] 90 91# Wait for r2 to become router and r1 establishes a link with it 92 93 94def check_r1_router_table(): 95 router_table = wpan.parse_router_table_result(r1.get(wpan.WPAN_THREAD_ROUTER_TABLE)) 96 verify(len(router_table) == 2) 97 for entry in router_table: 98 verify(entry.rloc16 == r1_rloc or entry.is_link_established()) 99 100 101wpan.verify_within(check_r1_router_table, WAIT_TIME) 102 103# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 104# Check that r1 detected both TREL and 15.4 as supported radio by r2 105 106r1_radios = wpan.parse_list(r1.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) 107verify( 108 len(r1_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r1_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r1_radios)) 109 110r2_radios = wpan.parse_list(r2.get(wpan.WPAN_OT_SUPPORTED_RADIO_LINKS)) 111verify( 112 len(r2_radios) == 2 and (wpan.RADIO_LINK_IEEE_802_15_4 in r2_radios) and (wpan.RADIO_LINK_TREL_UDP6 in r2_radios)) 113 114 115def check_r1_sees_r2_has_two_radio_links(): 116 r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO)) 117 verify(len(r1_neighbor_radios) == 1) 118 verify(len(r1_neighbor_radios[0].radios) == 2) 119 120 121wpan.verify_within(check_r1_sees_r2_has_two_radio_links, WAIT_TIME) 122 123# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 124# Send from r1 to r2 and verify that r1 prefers TREL radio link for sending to r2. 125 126sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi r2 from r1", 5) 127recver = r2.prepare_rx(sender) 128wpan.Node.perform_async_tx_rx() 129verify(sender.was_successful) 130verify(recver.was_successful) 131 132r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO)) 133verify(len(r1_neighbor_radios) == 1) 134r2_radio_info = r1_neighbor_radios[0] 135verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6)) 136verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) >= HIGH_PREFERENCE_THRESHOLD) 137 138# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 139# Now disable TREL link on r2 and send again. We expect that r1 would quickly learn that trel is 140# no longer supported by r2 and prefer 15.4 for tx to r2. 141 142r2.set(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE, 'false') 143verify(r2.get(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE) == 'false') 144 145sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi again r2 from r1", 5) 146wpan.Node.perform_async_tx_rx() 147verify(sender.was_successful) 148 149 150def check_r1_does_not_prefer_trel_for_r2(): 151 r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO)) 152 verify(len(r1_neighbor_radios) == 1) 153 r2_radio_info = r1_neighbor_radios[0] 154 verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6)) 155 verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) <= MIN_PREFERENCE_THRESHOLD) 156 157 158wpan.verify_within(check_r1_does_not_prefer_trel_for_r2, WAIT_TIME) 159 160# Check that we can send between r1 and r2 (now all tx should use 15.4) 161 162sender = r1.prepare_tx(r1_ml_address, r2_ml_address, "Hi on 15.4 r2 from r1", 5) 163recver = r2.prepare_rx(sender) 164wpan.Node.perform_async_tx_rx() 165verify(sender.was_successful) 166verify(recver.was_successful) 167 168r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO)) 169verify(len(r1_neighbor_radios) == 1) 170r2_radio_info = r1_neighbor_radios[0] 171verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6)) 172verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) <= MIN_PREFERENCE_THRESHOLD) 173verify(r2_radio_info.supports(wpan.RADIO_LINK_IEEE_802_15_4)) 174verify(r2_radio_info.preference(wpan.RADIO_LINK_IEEE_802_15_4) >= HIGH_PREFERENCE_THRESHOLD) 175 176# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 177# Enable trel back on r2, start sending traffic from r2 to r1. 178# r2 would use probe mehcnasim to discover that trel is enabled again 179# r1 should notice new rx on trel and update trel preference for r1 180 181r2.set(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE, 'true') 182verify(r2.get(wpan.WPAN_OT_TREL_TEST_MODE_ENABLE) == 'true') 183 184sender = r2.prepare_tx(r2_ml_address, r1_ml_address, "Probing r1 from r2", 80) 185recver = r1.prepare_rx(sender) 186wpan.Node.perform_async_tx_rx() 187verify(sender.was_successful) 188verify(recver.was_successful) 189 190 191def check_r1_again_prefers_trel_for_r2(): 192 r1_neighbor_radios = wpan.parse_multi_radio_result(r1.get(wpan.WPAN_OT_NEIGHBOR_TABLE_MULTI_RADIO_INFO)) 193 verify(len(r1_neighbor_radios) == 1) 194 r2_radio_info = r1_neighbor_radios[0] 195 verify(r2_radio_info.supports(wpan.RADIO_LINK_TREL_UDP6)) 196 verify(r2_radio_info.preference(wpan.RADIO_LINK_TREL_UDP6) >= HIGH_PREFERENCE_THRESHOLD) 197 198 199wpan.verify_within(check_r1_again_prefers_trel_for_r2, WAIT_TIME) 200 201# ----------------------------------------------------------------------------------------------------------------------- 202# Test finished 203 204wpan.Node.finalize_all_nodes() 205 206print('\'{}\' passed.'.format(test_name)) 207