1#!/usr/bin/env python3
2#
3#  Copyright (c) 2024, 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:
36#
37# Check tracking of peer BR (connected to same Thread mesh).
38#
39#      ______________
40#     /              \
41#   br1 --- br2 --- br3
42#
43
44test_name = __file__[:-3] if __file__.endswith('.py') else __file__
45print('-' * 120)
46print('Starting \'{}\''.format(test_name))
47
48# -----------------------------------------------------------------------------------------------------------------------
49# Creating `cli.Nodes` instances
50
51speedup = 60
52cli.Node.set_time_speedup_factor(speedup)
53
54br1 = cli.Node()
55br2 = cli.Node()
56br3 = cli.Node()
57
58IF_INDEX = 1
59
60# -----------------------------------------------------------------------------------------------------------------------
61# Form topology
62
63br1.form("peer-brs")
64br2.join(br1)
65br3.join(br2)
66
67verify(br1.get_state() == 'leader')
68verify(br2.get_state() == 'router')
69verify(br3.get_state() == 'router')
70
71# -----------------------------------------------------------------------------------------------------------------------
72# Test implementation
73
74# Start first border router `br1`
75
76br1.srp_server_set_addr_mode('unicast')
77br1.srp_server_auto_enable()
78
79br1.br_init(IF_INDEX, 1)
80br1.br_enable()
81
82time.sleep(1)
83verify(br1.br_get_state() == 'running')
84
85br1_local_omr = br1.br_get_local_omrprefix()
86br1_favored_omr = br1.br_get_favored_omrprefix().split()[0]
87verify(br1_local_omr == br1_favored_omr)
88
89br1_local_onlink = br1.br_get_local_onlinkprefix()
90br1_favored_onlink = br1.br_get_favored_onlinkprefix().split()[0]
91verify(br1_local_onlink == br1_favored_onlink)
92
93# Start `br2` and `br3` together
94
95br2.br_init(IF_INDEX, 1)
96br2.br_enable()
97
98br3.br_init(IF_INDEX, 1)
99br3.br_enable()
100
101time.sleep(1)
102verify(br2.br_get_state() == 'running')
103verify(br3.br_get_state() == 'running')
104
105# Validate that all BRs discovered the other ones as peer BR
106
107all_brs = [br1, br2, br3]
108
109for br in all_brs:
110    routers = br.br_get_routers()
111    verify(len(routers) == 2)
112    for router in routers:
113        verify(router.endswith('(peer BR)'))
114    verify(int(br.br_count_peers().split()[0]) == 2)
115    peers = br.br_get_peer_brs()
116    verify(len(peers) == 2)
117    other_brs = all_brs
118    other_brs.remove(br)
119    for other_br in other_brs:
120        rloc16 = other_br.get_rloc16()
121        verify(any([rloc16 in peer for peer in peers]))
122
123# Disable BR3 and validate that BR1 and BR2 detect this.
124# BR3 itself should continue to detect BR1 and BR2
125
126br3.br_disable()
127
128time.sleep(0.5)
129
130for br in [br1, br2]:
131    verify(len(br.br_get_peer_brs()) == 1)
132
133verify(len(br3.br_get_peer_brs()) == 2)
134
135# -----------------------------------------------------------------------------------------------------------------------
136# Test finished
137
138cli.Node.finalize_all_nodes()
139
140print('\'{}\' passed.'.format(test_name))
141