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 config 33import copy 34import mle 35import network_diag 36import network_layer 37import thread_cert 38from network_diag import TlvType 39from pktverify.consts import DIAG_RST_URI, DIAG_GET_URI, DG_MAC_EXTENDED_ADDRESS_TLV, DG_MAC_ADDRESS_TLV, DG_MODE_TLV, DG_CONNECTIVITY_TLV, DG_ROUTE64_TLV, DG_LEADER_DATA_TLV, DG_NETWORK_DATA_TLV, DG_IPV6_ADDRESS_LIST_TLV, DG_CHANNEL_PAGES_TLV, DG_TYPE_LIST_TLV, DG_MAC_COUNTERS_TLV, DG_TIMEOUT_TLV, DG_BATTERY_LEVEL_TLV, DG_SUPPLY_VOLTAGE_TLV, DG_CHILD_TABLE_TLV, DG_CHILD_TABLE_TLV 40from pktverify.packet_verifier import PacketVerifier 41from pktverify.null_field import nullField 42 43LEADER = 1 44ROUTER1 = 2 45REED1 = 3 46SED1 = 4 47MED1 = 5 48FED1 = 6 49 50MTDS = [MED1, SED1] 51 52# Test Purpose and Description: 53# ----------------------------- 54# These cases test the Diagnostic Get and Reset Commands as a part of the 55# Network Management 56# 57# Test Topology: 58# ------------- 59# Leader 60# | 61# FED - Router - REED 62# / \ 63# MED SED 64# 65# DUT Types: 66# ---------- 67# Router 68# FED 69 70 71class Cert_5_7_01_CoapDiagCommands_Base(thread_cert.TestCase): 72 USE_MESSAGE_FACTORY = False 73 SUPPORT_NCP = False 74 75 TOPOLOGY = { 76 LEADER: { 77 'name': 'LEADER', 78 'mode': 'rdn', 79 'allowlist': [ROUTER1], 80 }, 81 ROUTER1: { 82 'mode': 'rdn', 83 'allowlist': [LEADER, REED1, SED1, MED1, FED1], 84 }, 85 REED1: { 86 'name': 'REED', 87 'mode': 'rdn', 88 'allowlist': [ROUTER1], 89 'router_upgrade_threshold': 0 90 }, 91 SED1: { 92 'name': 'SED', 93 'is_mtd': True, 94 'mode': '-', 95 'allowlist': [ROUTER1], 96 'timeout': config.DEFAULT_CHILD_TIMEOUT 97 }, 98 MED1: { 99 'name': 'MED', 100 'is_mtd': True, 101 'mode': 'rn', 102 'allowlist': [ROUTER1] 103 }, 104 FED1: { 105 'allowlist': [ROUTER1], 106 'router_upgrade_threshold': 0 107 }, 108 } 109 110 def test(self): 111 # 1 - Form topology 112 self.nodes[LEADER].start() 113 self.simulator.go(config.LEADER_STARTUP_DELAY) 114 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 115 116 self.nodes[ROUTER1].start() 117 self.simulator.go(config.ROUTER_STARTUP_DELAY) 118 self.assertEqual(self.nodes[ROUTER1].get_state(), 'router') 119 120 for i in range(3, 7): 121 self.nodes[i].start() 122 self.simulator.go(10) 123 self.assertEqual(self.nodes[i].get_state(), 'child') 124 125 self.simulator.go(config.MAX_ADVERTISEMENT_INTERVAL) 126 127 self.collect_rlocs() 128 self.collect_rloc16s() 129 self.collect_ipaddrs() 130 131 DUT = ROUTER1 132 if self.TOPOLOGY[FED1]['name'] == 'DUT': 133 DUT = FED1 134 135 dut_rloc = self.nodes[DUT].get_ip6_address(config.ADDRESS_TYPE.RLOC) 136 137 # 2 - Leader sends DIAG_GET.req 138 tlv_types = [ 139 TlvType.EXT_ADDRESS, TlvType.ADDRESS16, TlvType.MODE, TlvType.CONNECTIVITY, TlvType.ROUTE64, 140 TlvType.LEADER_DATA, TlvType.NETWORK_DATA, TlvType.IPV6_ADDRESS_LIST, TlvType.CHANNEL_PAGES 141 ] 142 self.nodes[LEADER].send_network_diag_get(dut_rloc, tlv_types) 143 self.simulator.go(2) 144 145 # 3 - Leader sends DIAG_GET.req (MAC Counters TLV type included) 146 self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.MAC_COUNTERS]) 147 self.simulator.go(2) 148 149 # 4 - Leader sends DIAG_GET.req (Timeout/Polling Period TLV type included) 150 self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.POLLING_PERIOD]) 151 self.simulator.go(2) 152 153 # 5 - Leader sends DIAG_GET.req (Battery Level and Supply Voltage TLV types included) 154 self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.BATTERY_LEVEL, TlvType.SUPPLY_VOLTAGE]) 155 self.simulator.go(2) 156 157 # 6 - Leader sends DIAG_GET.req (Child Table TLV types included) 158 self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.CHILD_TABLE]) 159 self.simulator.go(2) 160 161 # 7 - Leader sends DIAG_RST.ntf (MAC Counters TLV type included) 162 self.nodes[LEADER].send_network_diag_reset(dut_rloc, [TlvType.MAC_COUNTERS]) 163 self.simulator.go(2) 164 165 # 8 - Leader Sends DIAG_GET.req (MAC Counters TLV type included) 166 self.nodes[LEADER].send_network_diag_get(dut_rloc, [TlvType.MAC_COUNTERS]) 167 self.simulator.go(2) 168 169 def verify(self, pv): 170 pkts = pv.pkts 171 pv.summary.show() 172 173 LEADER = pv.vars['LEADER'] 174 LEADER_RLOC = pv.vars['LEADER_RLOC'] 175 DUT = pv.vars['DUT'] 176 DUT_RLOC = pv.vars['DUT_RLOC'] 177 DUT_RLOC16 = pv.vars['DUT_RLOC16'] 178 REED = pv.vars['REED'] 179 REED_RLOC = pv.vars['REED_RLOC'] 180 MED = pv.vars['MED'] 181 MED_RLOC = pv.vars['MED_RLOC'] 182 SED = pv.vars['SED'] 183 SED_RLOC = pv.vars['SED_RLOC'] 184 MM = pv.vars['MM_PORT'] 185 186 #DUT_IPADDR = 187 188 # Step 1: Ensure topology is formed correctly 189 if self.TOPOLOGY[ROUTER1]['name'] == 'DUT': 190 FED = pv.vars['FED'] 191 pv.verify_attached('DUT', 'LEADER') 192 pv.verify_attached('REED', 'DUT') 193 pv.verify_attached('SED', 'DUT', 'MTD') 194 pv.verify_attached('MED', 'DUT', 'MTD') 195 pv.verify_attached('FED', 'DUT', 'FTD-ED') 196 else: 197 ROUTER = pv.vars['ROUTER'] 198 pv.verify_attached('ROUTER', 'LEADER') 199 pv.verify_attached('REED', 'ROUTER') 200 pv.verify_attached('SED', 'ROUTER', 'MTD') 201 pv.verify_attached('MED', 'ROUTER', 'MTD') 202 pv.verify_attached('DUT', 'ROUTER', 'FTD-ED') 203 204 # Step 2: Leader to send DIAG_GET.req to DUT’s RLOC. 205 # The DUT MUST respond with a DIAG_GET.rsp response containing 206 # the requested diagnostic TLVs: 207 # CoAP Response Code 208 # 2.04 Changed 209 # CoAP Payload 210 # TLV Type 0 - MAC Extended Address (64- bit) 211 # TLV Type 1 - MAC Address (16-bit) 212 # TLV Type 2 - Mode (Capability information) 213 # TLV Type 4 – Connectivity 214 # TLV Type 5 – Route64 215 # TLV Type 6 – Leader Data 216 # TLV Type 7 – Network Data 217 # TLV Type 8 – IPv6 address list 218 # TLV Type 17 – Channel Pages 219 pkts.filter_wpan_src64(LEADER).\ 220 filter_ipv6_dst(DUT_RLOC).\ 221 filter_coap_request(DIAG_GET_URI).\ 222 filter(lambda p: { 223 DG_TYPE_LIST_TLV, 224 DG_MAC_EXTENDED_ADDRESS_TLV, 225 DG_MAC_ADDRESS_TLV, 226 DG_MODE_TLV, 227 DG_CONNECTIVITY_TLV, 228 DG_ROUTE64_TLV, 229 DG_LEADER_DATA_TLV, 230 DG_NETWORK_DATA_TLV, 231 DG_IPV6_ADDRESS_LIST_TLV, 232 DG_CHANNEL_PAGES_TLV 233 } == set(p.thread_diagnostic.tlv.type) 234 ).\ 235 must_next() 236 pkts.filter_wpan_src64(DUT).\ 237 filter_ipv6_dst(LEADER_RLOC).\ 238 filter_coap_ack(DIAG_GET_URI).\ 239 filter(lambda p: { 240 DG_MAC_EXTENDED_ADDRESS_TLV, 241 DG_MAC_ADDRESS_TLV, 242 DG_MODE_TLV, 243 DG_CONNECTIVITY_TLV, 244 DG_ROUTE64_TLV, 245 DG_LEADER_DATA_TLV, 246 DG_NETWORK_DATA_TLV, 247 DG_IPV6_ADDRESS_LIST_TLV, 248 DG_CHANNEL_PAGES_TLV 249 } == set(p.thread_diagnostic.tlv.type) 250 ).\ 251 must_next() 252 253 # Step 3: Leader to send DIAG_GET.req to DUT’s RLOC. 254 # The DUT MUST respond with a DIAG_GET.rsp response containing 255 # the requested diagnostic TLVs: 256 # CoAP Response Code 257 # 2.04 Changed 258 # CoAP Payload 259 # TLV Type 9 - MAC Counters 260 pkts.filter_wpan_src64(LEADER).\ 261 filter_ipv6_dst(DUT_RLOC).\ 262 filter_coap_request(DIAG_GET_URI).\ 263 filter(lambda p: { 264 DG_TYPE_LIST_TLV, 265 DG_MAC_COUNTERS_TLV 266 } == set(p.thread_diagnostic.tlv.type) 267 ).\ 268 must_next() 269 pkts.filter_wpan_src64(DUT).\ 270 filter_ipv6_dst(LEADER_RLOC).\ 271 filter_coap_ack(DIAG_GET_URI).\ 272 filter(lambda p: { 273 DG_MAC_COUNTERS_TLV 274 } == set(p.thread_diagnostic.tlv.type) 275 ).\ 276 must_next() 277 278 # Step 4: Leader to send DIAG_GET.req to DUT’s RLOC. 279 # The DUT MUST respond with a DIAG_GET.rsp response containing 280 # the requested diagnostic TLVs: 281 # CoAP Response Code 282 # 2.04 Changed 283 # CoAP Payload 284 # TLV Type 3 - Timeout MUST be omitted from the response 285 pkts.filter_wpan_src64(LEADER).\ 286 filter_ipv6_dst(DUT_RLOC).\ 287 filter_coap_request(DIAG_GET_URI).\ 288 filter(lambda p: { 289 DG_TYPE_LIST_TLV, 290 DG_TIMEOUT_TLV 291 } == set(p.thread_diagnostic.tlv.type) 292 ).\ 293 must_next() 294 pkts.filter_wpan_src64(DUT).\ 295 filter_ipv6_dst(LEADER_RLOC).\ 296 filter_coap_ack(DIAG_GET_URI).\ 297 filter(lambda p: p.thread_diagnostic.tlv.type is nullField).\ 298 must_next() 299 300 # Step 5: Leader to send DIAG_GET.req to DUT’s RLOC. 301 # The DUT MUST respond with a DIAG_GET.rsp response containing 302 # the requested diagnostic TLVs: 303 # CoAP Response Code 304 # 2.04 Changed 305 # CoAP Payload 306 # TLV Type 3 - Timeout MUST be omitted from the response 307 pkts.filter_wpan_src64(LEADER).\ 308 filter_ipv6_dst(DUT_RLOC).\ 309 filter_coap_request(DIAG_GET_URI).\ 310 filter(lambda p: { 311 DG_TYPE_LIST_TLV, 312 DG_BATTERY_LEVEL_TLV, 313 DG_SUPPLY_VOLTAGE_TLV 314 } == set(p.thread_diagnostic.tlv.type) 315 ).\ 316 must_next() 317 pkts.filter_wpan_src64(DUT).\ 318 filter_ipv6_dst(LEADER_RLOC).\ 319 filter_coap_ack(DIAG_GET_URI).\ 320 filter(lambda p: p.thread_diagnostic.tlv.type is nullField).\ 321 must_next() 322 323 # Step 6: Leader to send DIAG_GET.req to DUT’s RLOC. 324 # The DUT MUST respond with a DIAG_GET.rsp response containing 325 # the requested diagnostic TLVs: 326 # CoAP Response Code 327 # 2.04 Changed 328 # CoAP Payload 329 # TLV Type 16 - Child Table (is empty if FED is DUT) 330 # 331 pkts.filter_wpan_src64(LEADER).\ 332 filter_ipv6_dst(DUT_RLOC).\ 333 filter_coap_request(DIAG_GET_URI).\ 334 filter(lambda p: { 335 DG_TYPE_LIST_TLV, 336 DG_CHILD_TABLE_TLV 337 } == set(p.thread_diagnostic.tlv.type) 338 ).\ 339 must_next() 340 341 if self.TOPOLOGY[ROUTER1]['name'] == 'DUT': 342 _pkt = pkts.filter_wpan_src64(DUT).\ 343 filter_ipv6_dst(LEADER_RLOC).\ 344 filter_coap_ack(DIAG_GET_URI).\ 345 filter(lambda p: { 346 DG_CHILD_TABLE_TLV 347 } == set(p.thread_diagnostic.tlv.type) 348 ).\ 349 must_next() 350 else: 351 pkts.filter_wpan_src64(DUT).\ 352 filter_ipv6_dst(LEADER_RLOC).\ 353 filter_coap_ack(DIAG_GET_URI).\ 354 filter(lambda p: p.thread_diagnostic.tlv.type is nullField).\ 355 must_next() 356 357 # Step 7: Leader to send DIAG_RST.req to DUT’s RLOC for the following diagnostic 358 # TLV type: 359 # TLV Type 9 - MAC Counters 360 # The DUT MUST respond with a CoAP response 361 # CoAP Response Code 362 # 2.04 Changed 363 pkts.filter_wpan_src64(LEADER).\ 364 filter_ipv6_dst(DUT_RLOC).\ 365 filter_coap_request(DIAG_RST_URI).\ 366 filter(lambda p: { 367 DG_TYPE_LIST_TLV, 368 DG_MAC_COUNTERS_TLV 369 } == set(p.thread_diagnostic.tlv.type) 370 ).\ 371 must_next() 372 pkts.filter_wpan_src64(DUT).\ 373 filter_ipv6_dst(LEADER_RLOC).\ 374 filter_coap_ack(DIAG_RST_URI).\ 375 must_next() 376 377 # Step 8: Leader to send DIAG_GET.req to DUT’s RLOC. 378 # The DUT MUST respond with a DIAG_GET.rsp response containing 379 # the requested diagnostic TLVs: 380 # CoAP Response Code 381 # 2.04 Changed 382 # CoAP Payload 383 # TLV Type 9 - MAC Counters 384 # TLV Type 9 - MAC Counters MUST contain a list of MAC Counters 385 # with 0 value or less than value returned in step 3. 386 pkts.filter_wpan_src64(LEADER).\ 387 filter_ipv6_dst(DUT_RLOC).\ 388 filter_coap_request(DIAG_GET_URI).\ 389 filter(lambda p: { 390 DG_TYPE_LIST_TLV, 391 DG_MAC_COUNTERS_TLV 392 } == set(p.thread_diagnostic.tlv.type) 393 ).\ 394 must_next() 395 pkts.filter_wpan_src64(DUT).\ 396 filter_ipv6_dst(LEADER_RLOC).\ 397 filter_coap_ack(DIAG_GET_URI).\ 398 filter(lambda p: { 399 DG_MAC_COUNTERS_TLV 400 } == set(p.thread_diagnostic.tlv.type) 401 ).\ 402 must_next() 403 404 405class Cert_5_7_01_CoapDiagCommands_Base_ROUTER(Cert_5_7_01_CoapDiagCommands_Base): 406 TOPOLOGY = copy.deepcopy(Cert_5_7_01_CoapDiagCommands_Base.TOPOLOGY) 407 TOPOLOGY[ROUTER1]['name'] = 'DUT' 408 TOPOLOGY[FED1]['name'] = 'FED' 409 410 411class Cert_5_7_01_CoapDiagCommands_Base_FED(Cert_5_7_01_CoapDiagCommands_Base): 412 TOPOLOGY = copy.deepcopy(Cert_5_7_01_CoapDiagCommands_Base.TOPOLOGY) 413 TOPOLOGY[ROUTER1]['name'] = 'ROUTER' 414 TOPOLOGY[FED1]['name'] = 'DUT' 415 416 417del (Cert_5_7_01_CoapDiagCommands_Base) 418 419if __name__ == '__main__': 420 unittest.main() 421