1#!/usr/bin/env python3 2# 3# Copyright (c) 2023, 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 33import command 34import config 35import mle 36import thread_cert 37from pktverify.consts import MLE_PARENT_REQUEST, 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 38from pktverify.packet_verifier import PacketVerifier 39from pktverify.null_field import nullField 40 41DUT_LEADER = 1 42DUT_ROUTER1 = 2 43 44# Test Purpose and Description: 45# ----------------------------- 46# The purpose of this test case is to show that when the Leader is rebooted, it sends MLE_MAX_CRITICAL_TRANSMISSION_COUNT MLE link request packets if no response is received. 47# 48# Test Topology: 49# ------------- 50# Leader 51# | 52# Router 53# 54# DUT Types: 55# ---------- 56# Leader 57# Router 58 59 60class Test_LeaderRebootMultipleLinkRequest(thread_cert.TestCase): 61 #USE_MESSAGE_FACTORY = False 62 63 TOPOLOGY = { 64 DUT_LEADER: { 65 'name': 'LEADER', 66 'mode': 'rdn', 67 'allowlist': [DUT_ROUTER1] 68 }, 69 DUT_ROUTER1: { 70 'name': 'ROUTER', 71 'mode': 'rdn', 72 'allowlist': [DUT_LEADER] 73 }, 74 } 75 76 def _setUpLeader(self): 77 self.nodes[DUT_LEADER].add_allowlist(self.nodes[DUT_ROUTER1].get_addr64()) 78 self.nodes[DUT_LEADER].enable_allowlist() 79 80 def test(self): 81 self.nodes[DUT_LEADER].start() 82 self.simulator.go(config.LEADER_STARTUP_DELAY) 83 self.assertEqual(self.nodes[DUT_LEADER].get_state(), 'leader') 84 85 self.nodes[DUT_ROUTER1].start() 86 self.simulator.go(config.ROUTER_STARTUP_DELAY) 87 self.assertEqual(self.nodes[DUT_ROUTER1].get_state(), 'router') 88 89 leader_rloc = self.nodes[DUT_LEADER].get_ip6_address(config.ADDRESS_TYPE.RLOC) 90 91 leader_rloc16 = self.nodes[DUT_LEADER].get_addr16() 92 self.nodes[DUT_LEADER].reset() 93 self.assertFalse(self.nodes[DUT_ROUTER1].ping(leader_rloc)) 94 self._setUpLeader() 95 96 # Router1 will not reply to leader's link request 97 self.nodes[DUT_ROUTER1].clear_allowlist() 98 99 self.nodes[DUT_LEADER].start() 100 101 self.simulator.go(config.LEADER_RESET_DELAY) 102 103 def verify(self, pv): 104 pkts = pv.pkts 105 pv.summary.show() 106 107 LEADER = pv.vars['LEADER'] 108 ROUTER = pv.vars['ROUTER'] 109 110 # Verify topology is formed correctly. 111 pv.verify_attached('ROUTER', 'LEADER') 112 113 # The DUT MUST send properly formatted MLE Advertisements with 114 # an IP Hop Limit of 255 to the Link-Local All Nodes multicast 115 # address (FF02::1). 116 # The following TLVs MUST be present in the MLE Advertisements: 117 # - Leader Data TLV 118 # - Route64 TLV 119 # - Source Address TLV 120 with pkts.save_index(): 121 pkts.filter_wpan_src64(LEADER).\ 122 filter_mle_advertisement('Leader').\ 123 must_next() 124 pkts.filter_wpan_src64(ROUTER).\ 125 filter_mle_advertisement('Router').\ 126 must_next() 127 128 pkts.filter_ping_request().\ 129 filter_wpan_src64(ROUTER).\ 130 must_next() 131 132 # The Leader MUST send MLE_MAX_CRITICAL_TRANSMISSION_COUNT multicast Link Request 133 # The following TLVs MUST be present in the Link Request: 134 # - Challenge TLV 135 # - Version TLV 136 # - TLV Request TLV: Address16 TLV, Route64 TLV 137 for i in range(0, config.MLE_MAX_CRITICAL_TRANSMISSION_COUNT): 138 pkts.filter_wpan_src64(LEADER).\ 139 filter_LLARMA().\ 140 filter_mle_cmd(MLE_LINK_REQUEST).\ 141 filter(lambda p: { 142 CHALLENGE_TLV, 143 VERSION_TLV, 144 TLV_REQUEST_TLV, 145 ADDRESS16_TLV, 146 ROUTE64_TLV 147 } <= set(p.mle.tlv.type) and\ 148 p.mle.tlv.addr16 is nullField and\ 149 p.mle.tlv.route64.id_mask is nullField 150 ).\ 151 must_next() 152 153 154if __name__ == '__main__': 155 unittest.main() 156