• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_PARENT_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_LINK_REQUEST, ADDR_SOL_URI, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, CONNECTIVITY_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, VERSION_TLV, TLV_REQUEST_TLV, LINK_MARGIN_TLV, SOURCE_ADDRESS_TLV, COAP_CODE_ACK, COAP_CODE_POST, NL_MAC_EXTENDED_ADDRESS_TLV, NL_STATUS_TLV, NL_RLOC16_TLV, NL_ROUTER_MASK_TLV
37from pktverify.packet_verifier import PacketVerifier
38
39LEADER = 1
40ROUTER1 = 2
41
42# Test Purpose and Description:
43# -----------------------------
44# The purpose of this test case is to verify that after deallocating a Router ID,
45# Leader as a DUT doesn't reassign the Router ID for at least ID_REUSE_DELAY
46# seconds
47#
48# Test Topology:
49# -------------
50# Leader
51#   |
52# Router
53#
54# DUT Types:
55# ----------
56# Leader
57
58
59class Cert_5_1_05_RouterAddressTimeout(thread_cert.TestCase):
60    USE_MESSAGE_FACTORY = False
61
62    TOPOLOGY = {
63        LEADER: {
64            'name': 'LEADER',
65            'mode': 'rdn',
66            'allowlist': [ROUTER1]
67        },
68        ROUTER1: {
69            'name': 'ROUTER',
70            'mode': 'rdn',
71            'allowlist': [LEADER]
72        },
73    }
74
75    def _setUpRouter1(self):
76        self.nodes[ROUTER1].add_allowlist(self.nodes[LEADER].get_addr64())
77        self.nodes[ROUTER1].enable_allowlist()
78        self.nodes[ROUTER1].set_router_selection_jitter(1)
79
80    def test(self):
81        self.nodes[LEADER].start()
82        self.simulator.go(config.LEADER_STARTUP_DELAY)
83        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
84
85        self.nodes[ROUTER1].start()
86        self.simulator.go(config.ROUTER_STARTUP_DELAY)
87        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
88
89        self.nodes[ROUTER1].reset()
90        self._setUpRouter1()
91        self.simulator.go(200)
92        self.nodes[ROUTER1].start()
93        self.simulator.go(15)
94        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
95
96        self.nodes[ROUTER1].reset()
97        self._setUpRouter1()
98        self.simulator.go(300)
99        self.nodes[ROUTER1].start()
100        self.simulator.go(15)
101        self.assertEqual(self.nodes[ROUTER1].get_state(), 'router')
102
103    def verify(self, pv):
104        pkts = pv.pkts
105        pv.summary.show()
106
107        LEADER = pv.vars['LEADER']
108        ROUTER = pv.vars['ROUTER']
109        MM = pv.vars['MM_PORT']
110
111        # Step 1: Verify topology is formed correctly.
112
113        pv.verify_attached('ROUTER')
114        _pkt_as = pkts.filter_wpan_src64(LEADER).\
115            filter_coap_ack(ADDR_SOL_URI, port=MM).\
116            filter(lambda p: {
117                              NL_STATUS_TLV,
118                              NL_RLOC16_TLV,
119                              NL_ROUTER_MASK_TLV
120                              } <= set(p.coap.tlv.type) and\
121                   p.coap.code == COAP_CODE_ACK and\
122                   p.thread_address.tlv.status == 0
123                   ).\
124            must_next()
125
126        # Step 3: Router automatically sends a link request, reattaches and
127        #         requests its original Router ID after reset within the
128        #         ID_REUSE_DELAY interval
129
130        pkts.filter_wpan_src64(ROUTER).\
131            filter_LLARMA().\
132            filter_mle_cmd(MLE_LINK_REQUEST).\
133            filter(lambda p: {
134                              CHALLENGE_TLV,
135                              VERSION_TLV,
136                              TLV_REQUEST_TLV,
137                              ADDRESS16_TLV,
138                              ROUTE64_TLV
139                              } <= set(p.mle.tlv.type)\
140                   ).\
141            must_next()
142
143        # Step 4: Leader MUST send a properly formatted Parent Response and
144        #         Child ID Response to Router.
145        #         And send Address Solicit Response Message to Router.
146        #         The RLOC16 TLV in the Address Solicit Response message MUST
147        #         contain a different Router ID then the one allocated in the
148        #         original attach because ID_REUSE_DELAY interval has not
149        #         timed out.
150        #
151        #         CoAP Response Code
152        #             - 2.04 Changed
153        #         CoAP Payload
154        #             - Status TLV (value = Success)
155        #             - RLOC16 TLV
156        #             - Router Mask TLV
157
158        pkts.filter_wpan_src64(LEADER).\
159            filter_wpan_dst64(ROUTER).\
160            filter_mle_cmd(MLE_PARENT_RESPONSE).\
161            filter(lambda p: {
162                              CHALLENGE_TLV,
163                              CONNECTIVITY_TLV,
164                              LEADER_DATA_TLV,
165                              LINK_LAYER_FRAME_COUNTER_TLV,
166                              LINK_MARGIN_TLV,
167                              RESPONSE_TLV,
168                              SOURCE_ADDRESS_TLV,
169                              VERSION_TLV
170                             } <= set(p.mle.tlv.type)
171                   ).\
172            must_next()
173
174        pkts.filter_wpan_src64(LEADER).\
175            filter_wpan_dst64(ROUTER).\
176            filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
177            filter(lambda p: {
178                              ADDRESS16_TLV,
179                              LEADER_DATA_TLV,
180                              NETWORK_DATA_TLV,
181                              SOURCE_ADDRESS_TLV,
182                              ROUTE64_TLV
183                              } <= set(p.mle.tlv.type) or\
184                             {
185                              ADDRESS16_TLV,
186                              LEADER_DATA_TLV,
187                              NETWORK_DATA_TLV,
188                              SOURCE_ADDRESS_TLV
189                             } <= set(p.mle.tlv.type)\
190                   ).\
191            must_next()
192
193        _pkt_as2 = pkts.filter_wpan_src64(ROUTER).\
194            filter_coap_request(ADDR_SOL_URI, port=MM).\
195            filter(lambda p: {
196                              NL_MAC_EXTENDED_ADDRESS_TLV,
197                              NL_RLOC16_TLV,
198                              NL_STATUS_TLV
199                              } <= set(p.coap.tlv.type) and\
200                   p.coap.code == COAP_CODE_POST and\
201                   p.thread_address.tlv.rloc16 ==
202                   _pkt_as.thread_address.tlv.rloc16
203                   ).\
204            must_next()
205
206        _pkt_as3 = pkts.filter_wpan_src64(LEADER).\
207            filter_coap_ack(ADDR_SOL_URI, port=MM).\
208            filter(lambda p: {
209                              NL_STATUS_TLV,
210                              NL_RLOC16_TLV,
211                              NL_ROUTER_MASK_TLV
212                              } <= set(p.coap.tlv.type) and\
213                   p.coap.code == COAP_CODE_ACK and\
214                   p.thread_address.tlv.rloc16 !=
215                   _pkt_as2.thread_address.tlv.rloc16 and\
216                   p.thread_address.tlv.status == 0
217                   ).\
218            must_next()
219
220        # Step 6: Router automatically sends a link request, reattaches and
221        #         requests its most recent Router ID after reset after the
222        #         ID_REUSE_DELAY interval
223
224        pkts.filter_wpan_src64(ROUTER).\
225            filter_LLARMA().\
226            filter_mle_cmd(MLE_LINK_REQUEST).\
227            filter(lambda p: {
228                              CHALLENGE_TLV,
229                              VERSION_TLV,
230                              TLV_REQUEST_TLV,
231                              ADDRESS16_TLV,
232                              ROUTE64_TLV
233                              } <= set(p.mle.tlv.type)\
234                   ).\
235            must_next()
236
237        # Step 7: Leader MUST send a properly formatted Parent Response and
238        #         Child ID Response to Router.
239        #         And send Address Solicit Response Message to Router.
240        #         The RLOC16 TLV in the Address Solicit Response message MUST
241        #         contain the requested Router ID
242        #
243        #         CoAP Response Code
244        #             - 2.04 Changed
245        #         CoAP Payload
246        #             - Status TLV (value = Success)
247        #             - RLOC16 TLV
248        #             - Router Mask TLV
249
250        pkts.filter_wpan_src64(LEADER).\
251            filter_wpan_dst64(ROUTER).\
252            filter_mle_cmd(MLE_PARENT_RESPONSE).\
253            filter(lambda p: {
254                              CHALLENGE_TLV,
255                              CONNECTIVITY_TLV,
256                              LEADER_DATA_TLV,
257                              LINK_LAYER_FRAME_COUNTER_TLV,
258                              LINK_MARGIN_TLV,
259                              RESPONSE_TLV,
260                              SOURCE_ADDRESS_TLV,
261                              VERSION_TLV
262                             } <= set(p.mle.tlv.type)
263                   ).\
264            must_next()
265
266        pkts.filter_wpan_src64(LEADER).\
267            filter_wpan_dst64(ROUTER).\
268            filter_mle_cmd(MLE_CHILD_ID_RESPONSE).\
269            filter(lambda p: {
270                              ADDRESS16_TLV,
271                              LEADER_DATA_TLV,
272                              NETWORK_DATA_TLV,
273                              SOURCE_ADDRESS_TLV,
274                              ROUTE64_TLV
275                              } <= set(p.mle.tlv.type) or\
276                             {
277                              ADDRESS16_TLV,
278                              LEADER_DATA_TLV,
279                              NETWORK_DATA_TLV,
280                              SOURCE_ADDRESS_TLV
281                             } <= set(p.mle.tlv.type)\
282                   ).\
283            must_next()
284
285        pkts.filter_wpan_src64(ROUTER).\
286            filter_coap_request(ADDR_SOL_URI, port=MM).\
287            filter(lambda p: {
288                              NL_MAC_EXTENDED_ADDRESS_TLV,
289                              NL_RLOC16_TLV,
290                              NL_STATUS_TLV
291                              } <= set(p.coap.tlv.type) and\
292                   p.coap.code == COAP_CODE_POST and\
293                   p.thread_address.tlv.rloc16 ==
294                   _pkt_as3.thread_address.tlv.rloc16
295                   ).\
296            must_next()
297
298        pkts.filter_wpan_src64(LEADER).\
299            filter_coap_ack(ADDR_SOL_URI, port=MM).\
300            filter(lambda p: {
301                              NL_STATUS_TLV,
302                              NL_RLOC16_TLV,
303                              NL_ROUTER_MASK_TLV
304                              } <= set(p.coap.tlv.type) and\
305                   p.coap.code == COAP_CODE_ACK and\
306                   p.thread_address.tlv.rloc16 ==
307                   _pkt_as3.thread_address.tlv.rloc16 and\
308                   p.thread_address.tlv.status == 0
309                   ).\
310            must_next()
311
312
313if __name__ == '__main__':
314    unittest.main()
315