xref: /aosp_15_r20/external/openthread/tests/toranj/ncp/test-013-off-mesh-route-traffic.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
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