blob: 8e41196d4cff9fc5ee884ddf87cd2d8cf02079f4 [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright (c) 2021, The OpenThread Authors.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the copyright holder nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
import unittest
import thread_cert
# Test description:
# This test verifies SRP function that SRP clients can register up to 500 services to one SRP server.
#
# Topology:
# LEADER (SRP server)
# |
# |
# ROUTER1 ... ROUTER12 ROUTER13 (SRP clients)
# | |
# FED14 ... FED25 (SRP clients)
#
NUM_SRP_CLIENTS = 25
INSTANCE_NUM_PER_CLIENT = 20
NUM_ROUTERS = (NUM_SRP_CLIENTS // 2) + (NUM_SRP_CLIENTS % 2)
NUM_FEDS = NUM_SRP_CLIENTS - NUM_ROUTERS
assert (NUM_FEDS <= NUM_ROUTERS)
SERVER = NUM_SRP_CLIENTS + 1
CLIENT1 = 1
ROUTER_IDS = tuple(range(1, NUM_ROUTERS + 1))
FED_IDS = tuple(range(NUM_ROUTERS + 1, NUM_SRP_CLIENTS + 1))
assert len(FED_IDS) == NUM_FEDS
CLIENT_IDS = tuple(range(1, NUM_SRP_CLIENTS + 1))
INSTANCE_IDS = tuple(range(1, INSTANCE_NUM_PER_CLIENT + 1))
SERVICE_NAME = '_srpclient._tcp'
SERVICE_PORT = 12345
class SrpRegister500Services(thread_cert.TestCase):
USE_MESSAGE_FACTORY = False
SUPPORT_NCP = False
TOPOLOGY = {
SERVER: {
'name': 'SRP_SERVER',
'mode': 'rdn',
'allowlist': [],
},
}
for nodeid in ROUTER_IDS:
TOPOLOGY[nodeid] = {
'name': f'SRP_CLIENT_{nodeid}',
'mode': 'rdn',
'allowlist': [SERVER],
}
TOPOLOGY[SERVER]['allowlist'].append(nodeid)
for nodeid in FED_IDS:
parentid = nodeid - NUM_ROUTERS
TOPOLOGY[nodeid] = {
'name': f'SRP_CLIENT_{nodeid}',
'mode': 'rdn',
'router_eligible': False,
'allowlist': [parentid],
}
TOPOLOGY[parentid]['allowlist'].append(nodeid)
def test(self):
self._test_impl()
def _test_impl(self):
server = self.nodes[SERVER]
def routers():
for nodeid in ROUTER_IDS:
yield self.nodes[nodeid]
def feds():
for nodeid in FED_IDS:
yield self.nodes[nodeid]
def clients():
for nodeid in CLIENT_IDS:
yield self.nodes[nodeid]
# Start the server & clients.
server.srp_server_set_enabled(True)
server.start()
self.simulator.go(5)
self.assertEqual(server.get_state(), 'leader')
for router in routers():
router.srp_server_set_enabled(False)
router.start()
self.simulator.go(3)
for router in routers():
self.assertEqual(router.get_state(), 'router')
for fed in feds():
fed.srp_server_set_enabled(False)
fed.start()
self.simulator.go(3)
for fed in feds():
self.assertEqual(fed.get_state(), 'child')
server_addr = server.get_rloc()
for clientid in CLIENT_IDS:
client = self.nodes[clientid]
client.srp_client_set_host_name(f'client{clientid}')
client.srp_client_set_host_address(f'2001::{clientid}')
client.srp_client_start(server_addr, client.get_srp_server_port())
for instanceid in INSTANCE_IDS:
client.srp_client_add_service(f'client{clientid}_{instanceid}', SERVICE_NAME, SERVICE_PORT)
if instanceid % 10 == 0 or instanceid == INSTANCE_IDS[-1]:
self._wait_client_all_services_registered(client)
self._check_client_host_and_services(client, clientid)
# Make sure all service are registered successfully
self._check_server_hosts_and_services(server)
def _wait_client_all_services_registered(self, client, timeout=60):
all_registered = False
while timeout > 0:
self.simulator.go(3)
timeout -= 3
client_services = client.srp_client_get_services()
all_registered = all(service['state'] == 'Registered' for service in client_services)
if all_registered:
break
self.assertTrue(all_registered, "Some services are not registered successfully")
def _check_client_host_and_services(self, client, clientid):
client_services = client.srp_client_get_services()
self.assertEqual(len(client_services), INSTANCE_NUM_PER_CLIENT)
service_instance_names = {f'client{clientid}_{instanceid}' for instanceid in INSTANCE_IDS}
for service in client_services:
self.assertEqual(service['name'], SERVICE_NAME)
self.assertEqual(service['state'], 'Registered')
self.assertEqual(int(service['port']), SERVICE_PORT)
self.assertIn(service['instance'], service_instance_names)
service_instance_names.discard(service['instance'])
def _check_server_hosts_and_services(self, server):
server_services = server.srp_server_get_services()
self.assertEqual(len(server_services), NUM_SRP_CLIENTS * INSTANCE_NUM_PER_CLIENT)
service_instance_names = {
f'client{clientid}_{instanceid}' for clientid in CLIENT_IDS for instanceid in INSTANCE_IDS
}
for service in server_services:
self.assertEqual(service['name'], SERVICE_NAME)
self.assertIn(service['instance'], service_instance_names)
service_instance_names.discard(service['instance'])
if __name__ == '__main__':
unittest.main()