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 mesh_cop
35import thread_cert
36from pktverify.consts import MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE, MLE_DATA_REQUEST, MGMT_COMMISSIONER_SET_URI, MGMT_ACTIVE_SET_URI, MGMT_PENDING_SET_URI, TLV_REQUEST_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, PENDING_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, PENDING_OPERATION_DATASET_TLV, NM_COMMISSIONER_SESSION_ID_TLV, NM_BORDER_AGENT_LOCATOR_TLV, NM_ACTIVE_TIMESTAMP_TLV, NM_NETWORK_NAME_TLV, NM_NETWORK_KEY_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV, NM_DELAY_TIMER_TLV, NM_STEERING_DATA_TLV, NWD_COMMISSIONING_DATA_TLV, LEADER_ALOC
37from pktverify.packet_verifier import PacketVerifier
38from pktverify.layer_fields import nullField
39
40CHANNEL_INIT = 19
41PANID_INIT = 0xface
42TIMESTAMP_INIT = 10
43CHANNEL_SECOND = 21
44
45COMM_ACTIVE_TIMESTAMP = 15
46COMM_ACTIVE_NET_NAME = 'Thread'
47COMM_ACTIVE_PSKC = '10b95765596ab9d0b86cebdd0fa24da3'
48
49COMM_PENDING_TIMESTAMP = 30
50COMM_PENDING_ACTIVE_TIMESTAMP = 75
51COMM_DELAY_TIMER = 60000
52
53COMMISSIONER = 1
54LEADER = 2
55ROUTER = 3
56MED = 4
57SED = 5
58
59# Test Purpose and Description:
60# -----------------------------
61# DUT as Leader:
62# The purpose of this test case is to verify that the Leader device properly
63# collects and disseminates Operational Datasets through a Thread network.
64# DUT as Router:
65# The purpose of this test case is to show that the Router device correctly
66# sets the Commissioning information propagated by the Leader device and sends
67# it properly to devices already attached to it.
68# DUT as MED/SED:
69# MED - requires full network data
70# SED - requires only stable network data
71# Set on Leader: Active TimeStamp = 10s
72#
73# Test Topology:
74# -------------
75#  Commissioner
76#       |
77#     Leader
78#       |
79#     Router
80#      /  \
81#   MED   SED
82#
83# DUT Types:
84# ----------
85#  Leader
86#  Router
87#  MED
88#  SED
89
90
91class Cert_9_2_06_DatasetDissemination(thread_cert.TestCase):
92    SUPPORT_NCP = False
93
94    TOPOLOGY = {
95        COMMISSIONER: {
96            'name': 'COMMISSIONER',
97            'active_dataset': {
98                'timestamp': TIMESTAMP_INIT,
99                'panid': PANID_INIT,
100                'channel': CHANNEL_INIT
101            },
102            'mode': 'rdn',
103            'allowlist': [LEADER]
104        },
105        LEADER: {
106            'name': 'LEADER',
107            'active_dataset': {
108                'timestamp': TIMESTAMP_INIT,
109                'panid': PANID_INIT,
110                'channel': CHANNEL_INIT
111            },
112            'mode': 'rdn',
113            'allowlist': [COMMISSIONER, ROUTER]
114        },
115        ROUTER: {
116            'name': 'ROUTER',
117            'active_dataset': {
118                'timestamp': TIMESTAMP_INIT,
119                'panid': PANID_INIT,
120                'channel': CHANNEL_INIT
121            },
122            'mode': 'rdn',
123            'allowlist': [LEADER, MED, SED]
124        },
125        MED: {
126            'name': 'MED',
127            'channel': CHANNEL_INIT,
128            'is_mtd': True,
129            'mode': 'rn',
130            'panid': PANID_INIT,
131            'allowlist': [ROUTER]
132        },
133        SED: {
134            'name': 'SED',
135            'channel': CHANNEL_INIT,
136            'is_mtd': True,
137            'mode': '-',
138            'panid': PANID_INIT,
139            'timeout': config.DEFAULT_CHILD_TIMEOUT,
140            'allowlist': [ROUTER]
141        },
142    }
143
144    def test(self):
145        self.nodes[LEADER].start()
146        self.simulator.go(config.LEADER_STARTUP_DELAY)
147        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
148
149        self.nodes[COMMISSIONER].start()
150        self.simulator.go(config.ROUTER_STARTUP_DELAY)
151        self.assertEqual(self.nodes[COMMISSIONER].get_state(), 'router')
152        self.simulator.get_messages_sent_by(LEADER)
153        self.nodes[COMMISSIONER].commissioner_start()
154        self.simulator.go(3)
155
156        leader_messages = self.simulator.get_messages_sent_by(LEADER)
157        msg = leader_messages.next_coap_message('2.04', assert_enabled=True)
158        self.nodes[ROUTER].start()
159        self.simulator.go(config.ROUTER_STARTUP_DELAY)
160        self.assertEqual(self.nodes[ROUTER].get_state(), 'router')
161
162        self.nodes[MED].start()
163        self.simulator.go(5)
164        self.assertEqual(self.nodes[MED].get_state(), 'child')
165
166        self.nodes[SED].start()
167        self.simulator.go(5)
168        self.assertEqual(self.nodes[SED].get_state(), 'child')
169
170        commissioner_session_id_tlv = command.get_sub_tlv(msg.coap.payload, mesh_cop.CommissionerSessionId)
171        steering_data_tlv = mesh_cop.SteeringData(bytes([0xff]))
172        # Step 2
173        self.nodes[COMMISSIONER].commissioner_mgmtset_with_tlvs([steering_data_tlv, commissioner_session_id_tlv])
174        self.simulator.go(10)
175
176        # Step 7
177        self.nodes[COMMISSIONER].send_mgmt_active_set(
178            active_timestamp=COMM_ACTIVE_TIMESTAMP,
179            network_name=COMM_ACTIVE_NET_NAME,
180            binary='0410' + COMM_ACTIVE_PSKC,
181        )
182        self.simulator.go(10)
183
184        # Step 18
185        self.nodes[COMMISSIONER].send_mgmt_pending_set(
186            pending_timestamp=COMM_PENDING_TIMESTAMP,
187            active_timestamp=COMM_PENDING_ACTIVE_TIMESTAMP,
188            delay_timer=COMM_DELAY_TIMER,
189            channel=CHANNEL_SECOND,
190        )
191        self.simulator.go(120)
192
193        self.collect_rlocs()
194        ed_rloc = self.nodes[MED].get_rloc()
195        sed_rloc = self.nodes[SED].get_rloc()
196        leader_rloc = self.nodes[LEADER].get_rloc()
197        router_rloc = self.nodes[ROUTER].get_rloc()
198        for rloc in (leader_rloc, router_rloc, ed_rloc, sed_rloc):
199            self.assertTrue(self.nodes[COMMISSIONER].ping(rloc))
200            self.simulator.go(10)
201
202    def verify(self, pv):
203        pkts = pv.pkts
204        pv.summary.show()
205
206        LEADER = pv.vars['LEADER']
207        COMMISSIONER = pv.vars['COMMISSIONER']
208        ROUTER = pv.vars['ROUTER']
209        MED = pv.vars['MED']
210        SED = pv.vars['SED']
211        LEADER_RLOC = pv.vars['LEADER_RLOC']
212        COMMISSIONER_RLOC = pv.vars['COMMISSIONER_RLOC']
213        ROUTER_RLOC = pv.vars['ROUTER_RLOC']
214        MED_RLOC = pv.vars['MED_RLOC']
215        SED_RLOC = pv.vars['SED_RLOC']
216
217        # Step 1: Ensure the topology is formed correctly
218        for node in ('COMMISSIONER', 'ROUTER'):
219            pv.verify_attached(node, 'LEADER')
220        for node in ('MED', 'SED'):
221            pv.verify_attached(node, 'ROUTER', 'MTD')
222        _pkt = pkts.last()
223
224        # Step 3: Leader sends MGMT_COMMISSIONER_SET.rsp to the Commissioner:
225        #         CoAP Response Code
226        #             2.04 Changed
227        #         CoAP Payload
228        #             - State TLV (value = Accept)
229        pkts.filter_coap_ack(MGMT_COMMISSIONER_SET_URI).\
230            filter_wpan_src64(LEADER).\
231            filter_ipv6_dst(COMMISSIONER_RLOC).\
232            must_next().\
233            must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
234
235        # Step 4: Leader MUST multicast MLE Data Response to the Link-Local
236        #         All Nodes multicast address (FF02::1) with the new information
237        #         including the following TLVs:
238        #             - Source Address TLV
239        #             - Leader Data TLV:
240        #                 Data Version field incremented
241        #                 Stable Version field NOT incremented
242        #             - Network Data TLV:
243        #                 - Commissioner Data TLV:
244        #                     Stable flag set to 0
245        #                     Border Agent Locator TLV
246        #                     Commissioner Session ID TLV
247        #                     Steering Data TLV
248        #             - Active Timestamp TLV
249        pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
250            filter_wpan_src64(LEADER). \
251            filter_LLANMA(). \
252            filter(lambda p: p.mle.tlv.active_tstamp == TIMESTAMP_INIT and \
253                             (p.mle.tlv.leader_data.data_version -
254                              _pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and \
255                             p.mle.tlv.leader_data.stable_data_version ==
256                             _pkt.mle.tlv.leader_data.stable_data_version and \
257                             p.thread_nwd.tlv.stable == [0] and \
258                             NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
259                             NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
260                             NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
261                             NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
262                   ). \
263            must_next()
264        idx_start = pkts.index
265
266        # Step 5: Router MUST multicast MLE Data Response to the Link-Local
267        #         All Nodes multicast address (FF02::1) with the new information
268        #         including the following TLVs:
269        #             - Source Address TLV
270        #             - Leader Data TLV:
271        #                 Data Version field incremented
272        #                 Stable Version field NOT incremented
273        #             - Network Data TLV:
274        #                 - Commissioner Data TLV:
275        #                     Stable flag set to 0
276        #                     Border Agent Locator TLV
277        #                     Commissioner Session ID TLV
278        #                     Steering Data TLV
279        #             - Active Timestamp TLV
280        pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
281            filter_wpan_src64(ROUTER). \
282            filter_LLANMA(). \
283            filter(lambda p: p.mle.tlv.active_tstamp == TIMESTAMP_INIT and \
284                             (p.mle.tlv.leader_data.data_version -
285                              _pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and \
286                             p.mle.tlv.leader_data.stable_data_version ==
287                             _pkt.mle.tlv.leader_data.stable_data_version and \
288                             p.thread_nwd.tlv.stable == [0] and \
289                             NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
290                             NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
291                             NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
292                             NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
293                   ). \
294            must_next()
295
296        # Step 8: Leader sends MGMT_ACTIVE_SET.rsp to the Commissioner:
297        #         CoAP Response Code
298        #             2.04 Changed
299        #         CoAP Payload
300        #             - State TLV (value = Accept)
301        pkts.filter_coap_ack(MGMT_ACTIVE_SET_URI). \
302            filter_wpan_src64(LEADER). \
303            filter_ipv6_dst(COMMISSIONER_RLOC). \
304            must_next(). \
305            must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
306        idx_end = pkts.index
307
308        # Step 6: Router MUST NOT send a unicast MLE Data Response or MLE Child
309        #         Update Request to SED_1
310        pkts.range(idx_start, idx_end).\
311            filter_mle_cmd(MLE_DATA_RESPONSE).\
312            filter_wpan_src64(ROUTER).\
313            filter_wpan_dst64(SED).\
314            must_not_next()
315
316        # Step 9: Leader MUST multicast MLE Data Response to the Link-Local
317        #         All Nodes multicast address (FF02::1) with the new information
318        #         including the following TLVs:
319        #             - Source Address TLV
320        #             - Leader Data TLV:
321        #                 Data Version field incremented
322        #                 Stable Version field incremented
323        #             - Network Data TLV:
324        #                 - Commissioner Data TLV:
325        #                     Stable flag set to 0
326        #                     Border Agent Locator TLV
327        #                     Commissioner Session ID TLV
328        #                     Steering Data TLV
329        #             - Active Timestamp TLV: 15s
330        _pkt9 = pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
331            filter_wpan_src64(LEADER). \
332            filter_LLANMA(). \
333            filter(lambda p: p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
334                             (p.mle.tlv.leader_data.data_version -
335                              _pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and \
336                             (p.mle.tlv.leader_data.stable_data_version -
337                              _pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and \
338                             p.thread_nwd.tlv.stable == [0] and \
339                             NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
340                             NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
341                             NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
342                             NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
343                   ). \
344            must_next()
345
346        # Step 10: Router MUST send a unicast MLE Data Request to the Leader, including the
347        #          following TLVs:
348        #              - TLV Request TLV:
349        #                 - Network Data TLV
350        #              - Active Timestamp TLV
351        pkts.filter_wpan_src64(ROUTER).\
352            filter_wpan_dst64(LEADER).\
353            filter_mle_cmd(MLE_DATA_REQUEST).\
354            filter(lambda p: {
355                              TLV_REQUEST_TLV,
356                              NETWORK_DATA_TLV,
357                              ACTIVE_TIMESTAMP_TLV
358                              } <= set(p.mle.tlv.type) and\
359                   p.thread_meshcop.tlv.type is nullField
360                   ).\
361            must_next()
362
363        # Step 11: Leader sends a MLE Data Response to Router_1 including the following TLVs:
364        #              - Source Address TLV
365        #              - Leader Data TLV
366        #                  Data version numbers should be
367        #                  the same as the ones sent in the
368        #                  multicast data response in step 9
369        #              - Network Data TLV
370        #                  - Commissioner Data TLV:
371        #                      Stable flag set to 0
372        #                      Border Agent Locator TLV
373        #                      Commissioner Session ID TLV
374        #                      Steering Data TLV
375        #              - Active Timestamp TLV: <new value>
376        #              - Active Operational Dataset TLV
377        #                  - Network Name TLV <new value>
378        #                  - Channel TLV
379        #                  - PAN ID TLV
380        #                  - PSKc TLV
381        #                  MUST NOT contain the Active Timestamp TLV
382        pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
383            filter_wpan_src64(LEADER). \
384            filter_wpan_dst64(ROUTER). \
385            filter(lambda p: {
386                                 SOURCE_ADDRESS_TLV,
387                                 LEADER_DATA_TLV,
388                                 ACTIVE_TIMESTAMP_TLV,
389                                 ACTIVE_OPERATION_DATASET_TLV
390                             } <= set(p.mle.tlv.type) and \
391                             {
392                                 NM_COMMISSIONER_SESSION_ID_TLV,
393                                 NM_BORDER_AGENT_LOCATOR_TLV,
394                                 NM_STEERING_DATA_TLV
395                             } <= set(p.thread_meshcop.tlv.type) and \
396                             p.mle.tlv.leader_data.data_version ==
397                             _pkt9.mle.tlv.leader_data.data_version and \
398                             p.mle.tlv.leader_data.stable_data_version ==
399                             _pkt9.mle.tlv.leader_data.stable_data_version and \
400                             NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
401                             NM_ACTIVE_TIMESTAMP_TLV not in p.thread_meshcop.tlv.type and \
402                             p.thread_nwd.tlv.stable == [0] and \
403                             p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
404                             p.thread_meshcop.tlv.channel == [CHANNEL_INIT] and \
405                             p.thread_meshcop.tlv.net_name == [COMM_ACTIVE_NET_NAME] and \
406                             p.thread_meshcop.tlv.pskc == COMM_ACTIVE_PSKC and \
407                             p.thread_meshcop.tlv.pan_id == [PANID_INIT]
408                   ). \
409            must_next()
410
411        # Step 12: Router MUST multicast MLE Data Response to the Link-Local
412        #          All Nodes multicast address (FF02::1) with the new information
413        #          including the following TLVs:
414        #              - Source Address TLV
415        #              - Leader Data TLV:
416        #                  Data version numbers should be
417        #                  the same as the ones sent in the
418        #                  multicast data response in step 9
419        #              - Network Data TLV:
420        #                  - Commissioner Data TLV:
421        #                      Stable flag set to 0
422        #                      Border Agent Locator TLV
423        #                      Commissioner Session ID TLV
424        #                      Steering Data TLV
425        #              - Active Timestamp TLV: 15s
426        with pkts.save_index():
427            pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
428                filter_wpan_src64(ROUTER). \
429                filter_LLANMA(). \
430                filter(lambda p: p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
431                                 p.mle.tlv.leader_data.data_version ==
432                                 _pkt9.mle.tlv.leader_data.data_version and \
433                                 p.mle.tlv.leader_data.stable_data_version ==
434                                 _pkt9.mle.tlv.leader_data.stable_data_version and \
435                                 p.thread_nwd.tlv.stable == [0] and \
436                                 NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
437                                 NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
438                                 NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
439                                 NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
440                       ). \
441                must_next()
442
443        # Step 13: MED MUST send a unicast MLE Data Request to the Router, including the
444        #          following TLVs:
445        #              - TLV Request TLV:
446        #                 - Network Data TLV
447        #              - Active Timestamp TLV
448
449        # Step 14: Router sends a MLE Data Response to MED including the following TLVs:
450        #              - Source Address TLV
451        #              - Leader Data TLV
452        #                  Data version numbers should be
453        #                  the same as the ones sent in the
454        #                  multicast data response in step 9
455        #              - Network Data TLV
456        #                  - Commissioner Data TLV:
457        #                      Stable flag set to 0
458        #                      Border Agent Locator TLV
459        #                      Commissioner Session ID TLV
460        #                      Steering Data TLV
461        #              - Active Timestamp TLV: <new value>
462        #              - Active Operational Dataset TLV
463        #                  - Network Name TLV <new value>
464        #                  - Channel TLV
465        #                  - PAN ID TLV
466        #                  MUST NOT contain the Active Timestamp TLV
467        with pkts.save_index():
468            pkts.filter_wpan_src64(MED). \
469                filter_wpan_dst64(ROUTER). \
470                filter_mle_cmd(MLE_DATA_REQUEST). \
471                filter(lambda p: {
472                                     TLV_REQUEST_TLV,
473                                     NETWORK_DATA_TLV,
474                                     ACTIVE_TIMESTAMP_TLV
475                                 } <= set(p.mle.tlv.type) and \
476                                 p.thread_meshcop.tlv.type is nullField
477                       ). \
478                must_next()
479
480            pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
481                filter_wpan_src64(ROUTER). \
482                filter_wpan_dst64(MED). \
483                filter(lambda p: {
484                                     SOURCE_ADDRESS_TLV,
485                                     LEADER_DATA_TLV,
486                                     ACTIVE_TIMESTAMP_TLV,
487                                     ACTIVE_OPERATION_DATASET_TLV
488                                 } <= set(p.mle.tlv.type) and \
489                                 {
490                                     NM_COMMISSIONER_SESSION_ID_TLV,
491                                     NM_BORDER_AGENT_LOCATOR_TLV,
492                                     NM_STEERING_DATA_TLV
493                                 } <= set(p.thread_meshcop.tlv.type) and \
494                                 p.mle.tlv.leader_data.data_version ==
495                                 _pkt9.mle.tlv.leader_data.data_version and \
496                                 p.mle.tlv.leader_data.stable_data_version ==
497                                 _pkt9.mle.tlv.leader_data.stable_data_version and \
498                                 NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
499                                 NM_ACTIVE_TIMESTAMP_TLV not in p.thread_meshcop.tlv.type and \
500                                 p.thread_nwd.tlv.stable == [0] and \
501                                 p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
502                                 p.thread_meshcop.tlv.channel == [CHANNEL_INIT] and \
503                                 p.thread_meshcop.tlv.net_name == [COMM_ACTIVE_NET_NAME] and \
504                                 p.thread_meshcop.tlv.pskc == COMM_ACTIVE_PSKC and \
505                                 p.thread_meshcop.tlv.pan_id == [PANID_INIT]
506                       ). \
507                must_next()
508
509        # Step 15: Router MUST send MLE Child Update Request or MLE Data Response
510        #          to SED, including the following TLVs:
511        #              - Source Address TLV
512        #              - Leader Data TLV:
513        #                  Data version numbers should be
514        #                  the same as the ones sent in the
515        #                  multicast data response in step 9
516        #              - Network Data TLV
517        #              - Active Timestamp TLV: 15s
518        pkts.filter_wpan_src64(ROUTER). \
519            filter_wpan_dst64(SED). \
520            filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE). \
521            filter(lambda p: p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
522                             p.mle.tlv.leader_data.data_version ==
523                             _pkt9.mle.tlv.leader_data.data_version and \
524                             p.mle.tlv.leader_data.stable_data_version ==
525                             _pkt9.mle.tlv.leader_data.stable_data_version and \
526                             NETWORK_DATA_TLV in p.mle.tlv.type and\
527                             SOURCE_ADDRESS_TLV in p.mle.tlv.type
528                   ). \
529            must_next()
530
531        # Step 16: SED MUST send a unicast MLE Data Request to the Router, including the
532        #          following TLVs:
533        #              - TLV Request TLV:
534        #                 - Network Data TLV
535        #              - Active Timestamp TLV
536        pkts.filter_wpan_src64(SED). \
537            filter_wpan_dst64(ROUTER). \
538            filter_mle_cmd(MLE_DATA_REQUEST). \
539            filter(lambda p: {
540                                 TLV_REQUEST_TLV,
541                                 NETWORK_DATA_TLV,
542                                 ACTIVE_TIMESTAMP_TLV
543                             } <= set(p.mle.tlv.type) and \
544                             p.thread_meshcop.tlv.type is nullField
545                   ). \
546            must_next()
547
548        # Step 17: Router sends a MLE Data Response to SED including the following TLVs:
549        #              - Source Address TLV
550        #              - Leader Data TLV
551        #                  Data version numbers should be
552        #                  the same as the ones sent in the
553        #                  multicast data response in step 9
554        #              - Network Data TLV
555        #              - Active Timestamp TLV: <15s>
556        #              - Active Operational Dataset TLV
557        #                  - Network Name TLV <new value>
558        #                  - Channel TLV
559        #                  - PAN ID TLV
560        #                  MUST NOT contain the Active Timestamp TLV
561        pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
562            filter_wpan_src64(ROUTER). \
563            filter_wpan_dst64(SED). \
564            filter(lambda p: {
565                                 SOURCE_ADDRESS_TLV,
566                                 LEADER_DATA_TLV,
567                                 ACTIVE_TIMESTAMP_TLV,
568                                 ACTIVE_OPERATION_DATASET_TLV
569                             } <= set(p.mle.tlv.type) and \
570                             p.mle.tlv.leader_data.data_version ==
571                             _pkt9.mle.tlv.leader_data.data_version and \
572                             p.mle.tlv.leader_data.stable_data_version ==
573                             _pkt9.mle.tlv.leader_data.stable_data_version and \
574                             NM_ACTIVE_TIMESTAMP_TLV not in p.thread_meshcop.tlv.type and \
575                             p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
576                             p.thread_meshcop.tlv.channel == [CHANNEL_INIT] and \
577                             p.thread_meshcop.tlv.net_name == [COMM_ACTIVE_NET_NAME] and \
578                             p.thread_meshcop.tlv.pskc == COMM_ACTIVE_PSKC and \
579                             p.thread_meshcop.tlv.pan_id == [PANID_INIT]
580                   ). \
581            must_next()
582
583        # Step 19: Leader sends MGMT_PENDING_SET.rsp to the Commissioner:
584        #          CoAP Response Code
585        #              2.04 Changed
586        #          CoAP Payload
587        #              - State TLV (value = Accept)
588        pkts.filter_coap_ack(MGMT_PENDING_SET_URI). \
589            filter_wpan_src64(LEADER). \
590            filter_ipv6_dst(COMMISSIONER_RLOC). \
591            must_next(). \
592            must_verify(lambda p: p.thread_meshcop.tlv.state == 1)
593
594        # Step 20: Leader MUST multicast MLE Data Response to the Link-Local
595        #          All Nodes multicast address (FF02::1) with the new information
596        #          including the following TLVs:
597        #              - Source Address TLV
598        #              - Leader Data TLV:
599        #                  Data Version field incremented
600        #                  Stable Version field incremented
601        #              - Network Data TLV:
602        #                  - Commissioner Data TLV:
603        #                      Stable flag set to 0
604        #                      Border Agent Locator TLV
605        #                      Commissioner Session ID TLV
606        #                      Steering Data TLV
607        #              - Active Timestamp TLV
608        #              - Pending Timestamp TLV
609        _pkt20 = pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
610            filter_wpan_src64(LEADER). \
611            filter_LLANMA(). \
612            filter(lambda p: {
613                                 SOURCE_ADDRESS_TLV,
614                                 LEADER_DATA_TLV,
615                                 ACTIVE_TIMESTAMP_TLV,
616                                 PENDING_TIMESTAMP_TLV
617                             } <= set(p.mle.tlv.type) and \
618                             {
619                                 NM_COMMISSIONER_SESSION_ID_TLV,
620                                 NM_BORDER_AGENT_LOCATOR_TLV,
621                                 NM_STEERING_DATA_TLV
622                             } <= set(p.thread_meshcop.tlv.type) and \
623                             (p.mle.tlv.leader_data.data_version -
624                              _pkt9.mle.tlv.leader_data.data_version) % 256 <= 127 and \
625                             (p.mle.tlv.leader_data.stable_data_version -
626                              _pkt9.mle.tlv.leader_data.stable_data_version) % 256 <= 127 and \
627                             p.thread_nwd.tlv.stable == [0] and \
628                             NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type
629                   ). \
630            must_next()
631
632        # Step 21: Router MUST send a unicast MLE Data Request to the Leader, including the
633        #          following TLVs:
634        #              - TLV Request TLV:
635        #                 - Network Data TLV
636        #              - Active Timestamp TLV
637        pkts.filter_wpan_src64(ROUTER). \
638            filter_wpan_dst64(LEADER). \
639            filter_mle_cmd(MLE_DATA_REQUEST). \
640            filter(lambda p: {
641                                 TLV_REQUEST_TLV,
642                                 NETWORK_DATA_TLV,
643                                 ACTIVE_TIMESTAMP_TLV
644                             } <= set(p.mle.tlv.type) and \
645                             p.thread_meshcop.tlv.type is nullField
646                   ). \
647            must_next()
648
649        # Step 22: Leader sends a MLE Data Response to Router including the following TLVs:
650        #              - Source Address TLV
651        #              - Leader Data TLV
652        #              - Network Data TLV
653        #                  - Commissioner Data TLV:
654        #                      Stable flag set to 0
655        #                      Border Agent Locator TLV
656        #                      Commissioner Session ID TLV
657        #                      Steering Data TLV
658        #              - Active Timestamp TLV
659        #              - Pending Timestamp TLV
660        #              - Pending Operational Dataset TLV
661
662        pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
663            filter_wpan_src64(LEADER). \
664            filter_wpan_dst64(ROUTER). \
665            filter(lambda p: {
666                                 SOURCE_ADDRESS_TLV,
667                                 LEADER_DATA_TLV,
668                                 ACTIVE_TIMESTAMP_TLV,
669                                 PENDING_TIMESTAMP_TLV,
670                                 PENDING_OPERATION_DATASET_TLV
671                             } <= set(p.mle.tlv.type) and \
672                             {
673                                 NM_COMMISSIONER_SESSION_ID_TLV,
674                                 NM_BORDER_AGENT_LOCATOR_TLV,
675                                 NM_STEERING_DATA_TLV
676                             } <= set(p.thread_meshcop.tlv.type) and \
677                             p.thread_nwd.tlv.stable == [0] and \
678                             NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
679                             p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
680                             p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and \
681                             p.thread_meshcop.tlv.delay_timer < COMM_DELAY_TIMER and \
682                             p.thread_meshcop.tlv.active_tstamp == COMM_PENDING_ACTIVE_TIMESTAMP and \
683                             p.thread_meshcop.tlv.channel == [CHANNEL_SECOND] and \
684                             p.thread_meshcop.tlv.pan_id == [PANID_INIT]
685                   ). \
686            must_next()
687
688        # Step 23: Router MUST multicast MLE Data Response to the Link-Local
689        #          All Nodes multicast address (FF02::1) with the new information
690        #          including the following TLVs:
691        #              - Source Address TLV
692        #              - Leader Data TLV:
693        #                  Data version numbers should be
694        #                  the same as the ones sent in the
695        #                  multicast data response in step 20
696        #              - Network Data TLV:
697        #                  - Commissioner Data TLV:
698        #                      Stable flag set to 0
699        #                      Border Agent Locator TLV
700        #                      Commissioner Session ID TLV
701        #                      Steering Data TLV
702        #              - Active Timestamp TLV: 15s
703        #              - Pending Timestamp TLV: 30s
704        with pkts.save_index():
705            pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
706                filter_wpan_src64(ROUTER). \
707                filter_LLANMA(). \
708                filter(lambda p: {
709                                     NM_COMMISSIONER_SESSION_ID_TLV,
710                                     NM_BORDER_AGENT_LOCATOR_TLV,
711                                     NM_STEERING_DATA_TLV
712                                 } <= set(p.thread_meshcop.tlv.type) and \
713                                 p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
714                                 p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP and \
715                                 p.mle.tlv.leader_data.data_version ==
716                                 _pkt20.mle.tlv.leader_data.data_version and \
717                                 p.mle.tlv.leader_data.stable_data_version ==
718                                 _pkt20.mle.tlv.leader_data.stable_data_version and \
719                                 p.thread_nwd.tlv.stable == [0] and \
720                                 NWD_COMMISSIONING_DATA_TLV in p.thread_nwd.tlv.type and \
721                                 NM_COMMISSIONER_SESSION_ID_TLV in p.thread_meshcop.tlv.type and \
722                                 NM_STEERING_DATA_TLV in p.thread_meshcop.tlv.type and \
723                                 NM_BORDER_AGENT_LOCATOR_TLV in p.thread_meshcop.tlv.type
724                       ). \
725                must_next()
726
727        # Step 24: MED MUST send a unicast MLE Data Request to the Router, including the
728        #          following TLVs:
729        #              - TLV Request TLV:
730        #                 - Network Data TLV
731        #              - Active Timestamp TLV
732
733        # Step 25: Router sends a MLE Data Response to MED including the following TLVs:
734        #              - Source Address TLV
735        #              - Leader Data TLV
736        #                  Data version numbers should be
737        #                  the same as the ones sent in the
738        #                  multicast data response in step 20
739        #              - Network Data TLV
740        #                  - Commissioner Data TLV:
741        #                      Stable flag set to 0
742        #                      Border Agent Locator TLV
743        #                      Commissioner Session ID TLV
744        #                      Steering Data TLV
745        #              - Active Timestamp TLV
746        #              - Pending Timestamp TLV
747        #              - Pending Operational Dataset TLV
748        #                  - Network Name TLV
749        #                  - Channel TLV
750        #                  - PAN ID TLV
751        with pkts.save_index():
752            pkts.filter_wpan_src64(MED). \
753                filter_wpan_dst64(ROUTER). \
754                filter_mle_cmd(MLE_DATA_REQUEST). \
755                filter(lambda p: {
756                                     TLV_REQUEST_TLV,
757                                     NETWORK_DATA_TLV,
758                                     ACTIVE_TIMESTAMP_TLV
759                                 } <= set(p.mle.tlv.type) and \
760                                 p.thread_meshcop.tlv.type is nullField
761                       ). \
762                must_next()
763
764            pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
765                filter_wpan_src64(ROUTER). \
766                filter_wpan_dst64(MED). \
767                filter(lambda p: {
768                                     SOURCE_ADDRESS_TLV,
769                                     LEADER_DATA_TLV,
770                                     ACTIVE_TIMESTAMP_TLV,
771                                     PENDING_TIMESTAMP_TLV,
772                                     PENDING_OPERATION_DATASET_TLV
773                                 } <= set(p.mle.tlv.type) and \
774                                 {
775                                     NM_COMMISSIONER_SESSION_ID_TLV,
776                                     NM_BORDER_AGENT_LOCATOR_TLV,
777                                     NM_STEERING_DATA_TLV
778                                 } <= set(p.thread_meshcop.tlv.type) and \
779                                 p.mle.tlv.leader_data.data_version ==
780                                 _pkt20.mle.tlv.leader_data.data_version and \
781                                 p.mle.tlv.leader_data.stable_data_version ==
782                                 _pkt20.mle.tlv.leader_data.stable_data_version and \
783                                 p.thread_nwd.tlv.stable == [0]
784                       ). \
785                must_next()
786
787        # Step 26: Router MUST send MLE Child Update Request or MLE Data Response
788        #          to SED, including the following TLVs:
789        #              - Source Address TLV
790        #              - Leader Data TLV:
791        #                  Data version numbers should be
792        #                  the same as the ones sent in the
793        #                  multicast data response in step 20
794        #              - Network Data TLV
795        #              - Active Timestamp TLV: 15s
796        #              - Pending Timestamp TLV: 30s
797        pkts.filter_wpan_src64(ROUTER). \
798            filter_wpan_dst64(SED). \
799            filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE). \
800            filter(lambda p: p.mle.tlv.active_tstamp ==
801                             COMM_ACTIVE_TIMESTAMP and \
802                             p.mle.tlv.pending_tstamp ==
803                             COMM_PENDING_TIMESTAMP and \
804                             p.mle.tlv.leader_data.data_version ==
805                             _pkt20.mle.tlv.leader_data.data_version and \
806                             p.mle.tlv.leader_data.stable_data_version ==
807                             _pkt20.mle.tlv.leader_data.stable_data_version and \
808                             NETWORK_DATA_TLV in p.mle.tlv.type
809                   ). \
810            must_next()
811
812        # Step 27: SED MUST send a unicast MLE Data Request to the Router, including the
813        #          following TLVs:
814        #              - TLV Request TLV:
815        #                 - Network Data TLV
816        #              - Active Timestamp TLV
817        pkts.filter_wpan_src64(SED). \
818            filter_wpan_dst64(ROUTER). \
819            filter_mle_cmd(MLE_DATA_REQUEST). \
820            filter(lambda p: {
821                                 TLV_REQUEST_TLV,
822                                 NETWORK_DATA_TLV,
823                                 ACTIVE_TIMESTAMP_TLV
824                             } <= set(p.mle.tlv.type) and \
825                             p.thread_meshcop.tlv.type is nullField
826                   ). \
827            must_next()
828
829        # Step 28: Router sends a MLE Data Response to SED including the following TLVs:
830        #              - Source Address TLV
831        #              - Leader Data TLV
832        #                  Data version numbers should be
833        #                  the same as the ones sent in the
834        #                  multicast data response in step 20
835        #              - Network Data TLV
836        #              - Active Timestamp TLV: 15s
837        #              - Pending Timestamp TLV: 30s
838        #              - Pending Operational Dataset TLV
839        #                  - Network Name TLV
840        #                  - Channel TLV
841        #                  - PAN ID TLV
842        pkts.filter_mle_cmd(MLE_DATA_RESPONSE). \
843            filter_wpan_src64(ROUTER). \
844            filter_wpan_dst64(SED). \
845            filter(lambda p: {
846                                 SOURCE_ADDRESS_TLV,
847                                 LEADER_DATA_TLV,
848                                 ACTIVE_TIMESTAMP_TLV,
849                                 PENDING_TIMESTAMP_TLV,
850                                 PENDING_OPERATION_DATASET_TLV
851                             } <= set(p.mle.tlv.type) and \
852                             p.mle.tlv.leader_data.data_version ==
853                             _pkt20.mle.tlv.leader_data.data_version and \
854                             p.mle.tlv.leader_data.stable_data_version ==
855                             _pkt20.mle.tlv.leader_data.stable_data_version and \
856                             p.mle.tlv.active_tstamp == COMM_ACTIVE_TIMESTAMP and \
857                             p.mle.tlv.pending_tstamp == COMM_PENDING_TIMESTAMP
858                   ). \
859            must_next()
860
861        # Step 30: The DUT MUST respond with an ICMPv6 Echo Reply
862        for DUT_RLOC in (LEADER_RLOC, ROUTER_RLOC, MED_RLOC, SED_RLOC):
863            _pkt = pkts.filter_ping_request().\
864                filter_ipv6_src_dst(COMMISSIONER_RLOC, DUT_RLOC).\
865                must_next()
866            pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
867                filter_ipv6_src_dst(DUT_RLOC, COMMISSIONER_RLOC).\
868                must_next()
869
870
871if __name__ == '__main__':
872    unittest.main()
873