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: Adding addresses with same prefix on multiple nodes. 34# 35 36test_name = __file__[:-3] if __file__.endswith('.py') else __file__ 37print('-' * 120) 38print('Starting \'{}\''.format(test_name)) 39 40# ----------------------------------------------------------------------------------------------------------------------- 41# Creating `wpan.Nodes` instances 42 43speedup = 4 44wpan.Node.set_time_speedup_factor(speedup) 45 46r1 = wpan.Node() 47r2 = wpan.Node() 48sed2 = wpan.Node() 49 50all_nodes = [r1, r2, sed2] 51 52# ----------------------------------------------------------------------------------------------------------------------- 53# Init all nodes 54 55wpan.Node.init_all_nodes() 56 57# ----------------------------------------------------------------------------------------------------------------------- 58# Build network topology 59# 60# Two routers r1 and r2 (sed2 is used for quick promotion of r2 to router 61# status). 62 63r1.allowlist_node(r2) 64r2.allowlist_node(r1) 65 66r2.allowlist_node(sed2) 67sed2.allowlist_node(r2) 68 69r1.form("same-prefix") 70 71r2.join_node(r1, wpan.JOIN_TYPE_ROUTER) 72sed2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE) 73 74sed2.set(wpan.WPAN_POLL_INTERVAL, '500') 75 76r2.status() 77 78# ----------------------------------------------------------------------------------------------------------------------- 79# Test implementation 80 81IP6_PREFIX = "fd00:abba::" 82 83IP6_ADDR_1 = IP6_PREFIX + "1" 84IP6_ADDR_2 = IP6_PREFIX + "2" 85 86# Add IP6_ADDR_2 to r2. 87 88r2.add_ip6_address_on_interface(IP6_ADDR_2, prefix_len=64) 89 90# Verify (within 5 seconds) that corresponding prefix is seen on both nodes. 91 92 93def check_prefix(): 94 for node in [r1, r2]: 95 prefixes = wpan.parse_on_mesh_prefix_result(node.get(wpan.WPAN_THREAD_ON_MESH_PREFIXES)) 96 for p in prefixes: 97 if p.prefix == IP6_PREFIX: 98 if (p.origin == 'ncp' and p.prefix_len == '64' and p.is_stable() and p.is_on_mesh() and 99 p.is_preferred() and not p.is_def_route() and not p.is_slaac() and not p.is_dhcp() and 100 not p.is_config() and p.priority == "med"): 101 break 102 else: # `for` loop finished without finding the prefix. 103 raise wpan.VerifyError('Did not find prefix {} on node {}'.format(IP6_PREFIX, r1)) 104 105 106wpan.verify_within(check_prefix, 5) 107 108# After prefix is seen on r1, add an address with same prefix on r1. 109r1.add_ip6_address_on_interface(IP6_ADDR_1, prefix_len=64) 110 111# Verify that the prefix is still seen on both nodes. 112wpan.verify_within(check_prefix, 5) 113 114# Remove the address from r2 which should remove the corresponding the prefix as well 115# After this since r1 still has the address, the prefix should be present 116# on both nodes. 117r2.remove_ip6_address_on_interface(IP6_ADDR_2, prefix_len=64) 118wpan.verify_within(check_prefix, 5) 119 120# Reset r1 and verify that the prefix is retained correctly (by wpantund). 121r1.reset() 122wpan.verify_within(check_prefix, 8) 123 124# Remove the address on r1. Verify that prefix list is empty. 125r1.remove_ip6_address_on_interface(IP6_ADDR_1, prefix_len=64) 126 127 128def check_empty_prefix_list(): 129 for node in [r1, r2]: 130 prefixes = wpan.parse_on_mesh_prefix_result(node.get(wpan.WPAN_THREAD_ON_MESH_PREFIXES)) 131 verify(len(prefixes) == 0) 132 133 134wpan.verify_within(check_empty_prefix_list, 5) 135 136# Add both addresses back-to-back and check the prefix list to contain the 137# prefix. 138r1.add_ip6_address_on_interface(IP6_ADDR_1, prefix_len=64) 139r2.add_ip6_address_on_interface(IP6_ADDR_2, prefix_len=64) 140wpan.verify_within(check_prefix, 5) 141 142# ----------------------------------------------------------------------------------------------------------------------- 143# Test finished 144 145wpan.Node.finalize_all_nodes() 146 147print('\'{}\' passed.'.format(test_name)) 148