1#!/usr/bin/env python3
2#
3#  Copyright (c) 2022, 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
29from cli import verify
30from cli import verify_within
31import cli
32import time
33
34# -----------------------------------------------------------------------------------------------------------------------
35# Test description: Test MLE discover scan with nodes supporting different radios
36#
37
38test_name = __file__[:-3] if __file__.endswith('.py') else __file__
39print('-' * 120)
40print('Starting \'{}\''.format(test_name))
41
42# -----------------------------------------------------------------------------------------------------------------------
43# Creating `cli.Node` instances
44
45speedup = 10
46cli.Node.set_time_speedup_factor(speedup)
47
48n1 = cli.Node(cli.RADIO_15_4)
49n2 = cli.Node(cli.RADIO_TREL)
50n3 = cli.Node(cli.RADIO_15_4_TREL)
51s1 = cli.Node(cli.RADIO_15_4)
52s2 = cli.Node(cli.RADIO_TREL)
53s3 = cli.Node(cli.RADIO_15_4_TREL)
54
55# -----------------------------------------------------------------------------------------------------------------------
56# Build network topology
57
58n1.form("n1", channel='20')
59n2.form("n2", channel='21')
60n3.form("n3", channel='22')
61
62# -----------------------------------------------------------------------------------------------------------------------
63# Test Implementation
64
65verify(n1.multiradio_get_radios() == '[15.4]')
66verify(n2.multiradio_get_radios() == '[TREL]')
67verify(n3.multiradio_get_radios() == '[15.4, TREL]')
68verify(s1.multiradio_get_radios() == '[15.4]')
69verify(s2.multiradio_get_radios() == '[TREL]')
70verify(s3.multiradio_get_radios() == '[15.4, TREL]')
71
72
73def verify_scan_result_conatins_nodes(scan_result, nodes):
74    table = cli.Node.parse_table(scan_result)
75    verify(len(table) >= len(nodes))
76    for node in nodes:
77        ext_addr = node.get_ext_addr()
78        for entry in table:
79            if entry['MAC Address'] == ext_addr:
80                verify(int(entry['PAN'], 16) == int(node.get_panid(), 16))
81                verify(int(entry['Ch']) == int(node.get_channel()))
82                break
83        else:
84            verify(False)
85
86
87# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
88# Scan by scanner nodes (no network)
89
90s1.interface_up()
91s2.interface_up()
92s3.interface_up()
93
94# Scan by s1 (15.4 only), expect to see n1(15.4) and n3(15.4+trel)
95
96verify_scan_result_conatins_nodes(s1.cli('discover'), [n1, n3])
97
98# Scan by s2 (trel only), expect to see n2(trel) and n3(15.4+trel)
99verify_scan_result_conatins_nodes(s2.cli('discover'), [n2, n3])
100
101# Scan by s3 (trel+15.4), expect to see all nodes
102verify_scan_result_conatins_nodes(s3.cli('discover'), [n1, n2, n3])
103
104# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
105# Scan by the nodes
106
107# Scan by n1 (15.4 only), expect to see only n3(15.4+trel)
108verify_scan_result_conatins_nodes(n1.cli('discover'), [n3])
109
110# Scan by n2 (trel only), expect to see only n3(15.4+trel)
111verify_scan_result_conatins_nodes(n2.cli('discover'), [n3])
112
113# Scan by n3 (15.4+trel), expect to see n1(15.4) and n2(trel)
114verify_scan_result_conatins_nodes(n3.cli('discover'), [n1, n2])
115
116# -----------------------------------------------------------------------------------------------------------------------
117# Test finished
118
119cli.Node.finalize_all_nodes()
120
121print('\'{}\' passed.'.format(test_name))
122