• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3#  Copyright (c) 2020, 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#
29
30import unittest
31
32import command
33import config
34import mle
35import thread_cert
36
37LEADER_1_2 = 1
38MED_1_2 = 2
39SED_1_2 = 3
40MED_1_1 = 4
41SED_1_1 = 5
42ROUTER_1_1 = 6
43MED_1_2_2 = 7
44SED_1_2_2 = 8
45
46WAIT_ATTACH = 5
47WAIT_REDUNDANCE = 3
48ROUTER_SELECTION_JITTER = 1
49
50MA1_LINKLOCAL = 'ff02::1:2:3:4'
51MA2_ADMINSCOPE = 'ff04::1:2:3:4'
52"""
53 Topology
54
55             SED_1_2
56                |
57                |
58MED_1_2 --- LEADER_1_2 --- MED_1_1
59                |     \
60                |       \
61             SED_1_1     ROUTER_1_1 --- MED_1_2_2
62                            |
63                            |
64                         SED_1_2_2
65
66 1) Bring up Leader_1_2.
67
68 2) Bring up MED_1_2, which attaches to Thread 1.2 parent, only register MA with scope larger than realm local.
69    a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
70    b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
71
72 3) Bring up SED_1_2, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
73    a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
74    b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
75
76 4) Bring up MED_1_1, which attaches to Thread 1.2 parent, not register any external MA.
77    a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
78    b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
79
80 5) Bring up SED_1_1, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
81    a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
82    b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
83
84 6) Bring up ROUTER_1_1.
85
86 7) Bring up MED_1_2_2 which attaches to Thread 1.1 parent, not register any external MA.
87    a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request
88    b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
89
90 8) Bring up SED_1_2_2 which attaches to Thread 1.1 parent, register any external MA for indirect transmission.
91    a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
92    b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
93
94"""
95
96
97class TestMulticastRegistration(thread_cert.TestCase):
98    TOPOLOGY = {
99        LEADER_1_2: {
100            'version': '1.2',
101            'allowlist': [MED_1_2, SED_1_2, MED_1_1, SED_1_1, ROUTER_1_1],
102        },
103        MED_1_2: {
104            'mode': 'rn',
105            'version': '1.2',
106            'allowlist': [LEADER_1_2],
107        },
108        SED_1_2: {
109            'mode': 'n',
110            'version': '1.2',
111            'allowlist': [LEADER_1_2],
112        },
113        MED_1_1: {
114            'mode': 'rn',
115            'version': '1.1',
116            'allowlist': [LEADER_1_2],
117        },
118        SED_1_1: {
119            'mode': 'n',
120            'version': '1.1',
121            'allowlist': [LEADER_1_2],
122        },
123        ROUTER_1_1: {
124            'version': '1.1',
125            'allowlist': [LEADER_1_2, MED_1_2_2, SED_1_2_2],
126        },
127        MED_1_2_2: {
128            'mode': 'rn',
129            'version': '1.2',
130            'allowlist': [ROUTER_1_1],
131        },
132        SED_1_2_2: {
133            'mode': 'n',
134            'version': '1.2',
135            'allowlist': [ROUTER_1_1],
136        },
137    }
138    """All nodes are created with default configurations"""
139
140    def __check_multicast_registration(self,
141                                       node,
142                                       multicast_address,
143                                       child_update_request_assert=True,
144                                       in_address_registration=True):
145        ''' Check whether or not the addition of the multicast address on the specific node
146        would trigger Child Update Request for multicast address registration via Address
147        Registration TLV.
148
149        Args:
150            node (int) : The device id
151            multicast_address (string): The multicast address
152            child_update_request_assert (bool): whether or not the addition should trigger Child Update Request
153            in_address_registration (bool): Whether or not the multicast_address should be registered
154        '''
155        # Flush relative message queues.
156        self.flush_nodes([node])
157
158        self.nodes[node].add_ipmaddr(multicast_address)
159        WAIT_TIME = WAIT_REDUNDANCE
160        self.simulator.go(WAIT_TIME)
161
162        messages = self.simulator.get_messages_sent_by(node)
163
164        msg = messages.next_mle_message(mle.CommandType.CHILD_UPDATE_REQUEST,
165                                        assert_enabled=child_update_request_assert)
166
167        if msg:
168            is_in = command.check_address_registration_tlv(msg, multicast_address)
169
170            if in_address_registration:
171                assert is_in, 'Error: Expected {} in AddressRegistrationTLV not found'.format(multicast_address)
172            else:
173                assert not is_in, 'Error: Unexpected {} in AddressRegistrationTLV'.format(multicast_address)
174
175    def test(self):
176
177        # 1) Bring up Leader_1_2.
178        self.nodes[LEADER_1_2].start()
179        WAIT_TIME = WAIT_ATTACH
180        self.simulator.go(WAIT_TIME * 2)
181        self.assertEqual(self.nodes[LEADER_1_2].get_state(), 'leader')
182
183        # 2) Bring up MED_1_2, which attaches to Thread 1.2 parent, only register MA with scope larger than realm local.
184        self.nodes[MED_1_2].start()
185        WAIT_TIME = WAIT_ATTACH
186        self.simulator.go(WAIT_TIME)
187        self.assertEqual(self.nodes[MED_1_2].get_state(), 'child')
188
189        # 2a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
190        self.__check_multicast_registration(MED_1_2,
191                                            MA1_LINKLOCAL,
192                                            child_update_request_assert=False,
193                                            in_address_registration=False)
194
195        # 2b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
196        self.__check_multicast_registration(MED_1_2,
197                                            MA2_ADMINSCOPE,
198                                            child_update_request_assert=True,
199                                            in_address_registration=True)
200
201        # 3) Bring up SED_1_2, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
202        self.nodes[SED_1_2].start()
203        WAIT_TIME = WAIT_ATTACH
204        self.simulator.go(WAIT_TIME)
205        self.assertEqual(self.nodes[SED_1_2].get_state(), 'child')
206
207        # 3a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request.
208        self.__check_multicast_registration(SED_1_2,
209                                            MA1_LINKLOCAL,
210                                            child_update_request_assert=True,
211                                            in_address_registration=True)
212
213        # 3b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
214        self.__check_multicast_registration(SED_1_2,
215                                            MA2_ADMINSCOPE,
216                                            child_update_request_assert=True,
217                                            in_address_registration=True)
218
219        # 4) Bring up MED_1_1, which attaches to Thread 1.2 parent, not register any external MA.
220        self.nodes[MED_1_1].start()
221        WAIT_TIME = WAIT_ATTACH
222        self.simulator.go(WAIT_TIME)
223        self.assertEqual(self.nodes[MED_1_1].get_state(), 'child')
224
225        # 4a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request.
226        self.__check_multicast_registration(MED_1_1,
227                                            MA1_LINKLOCAL,
228                                            child_update_request_assert=False,
229                                            in_address_registration=False)
230
231        # 4b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
232        self.__check_multicast_registration(MED_1_1,
233                                            MA2_ADMINSCOPE,
234                                            child_update_request_assert=False,
235                                            in_address_registration=False)
236
237        # 5) Bring up SED_1_1, which attaches to Thread 1.2 parent, register any external MA for indirect transmission.
238        self.nodes[SED_1_1].start()
239        WAIT_TIME = WAIT_ATTACH
240        self.simulator.go(WAIT_TIME)
241        self.assertEqual(self.nodes[SED_1_1].get_state(), 'child')
242
243        # 5a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request.
244        self.__check_multicast_registration(SED_1_1,
245                                            MA1_LINKLOCAL,
246                                            child_update_request_assert=True,
247                                            in_address_registration=True)
248
249        # 5b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
250        self.__check_multicast_registration(SED_1_1,
251                                            MA2_ADMINSCOPE,
252                                            child_update_request_assert=True,
253                                            in_address_registration=True)
254
255        #6) Bring up ROUTER_1_1.
256        self.nodes[ROUTER_1_1].set_router_selection_jitter(ROUTER_SELECTION_JITTER)
257        self.nodes[ROUTER_1_1].start()
258        WAIT_TIME = WAIT_ATTACH + ROUTER_SELECTION_JITTER
259        self.simulator.go(WAIT_TIME)
260        self.assertEqual(self.nodes[ROUTER_1_1].get_state(), 'router')
261
262        # 7) Bring up MED_1_2_2 which attaches to Thread 1.1 parent, not register any external MA.
263        self.nodes[MED_1_2_2].start()
264        WAIT_TIME = WAIT_ATTACH
265        self.simulator.go(WAIT_TIME)
266        self.assertEqual(self.nodes[MED_1_2_2].get_state(), 'child')
267
268        # 7a) add MA1_LINKLOCAL which would NOT be registered in AddressRegistrationTLV of Child Update Request
269        self.__check_multicast_registration(MED_1_2_2,
270                                            MA1_LINKLOCAL,
271                                            child_update_request_assert=False,
272                                            in_address_registration=False)
273
274        # 7b) add MA2_ADMINSCOPE which would NOT be registered in AddressRegistrationTLV of Child Update Request.
275        self.__check_multicast_registration(MED_1_2_2,
276                                            MA2_ADMINSCOPE,
277                                            child_update_request_assert=False,
278                                            in_address_registration=False)
279
280        # 8) Bring up SED_1_2_2 which attaches to Thread 1.1 parent, register any external MA for indirect transmission.
281        self.nodes[SED_1_2_2].start()
282        WAIT_TIME = WAIT_ATTACH
283        self.simulator.go(WAIT_TIME)
284        self.assertEqual(self.nodes[SED_1_2_2].get_state(), 'child')
285
286        # 8a) add MA1_LINKLOCAL which would be registered in AddressRegistrationTLV of Child Update Request
287        self.__check_multicast_registration(SED_1_2_2,
288                                            MA1_LINKLOCAL,
289                                            child_update_request_assert=True,
290                                            in_address_registration=True)
291
292        # 8b) add MA2_ADMINSCOPE which would be registered in AddressRegistrationTLV of Child Update Request.
293        self.__check_multicast_registration(SED_1_2_2,
294                                            MA2_ADMINSCOPE,
295                                            child_update_request_assert=True,
296                                            in_address_registration=True)
297
298
299if __name__ == '__main__':
300    unittest.main()
301