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 31 32import thread_cert 33from pktverify.consts import MLE_DATA_RESPONSE, MGMT_ACTIVE_SET_URI, NETWORK_DATA_TLV, SOURCE_ADDRESS_TLV, LEADER_DATA_TLV, ACTIVE_TIMESTAMP_TLV, ACTIVE_OPERATION_DATASET_TLV, NM_CHANNEL_TLV, NM_CHANNEL_MASK_TLV, NM_EXTENDED_PAN_ID_TLV, NM_NETWORK_MESH_LOCAL_PREFIX_TLV, NM_NETWORK_KEY_TLV, NM_NETWORK_NAME_TLV, NM_PAN_ID_TLV, NM_PSKC_TLV, NM_SECURITY_POLICY_TLV 34from pktverify.packet_verifier import PacketVerifier 35 36ROUTER = 1 37LEADER = 2 38 39# Test Purpose and Description: 40# ----------------------------- 41# The purpose of this test case is to verify the DUT’s behavior when receiving 42# MGMT_ACTIVE_SET.req from an active Thread node. 43# 44# Test Topology: 45# ------------- 46# Router 47# | 48# Leader 49# 50# DUT Types: 51# ---------- 52# Leader 53 54 55class Cert_9_2_05_ActiveDataset(thread_cert.TestCase): 56 USE_MESSAGE_FACTORY = False 57 SUPPORT_NCP = False 58 59 TOPOLOGY = { 60 ROUTER: { 61 'name': 'ROUTER', 62 'channel': 11, 63 'network_key': '00112233445566778899aabbccddeeff', 64 'mode': 'rdn', 65 'allowlist': [LEADER] 66 }, 67 LEADER: { 68 'name': 'LEADER', 69 'channel': 11, 70 'network_key': '00112233445566778899aabbccddeeff', 71 'mode': 'rdn', 72 'allowlist': [ROUTER] 73 }, 74 } 75 76 def test(self): 77 self.nodes[LEADER].start() 78 self.simulator.go(5) 79 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 80 81 self.nodes[ROUTER].start() 82 self.simulator.go(5) 83 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 84 85 self.nodes[ROUTER].commissioner_start() 86 self.simulator.go(5) 87 88 self.collect_rlocs() 89 # Step 2: new, valid Timestamp TLV 90 # all valid Active Operational Dataset parameters, 91 # with new values in the TLVs that don’t affect connectivity 92 # binary = new pskc and security policy [3600, 0b11100000] 93 self.nodes[ROUTER].send_mgmt_active_set( 94 active_timestamp=100, 95 channel_mask=0x3fff800, 96 extended_panid='000db80000000001', 97 mesh_local='fd00:0db8::', 98 network_name='TEST_1', 99 network_key='00112233445566778899aabbccddeeff', 100 panid=0xface, 101 channel=11, 102 binary='0410d2aa9cd8dff7919122d77d37ec3c1b5f0c030e10e0', 103 ) 104 self.simulator.go(5) 105 106 # Step 7: old, invalid Active Timestamp TLV 107 # all valid Active Operational Dataset parameters, with 108 # new values in the TLVs that don’t affect connectivity 109 # binary = new pskc and security policy [3600, 0b11110000] 110 self.nodes[ROUTER].send_mgmt_active_set( 111 active_timestamp=100, 112 channel_mask=0x1fff800, 113 extended_panid='000db80000000002', 114 mesh_local='fd00:0db8::', 115 network_name='TEST_2', 116 network_key='00112233445566778899aabbccddeeff', 117 panid=0xface, 118 channel=11, 119 binary='041017d672be32b0c24a2f8385f2fbaf1d970c030e10f0', 120 ) 121 self.simulator.go(5) 122 123 # Step 9: new, valid Active Timestamp TLV 124 # all of valid Commissioner Dataset parameters plus one bogus TLV, and 125 # new values in the TLVs that don’t affect connectivity 126 # binary = new pskc and security policy [3600, 0b11111000] and BogusTLV=0x400 127 self.nodes[ROUTER].send_mgmt_active_set( 128 active_timestamp=101, 129 channel_mask=0xfff800, 130 extended_panid='000db80000000003', 131 mesh_local='fd00:0db8::', 132 network_name='TEST_3', 133 network_key='00112233445566778899aabbccddeeff', 134 panid=0xface, 135 channel=11, 136 binary='041008f4e9531e8efa8e852d5f4fb951b13e0c030e10f88202aa55', 137 ) 138 self.simulator.go(5) 139 140 # Step 14: new, valid Active Timestamp TLV 141 # attempt to set Channel TLV to an unsupported channel + all of other TLVs 142 # binary = pskc and security policy step 9 143 self.nodes[ROUTER].send_mgmt_active_set( 144 active_timestamp=102, 145 channel_mask=0x1fff800, 146 extended_panid='000db80000000003', 147 mesh_local='fd00:0db8::', 148 network_name='TEST_3', 149 network_key='00112233445566778899aabbccddeeff', 150 panid=0xface, 151 channel=63, 152 binary='041008f4e9531e8efa8e852d5f4fb951b13e0c030e10f8', 153 ) 154 self.simulator.go(5) 155 156 ipaddr = self.nodes[LEADER].get_rloc() 157 self.assertTrue(self.nodes[ROUTER].ping(ipaddr)) 158 159 def verify(self, pv): 160 pkts = pv.pkts 161 pv.summary.show() 162 163 LEADER = pv.vars['LEADER'] 164 LEADER_RLOC = pv.vars['LEADER_RLOC'] 165 ROUTER = pv.vars['ROUTER'] 166 ROUTER_RLOC = pv.vars['ROUTER_RLOC'] 167 168 # Step 1: Ensure the topology is formed correctly 169 pv.verify_attached('ROUTER', 'LEADER') 170 _pkt = pkts.last() 171 172 # Step 3: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 173 # with the following format: 174 # CoAP Response Code 175 # 2.04 Changed 176 # CoAP Payload 177 # State TLV (value = Accept (01)) 178 pkts.filter_wpan_src64(LEADER).\ 179 filter_ipv6_dst(ROUTER_RLOC).\ 180 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 181 filter(lambda p: p.thread_meshcop.tlv.state == 1).\ 182 must_next() 183 184 # Step 4: Leader MUST send a multicast MLE Data Response, including 185 # the following TLVs: 186 # - Source Address TLV 187 # - Leader Data TLV 188 # Data version field [incremented] 189 # Stable Version field [incremented] 190 # - Network Data TLV 191 # - Active Timestamp TLV [new value set in Step 9] 192 _dr_pkt = pkts.filter_wpan_src64(LEADER).\ 193 filter_LLANMA().\ 194 filter_mle_cmd(MLE_DATA_RESPONSE).\ 195 filter(lambda p: { 196 NETWORK_DATA_TLV, 197 SOURCE_ADDRESS_TLV, 198 LEADER_DATA_TLV, 199 ACTIVE_TIMESTAMP_TLV 200 } <= set(p.mle.tlv.type) and\ 201 p.mle.tlv.active_tstamp == 100 and\ 202 (p.mle.tlv.leader_data.data_version - 203 _pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\ 204 (p.mle.tlv.leader_data.stable_data_version - 205 _pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 206 ).\ 207 must_next() 208 209 # Step 6: Leader MUST send a unicast MLE Data Response to Router, including 210 # the following TLVs: 211 # - Source Address TLV 212 # - Leader Data TLV 213 # - Active Operational Dataset TLV 214 # - Channel TLV 215 # - Channel Mask TLV [new value set in Step 2] 216 # - Extended PAN ID TLV [new value set in Step 2] 217 # - Network Mesh-Local Prefix TLV 218 # - Network Key TLV 219 # - Network Name TLV [new value set in Step 2] 220 # - PAN ID TLV 221 # - PSKc TLV [new value set in Step 2] 222 # - Security Policy TLV [new value set in Step 2] 223 # - Active Timestamp TLV [new value set in Step 2] 224 pkts.filter_wpan_src64(LEADER).\ 225 filter_wpan_dst64(ROUTER).\ 226 filter_mle_cmd(MLE_DATA_RESPONSE).\ 227 filter(lambda p: { 228 NETWORK_DATA_TLV, 229 SOURCE_ADDRESS_TLV, 230 LEADER_DATA_TLV, 231 ACTIVE_OPERATION_DATASET_TLV, 232 ACTIVE_TIMESTAMP_TLV 233 } <= set(p.mle.tlv.type) and\ 234 { 235 NM_CHANNEL_TLV, 236 NM_CHANNEL_MASK_TLV, 237 NM_EXTENDED_PAN_ID_TLV, 238 NM_NETWORK_MESH_LOCAL_PREFIX_TLV, 239 NM_NETWORK_KEY_TLV, 240 NM_NETWORK_NAME_TLV, 241 NM_PAN_ID_TLV, 242 NM_PSKC_TLV, 243 NM_SECURITY_POLICY_TLV 244 } <= set(p.thread_meshcop.tlv.type) and\ 245 p.mle.tlv.active_tstamp == 100 and\ 246 p.thread_meshcop.tlv.chan_mask_mask == '001fffc0' and\ 247 p.thread_meshcop.tlv.xpan_id == '000db80000000001' and\ 248 p.thread_meshcop.tlv.net_name == ['TEST_1'] and\ 249 p.thread_meshcop.tlv.pskc == 'd2aa9cd8dff7919122d77d37ec3c1b5f' 250 ).\ 251 must_next() 252 253 # Step 8: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 254 # with the following format: 255 # CoAP Response Code 256 # 2.04 Changed 257 # CoAP Payload 258 # State TLV (value = Reject (ff)) 259 pkts.filter_wpan_src64(LEADER).\ 260 filter_ipv6_dst(ROUTER_RLOC).\ 261 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 262 filter(lambda p: p.thread_meshcop.tlv.state == -1).\ 263 must_next() 264 265 # Step 10: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 266 # with the following format: 267 # CoAP Response Code 268 # 2.04 Changed 269 # CoAP Payload 270 # State TLV (value = Accept (01)) 271 pkts.filter_wpan_src64(LEADER).\ 272 filter_ipv6_dst(ROUTER_RLOC).\ 273 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 274 filter(lambda p: p.thread_meshcop.tlv.state == 1).\ 275 must_next() 276 277 # Step 11: Leader MUST send a multicast MLE Data Response, including 278 # the following TLVs: 279 # - Source Address TLV 280 # - Leader Data TLV 281 # Data version field [incremented] 282 # Stable Version field [incremented] 283 # - Network Data TLV 284 # - Active Timestamp TLV [new value set in Step 9] 285 pkts.filter_wpan_src64(LEADER).\ 286 filter_LLANMA().\ 287 filter_mle_cmd(MLE_DATA_RESPONSE).\ 288 filter(lambda p: { 289 NETWORK_DATA_TLV, 290 SOURCE_ADDRESS_TLV, 291 LEADER_DATA_TLV, 292 ACTIVE_TIMESTAMP_TLV 293 } <= set(p.mle.tlv.type) and\ 294 p.mle.tlv.active_tstamp == 101 and\ 295 (p.mle.tlv.leader_data.data_version - 296 _dr_pkt.mle.tlv.leader_data.data_version) % 256 <= 127 and\ 297 (p.mle.tlv.leader_data.stable_data_version - 298 _dr_pkt.mle.tlv.leader_data.stable_data_version) % 256 <= 127 299 ).\ 300 must_next() 301 302 # Step 13: Leader MUST send a unicast MLE Data Response to Router, including 303 # the following TLVs: 304 # - Source Address TLV 305 # - Leader Data TLV 306 # - Active Operational Dataset TLV 307 # - Channel TLV 308 # - Channel Mask TLV [new value set in Step 9] 309 # - Extended PAN ID TLV [new value set in Step 9] 310 # - Network Mesh-Local Prefix TLV 311 # - Network Key TLV 312 # - Network Name TLV [new value set in Step 9] 313 # - PAN ID TLV 314 # - PSKc TLV [new value set in Step 9] 315 # - Security Policy TLV [new value set in Step 9] 316 # - Active Timestamp TLV [new value set in Step 9] 317 pkts.filter_wpan_src64(LEADER).\ 318 filter_wpan_dst64(ROUTER).\ 319 filter_mle_cmd(MLE_DATA_RESPONSE).\ 320 filter(lambda p: { 321 NETWORK_DATA_TLV, 322 SOURCE_ADDRESS_TLV, 323 LEADER_DATA_TLV, 324 ACTIVE_OPERATION_DATASET_TLV, 325 ACTIVE_TIMESTAMP_TLV 326 } <= set(p.mle.tlv.type) and\ 327 { 328 NM_CHANNEL_TLV, 329 NM_CHANNEL_MASK_TLV, 330 NM_EXTENDED_PAN_ID_TLV, 331 NM_NETWORK_MESH_LOCAL_PREFIX_TLV, 332 NM_NETWORK_KEY_TLV, 333 NM_NETWORK_NAME_TLV, 334 NM_PAN_ID_TLV, 335 NM_PSKC_TLV, 336 NM_SECURITY_POLICY_TLV 337 } <= set(p.thread_meshcop.tlv.type) and\ 338 p.mle.tlv.active_tstamp == 101 and\ 339 p.thread_meshcop.tlv.chan_mask_mask == '001fff00' and\ 340 p.thread_meshcop.tlv.xpan_id == '000db80000000003' and\ 341 p.thread_meshcop.tlv.net_name == ['TEST_3'] and\ 342 p.thread_meshcop.tlv.pskc == '08f4e9531e8efa8e852d5f4fb951b13e' 343 ).\ 344 must_next() 345 346 # Step 15: Leader MUST send MGMT_ACTIVE_SET.rsp to the Router with 347 # with the following format: 348 # CoAP Response Code 349 # 2.04 Changed 350 # CoAP Payload 351 # State TLV (value = Reject (ff))) 352 pkts.filter_wpan_src64(LEADER).\ 353 filter_ipv6_dst(ROUTER_RLOC).\ 354 filter_coap_ack(MGMT_ACTIVE_SET_URI).\ 355 filter(lambda p: p.thread_meshcop.tlv.state == -1).\ 356 must_next() 357 358 # Step 16: The DUT must respond with an ICMPv6 Echo Reply 359 _pkt = pkts.filter_ping_request().\ 360 filter_ipv6_src_dst(ROUTER_RLOC, LEADER_RLOC).\ 361 must_next() 362 pkts.filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier).\ 363 filter_ipv6_src_dst(LEADER_RLOC, ROUTER_RLOC).\ 364 must_next() 365 366 367if __name__ == '__main__': 368 unittest.main() 369