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