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 mle 34import thread_cert 35from pktverify.consts import MLE_ADVERTISEMENT, MLE_LINK_REQUEST, MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST, SOURCE_ADDRESS_TLV, CHALLENGE_TLV, RESPONSE_TLV, LINK_LAYER_FRAME_COUNTER_TLV, ROUTE64_TLV, ADDRESS16_TLV, LEADER_DATA_TLV, TLV_REQUEST_TLV, VERSION_TLV, MLE_MAX_RESPONSE_DELAY 36from pktverify.packet_verifier import PacketVerifier 37from pktverify.null_field import nullField 38 39LEADER = 1 40ROUTER = 2 41 42# Test Purpose and Description: 43# ----------------------------- 44# The purpose of this test case is to validate that when a router resets, 45# it will synchronize upon returning by using the Router Synchronization 46# after Reset procedure. 47# 48# Test Topology: 49# ------------- 50# Leader 51# | 52# Router 53# 54# DUT Types: 55# ---------- 56# Leader 57# Router 58 59 60class Cert_5_1_13_RouterReset(thread_cert.TestCase): 61 USE_MESSAGE_FACTORY = False 62 63 TOPOLOGY = { 64 LEADER: { 65 'name': 'LEADER', 66 'mode': 'rdn', 67 'allowlist': [ROUTER] 68 }, 69 ROUTER: { 70 'name': 'ROUTER', 71 'mode': 'rdn', 72 'allowlist': [LEADER] 73 }, 74 } 75 76 def _setUpRouter(self): 77 self.nodes[ROUTER].add_allowlist(self.nodes[LEADER].get_addr64()) 78 self.nodes[ROUTER].enable_allowlist() 79 self.nodes[ROUTER].set_router_selection_jitter(1) 80 81 def test(self): 82 self.nodes[LEADER].start() 83 self.simulator.go(config.LEADER_STARTUP_DELAY) 84 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 85 86 self.nodes[ROUTER].start() 87 self.simulator.go(config.ROUTER_STARTUP_DELAY) 88 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 89 self.collect_rloc16s() 90 91 self.nodes[ROUTER].reset() 92 self._setUpRouter() 93 self.simulator.go(5) 94 95 self.nodes[ROUTER].start() 96 self.simulator.go(config.ROUTER_STARTUP_DELAY) 97 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 98 99 def verify(self, pv): 100 pkts = pv.pkts 101 pv.summary.show() 102 103 LEADER = pv.vars['LEADER'] 104 ROUTER = pv.vars['ROUTER'] 105 ROUTER_RLOC16 = pv.vars['ROUTER_RLOC16'] 106 107 # Step 1: Verify topology is formed correctly. 108 109 # Step 2: Devices MUST send properly formatted MLE Advertisements with 110 # an IP Hop Limit of 255 to the Link-Local All Nodes multicast 111 # address (FF02::1). 112 # The following TLVs MUST be present in the MLE Advertisements: 113 # - Leader Data TLV 114 # - Route64 TLV 115 # - Source Address TLV 116 117 pv.verify_attached('ROUTER') 118 pkts.filter_wpan_src64(ROUTER).\ 119 filter_LLANMA().\ 120 filter_mle_cmd(MLE_ADVERTISEMENT).\ 121 filter(lambda p: { 122 LEADER_DATA_TLV, 123 ROUTE64_TLV, 124 SOURCE_ADDRESS_TLV 125 } <= set(p.mle.tlv.type) and\ 126 p.ipv6.hlim == 255 127 ).\ 128 must_next() 129 pkts.filter_wpan_src64(LEADER).\ 130 filter_LLANMA().\ 131 filter_mle_cmd(MLE_ADVERTISEMENT).\ 132 filter(lambda p: { 133 LEADER_DATA_TLV, 134 ROUTE64_TLV, 135 SOURCE_ADDRESS_TLV 136 } <= set(p.mle.tlv.type) and\ 137 p.ipv6.hlim == 255 138 ).\ 139 must_next() 140 141 # Step 4: Router sends multicast Link Request message 142 # 143 # The Link Request Message MUST be sent to the Link-Local All Routers 144 # Routers multicast address (FF02::2) and contain the following TLVs: 145 # - Challenge TLV 146 # - TLV Request TLV 147 # - Address16 TLV 148 # - Route64 TLV 149 # - Version TLV 150 # 151 152 _pkt_lq = pkts.filter_mle_cmd(MLE_LINK_REQUEST).\ 153 filter_LLARMA().\ 154 filter(lambda p: { 155 CHALLENGE_TLV, 156 VERSION_TLV, 157 TLV_REQUEST_TLV, 158 ADDRESS16_TLV, 159 ROUTE64_TLV 160 } <= set(p.mle.tlv.type) and\ 161 p.mle.tlv.addr16 is nullField and \ 162 p.mle.tlv.route64.id_mask is nullField 163 ).\ 164 must_next() 165 166 # Step 5: Leader replies to Router with Link Accept message 167 # The following TLVs MUST be present in the Link Accept message: 168 # - Leader Data TLV 169 # - Link-layer Frame Counter TLV 170 # - Link Margin TLV 171 # - Response TLV 172 # - Source Address TLV 173 # - Version TLV 174 # - TLV Request TLV: Link Margin 175 # - Challenge TLV (optional) 176 # - MLE Frame Counter TLV (optional) 177 # The Challenge TLV MUST be included if the response is an 178 # Accept and Request message. 179 # Responses to multicast Link Requests MUST be delayed by a 180 # random time of up to MLE_MAX_RESPONSE_DELAY (1 second). 181 182 _pkt = pkts.filter_wpan_src64(LEADER).\ 183 filter_wpan_dst64(ROUTER).\ 184 filter_mle_cmd2(MLE_LINK_ACCEPT, MLE_LINK_ACCEPT_AND_REQUEST).\ 185 filter(lambda p: { 186 ADDRESS16_TLV, 187 LEADER_DATA_TLV, 188 LINK_LAYER_FRAME_COUNTER_TLV, 189 RESPONSE_TLV, 190 ROUTE64_TLV, 191 SOURCE_ADDRESS_TLV, 192 VERSION_TLV 193 } <= set(p.mle.tlv.type) and\ 194 p.mle.tlv.addr16 is not nullField and \ 195 p.mle.tlv.route64.id_mask is not nullField and\ 196 p.mle.tlv.addr16 == ROUTER_RLOC16 and\ 197 p.sniff_timestamp - _pkt_lq.sniff_timestamp < 198 MLE_MAX_RESPONSE_DELAY + 0.1 199 ).\ 200 must_next() 201 if _pkt.mle.cmd == MLE_LINK_ACCEPT_AND_REQUEST: 202 _pkt.must_verify(lambda p: [CHALLENGE_TLV] in p.mle.tlv.type) 203 204 205if __name__ == '__main__': 206 unittest.main() 207