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 time 30import wpan 31from wpan import verify 32 33# ----------------------------------------------------------------------------------------------------------------------- 34# Test description: Adding off-mesh routes (on routers and FEDs) and traffic flow to off-mesh addresses. 35# 36# Test topology: 37# 38# r1 ---- r2 39# | | 40# | | 41# fed1 sed2 42# 43# The off-mesh-routes are added as follows: 44# - `r1` adds `OFF_MESH_ROUTE_1`, 45# - `r2` adds `OFF_MESH_ROUTE_2`, 46# - `fed1` adds `OFF_MESH_ROUTE_3`. 47# 48# Traffic flow: 49# - From `sed2` to an address matching `OFF_MESH_ROUTE_1` (verify it is received on `r1`), 50# - From `r1` to an address matching `OFF_MESH_ROUTE_2` (verify it is received on `r2`), 51# - From `r2` to an address matching `OFF_MESH_ROUTE_3` (verify it is received on `fed1`) 52# 53 54test_name = __file__[:-3] if __file__.endswith('.py') else __file__ 55print('-' * 120) 56print('Starting \'{}\''.format(test_name)) 57 58# ----------------------------------------------------------------------------------------------------------------------- 59# Creating `wpan.Nodes` instances 60 61speedup = 4 62wpan.Node.set_time_speedup_factor(speedup) 63 64r1 = wpan.Node() 65fed1 = wpan.Node() 66r2 = wpan.Node() 67sed2 = wpan.Node() 68 69all_nodes = [r1, fed1, r2, sed2] 70 71# ----------------------------------------------------------------------------------------------------------------------- 72# Init all nodes 73 74wpan.Node.init_all_nodes() 75for node in all_nodes: 76 # Disable `AutoUpdateInterfaceAddrsOnNCP` feature on wpantund 77 # for all nodes. This ensures that added IPv6 address (on linux 78 # interface) are not pushed to NCP (and therefore are not 79 # on-mesh). 80 node.set("Daemon:IPv6:AutoUpdateInterfaceAddrsOnNCP", '0') 81 82# ----------------------------------------------------------------------------------------------------------------------- 83# Build network topology 84# 85# r1 ---- r2 86# | | 87# | | 88# fed1 sed2 89 90r1.allowlist_node(r2) 91r2.allowlist_node(r1) 92 93r1.allowlist_node(fed1) 94fed1.allowlist_node(r1) 95 96r2.allowlist_node(sed2) 97sed2.allowlist_node(r2) 98 99r1.form("off-mesh") 100r2.join_node(r1, wpan.JOIN_TYPE_ROUTER) 101 102fed1.join_node(r1, wpan.JOIN_TYPE_END_DEVICE) 103sed2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE) 104 105sed2.set(wpan.WPAN_POLL_INTERVAL, '1500') 106 107# ----------------------------------------------------------------------------------------------------------------------- 108# Test implementation 109 110WAIT_TIME = 10 111NUM_ROUTES = 3 112NUM_ROUTES_LOCAL = 1 113ON_MESH_PREFIX = "fd00:1234::" 114OFF_MESH_ROUTE_1 = "fd00:abba::" 115OFF_MESH_ROUTE_2 = "fd00:cafe::" 116OFF_MESH_ROUTE_3 = "fd00:baba::" 117OFF_MESH_ADDR_1 = OFF_MESH_ROUTE_1 + "1" 118OFF_MESH_ADDR_2 = OFF_MESH_ROUTE_2 + "2" 119OFF_MESH_ADDR_3 = OFF_MESH_ROUTE_3 + "3" 120 121# Add on-mesh prefix 122r1.config_gateway(ON_MESH_PREFIX) 123 124# The off-mesh-routes are added as follows: 125# - `r1` adds OFF_MESH_ROUTE_1, 126# - `r2` adds OFF_MESH_ROUTE_2, 127# - `fed1` adds OFF_MESH_ROUTE_3. 128 129r1.add_route(OFF_MESH_ROUTE_1) 130r1.add_ip6_address_on_interface(OFF_MESH_ADDR_1) 131 132r2.add_route(OFF_MESH_ROUTE_2) 133r2.add_ip6_address_on_interface(OFF_MESH_ADDR_2) 134 135fed1.add_route(OFF_MESH_ROUTE_3) 136fed1.add_ip6_address_on_interface(OFF_MESH_ADDR_3) 137 138# Wait till network data is updated on r1, r2, and sed2 and they all see all 139# the added off-mesh routes. 140 141 142def check_off_mesh_routes(): 143 # If a node itself adds a route, the route entry will be seen twice in 144 # its WPAN_THREAD_OFF_MESH_ROUTES list (one time as part of network-wide 145 # network data and again as part of the local network data). Note that 146 # `r1 and `r2` each add a route, while `sed2` does not. 147 verify(len(wpan.parse_list(r1.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == NUM_ROUTES + NUM_ROUTES_LOCAL) 148 verify(len(wpan.parse_list(r2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == NUM_ROUTES + NUM_ROUTES_LOCAL) 149 verify(len(wpan.parse_list(sed2.get(wpan.WPAN_THREAD_OFF_MESH_ROUTES))) == NUM_ROUTES) 150 151 152wpan.verify_within(check_off_mesh_routes, WAIT_TIME) 153 154# Traffic from `sed2` to `OFF_MESH_ADDR_1` (verify that it is received on 155# `r1`). 156 157src = sed2.find_ip6_address_with_prefix(ON_MESH_PREFIX) 158sender = sed2.prepare_tx(src, OFF_MESH_ADDR_1, "Hello Route1") 159recver = r1.prepare_rx(sender) 160wpan.Node.perform_async_tx_rx() 161verify(sender.was_successful) 162verify(recver.was_successful) 163 164# Traffic from `r1` to `OFF_MESH_ADDR_2` (verify that it is received on `r2`), 165 166src = r1.find_ip6_address_with_prefix(ON_MESH_PREFIX) 167sender = r1.prepare_tx(src, OFF_MESH_ADDR_2, "Hello Route2") 168recver = r2.prepare_rx(sender) 169wpan.Node.perform_async_tx_rx() 170verify(sender.was_successful) 171verify(recver.was_successful) 172 173# Traffic from `r2` to `OFF_MESH_ADDR_3` (verify that it is received on `fed1`) 174 175src = r2.find_ip6_address_with_prefix(ON_MESH_PREFIX) 176sender = r2.prepare_tx(src, OFF_MESH_ADDR_3, "Hello Route3") 177recver = fed1.prepare_rx(sender) 178wpan.Node.perform_async_tx_rx() 179verify(sender.was_successful) 180verify(recver.was_successful) 181 182# ----------------------------------------------------------------------------------------------------------------------- 183# Test finished 184 185wpan.Node.finalize_all_nodes() 186 187print('\'{}\' passed.'.format(test_name)) 188