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 copy 31import unittest 32 33from mle import TlvType 34from pktverify import consts 35from pktverify.packet_verifier import PacketVerifier 36 37import config 38import thread_cert 39 40LEADER = 1 41ROUTER_1 = 2 42REED_1 = 3 43DUT = 4 44 45 46class LowPower_6_1_07_PreferringARouterOverAReed_Base(thread_cert.TestCase): 47 USE_MESSAGE_FACTORY = False 48 TOPOLOGY = { 49 LEADER: { 50 'version': '1.2', 51 'name': 'LEADER', 52 'mode': 'rdn', 53 'allowlist': [ROUTER_1, REED_1] 54 }, 55 ROUTER_1: { 56 'version': '1.1', 57 'name': 'ROUTER_1', 58 'mode': 'rdn', 59 'allowlist': [LEADER, DUT], 60 }, 61 REED_1: { 62 'version': '1.2', 63 'name': 'REED_1', 64 'mode': 'rdn', 65 'router_upgrade_threshold': 0, 66 'allowlist': [LEADER, DUT], 67 }, 68 DUT: { 69 'version': '1.2', 70 'name': 'DUT', 71 'is_mtd': True, 72 'allowlist': [ROUTER_1, REED_1], 73 }, 74 } 75 76 def test(self): 77 self.nodes[LEADER].start() 78 self.simulator.go(config.LEADER_STARTUP_DELAY) 79 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 80 81 self.nodes[ROUTER_1].start() 82 self.simulator.go(config.ROUTER_STARTUP_DELAY) 83 self.assertEqual(self.nodes[ROUTER_1].get_state(), 'router') 84 85 self.nodes[REED_1].start() 86 self.simulator.go(5) 87 self.assertEqual(self.nodes[REED_1].get_state(), 'child') 88 89 self.simulator.go(5) # wait for advertisements 90 91 # Step 2 - set outbound link quality of ROUTER_1 and REED_1 to 2 (medium) 92 self.nodes[ROUTER_1].set_outbound_link_quality(2) 93 self.nodes[REED_1].set_outbound_link_quality(2) 94 95 # Step 3 - DUT Automatically begins attach process by sending a multicast MLE Parent Request 96 self.nodes[DUT].start() 97 self.simulator.go(5) 98 self.assertEqual(self.nodes[DUT].get_state(), 'child') 99 100 def verify(self, pv): 101 pkts = pv.pkts 102 pv.summary.show() 103 LEADER = pv.vars['LEADER'] 104 ROUTER_1 = pv.vars['ROUTER_1'] 105 REED_1 = pv.vars['REED_1'] 106 DUT = pv.vars['DUT'] 107 108 # Step 1 - Ensure all routers and leader are sending MLE advertisements 109 pkts.filter_wpan_src64(LEADER) \ 110 .filter_mle_cmd(consts.MLE_ADVERTISEMENT) \ 111 .must_next() 112 pkts.filter_wpan_src64(ROUTER_1) \ 113 .filter_mle_cmd(consts.MLE_ADVERTISEMENT) \ 114 .must_next() 115 116 # Step 3 - DUT begins attach process by sending a multicast MLE Parent Request 117 pkts.filter_wpan_src64(DUT) \ 118 .filter_mle_cmd(consts.MLE_PARENT_REQUEST) \ 119 .filter_mle_has_tlv(TlvType.CHALLENGE, TlvType.MODE) \ 120 .filter(lambda p: p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 0) \ 121 .filter(lambda p: p.mle.tlv.version >= config.THREAD_VERSION_1_2) \ 122 .filter(lambda p: p.ipv6.hlim == 255) \ 123 .filter_LLARMA() \ 124 .must_next() 125 126 # Step 4 - Router_1 automatically Respond with MLE Parent Response 127 pkts.filter_wpan_src64(ROUTER_1) \ 128 .filter_wpan_dst64(DUT) \ 129 .filter_mle_cmd(consts.MLE_PARENT_RESPONSE) \ 130 .filter(lambda p: p.mle.tlv.version == config.THREAD_VERSION_1_1) \ 131 .must_next() 132 133 # Step 5 - DUT sends another multicast MLE Parent Request to the all-routers multicast with the Scan Mask TLV 134 # set for all routers and all REEDs 135 pkts.filter_wpan_src64(DUT) \ 136 .filter_mle_cmd(consts.MLE_PARENT_REQUEST) \ 137 .filter_mle_has_tlv(TlvType.CHALLENGE, TlvType.MODE) \ 138 .filter(lambda p: p.mle.tlv.scan_mask.r == 1 and p.mle.tlv.scan_mask.e == 1) \ 139 .filter(lambda p: p.mle.tlv.version >= consts.THREAD_VERSION_1_2) \ 140 .filter(lambda p: p.ipv6.hlim == 255) \ 141 .filter_LLARMA() \ 142 .must_next() 143 144 # Step 6 - REED_1 sends MLE Parent Response to the DUT 145 pkts.filter_wpan_src64(REED_1) \ 146 .filter_wpan_dst64(DUT) \ 147 .filter_mle_cmd(consts.MLE_PARENT_RESPONSE) \ 148 .must_next() 149 150 # # Step 7 - DUT sends a Child ID Request to REED_1 due to its better link quality 151 pkts.filter_wpan_src64(DUT) \ 152 .filter_mle_cmd(consts.MLE_CHILD_ID_REQUEST) \ 153 .filter_wpan_dst64(ROUTER_1) \ 154 .filter_mle_has_tlv(TlvType.ADDRESS_REGISTRATION, TlvType.LINK_LAYER_FRAME_COUNTER, TlvType.MODE, TlvType.RESPONSE, TlvType.TIMEOUT, TlvType.TLV_REQUEST) \ 155 .filter(lambda p: p.mle.tlv.version >= consts.THREAD_VERSION_1_2) \ 156 .must_next() 157 158 159class LowPower_6_1_07_PreferringARouterOverAReed_MED(LowPower_6_1_07_PreferringARouterOverAReed_Base): 160 TOPOLOGY = copy.deepcopy(LowPower_6_1_07_PreferringARouterOverAReed_Base.TOPOLOGY) 161 TOPOLOGY[DUT]['mode'] = 'rn' 162 163 164class LowPower_6_1_07_PreferringARouterOverAReed_SED(LowPower_6_1_07_PreferringARouterOverAReed_Base): 165 TOPOLOGY = copy.deepcopy(LowPower_6_1_07_PreferringARouterOverAReed_Base.TOPOLOGY) 166 TOPOLOGY[DUT]['mode'] = '-' 167 168 169del (LowPower_6_1_07_PreferringARouterOverAReed_Base) 170 171if __name__ == '__main__': 172 unittest.main() 173