• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#
29import ipaddress
30import typing
31import unittest
32
33import config
34import thread_cert
35
36# Test description:
37#
38#   This test verifies DHCP6 PD pauses requesting PD prefix when there is another BR advertising PD prefix.
39#
40
41LEADER = 1
42ROUTER = 2
43
44
45class TestDhcp6Pd(thread_cert.TestCase):
46    SUPPORT_NCP = False
47    USE_MESSAGE_FACTORY = False
48
49    TOPOLOGY = {
50        LEADER: {
51            'name': 'Leader',
52            'allowlist': [ROUTER],
53            'is_otbr': True,
54            'mode': 'rdn',
55        },
56        ROUTER: {
57            'name': 'Router',
58            'allowlist': [LEADER],
59            'is_otbr': True,
60            'mode': 'rdn',
61        },
62    }
63
64    def test(self):
65        leader = self.nodes[LEADER]
66        router = self.nodes[ROUTER]
67
68        #---------------------------------------------------------------
69        # Start the server & client devices.
70
71        # Case 1: Only 1 BR receives PD prefix
72
73        leader.start()
74        self.simulator.go(config.LEADER_STARTUP_DELAY)
75        self.assertEqual(leader.get_state(), 'leader')
76        leader.pd_set_enabled(True)
77
78        router.start()
79        self.simulator.go(config.ROUTER_STARTUP_DELAY)
80        self.assertEqual(router.get_state(), 'router')
81        router.pd_set_enabled(True)
82
83        leader.start_pd_radvd_service("2001:db8:abcd:1234::/64")
84        self.simulator.go(30)
85
86        self.assertSetEqual({leader.pd_state, router.pd_state}, {"running", "idle"})
87
88        self.assertEqual(leader.pd_get_prefix(), "2001:db8:abcd:1234::/64")
89
90        # Case 2: More than one BR receives PD prefix
91        # The BR with "smaller" PD prefix wins
92
93        # Clean up and ensure no prefix is currently published.
94        leader.pd_set_enabled(False)
95        router.pd_set_enabled(False)
96        self.simulator.go(30)
97
98        leader.start_pd_radvd_service("2001:db8:abcd:1234::/64")
99        router.start_pd_radvd_service("2001:db8:1234:abcd::/64")
100        leader.pd_set_enabled(True)
101        router.pd_set_enabled(True)
102        self.simulator.go(30)
103
104        self.assertSetEqual({leader.pd_state, router.pd_state}, {"running", "idle"})
105
106        # Case 3: When the other BR lost PD prefix, the remaining BR should try to request one.
107
108        if leader.pd_state == 'running':
109            br_to_stop = leader
110            br_to_continue = router
111            expected_prefix = "2001:db8:1234:abcd::/64"
112        else:
113            br_to_stop = router
114            br_to_continue = leader
115            expected_prefix = "2001:db8:abcd:1234::/64"
116        br_to_stop.pd_set_enabled(False)
117        self.simulator.go(30)
118
119        self.assertEqual(br_to_continue.pd_state, "running")
120        self.assertEqual(br_to_continue.pd_get_prefix(), expected_prefix)
121
122
123if __name__ == '__main__':
124    unittest.main()
125