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 WIRESHARK_OVERRIDE_PREFS, MLE_CHILD_UPDATE_REQUEST, MLE_CHILD_UPDATE_RESPONSE, MLE_DATA_RESPONSE, MLE_CHILD_ID_REQUEST, MLE_CHILD_ID_RESPONSE, SVR_DATA_URI, ACTIVE_TIMESTAMP_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, MODE_TLV, TIMEOUT_TLV, VERSION_TLV, TLV_REQUEST_TLV, ADDRESS16_TLV, NETWORK_DATA_TLV, ROUTE64_TLV, MODE_TLV, TIMEOUT_TLV, CHALLENGE_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ADDRESS_REGISTRATION_TLV 35from pktverify.packet_verifier import PacketVerifier 36from pktverify.addrs import Ipv6Addr 37 38LEADER = 1 39ROUTER = 2 40MED = 3 41SED = 4 42 43MTDS = [MED, SED] 44PREFIX_2001 = '2001::/64' 45PREFIX_2002 = '2002::/64' 46PREFIX_2003 = '2003::/64' 47 48# Test Purpose and Description: 49# ----------------------------- 50# The purpose of this test case is to verify that the DUT sends properly formatted 51# Server Data Notification CoAP frame when a third global prefix information is 52# set on the DUT. The DUT must also correctly set Network Data aggregated and 53# disseminated by the Leader and transmit it properly to all child devices already 54# attached to it. 55# 56# Test Topology: 57# ------------- 58# SED 59# | 60# Router(DUT) - MED 61# | 62# Leader 63# 64# DUT Types: 65# ---------- 66# Router 67 68 69class Cert_7_1_5_BorderRouterAsRouter(thread_cert.TestCase): 70 USE_MESSAGE_FACTORY = False 71 72 TOPOLOGY = { 73 LEADER: { 74 'name': 'LEADER', 75 'mode': 'rdn', 76 'allowlist': [ROUTER] 77 }, 78 ROUTER: { 79 'name': 'ROUTER', 80 'mode': 'rdn', 81 'allowlist': [LEADER, MED, SED] 82 }, 83 MED: { 84 'name': 'MED', 85 'is_mtd': True, 86 'mode': 'rn', 87 'allowlist': [ROUTER] 88 }, 89 SED: { 90 'name': 'SED', 91 'is_mtd': True, 92 'mode': '-', 93 'timeout': config.DEFAULT_CHILD_TIMEOUT, 94 'allowlist': [ROUTER] 95 }, 96 } 97 98 def test(self): 99 self.nodes[LEADER].start() 100 self.simulator.go(config.LEADER_STARTUP_DELAY) 101 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 102 103 self.nodes[ROUTER].start() 104 self.simulator.go(config.ROUTER_STARTUP_DELAY) 105 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 106 107 self.nodes[MED].start() 108 self.simulator.go(5) 109 self.assertEqual(self.nodes[MED].get_state(), 'child') 110 111 self.nodes[SED].start() 112 self.simulator.go(5) 113 self.assertEqual(self.nodes[SED].get_state(), 'child') 114 115 self.nodes[ROUTER].add_prefix(PREFIX_2001, 'paros') 116 self.nodes[ROUTER].add_prefix(PREFIX_2002, 'paro') 117 self.nodes[ROUTER].add_prefix(PREFIX_2003, 'paos') 118 self.nodes[ROUTER].register_netdata() 119 self.simulator.go(10) 120 121 def verify(self, pv): 122 pkts = pv.pkts 123 pv.summary.show() 124 125 LEADER = pv.vars['LEADER'] 126 ROUTER = pv.vars['ROUTER'] 127 SED = pv.vars['SED'] 128 MED = pv.vars['MED'] 129 130 # Step 1: Ensure topology is formed correctly 131 pv.verify_attached('ROUTER', 'LEADER') 132 pv.verify_attached('MED', 'ROUTER', 'MTD') 133 pv.verify_attached('SED', 'ROUTER', 'MTD') 134 135 # Step 3: The DUT MUST send a CoAP Server Data Notification frame 136 # to the Leader including the server’s information(Prefix, 137 # Border Router) for all three prefixes (Prefix 1, 2 and 3): 138 # CoAP Request URI 139 # coap://[<Leader address>]:MM/a/sd 140 # CoAP Payload 141 # Thread Network Data TLV 142 143 pkts.filter_wpan_src64(ROUTER).\ 144 filter_coap_request(SVR_DATA_URI).\ 145 filter(lambda p: { 146 Ipv6Addr(PREFIX_2001[:-3]), 147 Ipv6Addr(PREFIX_2002[:-3]), 148 Ipv6Addr(PREFIX_2003[:-3]) 149 } == set(p.thread_nwd.tlv.prefix) 150 ).\ 151 must_next() 152 _index = pkts.index 153 154 # Step 5: The DUT MUST send a multicast MLE Data Response, 155 # including at least three Prefix TLVs (Prefix 1, Prefix2, 156 # and Prefix 3). 157 with pkts.save_index(): 158 _dv_pkt = pkts.filter_wpan_src64(ROUTER).\ 159 filter_LLANMA().\ 160 filter_mle_cmd(MLE_DATA_RESPONSE).\ 161 filter(lambda p: { 162 Ipv6Addr(PREFIX_2001[:-3]), 163 Ipv6Addr(PREFIX_2002[:-3]), 164 Ipv6Addr(PREFIX_2003[:-3]) 165 } <= set(p.thread_nwd.tlv.prefix) 166 ).\ 167 must_next() 168 169 # Step 6: MED automatically sends MLE Child Update Request to its parent 170 # (DUT), reporting its configured global addresses in the Address 171 # Registration TLV 172 173 # Step 7: The DUT MUST send a MLE Child Update Response to MED 174 # The following TLVs MUST be present in the Child Update Response: 175 # - Source Address TLV 176 # - Address Registration TLV 177 # - Echoes back addresses configured in step 4 178 # - Mode TLV 179 _pkt = pkts.filter_wpan_src64(MED).\ 180 filter_wpan_dst64(ROUTER).\ 181 filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\ 182 filter(lambda p: len(p.mle.tlv.addr_reg_iid) >= 4).\ 183 must_next() 184 pkts.filter_wpan_src64(ROUTER).\ 185 filter_wpan_dst64(MED).\ 186 filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\ 187 filter(lambda p: { 188 SOURCE_ADDRESS_TLV, 189 MODE_TLV, 190 ADDRESS_REGISTRATION_TLV 191 } < set(p.mle.tlv.type) and\ 192 len(p.mle.tlv.addr_reg_iid) >= 3 and\ 193 set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid) 194 ).\ 195 must_next() 196 197 # Step 8: The DUT MUST send a MLE Child Update Request or MLE Data 198 # Response to SED, including the following TLVs: 199 # - Network Data TLV 200 # At least two Prefix TLVs (Prefix 1 and Prefix3) 201 # - Border Router TLV 202 # - P_border_router_16<0xFFFE> 203 # Prefix 2 TLV MUST NOT be included 204 # - Source Address TLV 205 # - Leader Data TLV 206 # Data version numbers should be the same as the ones 207 # sent in the multicast data response in step 5. 208 # - Active Timestamp TLV 209 pkts.range(_index).filter_wpan_src64(ROUTER).\ 210 filter_wpan_dst64(SED).\ 211 filter_mle_cmd2(MLE_CHILD_UPDATE_REQUEST, MLE_DATA_RESPONSE).\ 212 filter(lambda p: { 213 NETWORK_DATA_TLV, 214 SOURCE_ADDRESS_TLV, 215 LEADER_DATA_TLV, 216 ACTIVE_TIMESTAMP_TLV 217 } == set(p.mle.tlv.type) and\ 218 { 219 Ipv6Addr(PREFIX_2001[:-3]), 220 Ipv6Addr(PREFIX_2003[:-3]) 221 } == set(p.thread_nwd.tlv.prefix) and\ 222 p.mle.tlv.leader_data.data_version == 223 _dv_pkt.mle.tlv.leader_data.data_version and\ 224 [0xFFFE, 0xFFFE] == p.thread_nwd.tlv.border_router_16 225 ).\ 226 must_next() 227 228 # Step 9: SED automatically sends its global address configured to the Leader, 229 # in the Address Registration TLV from the Child Update request command 230 231 # Step 10: The DUT MUST send a MLE Child Update Response, each, to SED 232 # The following TLVs MUST be present in the Child Update Response: 233 # - Source Address TLV 234 # - Address Registration TLV 235 # - Echoes back addresses configured in step 9 236 # - Mode TLV 237 _pkt = pkts.filter_wpan_src64(SED).\ 238 filter_wpan_dst64(ROUTER).\ 239 filter_mle_cmd(MLE_CHILD_UPDATE_REQUEST).\ 240 filter(lambda p: len(p.mle.tlv.addr_reg_iid) >= 3).\ 241 must_next() 242 pkts.filter_wpan_src64(ROUTER).\ 243 filter_wpan_dst64(SED).\ 244 filter_mle_cmd(MLE_CHILD_UPDATE_RESPONSE).\ 245 filter(lambda p: { 246 SOURCE_ADDRESS_TLV, 247 MODE_TLV, 248 ADDRESS_REGISTRATION_TLV 249 } < set(p.mle.tlv.type) and\ 250 len(p.mle.tlv.addr_reg_iid) >= 2 and\ 251 set(p.mle.tlv.addr_reg_iid) < set(_pkt.mle.tlv.addr_reg_iid) 252 ).\ 253 must_next() 254 255 256if __name__ == '__main__': 257 unittest.main() 258