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 ipaddress 31import unittest 32 33import command 34import config 35import thread_cert 36 37# Test description: 38# This test verifies SRP client auto-start functionality that SRP client can 39# correctly discovers and connects to SRP server. 40# 41# Topology: 42# 43# Four routers, one acting as SRP client, others as SRP server. 44# 45 46CLIENT = 1 47SERVER1 = 2 48SERVER2 = 3 49SERVER3 = 4 50 51 52class SrpAutoStartMode(thread_cert.TestCase): 53 USE_MESSAGE_FACTORY = False 54 SUPPORT_NCP = False 55 56 TOPOLOGY = { 57 CLIENT: { 58 'name': 'SRP_CLIENT', 59 'mode': 'rdn', 60 }, 61 SERVER1: { 62 'name': 'SRP_SERVER1', 63 'mode': 'rdn', 64 }, 65 SERVER2: { 66 'name': 'SRP_SERVER2', 67 'mode': 'rdn', 68 }, 69 SERVER3: { 70 'name': 'SRP_SERVER3', 71 'mode': 'rdn', 72 }, 73 } 74 75 def test(self): 76 client = self.nodes[CLIENT] 77 server1 = self.nodes[SERVER1] 78 server2 = self.nodes[SERVER2] 79 server3 = self.nodes[SERVER3] 80 81 #------------------------------------------------------------------- 82 # Form the network. 83 84 client.srp_server_set_enabled(False) 85 client.start() 86 self.simulator.go(config.LEADER_STARTUP_DELAY) 87 self.assertEqual(client.get_state(), 'leader') 88 89 server1.start() 90 server2.start() 91 server3.start() 92 self.simulator.go(config.ROUTER_STARTUP_DELAY) 93 self.assertEqual(server1.get_state(), 'router') 94 self.assertEqual(server2.get_state(), 'router') 95 self.assertEqual(server3.get_state(), 'router') 96 97 server1_mleid = server1.get_mleid() 98 server2_mleid = server2.get_mleid() 99 server3_mleid = server3.get_mleid() 100 anycast_port = 53 101 102 #------------------------------------------------------------------- 103 # Enable server1 with unicast address mode 104 105 server1.srp_server_set_addr_mode('unicast') 106 server1.srp_server_set_enabled(True) 107 self.simulator.go(5) 108 109 #------------------------------------------------------------------- 110 # Enable auto start mode on client and check that server1 is selected 111 112 self.assertEqual(client.srp_client_get_state(), 'Disabled') 113 client.srp_client_enable_auto_start_mode() 114 self.assertEqual(client.srp_client_get_auto_start_mode(), 'Enabled') 115 self.simulator.go(2) 116 117 self.assertEqual(client.srp_client_get_state(), 'Enabled') 118 self.assertEqual(client.srp_client_get_server_address(), server1_mleid) 119 120 #------------------------------------------------------------------- 121 # Disable server1 and check client is stopped/disabled. 122 123 server1.srp_server_set_enabled(False) 124 self.simulator.go(5) 125 self.assertEqual(client.srp_client_get_state(), 'Disabled') 126 127 #------------------------------------------------------------------- 128 # Enable server2 with unicast address mode and check client starts 129 # again. 130 131 server1.srp_server_set_addr_mode('unicast') 132 server2.srp_server_set_enabled(True) 133 self.simulator.go(5) 134 self.assertEqual(client.srp_client_get_state(), 'Enabled') 135 self.assertEqual(client.srp_client_get_server_address(), server2_mleid) 136 137 #------------------------------------------------------------------- 138 # Enable server1 and check that client stays with server2 139 140 server1.srp_server_set_enabled(True) 141 self.simulator.go(5) 142 self.assertEqual(client.srp_client_get_state(), 'Enabled') 143 self.assertEqual(client.srp_client_get_server_address(), server2_mleid) 144 145 #------------------------------------------------------------------- 146 # Disable server2 and check client switches to server1. 147 148 server2.srp_server_set_enabled(False) 149 self.simulator.go(5) 150 self.assertEqual(client.srp_client_get_state(), 'Enabled') 151 self.assertEqual(client.srp_client_get_server_address(), server1_mleid) 152 153 #------------------------------------------------------------------- 154 # Enable server2 with anycast mode seq-num 1, and check that client 155 # switched to it. 156 157 server2.srp_server_set_addr_mode('anycast') 158 server2.srp_server_set_anycast_seq_num(1) 159 server2.srp_server_set_enabled(True) 160 self.simulator.go(5) 161 server2_alocs = server2.get_ip6_address(config.ADDRESS_TYPE.ALOC) 162 self.assertEqual(server2.srp_server_get_anycast_seq_num(), 1) 163 self.assertEqual(client.srp_client_get_state(), 'Enabled') 164 self.assertIn(client.srp_client_get_server_address(), server2_alocs) 165 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 166 167 #------------------------------------------------------------------- 168 # Enable server3 with anycast mode seq-num 2, and check that client 169 # switched to it since seq number is higher. 170 171 server3.srp_server_set_addr_mode('anycast') 172 server3.srp_server_set_anycast_seq_num(2) 173 server3.srp_server_set_enabled(True) 174 self.simulator.go(5) 175 server3_alocs = server3.get_ip6_address(config.ADDRESS_TYPE.ALOC) 176 self.assertEqual(server3.srp_server_get_anycast_seq_num(), 2) 177 self.assertEqual(client.srp_client_get_state(), 'Enabled') 178 self.assertIn(client.srp_client_get_server_address(), server3_alocs) 179 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 180 181 #------------------------------------------------------------------- 182 # Disable server3 and check that client goes back to server2. 183 184 server3.srp_server_set_enabled(False) 185 self.simulator.go(5) 186 self.assertEqual(client.srp_client_get_state(), 'Enabled') 187 self.assertIn(client.srp_client_get_server_address(), server2_alocs) 188 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 189 190 #------------------------------------------------------------------- 191 # Enable server3 with anycast mode seq-num 0 (which is smaller than 192 # server2 seq-num 1) and check that client stays with server2. 193 194 server3.srp_server_set_anycast_seq_num(0) 195 server3.srp_server_set_enabled(True) 196 self.simulator.go(5) 197 self.assertEqual(server3.srp_server_get_anycast_seq_num(), 0) 198 self.assertEqual(client.srp_client_get_state(), 'Enabled') 199 self.assertIn(client.srp_client_get_server_address(), server2_alocs) 200 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 201 202 #------------------------------------------------------------------- 203 # Disable server2 and check that client goes back to server3. 204 205 server2.srp_server_set_enabled(False) 206 self.simulator.go(5) 207 self.assertEqual(client.srp_client_get_state(), 'Enabled') 208 server3_alocs = server3.get_ip6_address(config.ADDRESS_TYPE.ALOC) 209 self.assertIn(client.srp_client_get_server_address(), server3_alocs) 210 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 211 212 #------------------------------------------------------------------- 213 # Disable server3 and check that client goes back to server1 with 214 # unicast address. 215 216 server3.srp_server_set_enabled(False) 217 self.simulator.go(5) 218 self.assertEqual(client.srp_client_get_state(), 'Enabled') 219 self.assertEqual(client.srp_client_get_server_address(), server1_mleid) 220 221 #------------------------------------------------------------------- 222 # Enable server2 with anycast mode seq-num 5, and check that client 223 # switched to it. 224 225 server2.srp_server_set_addr_mode('anycast') 226 server2.srp_server_set_anycast_seq_num(5) 227 server2.srp_server_set_enabled(True) 228 self.simulator.go(5) 229 server2_alocs = server2.get_ip6_address(config.ADDRESS_TYPE.ALOC) 230 self.assertEqual(server2.srp_server_get_anycast_seq_num(), 5) 231 self.assertEqual(client.srp_client_get_state(), 'Enabled') 232 self.assertIn(client.srp_client_get_server_address(), server2_alocs) 233 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 234 235 #------------------------------------------------------------------- 236 # Publish an entry on server3 with specific unicast address 237 # This entry should be now preferred over anycast of server2. 238 239 unicast_addr3 = 'fd00:0:0:0:0:3333:beef:cafe' 240 unicast_port3 = 1234 241 server3.netdata_publish_dnssrp_unicast(unicast_addr3, unicast_port3) 242 self.simulator.go(65) 243 self.assertEqual(client.srp_client_get_state(), 'Enabled') 244 self.assertEqual(client.srp_client_get_server_address(), unicast_addr3) 245 self.assertEqual(client.srp_client_get_server_port(), unicast_port3) 246 247 #------------------------------------------------------------------- 248 # Publish an entry on server1 with specific unicast address 249 # Client should still stay with server3 which it originally selected. 250 251 unicast_addr1 = 'fd00:0:0:0:0:2222:beef:cafe' 252 unicast_port1 = 10203 253 server1.srp_server_set_enabled(False) 254 server1.netdata_publish_dnssrp_unicast(unicast_addr1, unicast_port1) 255 self.simulator.go(65) 256 self.assertEqual(client.srp_client_get_state(), 'Enabled') 257 self.assertEqual(client.srp_client_get_server_address(), unicast_addr3) 258 self.assertEqual(client.srp_client_get_server_port(), unicast_port3) 259 260 #------------------------------------------------------------------- 261 # Unpublish the entry on server3. Now client should switch to entry 262 # from server1. 263 264 server3.netdata_unpublish_dnssrp() 265 self.simulator.go(65) 266 self.assertEqual(client.srp_client_get_state(), 'Enabled') 267 self.assertEqual(client.srp_client_get_server_address(), unicast_addr1) 268 self.assertEqual(client.srp_client_get_server_port(), unicast_port1) 269 270 #------------------------------------------------------------------- 271 # Unpublish the entry on server1 and check client goes back to anycast 272 # entry from server2. 273 274 server1.netdata_unpublish_dnssrp() 275 self.simulator.go(65) 276 self.assertEqual(client.srp_client_get_state(), 'Enabled') 277 self.assertIn(client.srp_client_get_server_address(), server2_alocs) 278 self.assertEqual(client.srp_client_get_server_port(), anycast_port) 279 280 #------------------------------------------------------------------- 281 # Finally disable server2, and check that client is disabled. 282 283 server2.srp_server_set_enabled(False) 284 self.simulator.go(5) 285 self.assertEqual(client.srp_client_get_state(), 'Disabled') 286 287 288if __name__ == '__main__': 289 unittest.main() 290