xref: /aosp_15_r20/external/openthread/tests/toranj/ncp/test-016-neighbor-table.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 wpan
30from wpan import verify
31
32# -----------------------------------------------------------------------------------------------------------------------
33# Test description: Neighbor table
34#
35# - Network with NUM_ROUTERS(= 2) routers, all within range of each other.
36# - The first router has NUM_CHILDREN(= 1) sleepy children attached to it.
37# - The test verifies that all children and routers are observed in the "Thread:NeighborTable" of the first router.
38#
39
40test_name = __file__[:-3] if __file__.endswith('.py') else __file__
41print('-' * 120)
42print('Starting \'{}\''.format(test_name))
43
44# -----------------------------------------------------------------------------------------------------------------------
45# Creating `wpan.Nodes` instances
46
47speedup = 4
48wpan.Node.set_time_speedup_factor(speedup)
49
50NUM_ROUTERS = 2
51NUM_CHILDREN = 1
52
53routers = []
54for num in range(NUM_ROUTERS):
55    routers.append(wpan.Node())
56
57children = []
58for num in range(NUM_CHILDREN):
59    children.append(wpan.Node())
60
61# end-device per router used for quick promotion to router role
62ed = [0]
63for num in range(1, NUM_ROUTERS):
64    ed.append(wpan.Node())
65
66all_nodes = routers + children + ed
67
68# -----------------------------------------------------------------------------------------------------------------------
69# Init all nodes
70
71wpan.Node.init_all_nodes()
72
73# -----------------------------------------------------------------------------------------------------------------------
74# Build network topology
75#
76
77# allowlist all routers with one another
78for i in range(NUM_ROUTERS):
79    for j in range(NUM_ROUTERS):
80        if i != j:
81            routers[i].allowlist_node(routers[j])
82
83# All children should attach to routers[0]
84for num in range(NUM_CHILDREN):
85    children[num].allowlist_node(routers[0])
86    routers[0].allowlist_node(children[num])
87
88# allowlist the end-device ed with its corresponding router
89for num in range(1, NUM_ROUTERS):
90    ed[num].allowlist_node(routers[num])
91    routers[num].allowlist_node(ed[num])
92
93routers[0].form("neigh-table")
94
95for router in routers[1:]:
96    router.join_node(routers[0], wpan.JOIN_TYPE_ROUTER)
97
98for num in range(1, NUM_ROUTERS):
99    ed[num].join_node(routers[num], wpan.JOIN_TYPE_END_DEVICE)
100
101for num in range(NUM_CHILDREN):
102    children[num].join_node(routers[0], wpan.JOIN_TYPE_SLEEPY_END_DEVICE)
103    children[num].set(wpan.WPAN_POLL_INTERVAL, '300')
104
105# -----------------------------------------------------------------------------------------------------------------------
106# Test implementation
107
108for router in routers[1:]:
109    verify(router.get(wpan.WPAN_NODE_TYPE) == wpan.NODE_TYPE_ROUTER)
110
111# Get and parse the neighbor table on routers[0].
112neighbor_table = wpan.parse_neighbor_table_result(routers[0].get(wpan.WPAN_THREAD_NEIGHBOR_TABLE))
113
114verify(len(neighbor_table) == NUM_ROUTERS - 1 + NUM_CHILDREN)
115
116# Verify that all children are seen in the neighbor table
117for child in children:
118    ext_addr = child.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
119    for entry in neighbor_table:
120        if entry.ext_address == ext_addr:
121            break
122    else:
123        raise wpan.VerifyError('Failed to find a child entry for extended address {} in table'.format(ext_addr))
124
125    verify(int(entry.rloc16, 16) == int(child.get(wpan.WPAN_THREAD_RLOC16), 16))
126    verify(entry.is_rx_on_when_idle() is False)
127    verify(entry.is_ftd() is False)
128    verify(entry.is_child())
129
130# Verify that all other routers are seen in the neighbor table
131for router in routers[1:]:
132    ext_addr = router.get(wpan.WPAN_EXT_ADDRESS)[1:-1]
133    for entry in neighbor_table:
134        if entry.ext_address == ext_addr:
135            break
136    else:
137        raise wpan.VerifyError('Failed to find a router entry for extended address {} in table'.format(ext_addr))
138
139    verify(int(entry.rloc16, 16) == int(router.get(wpan.WPAN_THREAD_RLOC16), 16))
140    verify(entry.is_rx_on_when_idle())
141    verify(entry.is_ftd())
142    verify(entry.is_child() is False)
143
144# -----------------------------------------------------------------------------------------------------------------------
145# Test finished
146
147wpan.Node.finalize_all_nodes()
148
149print('\'{}\' passed.'.format(test_name))
150