1#!/usr/bin/env python3 2# 3# Copyright (c) 2018, 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 wpan 30from wpan import verify 31 32# ----------------------------------------------------------------------------------------------------------------------- 33# Test description: Network Data (on-mesh prefix) timeout and entry removal 34# 35# Network topology 36# 37# r1 ----- r2 38# | 39# | 40# c2 (sleepy) 41# 42# 43# Test covers the following steps: 44# 45# - Every node adds a unique on-mesh prefix. 46# - Every node also adds a common on-mesh prefix (with different flags). 47# - Verify that all the unique and common prefixes are present on all nodes are associated with correct RLOC16. 48# - Remove `r2` from network (which removes `c2` as well) from Thread partition created by `r1`. 49# - Verify that all on-mesh prefixes added by `r2` or `c2` (unique and common) are removed on `r1`. 50# 51 52test_name = __file__[:-3] if __file__.endswith('.py') else __file__ 53print('-' * 120) 54print('Starting \'{}\''.format(test_name)) 55 56 57def verify_prefix( 58 node_list, 59 prefix, 60 rloc16, 61 prefix_len=64, 62 stable=True, 63 priority='med', 64 on_mesh=False, 65 slaac=False, 66 dhcp=False, 67 configure=False, 68 default_route=False, 69 preferred=True, 70): 71 """ 72 This function verifies that the `prefix` is present on all the nodes in the `node_list`. It also verifies that the 73 `prefix` is associated with the given `rloc16` (as an integer). 74 """ 75 for node in node_list: 76 prefixes = wpan.parse_on_mesh_prefix_result(node.get(wpan.WPAN_THREAD_ON_MESH_PREFIXES)) 77 for p in prefixes: 78 if (p.prefix == prefix and p.origin == "ncp" and int(p.rloc16(), 0) == rloc16): 79 verify(int(p.prefix_len) == prefix_len) 80 verify(p.is_stable() == stable) 81 verify(p.is_on_mesh() == on_mesh) 82 verify(p.is_def_route() == default_route) 83 verify(p.is_slaac() == slaac) 84 verify(p.is_dhcp() == dhcp) 85 verify(p.is_config() == configure) 86 verify(p.is_preferred() == preferred) 87 verify(p.priority == priority) 88 break 89 else: 90 raise wpan.VerifyError("Did not find prefix {} on node {}".format(prefix, node)) 91 92 93def verify_no_prefix(node_list, prefix, rloc16): 94 """ 95 This function verifies that none of the nodes in `node_list` contains the on-mesh `prefix` associated with the 96 given `rloc16`. 97 """ 98 for node in node_list: 99 prefixes = wpan.parse_on_mesh_prefix_result(node.get(wpan.WPAN_THREAD_ON_MESH_PREFIXES)) 100 for p in prefixes: 101 if (p.prefix == prefix and p.origin == "ncp" and int(p.rloc16(), 0) == rloc16): 102 raise wpan.VerifyError("Did find prefix {} with rloc {} on node {}".format(prefix, hex(rloc16), node)) 103 104 105# ----------------------------------------------------------------------------------------------------------------------- 106# Creating `wpan.Nodes` instances 107 108speedup = 25 109wpan.Node.set_time_speedup_factor(speedup) 110 111r1 = wpan.Node() 112r2 = wpan.Node() 113c2 = wpan.Node() 114 115# ----------------------------------------------------------------------------------------------------------------------- 116# Init all nodes 117 118wpan.Node.init_all_nodes() 119 120# ----------------------------------------------------------------------------------------------------------------------- 121# Build network topology 122# 123# Test topology: 124# 125# r1 ----- r2 126# | 127# | 128# c2 129 130r1.form("net-data") 131 132r1.allowlist_node(r2) 133r2.allowlist_node(r1) 134r2.join_node(r1, wpan.JOIN_TYPE_ROUTER) 135 136r2.allowlist_node(c2) 137c2.allowlist_node(r2) 138c2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE) 139c2.set(wpan.WPAN_POLL_INTERVAL, '400') 140 141# ----------------------------------------------------------------------------------------------------------------------- 142# Test implementation 143 144common_prefix = "fd00:cafe::" 145prefix1 = "fd00:1::" 146prefix2 = "fd00:2::" 147prefix3 = "fd00:3::" 148 149wait_time = 15 150 151# Each node adds its own prefix. 152r1.add_prefix(prefix1, on_mesh=True, preferred=True, stable=True) 153r2.add_prefix(prefix2, on_mesh=True, preferred=True, stable=True) 154c2.add_prefix(prefix3, on_mesh=True, preferred=True, stable=True) 155 156# `common_prefix` is added by all three nodes (with different flags) 157r1.add_prefix(common_prefix, on_mesh=True, preferred=True, stable=False) 158r2.add_prefix(common_prefix, on_mesh=True, preferred=True, stable=True) 159c2.add_prefix(common_prefix, on_mesh=True, preferred=False, stable=True) 160 161r1_rloc = int(r1.get(wpan.WPAN_THREAD_RLOC16), 0) 162r2_rloc = int(r2.get(wpan.WPAN_THREAD_RLOC16), 0) 163c2_rloc = int(c2.get(wpan.WPAN_THREAD_RLOC16), 0) 164 165 166def check_prefixes(): 167 # Verify that all three `prefix1`, 'prefix2', and `prefix3` are present on all nodes 168 # and respectively associated with `r1`, r2, and `r3` nodes. 169 verify_prefix( 170 [r1, r2, c2], 171 prefix1, 172 r1_rloc, 173 on_mesh=True, 174 preferred=True, 175 stable=True, 176 ) 177 verify_prefix( 178 [r1, r2, c2], 179 prefix2, 180 r2_rloc, 181 on_mesh=True, 182 preferred=True, 183 stable=True, 184 ) 185 verify_prefix( 186 [r1, r2, c2], 187 prefix3, 188 c2_rloc, 189 on_mesh=True, 190 preferred=True, 191 stable=True, 192 ) 193 194 # Verify the presence of `common_prefix` associated with each node (with 195 # correct flags). 196 verify_prefix( 197 [r1, r2, c2], 198 common_prefix, 199 r1_rloc, 200 on_mesh=True, 201 preferred=True, 202 stable=False, 203 ) 204 verify_prefix( 205 [r1, r2, c2], 206 common_prefix, 207 r2_rloc, 208 on_mesh=True, 209 preferred=True, 210 stable=True, 211 ) 212 verify_prefix( 213 [r1, r2, c2], 214 common_prefix, 215 c2_rloc, 216 on_mesh=True, 217 preferred=False, 218 stable=True, 219 ) 220 221 222wpan.verify_within(check_prefixes, wait_time) 223 224# Remove `r2`. This should trigger all the prefixes added by it or its 225# child to timeout and be removed. 226r2.leave() 227 228 229def check_prefixes_on_r1_after_r2_leave(): 230 # Verify that entries added by r1 are still present 231 verify_prefix([r1], prefix1, r1_rloc, on_mesh=True, preferred=True, stable=True) 232 verify_prefix( 233 [r1], 234 common_prefix, 235 r1_rloc, 236 on_mesh=True, 237 preferred=True, 238 stable=False, 239 ) 240 241 # Verify all entries added by `r2` or `c2` are removed 242 verify_no_prefix([r1], prefix2, r2_rloc) 243 verify_no_prefix([r1], prefix3, c2_rloc) 244 verify_no_prefix([r1], common_prefix, r2_rloc) 245 verify_no_prefix([r1], common_prefix, c2_rloc) 246 247 248wpan.verify_within(check_prefixes_on_r1_after_r2_leave, wait_time) 249 250# ----------------------------------------------------------------------------------------------------------------------- 251# Test finished 252 253wpan.Node.finalize_all_nodes() 254 255print('\'{}\' passed.'.format(test_name)) 256