1#!/usr/bin/env python3 2# 3# Copyright (c) 2021, 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 logging 31import unittest 32 33import pktverify 34from pktverify import packet_verifier 35from pktverify.consts import MA1, MA1g, MA2 36import config 37import thread_cert 38 39# Test description: 40# The purpose of this test is to verify the functionality of ping command. 41# 42# Topology: 43# 44# 45# ROUTER_2 ----- ROUTER_1 ---- ROUTER_3 46# 47# 48 49ROUTER_1 = 1 50ROUTER_2 = 2 51ROUTER_3 = 3 52 53 54class TestPing(thread_cert.TestCase): 55 USE_MESSAGE_FACTORY = False 56 SUPPORT_NCP = False 57 58 TOPOLOGY = { 59 ROUTER_1: { 60 'name': 'Router_1', 61 'allowlist': [ROUTER_2, ROUTER_3], 62 }, 63 ROUTER_2: { 64 'name': 'Router_2', 65 'allowlist': [ROUTER_1], 66 }, 67 ROUTER_3: { 68 'name': 'Router_3', 69 'allowlist': [ROUTER_1], 70 }, 71 } 72 73 def test(self): 74 router1 = self.nodes[ROUTER_1] 75 router2 = self.nodes[ROUTER_2] 76 router3 = self.nodes[ROUTER_3] 77 78 router1.start() 79 self.simulator.go(5) 80 self.assertEqual('leader', router1.get_state()) 81 82 router2.start() 83 self.simulator.go(5) 84 self.assertEqual('router', router2.get_state()) 85 86 router3.start() 87 self.simulator.go(5) 88 self.assertEqual('router', router3.get_state()) 89 90 # 1. ROUTER_1 pings ROUTER_2. 91 self.assertTrue(router1.ping(router2.get_ip6_address(config.ADDRESS_TYPE.RLOC))) 92 93 # 2. ROUTER_1 pings ROUTER_2 multiple times. 94 self.assertTrue(router1.ping(router2.get_ip6_address(config.ADDRESS_TYPE.RLOC), count=5)) 95 96 # 3. ROUTER_2 pings ROUTER_1 from the link-local address to the 97 # link-local address. 98 self.assertTrue( 99 router2.ping(router1.get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL), 100 interface=router2.get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL))) 101 102 # 4. ROUTER_2 pings ROUTER_3 using the RLOC. 103 self.assertTrue(router2.ping(router3.get_ip6_address(config.ADDRESS_TYPE.RLOC))) 104 105 # 5. ROUTER_2 pings ROUTER_3's link-local address. The ping should fail. 106 self.assertFalse(router2.ping(router3.get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL))) 107 108 # 6. ROUTER_2 pings ROUTER_3's RLOC from the link-local address. The 109 # ping should fail. 110 self.assertFalse( 111 router2.ping(router3.get_ip6_address(config.ADDRESS_TYPE.RLOC), 112 interface=router2.get_ip6_address(config.ADDRESS_TYPE.LINK_LOCAL))) 113 114 # 7. ROUTER_2 pings ROUTER_3's RLOC from an non-existent address. The 115 # ping command should be rejected by CLI. 116 self.assertFalse(router2.ping(router3.get_ip6_address(config.ADDRESS_TYPE.RLOC), interface='1::1')) 117 118 self.collect_ipaddrs() 119 self.collect_rloc16s() 120 self.collect_rlocs() 121 self.collect_extra_vars() 122 123 def verify(self, pv: pktverify.packet_verifier.PacketVerifier): 124 pkts = pv.pkts 125 vars = pv.vars 126 pv.summary.show() 127 128 logging.info(f'vars = {vars}') 129 130 # Ensure the topology is formed correctly 131 pv.verify_attached('Router_2', 'Router_1') 132 pv.verify_attached('Router_3', 'Router_1') 133 134 # 1. Router_1 pings Router_2. 135 _pkt = pkts.filter_wpan_src64(vars['Router_1']) \ 136 .filter_ipv6_2dsts(vars['Router_2_RLOC'], vars['Router_2_LLA']) \ 137 .filter_ping_request() \ 138 .must_next() 139 140 pkts.filter_wpan_src64(vars['Router_2']) \ 141 .filter_ipv6_dst(_pkt.ipv6.src) \ 142 .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \ 143 .must_next() 144 145 # 2. Router_1 pings Router_2 multiple times. 146 for i in range(5): 147 _pkt = pkts.filter_wpan_src64(vars['Router_1']) \ 148 .filter_ipv6_2dsts(vars['Router_2_RLOC'], vars['Router_2_LLA']) \ 149 .filter_ping_request() \ 150 .must_next() 151 pkts.filter_wpan_src64(vars['Router_2']) \ 152 .filter_ipv6_dst(_pkt.ipv6.src) \ 153 .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \ 154 .must_next() 155 156 # 3. Router_2 pings Router_1 from the link-local address to the 157 # link-local address. 158 _pkt = pkts.filter_wpan_src64(vars['Router_2']) \ 159 .filter_ipv6_src_dst(vars['Router_2_LLA'], vars['Router_1_LLA']) \ 160 .filter_ping_request() \ 161 .must_next() 162 163 pkts.filter_wpan_src64(vars['Router_1']) \ 164 .filter_ipv6_dst(_pkt.ipv6.src) \ 165 .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \ 166 .must_next() 167 168 # 4. Router_2 pings Router_3 using the RLOC. 169 _pkt = pkts.filter_wpan_src64(vars['Router_2']) \ 170 .filter_ipv6_dst(vars['Router_3_RLOC']) \ 171 .filter_ping_request() \ 172 .must_next() 173 174 pkts.filter_wpan_src64(vars['Router_3']) \ 175 .filter_ipv6_dst(_pkt.ipv6.src) \ 176 .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \ 177 .must_next() 178 179 # 5. Router_2 pings Router_3's link-local address. The ping should fail. 180 _pkt = pkts.filter_wpan_src64(vars['Router_2']) \ 181 .filter_ipv6_dst(vars['Router_3_LLA']) \ 182 .filter_ping_request() \ 183 .must_next() 184 185 pkts.filter_wpan_src64(vars['Router_3']) \ 186 .filter_ipv6_dst(_pkt.ipv6.src) \ 187 .filter_ping_reply(identifier=_pkt.icmpv6.echo.identifier) \ 188 .must_not_next() 189 190 # 5. Router_2 pings Router_3's RLOC from the link-local address. The 191 # ping should fail. 192 _pkt = pkts.filter_wpan_src64(vars['Router_2']) \ 193 .filter_ipv6_src_dst(vars['Router_2_LLA'], vars['Router_3_RLOC']) \ 194 .filter_ping_request() \ 195 .must_next() 196 197 198if __name__ == '__main__': 199 unittest.main() 200