1#!/usr/bin/env python3
2#
3#  Copyright (c) 2016, 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 config
33import mle
34import network_layer
35import thread_cert
36from pktverify.consts import MLE_ADVERTISEMENT, MLE_PARENT_RESPONSE, MLE_CHILD_ID_RESPONSE, ADDR_SOL_URI, SOURCE_ADDRESS_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ADDRESS16_TLV, ROUTE64_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, CONNECTIVITY_TLV, LINK_MARGIN_TLV, VERSION_TLV, ADDRESS_REGISTRATION_TLV, NL_MAC_EXTENDED_ADDRESS_TLV, NL_RLOC16_TLV, NL_STATUS_TLV, NL_ROUTER_MASK_TLV, COAP_CODE_ACK, ADDR_SOL_NA, ADDR_SOL_SUCCESS
37from pktverify.packet_verifier import PacketVerifier
38from pktverify.null_field import nullField
39
40DUT_LEADER = 1
41ROUTER_1 = 2
42ROUTER_31 = 32
43ROUTER_32 = 33
44
45# Test Purpose and Description:
46# -----------------------------
47# The purpose of this test case is to show that the DUT will
48# only allow 32 active routers on the network and reject the
49# Address Solicit Request from a 33rd router - that is
50# 2-hops away - with a No Address Available status.
51#
52# Test Topology:
53# -------------
54#         Leader[DUT]
55#         /    \
56# Router_1 --- Router_31
57#    |
58#    |
59# Router_32
60#
61# DUT Types:
62# ----------
63# Leader
64
65
66class Cert_5_2_3_LeaderReject2Hops(thread_cert.TestCase):
67    USE_MESSAGE_FACTORY = False
68
69    TOPOLOGY = {
70        DUT_LEADER: {
71            'name':
72                'LEADER',
73            'mode':
74                'rdn',
75            'panid':
76                0xface,
77            'router_downgrade_threshold':
78                33,
79            'router_upgrade_threshold':
80                32,
81            'allowlist': [
82                ROUTER_1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
83                28, 29, 30, 31, ROUTER_31
84            ]
85        },
86        ROUTER_1: {
87            'name': 'ROUTER_1',
88            'mode': 'rdn',
89            'router_downgrade_threshold': 33,
90            'router_upgrade_threshold': 33,
91            'allowlist': [DUT_LEADER, ROUTER_32]
92        },
93        3: {
94            'name': 'ROUTER_2',
95            'mode': 'rdn',
96            'router_downgrade_threshold': 33,
97            'router_upgrade_threshold': 33,
98            'allowlist': [DUT_LEADER]
99        },
100        4: {
101            'name': 'ROUTER_3',
102            'mode': 'rdn',
103            'router_downgrade_threshold': 33,
104            'router_upgrade_threshold': 33,
105            'allowlist': [DUT_LEADER]
106        },
107        5: {
108            'name': 'ROUTER_4',
109            'mode': 'rdn',
110            'router_downgrade_threshold': 33,
111            'router_upgrade_threshold': 33,
112            'allowlist': [DUT_LEADER]
113        },
114        6: {
115            'name': 'ROUTER_5',
116            'mode': 'rdn',
117            'router_downgrade_threshold': 33,
118            'router_upgrade_threshold': 33,
119            'allowlist': [DUT_LEADER]
120        },
121        7: {
122            'name': 'ROUTER_6',
123            'mode': 'rdn',
124            'router_downgrade_threshold': 33,
125            'router_upgrade_threshold': 33,
126            'allowlist': [DUT_LEADER]
127        },
128        8: {
129            'name': 'ROUTER_7',
130            'mode': 'rdn',
131            'router_downgrade_threshold': 33,
132            'router_upgrade_threshold': 33,
133            'allowlist': [DUT_LEADER]
134        },
135        9: {
136            'name': 'ROUTER_8',
137            'mode': 'rdn',
138            'router_downgrade_threshold': 33,
139            'router_upgrade_threshold': 33,
140            'allowlist': [DUT_LEADER]
141        },
142        10: {
143            'name': 'ROUTER_9',
144            'mode': 'rdn',
145            'router_downgrade_threshold': 33,
146            'router_upgrade_threshold': 33,
147            'allowlist': [DUT_LEADER]
148        },
149        11: {
150            'name': 'ROUTER_10',
151            'mode': 'rdn',
152            'router_downgrade_threshold': 33,
153            'router_upgrade_threshold': 33,
154            'allowlist': [DUT_LEADER]
155        },
156        12: {
157            'name': 'ROUTER_11',
158            'mode': 'rdn',
159            'router_downgrade_threshold': 33,
160            'router_upgrade_threshold': 33,
161            'allowlist': [DUT_LEADER]
162        },
163        13: {
164            'name': 'ROUTER_12',
165            'mode': 'rdn',
166            'router_downgrade_threshold': 33,
167            'router_upgrade_threshold': 33,
168            'allowlist': [DUT_LEADER]
169        },
170        14: {
171            'name': 'ROUTER_13',
172            'mode': 'rdn',
173            'router_downgrade_threshold': 33,
174            'router_upgrade_threshold': 33,
175            'allowlist': [DUT_LEADER]
176        },
177        15: {
178            'name': 'ROUTER_14',
179            'mode': 'rdn',
180            'router_downgrade_threshold': 33,
181            'router_upgrade_threshold': 33,
182            'allowlist': [DUT_LEADER]
183        },
184        16: {
185            'name': 'ROUTER_15',
186            'mode': 'rdn',
187            'router_downgrade_threshold': 33,
188            'router_upgrade_threshold': 33,
189            'allowlist': [DUT_LEADER]
190        },
191        17: {
192            'name': 'ROUTER_16',
193            'mode': 'rdn',
194            'router_downgrade_threshold': 33,
195            'router_upgrade_threshold': 33,
196            'allowlist': [DUT_LEADER]
197        },
198        18: {
199            'name': 'ROUTER_17',
200            'mode': 'rdn',
201            'router_downgrade_threshold': 33,
202            'router_upgrade_threshold': 33,
203            'allowlist': [DUT_LEADER]
204        },
205        19: {
206            'name': 'ROUTER_18',
207            'mode': 'rdn',
208            'router_downgrade_threshold': 33,
209            'router_upgrade_threshold': 33,
210            'allowlist': [DUT_LEADER]
211        },
212        20: {
213            'name': 'ROUTER_19',
214            'mode': 'rdn',
215            'router_downgrade_threshold': 33,
216            'router_upgrade_threshold': 33,
217            'allowlist': [DUT_LEADER]
218        },
219        21: {
220            'name': 'ROUTER_20',
221            'mode': 'rdn',
222            'router_downgrade_threshold': 33,
223            'router_upgrade_threshold': 33,
224            'allowlist': [DUT_LEADER]
225        },
226        22: {
227            'name': 'ROUTER_21',
228            'mode': 'rdn',
229            'router_downgrade_threshold': 33,
230            'router_upgrade_threshold': 33,
231            'allowlist': [DUT_LEADER]
232        },
233        23: {
234            'name': 'ROUTER_22',
235            'mode': 'rdn',
236            'router_downgrade_threshold': 33,
237            'router_upgrade_threshold': 33,
238            'allowlist': [DUT_LEADER]
239        },
240        24: {
241            'name': 'ROUTER_23',
242            'mode': 'rdn',
243            'router_downgrade_threshold': 33,
244            'router_upgrade_threshold': 33,
245            'allowlist': [DUT_LEADER]
246        },
247        25: {
248            'name': 'ROUTER_24',
249            'mode': 'rdn',
250            'router_downgrade_threshold': 33,
251            'router_upgrade_threshold': 33,
252            'allowlist': [DUT_LEADER]
253        },
254        26: {
255            'name': 'ROUTER_25',
256            'mode': 'rdn',
257            'router_downgrade_threshold': 33,
258            'router_upgrade_threshold': 33,
259            'allowlist': [DUT_LEADER]
260        },
261        27: {
262            'name': 'ROUTER_26',
263            'mode': 'rdn',
264            'router_downgrade_threshold': 33,
265            'router_upgrade_threshold': 33,
266            'allowlist': [DUT_LEADER]
267        },
268        28: {
269            'name': 'ROUTER_27',
270            'mode': 'rdn',
271            'router_downgrade_threshold': 33,
272            'router_upgrade_threshold': 33,
273            'allowlist': [DUT_LEADER]
274        },
275        29: {
276            'name': 'ROUTER_28',
277            'mode': 'rdn',
278            'router_downgrade_threshold': 33,
279            'router_upgrade_threshold': 33,
280            'allowlist': [DUT_LEADER]
281        },
282        30: {
283            'name': 'ROUTER_29',
284            'mode': 'rdn',
285            'router_downgrade_threshold': 33,
286            'router_upgrade_threshold': 33,
287            'allowlist': [DUT_LEADER]
288        },
289        31: {
290            'name': 'ROUTER_30',
291            'mode': 'rdn',
292            'router_downgrade_threshold': 33,
293            'router_upgrade_threshold': 33,
294            'allowlist': [DUT_LEADER]
295        },
296        ROUTER_31: {
297            'name': 'ROUTER_31',
298            'mode': 'rdn',
299            'router_downgrade_threshold': 33,
300            'router_upgrade_threshold': 33,
301            'allowlist': [DUT_LEADER]
302        },
303        ROUTER_32: {
304            'name': 'ROUTER_32',
305            'mode': 'rdn',
306            'router_downgrade_threshold': 33,
307            'router_upgrade_threshold': 33,
308            'allowlist': [ROUTER_1]
309        },
310    }
311
312    def test(self):
313        self.nodes[DUT_LEADER].start()
314        self.simulator.go(config.LEADER_STARTUP_DELAY)
315        self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader')
316
317        for i in range(2, 32):
318            self.nodes[i].start()
319            self.simulator.go(config.ROUTER_STARTUP_DELAY)
320            self.assertEqual(self.nodes[i].get_state(), 'router')
321        self.collect_rlocs()
322
323        self.nodes[ROUTER_31].start()
324        self.simulator.go(config.ROUTER_STARTUP_DELAY)
325        self.assertEqual(self.nodes[ROUTER_31].get_state(), 'router')
326
327        self.nodes[ROUTER_32].start()
328        self.simulator.go(config.ROUTER_STARTUP_DELAY)
329
330    def verify(self, pv: PacketVerifier):
331        pkts = pv.pkts
332        pv.summary.show()
333
334        LEADER = pv.vars['LEADER']
335        LEADER_RLOC = pv.vars['LEADER_RLOC']
336        ROUTER_31 = pv.vars['ROUTER_31']
337        ROUTER_32 = pv.vars['ROUTER_32']
338
339        # Step 1: Topology is created, the DUT is the Leader of the network
340        #         and there is a total of 32 active routers, including the Leader.
341        for i in range(1, 32):
342            pv.verify_attached('ROUTER_%d' % i)
343
344        # Step 2: Router_31 to attaches to the network and sends an Address
345        #         Solicit Request to become an active router.
346
347        _pkt = pkts.filter_wpan_src64(ROUTER_31).\
348            filter_ipv6_dst(LEADER_RLOC).\
349            filter_coap_request(ADDR_SOL_URI).\
350            filter(lambda p: {
351                              NL_MAC_EXTENDED_ADDRESS_TLV,
352                              NL_STATUS_TLV
353                              } == set(p.coap.tlv.type)
354                  ).\
355            must_next()
356
357        # Step 3: Leader sends an Address Solicit Response.
358        #         Ensure the Address Solicit Response is properly formatted:
359        #         CoAP Response Code
360        #             2.04 Changed
361        #         CoAP Payload
362        #             - Status TLV (value = Success)
363        #             - RLOC16 TLV
364        #             - Router Mask TLV
365
366        pkts.filter_wpan_src64(LEADER).\
367            filter_ipv6_dst(_pkt.ipv6.src).\
368            filter_coap_ack(ADDR_SOL_URI).\
369            filter(lambda p: {
370                              NL_STATUS_TLV,
371                              NL_RLOC16_TLV,
372                              NL_ROUTER_MASK_TLV
373                              } == set(p.coap.tlv.type) and\
374                   p.coap.code == COAP_CODE_ACK and\
375                   p.thread_address.tlv.status == ADDR_SOL_SUCCESS\
376                   ).\
377            must_next()
378
379        # Step 4: Leader The DUT sends MLE Advertisements.
380        #         The MLE Advertisements from the Leader MUST contain
381        #         the Route64 TLV with 32 assigned Router IDs.
382
383        pkts.filter_wpan_src64(LEADER).\
384            filter_LLANMA().\
385            filter_mle_cmd(MLE_ADVERTISEMENT).\
386            filter(lambda p: {
387                              LEADER_DATA_TLV,
388                              ROUTE64_TLV,
389                              SOURCE_ADDRESS_TLV
390                              } == set(p.mle.tlv.type) and\
391                   len(p.mle.tlv.route64.cost) == 32 and\
392                   p.ipv6.hlim == 255
393                  ).\
394            must_next()
395
396        # Step 5: Router_32 to attach to any of the active routers, 2-hops
397        #         from the leader, and to send an Address Solicit Request
398        #         to become an active router.
399
400        _pkt = pkts.filter_wpan_src64(ROUTER_32).\
401            filter_ipv6_dst(LEADER_RLOC).\
402            filter_coap_request(ADDR_SOL_URI).\
403            filter(lambda p: {
404                              NL_MAC_EXTENDED_ADDRESS_TLV,
405                              NL_STATUS_TLV
406                              } == set(p.coap.tlv.type)
407                  ).\
408           must_next()
409
410        # Step 6: Leader sends an Address Solicit Response.
411        #         Ensure the Address Solicit Response is properly formatted:
412        #         CoAP Response Code
413        #             2.04 Changed
414        #         CoAP Payload
415        #             - Status TLV (value = No Address Available)
416
417        pkts.filter_wpan_src64(LEADER).\
418            filter_ipv6_dst(_pkt.ipv6.src).\
419            filter_coap_ack(ADDR_SOL_URI).\
420            filter(lambda p:
421                   p.coap.code == COAP_CODE_ACK and\
422                   p.thread_address.tlv.status == ADDR_SOL_NA
423                   ).\
424            must_next()
425
426
427if __name__ == '__main__':
428    unittest.main()
429