1#!/usr/bin/env python3 2# 3# Copyright (c) 2019, 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 ipv6 34import thread_cert 35 36LEADER = 1 37ROUTER = 2 38 39 40class TestIPv6SourceSelection(thread_cert.TestCase): 41 SUPPORT_NCP = False 42 43 TOPOLOGY = { 44 LEADER: { 45 'mode': 'rdn', 46 'panid': 0xcafe, 47 'allowlist': [ROUTER] 48 }, 49 ROUTER: { 50 'mode': 'rdn', 51 'panid': 0xcafe, 52 'allowlist': [LEADER] 53 }, 54 } 55 56 def test(self): 57 self.nodes[LEADER].start() 58 self.simulator.go(config.LEADER_STARTUP_DELAY) 59 self.assertEqual(self.nodes[LEADER].get_state(), 'leader') 60 61 self.nodes[ROUTER].start() 62 self.simulator.go(config.ROUTER_STARTUP_DELAY) 63 self.assertEqual(self.nodes[ROUTER].get_state(), 'router') 64 65 leader_aloc = self.nodes[LEADER].get_addr_leader_aloc() 66 leader_mleid = self.nodes[LEADER].get_mleid() 67 leader_rloc = self.nodes[LEADER].get_rloc() 68 leader_linklocal = self.nodes[LEADER].get_linklocal() 69 multicast_addr = 'ff03::1' 70 external_addr = '2007::1' 71 72 router_rloc = self.nodes[ROUTER].get_rloc() 73 router_linklocal = self.nodes[ROUTER].get_linklocal() 74 router_mleid = self.nodes[ROUTER].get_mleid() 75 76 # Source check - RLOC source for RLOC destination 77 self.assertTrue(self.nodes[ROUTER].ping(leader_rloc)) 78 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 79 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 80 msg.assertSentFromSourceAddress(router_rloc) 81 82 # Source check - ML-EID source for ALOC destination 83 self.assertTrue(self.nodes[ROUTER].ping(leader_aloc)) 84 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 85 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 86 msg.assertSentFromSourceAddress(router_mleid) 87 88 # Source check - ML-EID source for ML-EID destination 89 self.assertTrue(self.nodes[ROUTER].ping(leader_mleid)) 90 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 91 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 92 msg.assertSentFromSourceAddress(router_mleid) 93 94 # Source check - link local source source for link local address 95 self.assertTrue(self.nodes[ROUTER].ping(leader_linklocal)) 96 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 97 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 98 msg.assertSentFromSourceAddress(router_linklocal) 99 100 # Source check - ML-EID source for realmlocal multicast destination 101 self.assertTrue(self.nodes[ROUTER].ping(multicast_addr)) 102 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 103 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 104 msg.assertSentFromSourceAddress(router_mleid) 105 106 # GUA and default gateway 107 self.nodes[LEADER].add_prefix('2001::/64', 'paros') 108 self.nodes[LEADER].register_netdata() 109 self.simulator.go(5) 110 111 # Set lowpan context of sniffer 112 self.simulator.set_lowpan_context(1, '2001::/64') 113 114 # Flushes message queue before next ping 115 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 116 117 # Source check - GUA source for GUA destination 118 leader_gua = self.nodes[LEADER].get_addr("2001::/64") 119 router_gua = self.nodes[ROUTER].get_addr("2001::/64") 120 self.assertTrue(leader_gua is not None) 121 self.assertTrue(router_gua is not None) 122 self.assertTrue(self.nodes[ROUTER].ping(leader_gua)) 123 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 124 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 125 msg.assertSentFromSourceAddress(router_gua) 126 127 # Source check - GUA source for external address (default route) 128 self.nodes[ROUTER].ping(external_addr) 129 router_msgs = self.simulator.get_messages_sent_by(ROUTER) 130 msg = router_msgs.get_icmp_message(ipv6.ICMP_ECHO_REQUEST) 131 msg.assertSentFromSourceAddress(router_gua) 132 133 134if __name__ == '__main__': 135 unittest.main() 136