1#!/usr/bin/env python3 2# 3# Copyright (c) 2016, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29 30import unittest 31 32import config 33import thread_cert 34from pktverify.consts import MLE_ADVERTISEMENT, MLE_DATA_RESPONSE, MLE_CHILD_ID_RESPONSE, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, SOURCE_ADDRESS_TLV, MODE_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ADDRESS_REGISTRATION_TLV, NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_HAS_ROUTER_TLV, LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS 35from pktverify.packet_verifier import PacketVerifier 36from pktverify.addrs import Ipv6Addr 37 38LEADER = 1 39ROUTER1 = 2 40ROUTER2 = 3 41ED = 4 42SED = 5 43 44MTDS = [ED, SED] 45 46 47class Cert_5_6_9_NetworkDataForwarding(thread_cert.TestCase): 48 TOPOLOGY = { 49 LEADER: { 50 'name': 'LEADER', 51 'mode': 'rdn', 52 'allowlist': [ROUTER1, ROUTER2] 53 }, 54 ROUTER1: { 55 'name': 'ROUTER_1', 56 'mode': 'rdn', 57 'allowlist': [LEADER, ED, SED] 58 }, 59 ROUTER2: { 60 'name': 'ROUTER_2', 61 'mode': 'rdn', 62 'allowlist': [LEADER] 63 }, 64 ED: { 65 'name': 'MED', 66 'is_mtd': True, 67 'mode': 'rn', 68 'allowlist': [ROUTER1] 69 }, 70 SED: { 71 'name': 'SED', 72 'is_mtd': True, 73 'mode': '-', 74 'timeout': config.DEFAULT_CHILD_TIMEOUT, 75 'allowlist': [ROUTER1] 76 }, 77 } 78 79 def test(self): 80 self.nodes[LEADER].start() 81 self.simulator.go(config.LEADER_STARTUP_DELAY) 82 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 83 84 self.nodes[ROUTER1].start() 85 self.simulator.go(config.ROUTER_STARTUP_DELAY) 86 self.assertEqual(self.nodes[ROUTER1].get_state(), 'router') 87 88 self.nodes[ROUTER2].start() 89 self.simulator.go(config.ROUTER_STARTUP_DELAY) 90 self.assertEqual(self.nodes[ROUTER2].get_state(), 'router') 91 92 self.nodes[ED].start() 93 self.simulator.go(5) 94 self.assertEqual(self.nodes[ED].get_state(), 'child') 95 96 self.nodes[SED].start() 97 self.simulator.go(5) 98 self.assertEqual(self.nodes[SED].get_state(), 'child') 99 100 self.collect_rloc16s() 101 self.collect_ipaddrs() 102 self.nodes[LEADER].add_prefix('2001:2:0:1::/64', 'aros', 'med') 103 self.nodes[LEADER].add_route('2001:2:0:2::/64', stable=True, prf='med') 104 self.nodes[LEADER].register_netdata() 105 106 # Set lowpan context of sniffer 107 self.simulator.set_lowpan_context(1, '2001:2:0:1::/64') 108 109 self.simulator.go(10) 110 111 self.nodes[ROUTER2].add_prefix('2001:2:0:1::/64', 'aos', 'med') 112 self.nodes[ROUTER2].add_route('2001:2:0:2::/64', stable=True, prf='high') 113 self.nodes[ROUTER2].register_netdata() 114 self.simulator.go(15) 115 116 self.assertFalse(self.nodes[SED].ping('2001:2:0:2::1', timeout=10)) 117 118 self.assertFalse(self.nodes[SED].ping('2007::1', timeout=10)) 119 120 self.nodes[ROUTER2].remove_prefix('2001:2:0:1::/64') 121 self.nodes[ROUTER2].add_prefix('2001:2:0:1::/64', 'paros', 'high') 122 self.nodes[ROUTER2].register_netdata() 123 self.simulator.go(15) 124 125 self.assertFalse(self.nodes[SED].ping('2007::1', timeout=10)) 126 127 self.nodes[ROUTER2].remove_prefix('2001:2:0:1::/64') 128 self.nodes[ROUTER2].add_prefix('2001:2:0:1::/64', 'paros', 'med') 129 self.nodes[ROUTER2].register_netdata() 130 self.simulator.go(15) 131 132 self.assertFalse(self.nodes[SED].ping('2007::1', timeout=10)) 133 134 def verify(self, pv): 135 pkts = pv.pkts 136 pv.summary.show() 137 138 ROUTER_1 = pv.vars['ROUTER_1'] 139 MED = pv.vars['MED'] 140 SED = pv.vars['SED'] 141 _rpkts = pkts.filter_wpan_src64(ROUTER_1) 142 143 # Step 1: Ensure the topology is formed correctly 144 _rpkts.filter_mle_cmd(MLE_CHILD_ID_RESPONSE).filter_wpan_dst64(SED).must_next() 145 146 # Step 4: The DUT MUST send a multicast MLE Data Response with 147 # the new network information 148 _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst(LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next( 149 ).must_verify(lambda p: {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set( 150 p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [0] and p.thread_nwd.tlv. 151 border_router.flag.s == [1] and p.thread_nwd.tlv.border_router.flag.r == [1] and p.thread_nwd.tlv 152 .border_router.flag.o == [1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 1, 1]) 153 154 # Step 5: The DUT MUST send a unicast MLE Child Update 155 # Request to SED_1 156 _rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next( 157 ).must_verify(lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set( 158 p.mle.tlv.type 159 ) and {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV} <= set( 160 p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set( 161 p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16)) 162 163 # Step 6: The DUT MUST forward the SED_1 ICMPv6 Echo Request to Router_2 164 # due to higher preference 165 router1_rloc16 = pv.vars['ROUTER_1_RLOC16'] 166 leader_rloc16 = pv.vars['LEADER_RLOC16'] 167 _rpkts.filter_ping_request().filter_ipv6_dst('2001:2:0:2::1').must_next().must_verify( 168 lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16) 169 170 # Step 7: The DUT MUST forward the MED_1 ICMPv6 Echo Request to the 171 # Leader due to default route 172 _rpkts.filter_ping_request().filter_ipv6_dst('2007::1').must_next().must_verify( 173 lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16) 174 175 # Step 9: The DUT MUST send a multicast MLE Data Response with 176 # the new network information 177 _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst( 178 LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify( 179 lambda p: { 180 NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, 181 NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV 182 } <= set(p.thread_nwd.tlv.type) and { 183 Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::') 184 } == set(p.thread_nwd.tlv.prefix) and p.thread_nwd.tlv.border_router.flag.p == [0, 1] and p.thread_nwd. 185 tlv.border_router.flag.s == [1, 1] and p.thread_nwd.tlv.border_router.flag.r == [1, 1] and p.thread_nwd 186 .tlv.border_router.flag.o == [1, 1] and p.thread_nwd.tlv.stable == [0, 1, 1, 1, 1, 1]) 187 188 # Step 10: The DUT MUST send a unicast MLE Child Update Request to SED_1 189 _rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next( 190 ).must_verify(lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set( 191 p.mle.tlv.type 192 ) and {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV} <= set( 193 p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set( 194 p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16)) 195 196 # Step 11: The DUT MUST forward the SED_1 ICMPv6 Echo Request to Router_2 197 # due to higher preference 198 _rpkts.filter_ping_request().filter_ipv6_dst('2007::1').must_next().must_verify( 199 lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16) 200 201 # Step 13: The DUT MUST send a multicast MLE Data Response with 202 # the new network information 203 _rpkts.filter_mle_cmd(MLE_DATA_RESPONSE).filter_ipv6_dst( 204 LINK_LOCAL_ALL_NODES_MULTICAST_ADDRESS).must_next().must_verify( 205 lambda p: { 206 NWD_COMMISSIONING_DATA_TLV, NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, 207 NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV 208 } <= set(p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), 209 Ipv6Addr('2001:2:0:2::')} == set(p.thread_nwd.tlv.prefix)) 210 211 # Step 14: The DUT MUST send a unicast MLE Child Update Request to SED_1 212 _rpkts.filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).filter_wpan_dst64(SED).must_next( 213 ).must_verify(lambda p: {SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, NETWORK_DATA_TLV, ACTIVE_TIMESTAMP_TLV} <= set( 214 p.mle.tlv.type 215 ) and {NWD_PREFIX_TLV, NWD_BORDER_ROUTER_TLV, NWD_6LOWPAN_ID_TLV, NWD_PREFIX_TLV, NWD_HAS_ROUTER_TLV} <= set( 216 p.thread_nwd.tlv.type) and {Ipv6Addr('2001:2:0:1::'), Ipv6Addr('2001:2:0:2::')} == set( 217 p.thread_nwd.tlv.prefix) and {0xFFFE, 0xFFFE} == set(p.thread_nwd.tlv.border_router_16)) 218 219 # Step 15: The DUT MUST forward the SED_1 ICMPv6 Echo Request to Router_2 220 # due to higher preference 221 _rpkts.filter_ping_request().filter_ipv6_dst('2007::1').must_next().must_verify( 222 lambda p: p.wpan.dst16 == leader_rloc16 and p.wpan.src16 == router1_rloc16) 223 224 225if __name__ == '__main__': 226 unittest.main() 227