xref: /aosp_15_r20/external/openthread/tests/toranj/ncp/test-021-address-cache-table.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*cfb92d14SAndroid Build Coastguard Worker#
3*cfb92d14SAndroid Build Coastguard Worker#  Copyright (c) 2018, The OpenThread Authors.
4*cfb92d14SAndroid Build Coastguard Worker#  All rights reserved.
5*cfb92d14SAndroid Build Coastguard Worker#
6*cfb92d14SAndroid Build Coastguard Worker#  Redistribution and use in source and binary forms, with or without
7*cfb92d14SAndroid Build Coastguard Worker#  modification, are permitted provided that the following conditions are met:
8*cfb92d14SAndroid Build Coastguard Worker#  1. Redistributions of source code must retain the above copyright
9*cfb92d14SAndroid Build Coastguard Worker#     notice, this list of conditions and the following disclaimer.
10*cfb92d14SAndroid Build Coastguard Worker#  2. Redistributions in binary form must reproduce the above copyright
11*cfb92d14SAndroid Build Coastguard Worker#     notice, this list of conditions and the following disclaimer in the
12*cfb92d14SAndroid Build Coastguard Worker#     documentation and/or other materials provided with the distribution.
13*cfb92d14SAndroid Build Coastguard Worker#  3. Neither the name of the copyright holder nor the
14*cfb92d14SAndroid Build Coastguard Worker#     names of its contributors may be used to endorse or promote products
15*cfb92d14SAndroid Build Coastguard Worker#     derived from this software without specific prior written permission.
16*cfb92d14SAndroid Build Coastguard Worker#
17*cfb92d14SAndroid Build Coastguard Worker#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18*cfb92d14SAndroid Build Coastguard Worker#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*cfb92d14SAndroid Build Coastguard Worker#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*cfb92d14SAndroid Build Coastguard Worker#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21*cfb92d14SAndroid Build Coastguard Worker#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*cfb92d14SAndroid Build Coastguard Worker#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*cfb92d14SAndroid Build Coastguard Worker#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*cfb92d14SAndroid Build Coastguard Worker#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*cfb92d14SAndroid Build Coastguard Worker#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*cfb92d14SAndroid Build Coastguard Worker#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*cfb92d14SAndroid Build Coastguard Worker#  POSSIBILITY OF SUCH DAMAGE.
28*cfb92d14SAndroid Build Coastguard Worker
29*cfb92d14SAndroid Build Coastguard Workerimport wpan
30*cfb92d14SAndroid Build Coastguard Workerfrom wpan import verify
31*cfb92d14SAndroid Build Coastguard Worker
32*cfb92d14SAndroid Build Coastguard Worker# -----------------------------------------------------------------------------------------------------------------------
33*cfb92d14SAndroid Build Coastguard Worker# Test description: Address Cache Table
34*cfb92d14SAndroid Build Coastguard Worker#
35*cfb92d14SAndroid Build Coastguard Worker# This test verifies the behavior of `AddressResolver` module and entries in
36*cfb92d14SAndroid Build Coastguard Worker# address cache table. It also tests the behavior of nodes when there are
37*cfb92d14SAndroid Build Coastguard Worker# topology changes in the network (e.g., a child switches parent). In
38*cfb92d14SAndroid Build Coastguard Worker# particular, the test covers the address cache update through snooping, i.e.,
39*cfb92d14SAndroid Build Coastguard Worker# the logic which inspects forwarded frames to update address cache table if
40*cfb92d14SAndroid Build Coastguard Worker# source RLOC16 on a received frame differs from an existing entry in the
41*cfb92d14SAndroid Build Coastguard Worker# address cache table.
42*cfb92d14SAndroid Build Coastguard Worker
43*cfb92d14SAndroid Build Coastguard Workertest_name = __file__[:-3] if __file__.endswith('.py') else __file__
44*cfb92d14SAndroid Build Coastguard Workerprint('-' * 120)
45*cfb92d14SAndroid Build Coastguard Workerprint('Starting \'{}\''.format(test_name))
46*cfb92d14SAndroid Build Coastguard Worker
47*cfb92d14SAndroid Build Coastguard Worker# -----------------------------------------------------------------------------------------------------------------------
48*cfb92d14SAndroid Build Coastguard Worker# Creating `wpan.Nodes` instances
49*cfb92d14SAndroid Build Coastguard Worker
50*cfb92d14SAndroid Build Coastguard Workerspeedup = 4
51*cfb92d14SAndroid Build Coastguard Workerwpan.Node.set_time_speedup_factor(speedup)
52*cfb92d14SAndroid Build Coastguard Worker
53*cfb92d14SAndroid Build Coastguard Workerr1 = wpan.Node()
54*cfb92d14SAndroid Build Coastguard Workerr2 = wpan.Node()
55*cfb92d14SAndroid Build Coastguard Workerr3 = wpan.Node()
56*cfb92d14SAndroid Build Coastguard Workerc1 = wpan.Node()
57*cfb92d14SAndroid Build Coastguard Workerc2 = wpan.Node()
58*cfb92d14SAndroid Build Coastguard Workerc3 = wpan.Node()
59*cfb92d14SAndroid Build Coastguard Worker
60*cfb92d14SAndroid Build Coastguard Worker# -----------------------------------------------------------------------------------------------------------------------
61*cfb92d14SAndroid Build Coastguard Worker# Init all nodes
62*cfb92d14SAndroid Build Coastguard Worker
63*cfb92d14SAndroid Build Coastguard Workerwpan.Node.init_all_nodes()
64*cfb92d14SAndroid Build Coastguard Worker
65*cfb92d14SAndroid Build Coastguard Worker# -----------------------------------------------------------------------------------------------------------------------
66*cfb92d14SAndroid Build Coastguard Worker# Build network topology
67*cfb92d14SAndroid Build Coastguard Worker#
68*cfb92d14SAndroid Build Coastguard Worker#     r1 ---- r2 ---- r3
69*cfb92d14SAndroid Build Coastguard Worker#     |       |       |
70*cfb92d14SAndroid Build Coastguard Worker#     |       |       |
71*cfb92d14SAndroid Build Coastguard Worker#     c1      c2(s)   c3
72*cfb92d14SAndroid Build Coastguard Worker#
73*cfb92d14SAndroid Build Coastguard Worker# c1 and c3 are FED children, c2 is an SED which is first attached to r2 and
74*cfb92d14SAndroid Build Coastguard Worker# then forced to switch to r3.
75*cfb92d14SAndroid Build Coastguard Worker
76*cfb92d14SAndroid Build Coastguard WorkerPREFIX = "fd00:1234::"
77*cfb92d14SAndroid Build Coastguard WorkerPOLL_INTERVAL = 400
78*cfb92d14SAndroid Build Coastguard Worker
79*cfb92d14SAndroid Build Coastguard Workerr1.form("addr-cache-tbl")
80*cfb92d14SAndroid Build Coastguard Worker
81*cfb92d14SAndroid Build Coastguard Workerr1.add_prefix(PREFIX, stable=True, on_mesh=True, slaac=True, preferred=True)
82*cfb92d14SAndroid Build Coastguard Worker
83*cfb92d14SAndroid Build Coastguard Workerr1.allowlist_node(c1)
84*cfb92d14SAndroid Build Coastguard Workerc1.allowlist_node(r1)
85*cfb92d14SAndroid Build Coastguard Workerc1.join_node(r1, wpan.JOIN_TYPE_END_DEVICE)
86*cfb92d14SAndroid Build Coastguard Worker
87*cfb92d14SAndroid Build Coastguard Workerr1.allowlist_node(r2)
88*cfb92d14SAndroid Build Coastguard Workerr2.allowlist_node(r1)
89*cfb92d14SAndroid Build Coastguard Workerr2.join_node(r1, wpan.JOIN_TYPE_ROUTER)
90*cfb92d14SAndroid Build Coastguard Worker
91*cfb92d14SAndroid Build Coastguard Workerc2.allowlist_node(r2)
92*cfb92d14SAndroid Build Coastguard Workerr2.allowlist_node(c2)
93*cfb92d14SAndroid Build Coastguard Workerc2.join_node(r2, wpan.JOIN_TYPE_SLEEPY_END_DEVICE)
94*cfb92d14SAndroid Build Coastguard Workerc2.set(wpan.WPAN_POLL_INTERVAL, str(POLL_INTERVAL))
95*cfb92d14SAndroid Build Coastguard Worker
96*cfb92d14SAndroid Build Coastguard Workerr2.allowlist_node(r3)
97*cfb92d14SAndroid Build Coastguard Workerr3.allowlist_node(r2)
98*cfb92d14SAndroid Build Coastguard Workerr3.join_node(r2, wpan.JOIN_TYPE_ROUTER)
99*cfb92d14SAndroid Build Coastguard Worker
100*cfb92d14SAndroid Build Coastguard Workerc3.allowlist_node(r3)
101*cfb92d14SAndroid Build Coastguard Workerr3.allowlist_node(c3)
102*cfb92d14SAndroid Build Coastguard Workerc3.join_node(r3, wpan.JOIN_TYPE_END_DEVICE)
103*cfb92d14SAndroid Build Coastguard Worker
104*cfb92d14SAndroid Build Coastguard Worker# -----------------------------------------------------------------------------------------------------------------------
105*cfb92d14SAndroid Build Coastguard Worker# Test implementation
106*cfb92d14SAndroid Build Coastguard Worker#
107*cfb92d14SAndroid Build Coastguard Worker
108*cfb92d14SAndroid Build Coastguard WorkerROUTER_TABLE_WAIT_TIME = 30 / speedup + 5
109*cfb92d14SAndroid Build Coastguard Worker
110*cfb92d14SAndroid Build Coastguard WorkerINVALID_ROUTER_ID = 63
111*cfb92d14SAndroid Build Coastguard Worker
112*cfb92d14SAndroid Build Coastguard Workerverify(r1.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_LEADER)
113*cfb92d14SAndroid Build Coastguard Workerverify(r2.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_ROUTER)
114*cfb92d14SAndroid Build Coastguard Workerverify(r3.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_ROUTER)
115*cfb92d14SAndroid Build Coastguard Workerverify(c1.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_END_DEVICE)
116*cfb92d14SAndroid Build Coastguard Workerverify(c2.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_SLEEPY_END_DEVICE)
117*cfb92d14SAndroid Build Coastguard Workerverify(c3.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_END_DEVICE)
118*cfb92d14SAndroid Build Coastguard Worker
119*cfb92d14SAndroid Build Coastguard Workerr2_rloc = int(r2.get(wpan.WPAN_THREAD_RLOC16), 16)
120*cfb92d14SAndroid Build Coastguard Workerr3_rloc = int(r3.get(wpan.WPAN_THREAD_RLOC16), 16)
121*cfb92d14SAndroid Build Coastguard Workerc3_rloc = int(c3.get(wpan.WPAN_THREAD_RLOC16), 16)
122*cfb92d14SAndroid Build Coastguard Worker
123*cfb92d14SAndroid Build Coastguard Worker# Wait till we have a valid "next hop" route on r1 towards r3
124*cfb92d14SAndroid Build Coastguard Worker
125*cfb92d14SAndroid Build Coastguard Worker
126*cfb92d14SAndroid Build Coastguard Workerdef check_r1_router_table():
127*cfb92d14SAndroid Build Coastguard Worker    router_table = wpan.parse_router_table_result(r1.get(wpan.WPAN_THREAD_ROUTER_TABLE))
128*cfb92d14SAndroid Build Coastguard Worker    verify(len(router_table) == 3)
129*cfb92d14SAndroid Build Coastguard Worker    for entry in router_table:
130*cfb92d14SAndroid Build Coastguard Worker        if entry.rloc16 == r3_rloc:
131*cfb92d14SAndroid Build Coastguard Worker            verify(entry.next_hop != INVALID_ROUTER_ID)
132*cfb92d14SAndroid Build Coastguard Worker
133*cfb92d14SAndroid Build Coastguard Worker
134*cfb92d14SAndroid Build Coastguard Workerwpan.verify_within(check_r1_router_table, ROUTER_TABLE_WAIT_TIME)
135*cfb92d14SAndroid Build Coastguard Worker
136*cfb92d14SAndroid Build Coastguard Workerr1_address = r1.find_ip6_address_with_prefix(PREFIX)
137*cfb92d14SAndroid Build Coastguard Workerc1_address = c1.find_ip6_address_with_prefix(PREFIX)
138*cfb92d14SAndroid Build Coastguard Workerc2_address = c2.find_ip6_address_with_prefix(PREFIX)
139*cfb92d14SAndroid Build Coastguard Workerc3_address = c3.find_ip6_address_with_prefix(PREFIX)
140*cfb92d14SAndroid Build Coastguard Worker
141*cfb92d14SAndroid Build Coastguard Worker# Send a single UDP message from r1 to c2
142*cfb92d14SAndroid Build Coastguard Worker
143*cfb92d14SAndroid Build Coastguard Workersender = r1.prepare_tx(r1_address, c2_address, "Hi from r1 to c2")
144*cfb92d14SAndroid Build Coastguard Workerrecver = c2.prepare_rx(sender)
145*cfb92d14SAndroid Build Coastguard Workerwpan.Node.perform_async_tx_rx()
146*cfb92d14SAndroid Build Coastguard Workerverify(sender.was_successful and recver.was_successful)
147*cfb92d14SAndroid Build Coastguard Worker
148*cfb92d14SAndroid Build Coastguard Worker# Send a single UDP message from r1 to c3
149*cfb92d14SAndroid Build Coastguard Worker
150*cfb92d14SAndroid Build Coastguard Workersender = r1.prepare_tx(r1_address, c3_address, "Hi from r1 to c3")
151*cfb92d14SAndroid Build Coastguard Workerrecver = c3.prepare_rx(sender)
152*cfb92d14SAndroid Build Coastguard Workerwpan.Node.perform_async_tx_rx()
153*cfb92d14SAndroid Build Coastguard Workerverify(sender.was_successful and recver.was_successful)
154*cfb92d14SAndroid Build Coastguard Worker
155*cfb92d14SAndroid Build Coastguard Worker# The address cache table on r1 should contain two entries for
156*cfb92d14SAndroid Build Coastguard Worker# c2 and c3 addresses.
157*cfb92d14SAndroid Build Coastguard Worker
158*cfb92d14SAndroid Build Coastguard Workeraddr_cache_table = wpan.parse_address_cache_table_result(r1.get(wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE))
159*cfb92d14SAndroid Build Coastguard Workerverify(len(addr_cache_table) == 2)
160*cfb92d14SAndroid Build Coastguard Worker
161*cfb92d14SAndroid Build Coastguard Workerfor entry in addr_cache_table:
162*cfb92d14SAndroid Build Coastguard Worker    if entry.address == c2_address:
163*cfb92d14SAndroid Build Coastguard Worker        # Entry for c2 should point towards its parent r2.
164*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == r2_rloc)
165*cfb92d14SAndroid Build Coastguard Worker    elif entry.address == c3_address:
166*cfb92d14SAndroid Build Coastguard Worker        # Entry for c3 should point towards c3 itself.
167*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == c3_rloc)
168*cfb92d14SAndroid Build Coastguard Worker    else:
169*cfb92d14SAndroid Build Coastguard Worker        raise (wpan.VerifyError("Unknown entry in the address cache table"))
170*cfb92d14SAndroid Build Coastguard Worker
171*cfb92d14SAndroid Build Coastguard Worker# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
172*cfb92d14SAndroid Build Coastguard Worker
173*cfb92d14SAndroid Build Coastguard Worker# Force c2 to switch its parent from r2 to r3
174*cfb92d14SAndroid Build Coastguard Worker
175*cfb92d14SAndroid Build Coastguard WorkerCHILD_SUPERVISION_CHECK_TIMEOUT = 2
176*cfb92d14SAndroid Build Coastguard WorkerPARENT_SUPERVISION_INTERVAL = 1
177*cfb92d14SAndroid Build Coastguard Worker
178*cfb92d14SAndroid Build Coastguard WorkerREATTACH_WAIT_TIME = CHILD_SUPERVISION_CHECK_TIMEOUT / speedup + 6
179*cfb92d14SAndroid Build Coastguard Worker
180*cfb92d14SAndroid Build Coastguard Workerc2.set(
181*cfb92d14SAndroid Build Coastguard Worker    wpan.WPAN_CHILD_SUPERVISION_CHECK_TIMEOUT,
182*cfb92d14SAndroid Build Coastguard Worker    str(CHILD_SUPERVISION_CHECK_TIMEOUT),
183*cfb92d14SAndroid Build Coastguard Worker)
184*cfb92d14SAndroid Build Coastguard Workerr3.set(wpan.WPAN_CHILD_SUPERVISION_INTERVAL, str(PARENT_SUPERVISION_INTERVAL))
185*cfb92d14SAndroid Build Coastguard Worker
186*cfb92d14SAndroid Build Coastguard Workerr2.un_allowlist_node(c2)
187*cfb92d14SAndroid Build Coastguard Workerr3.allowlist_node(c2)
188*cfb92d14SAndroid Build Coastguard Workerc2.allowlist_node(r3)
189*cfb92d14SAndroid Build Coastguard Worker
190*cfb92d14SAndroid Build Coastguard Worker# Wait for c2 to detach from r2 and attach to r3.
191*cfb92d14SAndroid Build Coastguard Worker#
192*cfb92d14SAndroid Build Coastguard Worker# Upon re-attach, previous parent r2 is notified and should remove c2 from
193*cfb92d14SAndroid Build Coastguard Worker# its child table.
194*cfb92d14SAndroid Build Coastguard Worker
195*cfb92d14SAndroid Build Coastguard Worker
196*cfb92d14SAndroid Build Coastguard Workerdef check_c2_is_removed_from_r2_child_table():
197*cfb92d14SAndroid Build Coastguard Worker    child_table = wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE))
198*cfb92d14SAndroid Build Coastguard Worker    verify(len(child_table) == 0)
199*cfb92d14SAndroid Build Coastguard Worker
200*cfb92d14SAndroid Build Coastguard Worker
201*cfb92d14SAndroid Build Coastguard Workerwpan.verify_within(check_c2_is_removed_from_r2_child_table, REATTACH_WAIT_TIME)
202*cfb92d14SAndroid Build Coastguard Worker
203*cfb92d14SAndroid Build Coastguard Worker# Verify that both c2, c3 are children of r3
204*cfb92d14SAndroid Build Coastguard Worker
205*cfb92d14SAndroid Build Coastguard Workerchild_table = wpan.parse_list(r3.get(wpan.WPAN_THREAD_CHILD_TABLE))
206*cfb92d14SAndroid Build Coastguard Workerverify(len(child_table) == 2)
207*cfb92d14SAndroid Build Coastguard Worker
208*cfb92d14SAndroid Build Coastguard Worker# New network topology
209*cfb92d14SAndroid Build Coastguard Worker#
210*cfb92d14SAndroid Build Coastguard Worker#     r1 ---- r2 ---- r3
211*cfb92d14SAndroid Build Coastguard Worker#     |               /\
212*cfb92d14SAndroid Build Coastguard Worker#     |              /  \
213*cfb92d14SAndroid Build Coastguard Worker#     c1           c2(s) c3
214*cfb92d14SAndroid Build Coastguard Worker
215*cfb92d14SAndroid Build Coastguard Worker# From r1 send again to c2 (which is now a child of r3).
216*cfb92d14SAndroid Build Coastguard Worker#
217*cfb92d14SAndroid Build Coastguard Worker# Note that r1 still has r2 as the destination for c2's address in its address
218*cfb92d14SAndroid Build Coastguard Worker# cache table.  But since r2 is aware that c2 is no longer its child, when it
219*cfb92d14SAndroid Build Coastguard Worker# receives the IPv6 message with c2's address, r2 itself would do an address
220*cfb92d14SAndroid Build Coastguard Worker# query for the address and forward the IPv6 message.
221*cfb92d14SAndroid Build Coastguard Worker
222*cfb92d14SAndroid Build Coastguard Workersender = r1.prepare_tx(r1_address, c2_address, "Hi again c2")
223*cfb92d14SAndroid Build Coastguard Workerrecver = c2.prepare_rx(sender)
224*cfb92d14SAndroid Build Coastguard Workerwpan.Node.perform_async_tx_rx()
225*cfb92d14SAndroid Build Coastguard Workerverify(sender.was_successful and recver.was_successful)
226*cfb92d14SAndroid Build Coastguard Worker
227*cfb92d14SAndroid Build Coastguard Worker# The address cache table on r1 should have c2's address removed.
228*cfb92d14SAndroid Build Coastguard Worker
229*cfb92d14SAndroid Build Coastguard Workeraddr_cache_table = wpan.parse_address_cache_table_result(r1.get(wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE))
230*cfb92d14SAndroid Build Coastguard Workerverify(len(addr_cache_table) == 1)
231*cfb92d14SAndroid Build Coastguard Worker
232*cfb92d14SAndroid Build Coastguard Workerfor entry in addr_cache_table:
233*cfb92d14SAndroid Build Coastguard Worker    if entry.address == c3_address:
234*cfb92d14SAndroid Build Coastguard Worker        # Entry for c3 should still point towards c3
235*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == c3_rloc)
236*cfb92d14SAndroid Build Coastguard Worker    else:
237*cfb92d14SAndroid Build Coastguard Worker        raise (wpan.VerifyError("Unknown entry in the address cache table"))
238*cfb92d14SAndroid Build Coastguard Worker
239*cfb92d14SAndroid Build Coastguard Worker# Send a UDP message from r1 to c2.
240*cfb92d14SAndroid Build Coastguard Worker
241*cfb92d14SAndroid Build Coastguard Workersender = r1.prepare_tx(r1_address, c2_address, "Hi again c2")
242*cfb92d14SAndroid Build Coastguard Workerrecver = c2.prepare_rx(sender)
243*cfb92d14SAndroid Build Coastguard Workerwpan.Node.perform_async_tx_rx()
244*cfb92d14SAndroid Build Coastguard Workerverify(sender.was_successful and recver.was_successful)
245*cfb92d14SAndroid Build Coastguard Worker
246*cfb92d14SAndroid Build Coastguard Worker# The address cache table on r1 should have both c1 and c2.
247*cfb92d14SAndroid Build Coastguard Worker
248*cfb92d14SAndroid Build Coastguard Workeraddr_cache_table = wpan.parse_address_cache_table_result(r1.get(wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE))
249*cfb92d14SAndroid Build Coastguard Workerverify(len(addr_cache_table) == 2)
250*cfb92d14SAndroid Build Coastguard Worker
251*cfb92d14SAndroid Build Coastguard Workerfor entry in addr_cache_table:
252*cfb92d14SAndroid Build Coastguard Worker    if entry.address == c2_address:
253*cfb92d14SAndroid Build Coastguard Worker        # Entry for c2 should point towards r3
254*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == r3_rloc)
255*cfb92d14SAndroid Build Coastguard Worker    elif entry.address == c3_address:
256*cfb92d14SAndroid Build Coastguard Worker        # Entry for c3 should still point towards c3
257*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == c3_rloc)
258*cfb92d14SAndroid Build Coastguard Worker    else:
259*cfb92d14SAndroid Build Coastguard Worker        raise (wpan.VerifyError("Unknown entry in the address cache table"))
260*cfb92d14SAndroid Build Coastguard Worker
261*cfb92d14SAndroid Build Coastguard Worker# Force c2 to switch its parent from r3 to r2
262*cfb92d14SAndroid Build Coastguard Worker
263*cfb92d14SAndroid Build Coastguard Workerc2.set(
264*cfb92d14SAndroid Build Coastguard Worker    wpan.WPAN_CHILD_SUPERVISION_CHECK_TIMEOUT,
265*cfb92d14SAndroid Build Coastguard Worker    str(CHILD_SUPERVISION_CHECK_TIMEOUT),
266*cfb92d14SAndroid Build Coastguard Worker)
267*cfb92d14SAndroid Build Coastguard Workerr2.set(wpan.WPAN_CHILD_SUPERVISION_INTERVAL, str(PARENT_SUPERVISION_INTERVAL))
268*cfb92d14SAndroid Build Coastguard Worker
269*cfb92d14SAndroid Build Coastguard Workerr3.un_allowlist_node(c2)
270*cfb92d14SAndroid Build Coastguard Workerr2.allowlist_node(c2)
271*cfb92d14SAndroid Build Coastguard Workerc2.allowlist_node(r2)
272*cfb92d14SAndroid Build Coastguard Worker
273*cfb92d14SAndroid Build Coastguard Worker# Wait for c2 to detach from r3 and attach to r2.
274*cfb92d14SAndroid Build Coastguard Worker#
275*cfb92d14SAndroid Build Coastguard Worker# Upon re-attach, previous parent r3 is notified and should remove c2 from
276*cfb92d14SAndroid Build Coastguard Worker# its child table.
277*cfb92d14SAndroid Build Coastguard Worker
278*cfb92d14SAndroid Build Coastguard Worker
279*cfb92d14SAndroid Build Coastguard Workerdef check_c2_is_removed_from_r3_child_table():
280*cfb92d14SAndroid Build Coastguard Worker    child_table = wpan.parse_list(r3.get(wpan.WPAN_THREAD_CHILD_TABLE))
281*cfb92d14SAndroid Build Coastguard Worker    verify(len(child_table) == 1)
282*cfb92d14SAndroid Build Coastguard Worker
283*cfb92d14SAndroid Build Coastguard Worker
284*cfb92d14SAndroid Build Coastguard Workerwpan.verify_within(check_c2_is_removed_from_r3_child_table, REATTACH_WAIT_TIME)
285*cfb92d14SAndroid Build Coastguard Worker
286*cfb92d14SAndroid Build Coastguard Worker# Verify that both c2 is a child of r2
287*cfb92d14SAndroid Build Coastguard Worker
288*cfb92d14SAndroid Build Coastguard Workerchild_table = wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE))
289*cfb92d14SAndroid Build Coastguard Workerverify(len(child_table) == 1)
290*cfb92d14SAndroid Build Coastguard Worker
291*cfb92d14SAndroid Build Coastguard Worker# New network topology
292*cfb92d14SAndroid Build Coastguard Worker#
293*cfb92d14SAndroid Build Coastguard Worker#     r1 ---- r2 ---- r3
294*cfb92d14SAndroid Build Coastguard Worker#     |       |       |
295*cfb92d14SAndroid Build Coastguard Worker#     |       |       |
296*cfb92d14SAndroid Build Coastguard Worker#     c1      c2(s)   c3
297*cfb92d14SAndroid Build Coastguard Worker
298*cfb92d14SAndroid Build Coastguard Worker# Send a UDP message from c2 to c1.
299*cfb92d14SAndroid Build Coastguard Worker# This message will be forwarded by r1 to its FED child c1.
300*cfb92d14SAndroid Build Coastguard Worker
301*cfb92d14SAndroid Build Coastguard Workersender = c2.prepare_tx(c2_address, c1_address, "Hi c1 child of r1")
302*cfb92d14SAndroid Build Coastguard Workerrecver = c1.prepare_rx(sender)
303*cfb92d14SAndroid Build Coastguard Workerwpan.Node.perform_async_tx_rx()
304*cfb92d14SAndroid Build Coastguard Workerverify(sender.was_successful and recver.was_successful)
305*cfb92d14SAndroid Build Coastguard Worker
306*cfb92d14SAndroid Build Coastguard Worker# r1 upon receiving and forwarding the message from c2 (through r2 now) should
307*cfb92d14SAndroid Build Coastguard Worker# update its address cache table for c2 (address cache update through snooping).
308*cfb92d14SAndroid Build Coastguard Worker#
309*cfb92d14SAndroid Build Coastguard Worker# verify that the address cache table is updated correctly.
310*cfb92d14SAndroid Build Coastguard Worker
311*cfb92d14SAndroid Build Coastguard Workeraddr_cache_table = wpan.parse_address_cache_table_result(r1.get(wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE))
312*cfb92d14SAndroid Build Coastguard Workerverify(len(addr_cache_table) == 2)
313*cfb92d14SAndroid Build Coastguard Worker
314*cfb92d14SAndroid Build Coastguard Workerfor entry in addr_cache_table:
315*cfb92d14SAndroid Build Coastguard Worker    if entry.address == c2_address:
316*cfb92d14SAndroid Build Coastguard Worker        # Entry for c2's address should now point to r2
317*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == r2_rloc)
318*cfb92d14SAndroid Build Coastguard Worker    elif entry.address == c3_address:
319*cfb92d14SAndroid Build Coastguard Worker        # Entry for c3's address should still point to c3
320*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == c3_rloc)
321*cfb92d14SAndroid Build Coastguard Worker    else:
322*cfb92d14SAndroid Build Coastguard Worker        raise (wpan.VerifyError("Unknown entry in the address cache table"))
323*cfb92d14SAndroid Build Coastguard Worker
324*cfb92d14SAndroid Build Coastguard Worker# Force c2 to switch its parent from r2 to r3
325*cfb92d14SAndroid Build Coastguard Worker
326*cfb92d14SAndroid Build Coastguard WorkerCHILD_SUPERVISION_CHECK_TIMEOUT = 2
327*cfb92d14SAndroid Build Coastguard WorkerPARENT_SUPERVISION_INTERVAL = 1
328*cfb92d14SAndroid Build Coastguard Worker
329*cfb92d14SAndroid Build Coastguard WorkerREATTACH_WAIT_TIME = CHILD_SUPERVISION_CHECK_TIMEOUT / speedup + 6
330*cfb92d14SAndroid Build Coastguard Worker
331*cfb92d14SAndroid Build Coastguard Workerc2.set(
332*cfb92d14SAndroid Build Coastguard Worker    wpan.WPAN_CHILD_SUPERVISION_CHECK_TIMEOUT,
333*cfb92d14SAndroid Build Coastguard Worker    str(CHILD_SUPERVISION_CHECK_TIMEOUT),
334*cfb92d14SAndroid Build Coastguard Worker)
335*cfb92d14SAndroid Build Coastguard Workerr3.set(wpan.WPAN_CHILD_SUPERVISION_INTERVAL, str(PARENT_SUPERVISION_INTERVAL))
336*cfb92d14SAndroid Build Coastguard Worker
337*cfb92d14SAndroid Build Coastguard Workerr2.un_allowlist_node(c2)
338*cfb92d14SAndroid Build Coastguard Workerr3.allowlist_node(c2)
339*cfb92d14SAndroid Build Coastguard Workerc2.allowlist_node(r3)
340*cfb92d14SAndroid Build Coastguard Worker
341*cfb92d14SAndroid Build Coastguard Worker# Wait for c2 to detach from r2 and attach to r3.
342*cfb92d14SAndroid Build Coastguard Worker#
343*cfb92d14SAndroid Build Coastguard Worker# Upon re-attach, previous parent r2 is notified and should remove c2 from
344*cfb92d14SAndroid Build Coastguard Worker# its child table.
345*cfb92d14SAndroid Build Coastguard Worker
346*cfb92d14SAndroid Build Coastguard Worker
347*cfb92d14SAndroid Build Coastguard Workerdef check_c2_is_removed_from_r2_child_table():
348*cfb92d14SAndroid Build Coastguard Worker    child_table = wpan.parse_list(r2.get(wpan.WPAN_THREAD_CHILD_TABLE))
349*cfb92d14SAndroid Build Coastguard Worker    verify(len(child_table) == 0)
350*cfb92d14SAndroid Build Coastguard Worker
351*cfb92d14SAndroid Build Coastguard Worker
352*cfb92d14SAndroid Build Coastguard Workerwpan.verify_within(check_c2_is_removed_from_r2_child_table, REATTACH_WAIT_TIME)
353*cfb92d14SAndroid Build Coastguard Worker
354*cfb92d14SAndroid Build Coastguard Worker# Verify that both c2, c3 are children of r3
355*cfb92d14SAndroid Build Coastguard Worker
356*cfb92d14SAndroid Build Coastguard Workerchild_table = wpan.parse_list(r3.get(wpan.WPAN_THREAD_CHILD_TABLE))
357*cfb92d14SAndroid Build Coastguard Workerverify(len(child_table) == 2)
358*cfb92d14SAndroid Build Coastguard Worker
359*cfb92d14SAndroid Build Coastguard Worker# New network topology
360*cfb92d14SAndroid Build Coastguard Worker#
361*cfb92d14SAndroid Build Coastguard Worker#     r1 ---- r2 ---- r3
362*cfb92d14SAndroid Build Coastguard Worker#     |               /\
363*cfb92d14SAndroid Build Coastguard Worker#     |              /  \
364*cfb92d14SAndroid Build Coastguard Worker#     c1           c2(s) c3
365*cfb92d14SAndroid Build Coastguard Worker
366*cfb92d14SAndroid Build Coastguard Worker# Send a UDP message from c2 to c1.
367*cfb92d14SAndroid Build Coastguard Worker# This message will be forwarded by r1 to its FED child c1.
368*cfb92d14SAndroid Build Coastguard Worker
369*cfb92d14SAndroid Build Coastguard Workersender = c2.prepare_tx(c2_address, c1_address, "Hi c1 child of r1")
370*cfb92d14SAndroid Build Coastguard Workerrecver = c1.prepare_rx(sender)
371*cfb92d14SAndroid Build Coastguard Workerwpan.Node.perform_async_tx_rx()
372*cfb92d14SAndroid Build Coastguard Workerverify(sender.was_successful and recver.was_successful)
373*cfb92d14SAndroid Build Coastguard Worker
374*cfb92d14SAndroid Build Coastguard Worker# r1 upon receiving and forwarding the message from c2 (through r2 now) should
375*cfb92d14SAndroid Build Coastguard Worker# update its address cache table for c2 (address cache update through snooping).
376*cfb92d14SAndroid Build Coastguard Worker#
377*cfb92d14SAndroid Build Coastguard Worker# verify that the address cache table is updated correctly.
378*cfb92d14SAndroid Build Coastguard Worker
379*cfb92d14SAndroid Build Coastguard Workeraddr_cache_table = wpan.parse_address_cache_table_result(r1.get(wpan.WPAN_THREAD_ADDRESS_CACHE_TABLE))
380*cfb92d14SAndroid Build Coastguard Workerverify(len(addr_cache_table) == 2)
381*cfb92d14SAndroid Build Coastguard Worker
382*cfb92d14SAndroid Build Coastguard Workerfor entry in addr_cache_table:
383*cfb92d14SAndroid Build Coastguard Worker    if entry.address == c2_address:
384*cfb92d14SAndroid Build Coastguard Worker        # Entry for c2's address should now point to r3
385*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == r3_rloc)
386*cfb92d14SAndroid Build Coastguard Worker    elif entry.address == c3_address:
387*cfb92d14SAndroid Build Coastguard Worker        # Entry for c3's address should still point to c3
388*cfb92d14SAndroid Build Coastguard Worker        verify(entry.rloc16 == c3_rloc)
389*cfb92d14SAndroid Build Coastguard Worker    else:
390*cfb92d14SAndroid Build Coastguard Worker        raise (wpan.VerifyError("Unknown entry in the address cache table"))
391*cfb92d14SAndroid Build Coastguard Worker
392*cfb92d14SAndroid Build Coastguard Worker# -----------------------------------------------------------------------------------------------------------------------
393*cfb92d14SAndroid Build Coastguard Worker# Test finished
394*cfb92d14SAndroid Build Coastguard Worker
395*cfb92d14SAndroid Build Coastguard Workerwpan.Node.finalize_all_nodes()
396*cfb92d14SAndroid Build Coastguard Worker
397*cfb92d14SAndroid Build Coastguard Workerprint('\'{}\' passed.'.format(test_name))
398