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
31import copy
32
33import config
34import thread_cert
35from pktverify.consts import WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, SVR_DATA_URI, ACTIVE_TIMESTAMP_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, VERSION_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, CHALLENGE_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV
36from pktverify.packet_verifier import PacketVerifier
37from pktverify.bytes import Bytes
38from pktverify.addrs import Ipv6Addr
39from pktverify.null_field import nullField
40from pktverify.utils import is_sublist
41
42LEADER = 1
43ROUTER_1 = 2
44ROUTER_2 = 3
45MED = 4
46SED = 5
47
48MTDS = [MED, SED]
49PREFIX_1 = '2001:0db8:0001::/64'
50PREFIX_2 = '2001:0db8:0002::/64'
51
52# Test Purpose and Description:
53# -----------------------------
54# The purpose of this test case is to verify that network data is properly updated
55# when a server from the network leaves and rejoins.
56# Router_1 is configured as Border Router for prefix 2001:db8:1::/64.
57# Router_2 is configured as Border Router for prefix 2001:db8:1::/64.
58# MED is configured to require complete network data.
59# SED is configured to request only stable network data.
60#
61# Test Topology:
62# -------------
63#             SED
64#              |
65# Router_1 - Leader(DUT) - MED
66#              |
67#            Router_2
68#
69# DUT Types:
70# ----------
71# Leader
72
73
74class Cert_7_1_7_BorderRouterAsLeader(thread_cert.TestCase):
75    USE_MESSAGE_FACTORY = False
76    SUPPORT_NCP = False
77
78    TOPOLOGY = {
79        LEADER: {
80            'name': 'LEADER',
81            'mode': 'rdn',
82            'allowlist': [ROUTER_1, ROUTER_2, MED, SED]
83        },
84        ROUTER_1: {
85            'name': 'ROUTER_1',
86            'mode': 'rdn',
87            'allowlist': [LEADER]
88        },
89        ROUTER_2: {
90            'name': 'ROUTER_2',
91            'mode': 'rdn',
92            'allowlist': [LEADER]
93        },
94        MED: {
95            'name': 'MED',
96            'is_mtd': True,
97            'mode': 'rn',
98            'timeout': config.DEFAULT_CHILD_TIMEOUT,
99            'allowlist': [LEADER]
100        },
101        SED: {
102            'name': 'SED',
103            'is_mtd': True,
104            'mode': '-',
105            'timeout': config.DEFAULT_CHILD_TIMEOUT,
106            'allowlist': [LEADER]
107        },
108    }
109    # override wireshark preferences with case needed parameters
110    CASE_WIRESHARK_PREFS = copy.deepcopy(WIRESHARK_OVERRIDE_PREFS)
111    CASE_WIRESHARK_PREFS['6lowpan.context1'] = PREFIX_1
112    CASE_WIRESHARK_PREFS['6lowpan.context2'] = PREFIX_2
113
114    def test(self):
115        self.nodes[LEADER].start()
116        self.simulator.go(config.LEADER_STARTUP_DELAY)
117        self.assertEqual(self.nodes[LEADER].get_state(), 'leader')
118
119        for i in (2, 3):
120            self.nodes[i].start()
121            self.simulator.go(config.ROUTER_STARTUP_DELAY)
122            self.assertEqual(self.nodes[i].get_state(), 'router')
123
124        self.nodes[MED].start()
125        self.simulator.go(5)
126        self.assertEqual(self.nodes[MED].get_state(), 'child')
127
128        self.nodes[SED].start()
129        self.simulator.go(5)
130        self.assertEqual(self.nodes[SED].get_state(), 'child')
131
132        self.collect_rlocs()
133
134        self.nodes[ROUTER_1].add_prefix(PREFIX_1, 'paosr')
135        self.nodes[ROUTER_1].register_netdata()
136        self.simulator.go(5)
137        self.nodes[ROUTER_2].add_prefix(PREFIX_1, 'paro')
138        self.nodes[ROUTER_2].register_netdata()
139        self.simulator.go(5)
140
141        self.nodes[ROUTER_2].set_preferred_partition_id(1)
142        self.nodes[ROUTER_2].set_network_id_timeout(50)
143
144        self.nodes[ROUTER_2].remove_allowlist(self.nodes[LEADER].get_addr64())
145        self.nodes[LEADER].remove_allowlist(self.nodes[ROUTER_2].get_addr64())
146
147        # Wait for NETWORK_ID_TIMEOUT taking effect
148        # Router_2 creates a new partition
149        self.simulator.go(80)
150        self.assertEqual(self.nodes[ROUTER_2].get_state(), 'leader')
151        self.nodes[ROUTER_2].remove_domain_prefix(PREFIX_1)
152        self.nodes[ROUTER_2].add_prefix(PREFIX_2, 'paros')
153        self.nodes[ROUTER_2].register_netdata()
154
155        # Router_2 reattaches to Leader
156        self.nodes[ROUTER_2].add_allowlist(self.nodes[LEADER].get_addr64())
157        self.nodes[LEADER].add_allowlist(self.nodes[ROUTER_2].get_addr64())
158
159        # Wait for Router_2 reattachment and network data propagation
160        # ADVERTISEMENT_I_MAX + DEFAULT_CHILD_TIMEOUT + ATTACH_DELAY + Extra
161        self.simulator.go(120)
162        self.assertEqual(self.nodes[ROUTER_2].get_state(), 'router')
163        self.collect_ipaddrs()
164        self.collect_rloc16s()
165
166        # ping Leader's PREFIX_1 and PREFIX_2 addrs
167        dut_addrs = []
168        dut_addrs.append(self.nodes[LEADER].get_addr(PREFIX_1))
169        dut_addrs.append(self.nodes[LEADER].get_addr(PREFIX_2))
170        for addr in dut_addrs:
171            self.assertTrue(self.nodes[ROUTER_1].ping(addr))
172            self.simulator.go(1)
173            self.assertTrue(self.nodes[SED].ping(addr))
174            self.simulator.go(1)
175
176        self.nodes[ROUTER_2].remove_domain_prefix(PREFIX_2)
177        self.nodes[ROUTER_2].register_netdata()
178        self.simulator.go(5)
179
180    def verify(self, pv):
181        pkts = pv.pkts
182        pv.summary.show()
183
184        LEADER = pv.vars['LEADER']
185        LEADER_RLOC = pv.vars['LEADER_RLOC']
186        LEADER_RLOC16 = pv.vars['LEADER_RLOC16']
187        ROUTER_1 = pv.vars['ROUTER_1']
188        ROUTER_1_RLOC16 = pv.vars['ROUTER_1_RLOC16']
189        ROUTER_1_RLOC = pv.vars['ROUTER_1_RLOC']
190        ROUTER_2 = pv.vars['ROUTER_2']
191        ROUTER_2_RLOC16 = pv.vars['ROUTER_2_RLOC16']
192        ROUTER_2_RLOC = pv.vars['ROUTER_2_RLOC']
193        SED = pv.vars['SED']
194        MED = pv.vars['MED']
195        GUA = [{}, {}]
196        PREFIXES = [Bytes(PREFIX_1[:-5]), Bytes(PREFIX_2[:-5])]
197
198        for i in (0, 1):
199            for node in ('LEADER', 'ROUTER_1', 'SED'):
200                for addr in pv.vars['%s_IPADDRS' % node]:
201                    if addr.startswith(PREFIXES[i]):
202                        GUA[i][node] = addr
203
204        # Step 1: Ensure topology is formed correctly
205        pv.verify_attached('ROUTER_1', 'LEADER')
206        pv.verify_attached('ROUTER_2', 'LEADER')
207        pv.verify_attached('MED', 'LEADER', 'MTD')
208        pv.verify_attached('SED', 'LEADER', 'MTD')
209        _pkt = pkts.last()
210
211        # Step 2,3: Router_1 and Router_2 MUST send a CoAP Server Data
212        #           Notification frame to the Leader including the server’s
213        #           information(Prefix, Border Router):
214        #             CoAP Request URI
215        #                 coap://[<Leader address>]:MM/a/sd
216        #             CoAP Payload
217        #                 Thread Network Data TLV
218
219        # Step 4: Leader sends a CoAP ACK frame to each of Router_1 and
220        #         Router_2
221        with pkts.save_index():
222            for node in ('ROUTER_1', 'ROUTER_2'):
223                _dn_pkt = pkts.filter_wpan_src64(pv.vars['%s' %node]).\
224                    filter_wpan_dst16(LEADER_RLOC16).\
225                    filter_coap_request(SVR_DATA_URI).\
226                    filter(lambda p:
227                           [Ipv6Addr(PREFIX_1[:-3])] ==
228                           p.thread_nwd.tlv.prefix and\
229                           [pv.vars['%s_RLOC16' %node]] ==
230                           p.thread_nwd.tlv.border_router_16
231                           ).\
232                    must_next()
233                pkts.filter_wpan_src64(LEADER).\
234                    filter_ipv6_dst(pv.vars['%s_RLOC' %node]).\
235                    filter_coap_ack(SVR_DATA_URI).\
236                    filter(lambda p: p.coap.mid == _dn_pkt.coap.mid).\
237                    must_next()
238
239        # Step 5: Leader MUST multicast MLE Data Response with the new
240        #         information collected from Router_1 and Router_2,
241        #         including the following TLVs:,
242        #              - Source Address TLV
243        #              - Leader Data TLV
244        #                  - Data Version field <incremented>
245        #                  - Stable Data Version field <incremented>
246        #              - Network Data TLV
247        #                  - Stable Flag set
248        #                  - At least one Prefix TLV (Prefix 1)
249        #                      - Two Border Router sub-TLVs
250        #                          Border Router1 TLV: Stable Flag set
251        #                          Border Router2 TLV: Stable Flag not set
252        #                      - 6LoWPAN ID sub-TLV
253        #                          Stable Flag set
254        _dr_pkt = pkts.filter_wpan_src64(LEADER).\
255            filter_LLANMA().\
256            filter_mle_cmd(MLE_DATA_RESPONSE).\
257            filter(lambda p: {
258                              NETWORK_DATA_TLV,
259                              SOURCE_ADDRESS_TLV,
260                              LEADER_DATA_TLV
261                             } <= set(p.mle.tlv.type) and\
262                   [Ipv6Addr(PREFIX_1[:-3])] ==
263                   p.thread_nwd.tlv.prefix and\
264                   p.mle.tlv.leader_data.data_version ==
265                   (_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
266                   p.mle.tlv.leader_data.stable_data_version ==
267                   (_pkt.mle.tlv.leader_data.stable_data_version + 1) % 256
268                   ).\
269            must_next()
270        with pkts.save_index():
271            _dr_pkt1 = pkts.filter_wpan_src64(LEADER).\
272                filter_LLANMA().\
273                filter_mle_cmd(MLE_DATA_RESPONSE).\
274                filter(lambda p: {
275                                  NETWORK_DATA_TLV,
276                                  SOURCE_ADDRESS_TLV,
277                                  LEADER_DATA_TLV
278                                 } <= set(p.mle.tlv.type) and\
279                                 {
280                                  NWD_BORDER_ROUTER_TLV,
281                                  NWD_6LOWPAN_ID_TLV
282                                 } <= set(p.thread_nwd.tlv.type) and\
283                       p.mle.tlv.leader_data.data_version ==
284                       (_dr_pkt.mle.tlv.leader_data.data_version + 1) % 256 and\
285                       p.mle.tlv.leader_data.stable_data_version ==
286                       _dr_pkt.mle.tlv.leader_data.stable_data_version and\
287                       is_sublist([ROUTER_1_RLOC16, ROUTER_2_RLOC16],
288                               p.thread_nwd.tlv.border_router_16) and\
289                       is_sublist([0, 1, 1, 1, 0], p.thread_nwd.tlv.stable) and\
290                       is_sublist([1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
291                       is_sublist([Ipv6Addr(PREFIX_1[:-3])], p.thread_nwd.tlv.prefix)
292                       ).\
293                must_next()
294
295        # Step 6: Leader MUST send a MLE Child Update Request or MLE Data
296        #         Response to SED, including the following TLVs:
297        #             - Network Data TLV
298        #                 At least one Prefix TLV (Prefix 1) including:
299        #                     - Stable Flag set
300        #                     - Border Router sub-TLV(corresponding to Router_1)
301        #                         - P_border_router_16<0xFFFE>
302        #                         - Stable Flag set
303        #                     - 6LoWPAN ID sub-TLV
304        #                         - Stable Flag set
305        #             - Source Address TLV
306        #             - Leader Data TLV
307        #             - Active Timestamp TLV
308        pkts.filter_wpan_src64(LEADER).\
309            filter_wpan_dst64(SED).\
310            filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
311            filter(lambda p: {
312                              NETWORK_DATA_TLV,
313                              SOURCE_ADDRESS_TLV,
314                              LEADER_DATA_TLV,
315                              ACTIVE_TIMESTAMP_TLV
316                             } == set(p.mle.tlv.type) and\
317                   is_sublist([Ipv6Addr(PREFIX_1[:-3])], p.thread_nwd.tlv.prefix) and\
318                   is_sublist([1, 1, 1], p.thread_nwd.tlv.stable) and\
319                   is_sublist([1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
320                   is_sublist([0xFFFE], p.thread_nwd.tlv.border_router_16)
321                   ).\
322            must_next()
323
324        # Step 10: Router_2 automatically reattaches to the Leader and sends
325        #          a CoAP Server Data Notification message with the server’s
326        #          information (Prefix, Border Router) to the Leader:
327        #              CoAP Request URI
328        #                  coap://[<leader address>]:MM/a/sd
329        #              CoAP Payload
330        #                  Thread Network Data TLV
331
332        # Step 11: Leader sends a CoAP ACK frame to each of Routers
333        pv.verify_attached('ROUTER_2', 'LEADER')
334        with pkts.save_index():
335            _dn_pkt = pkts.filter_wpan_src64(ROUTER_2).\
336                  filter_wpan_dst16(LEADER_RLOC16).\
337                  filter_coap_request(SVR_DATA_URI).\
338                  filter(lambda p:
339                         [Ipv6Addr(PREFIX_2[:-3])] ==
340                         p.thread_nwd.tlv.prefix and\
341                         [ROUTER_2_RLOC16] ==
342                         p.thread_nwd.tlv.border_router_16
343                         ).\
344                  must_next()
345
346            pkts.filter_wpan_src64(LEADER).\
347                filter_ipv6_dst(ROUTER_2_RLOC).\
348                filter_coap_ack(SVR_DATA_URI).\
349                filter(lambda p: p.coap.mid == _dn_pkt.coap.mid).\
350                must_next()
351
352        # Step 12: Leader MUST multicast MLE Data Response with the new
353        #          information collected from Router_2,
354        #          including the following TLVs:,
355        #              - Source Address TLV
356        #              - Leader Data TLV
357        #                  - Data Version field <incremented>
358        #                  - Stable Data Version field <incremented>
359        #              - Network Data TLV
360        #                  - Stable Flag set
361        #                  - At least two Prefix TLVs (Prefix 1 and Prefix 2)
362        #                      - Prefix 1 TLV
363        #                          - Stable Flag set
364        #                          - Only one Border Router sub-TLV
365        #                            corresponding to Router_1
366        #                          - 6LoWPAN ID sub-TLV
367        #                                - Stable Flag set
368        #                      - Prefix 2 TLV
369        #                          - Stable Flag set
370        #                          - Only one Border Router sub-TLV
371        #                            corresponding to Router_2
372        #                          - 6LoWPAN ID sub-TLV
373        _dr_pkt2 = pkts.filter_wpan_src64(LEADER).\
374            filter_LLANMA().\
375            filter_mle_cmd(MLE_DATA_RESPONSE).\
376            filter(lambda p: {
377                              NETWORK_DATA_TLV,
378                              SOURCE_ADDRESS_TLV,
379                              LEADER_DATA_TLV
380                             } <= set(p.mle.tlv.type) and\
381                             {
382                              NWD_BORDER_ROUTER_TLV,
383                              NWD_6LOWPAN_ID_TLV
384                             } <= set(p.thread_nwd.tlv.type) and\
385                   is_sublist([ROUTER_1_RLOC16, ROUTER_2_RLOC16],
386                           p.thread_nwd.tlv.border_router_16) and\
387                   is_sublist([0, 1, 1, 1, 1, 1, 1],
388                           p.thread_nwd.tlv.stable) and\
389                   is_sublist([1, 1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
390                   is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
391                           p.thread_nwd.tlv.prefix) and\
392                   p.mle.tlv.leader_data.data_version ==
393                   (_dr_pkt1.mle.tlv.leader_data.data_version + 1) % 256 and\
394                   p.mle.tlv.leader_data.stable_data_version ==
395                   (_dr_pkt1.mle.tlv.leader_data.stable_data_version + 1) % 256
396                   ).\
397            must_next()
398
399        # Step 13: Leader MUST send a MLE Child Update Request or MLE Data
400        #          Response to SED, containing the stable Network Data
401        #          including the following TLVs:
402        #              - Source Address TLV
403        #              - Leader Data TLV
404        #              - Network Data TLV
405        #                  - At least two Prefix TLVs (Prefix 1 and Prefix 2)
406        #                      - Prefix 1 TLV
407        #                          - Stable Flag set
408        #                          - Border Router sub-TLV
409        #                            corresponding to Router_1
410        #                                - P_border_router_16 <0xFFFE>
411        #                                - Stable flag set
412        #                          - 6LoWPAN ID sub-TLV
413        #                                - Stable flag set
414        #                      - Prefix 2 TLV
415        #                          - Stable Flag set
416        #                          - Border Router sub-TLV
417        #                            corresponding to Router_2
418        #                                - P_border_router_16 <0xFFFE>
419        #                                - Stable flag set
420        #                          - 6LoWPAN ID sub-TLV
421        #                                - Stable flag set
422        #              - Active Timestamp TLV
423        with pkts.save_index():
424            pkts.filter_wpan_src64(LEADER).\
425                filter_wpan_dst64(SED).\
426                filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
427                filter(lambda p: {
428                                  NETWORK_DATA_TLV,
429                                  SOURCE_ADDRESS_TLV,
430                                  LEADER_DATA_TLV,
431                                  ACTIVE_TIMESTAMP_TLV
432                                 } == set(p.mle.tlv.type) and\
433                       is_sublist([1, 1, 1, 1, 1, 1],
434                               p.thread_nwd.tlv.stable) and\
435                       is_sublist([1, 1], getattr(p.thread_nwd.tlv, '6co').flag.c) and\
436                       is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
437                               p.thread_nwd.tlv.prefix) and\
438                       is_sublist([0xFFFE, 0xFFFE], p.thread_nwd.tlv.border_router_16)
439                       ).\
440                must_next()
441
442        # Step 14: Verifies connectivity by sending ICMPv6 Echo Requests from
443        #          Router_1 and SED_1 to the Leader Prefix_1 and Prefix_2-based
444        #          address.
445        #          Leader must respond with ICMPv6 Echo Replies
446        for i in (0, 1):
447            for node in ('ROUTER_1', 'SED'):
448                _pkt = pkts.filter_ping_request().\
449                    filter_ipv6_src_dst(GUA[i][node], GUA[i]['LEADER']).\
450                    must_next()
451                pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\
452                    filter_ipv6_src_dst(GUA[i]['LEADER'], GUA[i][node]).\
453                    must_next()
454
455        # Step 15: Router_2 sends a CoAP Server Data Notification message with
456        #          the server’s information (Prefix, Border Router) to the Leader:
457        #              CoAP Request URI
458        #                  coap://[<leader address>]:MM/a/sd
459        #              CoAP Payload
460        #                  empty payload
461
462        # Step 16: Leader sends a CoAP ACK frame to each of Router_1 and
463        #          Router_2
464        with pkts.save_index():
465            _dn_pkt = pkts.filter_wpan_src64(ROUTER_2).\
466                filter_wpan_dst16(LEADER_RLOC16).\
467                filter_coap_request(SVR_DATA_URI).\
468                filter(lambda p:
469                       p.thread_nwd.tlv.border_router_16 is nullField
470                       ).\
471                must_next()
472
473            pkts.filter_wpan_src64(LEADER).\
474                filter_ipv6_dst(ROUTER_2_RLOC).\
475                filter_coap_ack(SVR_DATA_URI).\
476                filter(lambda p: p.coap.mid == _dn_pkt.coap.mid).\
477                must_next()
478
479        # Step 17: Leader MUST multicast MLE Data Response with the new
480        #          information collected from Router_2,
481        #          including the following TLVs:,
482        #              - Source Address TLV
483        #              - Leader Data TLV
484        #                  - Data Version field <incremented>
485        #                  - Stable Data Version field <incremented>
486        #              - Network Data TLV
487        #                  - Stable Flag set
488        #                  - At least two Prefix TLVs (Prefix 1 and Prefix 2)
489        #                      - Prefix 1 TLV
490        #                          - Stable Flag set
491        #                          - Only one Border Router sub-TLV
492        #                            corresponding to Router_1
493        #                          - 6LoWPAN ID sub-TLV
494        #                                - Stable Flag set
495        #                      - Prefix 2 TLV
496        #                          - Stable Flag set
497        #                          - 6LoWPAN ID sub-TLV
498        #                                - Stable Flag set
499        #                                - compression flag set to 0
500        _pkt = pkts.filter_wpan_src64(LEADER).\
501            filter_LLANMA().\
502            filter_mle_cmd(MLE_DATA_RESPONSE).\
503            filter(lambda p: {
504                              NETWORK_DATA_TLV,
505                              SOURCE_ADDRESS_TLV,
506                              LEADER_DATA_TLV
507                             } <= set(p.mle.tlv.type) and\
508                             {
509                              NWD_BORDER_ROUTER_TLV,
510                              NWD_6LOWPAN_ID_TLV
511                             } <= set(p.thread_nwd.tlv.type) and\
512                   p.mle.tlv.leader_data.data_version ==
513                   (_dr_pkt2.mle.tlv.leader_data.data_version + 1) % 256 and\
514                   p.mle.tlv.leader_data.stable_data_version ==
515                   (_dr_pkt2.mle.tlv.leader_data.stable_data_version + 1) % 256 and\
516                   is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
517                           p.thread_nwd.tlv.prefix) and\
518                   is_sublist([1,0], getattr(p.thread_nwd.tlv, '6co').flag.c)
519                   ).\
520            must_next()
521
522        # Step 18: Leader MUST send a MLE Child Update Request or MLE Data
523        #          Response to SED, containing the stable Network Data
524        #          including the following TLVs:
525        #              - Source Address TLV
526        #              - Leader Data TLV
527        #              - Network Data TLV
528        #                  - At least two Prefix TLVs (Prefix 1 and Prefix 2)
529        #                      - Prefix 1 TLV
530        #                          - Stable Flag set
531        #                          - Border Router sub-TLV
532        #                            corresponding to Router_1
533        #                                - P_border_router_16 <0xFFFE>
534        #                                - Stable flag set
535        #                          - 6LoWPAN ID sub-TLV
536        #                                - Stable flag set
537        #                      - Prefix 2 TLV
538        #                          - Stable Flag set
539        #                          - 6LoWPAN ID sub-TLV
540        #                                - Stable flag set
541        #                                - compression flag set to 0
542        #              - Active Timestamp TLV
543        pkts.filter_wpan_src64(LEADER).\
544            filter_wpan_dst64(SED).\
545            filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\
546            filter(lambda p: {
547                              NETWORK_DATA_TLV,
548                              SOURCE_ADDRESS_TLV,
549                              LEADER_DATA_TLV,
550                              ACTIVE_TIMESTAMP_TLV
551                             } == set(p.mle.tlv.type) and\
552                   is_sublist([Ipv6Addr(PREFIX_1[:-3]), Ipv6Addr(PREFIX_2[:-3])],
553                           p.thread_nwd.tlv.prefix) and\
554                   is_sublist([1, 1, 1, 1, 1], p.thread_nwd.tlv.stable) and\
555                   is_sublist([0xFFFE], p.thread_nwd.tlv.border_router_16) and\
556                   is_sublist([1,0], getattr(p.thread_nwd.tlv, '6co').flag.c)
557                   ).\
558            must_next()
559
560
561if __name__ == '__main__':
562    unittest.main()
563