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 31import copy 32 33import config 34import thread_cert 35from pktverify.packet_verifier import PacketVerifier 36 37LEADER = 1 38ROUTER = 2 39MTD = 3 40FRAGMENTED_DATA_LEN = 256 41 42# Test Purpose and Description: 43# ----------------------------- 44# The purpose of this test case is to validate the Realm-Local addresses 45# that the DUT configures. 46# 47# Test Topology: 48# ------------- 49# Leader 50# | 51# Router 52# | 53# DUT 54# 55# DUT Types: 56# ---------- 57# ED 58# SED 59 60 61class Cert_6_4_2_RealmLocal_Base(thread_cert.TestCase): 62 TOPOLOGY = { 63 LEADER: { 64 'name': 'LEADER', 65 'mode': 'rdn', 66 'allowlist': [ROUTER] 67 }, 68 ROUTER: { 69 'name': 'ROUTER', 70 'mode': 'rdn', 71 'allowlist': [LEADER, MTD] 72 }, 73 MTD: { 74 'name': 'DUT', 75 'is_mtd': True, 76 'timeout': config.DEFAULT_CHILD_TIMEOUT, 77 'allowlist': [ROUTER] 78 }, 79 } 80 81 def test(self): 82 self.nodes[LEADER].start() 83 self.simulator.go(5) 84 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 85 86 self.nodes[ROUTER].start() 87 self.simulator.go(5) 88 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 89 90 self.nodes[MTD].start() 91 self.simulator.go(5) 92 self.assertEqual(self.nodes[MTD].get_state(), 'child') 93 94 self.collect_ipaddrs() 95 self.collect_rloc16s() 96 97 dut_addr = self.nodes[MTD].get_ip6_address(config.ADDRESS_TYPE.ML_EID) 98 self.assertTrue(self.nodes[LEADER].\ 99 ping(dut_addr, 100 size=FRAGMENTED_DATA_LEN)) 101 self.simulator.go(1) 102 self.assertTrue(self.nodes[LEADER].\ 103 ping(dut_addr)) 104 self.simulator.go(1) 105 106 if self.TOPOLOGY[MTD]['mode'] == 'rn': 107 self.assertTrue(self.nodes[LEADER].\ 108 ping(config.REALM_LOCAL_ALL_NODES_ADDRESS, 109 num_responses=2, 110 size=FRAGMENTED_DATA_LEN)) 111 self.simulator.go(2) 112 self.assertTrue(self.nodes[LEADER].\ 113 ping(config.REALM_LOCAL_ALL_NODES_ADDRESS, 114 num_responses=2)) 115 self.simulator.go(2) 116 117 self.assertTrue(self.nodes[LEADER].\ 118 ping(config.REALM_LOCAL_All_THREAD_NODES_MULTICAST_ADDRESS, 119 num_responses=2, 120 size=FRAGMENTED_DATA_LEN)) 121 self.simulator.go(2) 122 self.assertTrue(self.nodes[LEADER].\ 123 ping(config.REALM_LOCAL_All_THREAD_NODES_MULTICAST_ADDRESS, 124 num_responses=2)) 125 self.simulator.go(2) 126 127 def verify(self, pv): 128 pkts = pv.pkts 129 pv.summary.show() 130 131 LEADER = pv.vars['LEADER'] 132 LEADER_MLEID = pv.vars['LEADER_MLEID'] 133 ROUTER = pv.vars['ROUTER'] 134 ROUTER_MLEID = pv.vars['ROUTER_MLEID'] 135 ROUTER_RLOC16 = pv.vars['ROUTER_RLOC16'] 136 DUT = pv.vars['DUT'] 137 DUT_MLEID = pv.vars['DUT_MLEID'] 138 DUT_RLOC16 = pv.vars['DUT_RLOC16'] 139 140 # Step 1: Ensure topology is formed correctly 141 pv.verify_attached('ROUTER', 'LEADER') 142 pv.verify_attached('DUT', 'ROUTER', 'MTD') 143 144 # Step 2: Leader sends a Fragmented ICMPv6 Echo Request to 145 # DUT's ML-EID 146 # The DUT MUST respond with an ICMPv6 Echo Reply 147 148 _pkt = pkts.filter_ping_request().\ 149 filter_ipv6_src_dst(LEADER_MLEID, DUT_MLEID).\ 150 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 151 must_next() 152 pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ 153 filter_ipv6_src_dst(DUT_MLEID, LEADER_MLEID).\ 154 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 155 must_next() 156 157 # Step 3: Leader sends an Unfragmented ICMPv6 Echo Request to 158 # DUT’s ML-EID 159 # The DUT MUST respond with an ICMPv6 Echo Reply 160 161 _pkt = pkts.filter_ping_request().\ 162 filter_ipv6_src_dst(LEADER_MLEID, DUT_MLEID).\ 163 must_next() 164 pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ 165 filter_ipv6_src_dst(DUT_MLEID, LEADER_MLEID).\ 166 must_next() 167 168 if self.TOPOLOGY[MTD]['mode'] == 'rn': 169 # Step 4: Leader sends a Fragmented ICMPv6 Echo Request to the 170 # Realm-Local All Nodes multicast address (FF03::1) 171 # The DUT MUST respond with an ICMPv6 Echo Reply 172 173 _pkt1 = pkts.filter_ping_request().\ 174 filter_wpan_src64(LEADER).\ 175 filter_RLANMA().\ 176 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 177 must_next() 178 with pkts.save_index(): 179 pkts.filter_ping_reply(identifier=_pkt1.icmpv6.echo.identifier).\ 180 filter_ipv6_src_dst(ROUTER_MLEID, LEADER_MLEID).\ 181 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 182 must_next() 183 pkts.filter_ping_request(identifier=_pkt1.icmpv6.echo.identifier).\ 184 filter_wpan_src16_dst16(ROUTER_RLOC16, DUT_RLOC16).\ 185 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 186 must_not_next() 187 188 # Step 5: Leader sends an Unfragmented ICMPv6 Echo Request to the 189 # Realm-Local All Nodes multicast address (FF03::1) 190 # The DUT MUST respond with an ICMPv6 Echo Reply 191 192 _pkt2 = pkts.filter_ping_request().\ 193 filter_wpan_src64(LEADER).\ 194 filter_RLANMA().\ 195 filter(lambda p: p.icmpv6.echo.sequence_number != 196 _pkt1.icmpv6.echo.sequence_number 197 ).\ 198 must_next() 199 with pkts.save_index(): 200 pkts.filter_ping_reply(identifier=_pkt2.icmpv6.echo.identifier).\ 201 filter_ipv6_src_dst(ROUTER_MLEID, LEADER_MLEID).\ 202 must_next() 203 pkts.filter_ping_request(identifier = _pkt2.icmpv6.echo.identifier).\ 204 filter_wpan_src16_dst16(ROUTER_RLOC16, DUT_RLOC16).\ 205 must_not_next() 206 207 # Step 6: Leader sends a Fragmented ICMPv6 Echo Request to the 208 # Realm-Local All Thread Nodes multicast address 209 # The DUT MUST respond with an ICMPv6 Echo Reply 210 211 _pkt = pkts.filter_ping_request().\ 212 filter_wpan_src64(LEADER).\ 213 filter_RLATNMA().\ 214 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 215 must_next() 216 pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ 217 filter_wpan_src64(DUT).\ 218 filter_ipv6_dst(LEADER_MLEID).\ 219 filter(lambda p: p.icmpv6.data.len == FRAGMENTED_DATA_LEN).\ 220 must_next() 221 222 # Step 7: Leader sends an Unfragmented ICMPv6 Echo Request to the 223 # Realm-Local All Thread Nodes multicast address 224 # The DUT MUST respond with an ICMPv6 Echo Reply 225 226 _pkt = pkts.filter_ping_request().\ 227 filter_wpan_src64(LEADER).\ 228 filter_RLATNMA().\ 229 filter(lambda p: p.icmpv6.data.len != FRAGMENTED_DATA_LEN).\ 230 must_next() 231 pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ 232 filter_wpan_src64(DUT).\ 233 filter_ipv6_dst(LEADER_MLEID).\ 234 must_next() 235 236 237class Cert_6_4_2_RealmLocal_ED(Cert_6_4_2_RealmLocal_Base): 238 TOPOLOGY = copy.deepcopy(Cert_6_4_2_RealmLocal_Base.TOPOLOGY) 239 TOPOLOGY[MTD]['mode'] = 'rn' 240 241 242class Cert_6_4_2_RealmLocal_SED(Cert_6_4_2_RealmLocal_Base): 243 TOPOLOGY = copy.deepcopy(Cert_6_4_2_RealmLocal_Base.TOPOLOGY) 244 TOPOLOGY[MTD]['mode'] = '-' 245 246 247del (Cert_6_4_2_RealmLocal_Base) 248 249if __name__ == '__main__': 250 unittest.main() 251