1#!/usr/bin/env python3 2# 3# Copyright (c) 2022, 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# 29import logging 30import unittest 31from ipaddress import IPv6Network 32 33import config 34import thread_cert 35 36# Test description: 37# This test verifies that Discovery Proxy and Advertising Proxy of otbr-agent work well after the mDNS daemon 38# (mdns or avahi-daemon) restarts. 39# 40# Topology: 41# ----------------(eth)------------------ 42# | | | 43# BR1 (Leader) ----- BR2 HOST 44# | | 45# ED1 ED2 46# 47 48BR1 = 1 49BR2 = 2 50HOST = 3 51ED1 = 4 52ED2 = 5 53 54LEASE = 200 # Seconds 55KEY_LEASE = 200 # Seconds 56 57 58class MdnsRestart(thread_cert.TestCase): 59 USE_MESSAGE_FACTORY = False 60 61 TOPOLOGY = { 62 BR1: { 63 'name': 'BR1', 64 'allowlist': [BR2, ED1], 65 'is_otbr': True, 66 'version': '1.2', 67 }, 68 BR2: { 69 'name': 'BR2', 70 'allowlist': [BR1, ED2], 71 'is_otbr': True, 72 'version': '1.2', 73 }, 74 HOST: { 75 'name': 'Host', 76 'is_host': True, 77 }, 78 ED1: { 79 'name': 'ED1', 80 'allowlist': [BR1], 81 'version': '1.2', 82 'mode': 'rn', 83 }, 84 ED2: { 85 'name': 'ED2', 86 'allowlist': [BR2], 87 'version': '1.2', 88 'mode': 'rn', 89 }, 90 } 91 92 def test(self): 93 br1 = self.nodes[BR1] 94 br2 = self.nodes[BR2] 95 host = self.nodes[HOST] 96 ed1 = self.nodes[ED1] 97 ed2 = self.nodes[ED2] 98 99 host.start(start_radvd=False) 100 self.simulator.go(5) 101 102 br1.start() 103 self.simulator.go(config.LEADER_STARTUP_DELAY) 104 self.assertEqual('leader', br1.get_state()) 105 106 self.simulator.go(5) 107 108 br2.start() 109 self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY) 110 self.assertEqual('router', br2.get_state()) 111 112 ed1.start() 113 ed2.start() 114 self.simulator.go(5) 115 self.assertEqual('child', ed1.get_state()) 116 self.assertEqual('child', ed2.get_state()) 117 118 br1.srp_server_set_enabled(True) 119 br1.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE) 120 br2.srp_server_set_enabled(True) 121 br2.srp_server_set_lease_range(LEASE, LEASE, KEY_LEASE, KEY_LEASE) 122 self.simulator.go(3) 123 self.assertEqual(br1.srp_server_get_state(), 'running') 124 self.assertEqual(br2.srp_server_get_state(), 'running') 125 126 # ED1 and ED2 register a service by SRP respectively. 127 128 ed1.srp_client_set_host_name('ed1-host') 129 ed1.srp_client_set_host_address(ed1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]) 130 ed1.srp_client_add_service('ed1', '_ed1._tcp', 12345, txt_entries=['id=ed1']) 131 ed1.srp_client_enable_auto_start_mode() 132 133 ed2.srp_client_set_host_name('ed2-host') 134 ed2.srp_client_set_host_address(ed2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0]) 135 ed2.srp_client_add_service('ed2', '_ed2._tcp', 12345, txt_entries=['id=ed2']) 136 ed2.srp_client_enable_auto_start_mode() 137 138 self.simulator.go(10) 139 140 self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2) 141 self.assertEqual(len(host.browse_mdns_services('_ed1._tcp')), 1) 142 self.assertEqual(len(host.browse_mdns_services('_ed2._tcp')), 1) 143 144 # BR1's mdns restart 145 br1.stop_mdns_service() 146 br1.start_mdns_service() 147 148 self.simulator.go(10) 149 150 self.assertEqual(len(host.browse_mdns_services('_meshcop._udp')), 2) 151 self.assertEqual(len(host.browse_mdns_services('_ed1._tcp')), 1) 152 self.assertEqual(len(host.browse_mdns_services('_ed2._tcp')), 1) 153 154 ed1.dns_set_config(br1.get_ip6_address(config.ADDRESS_TYPE.ML_EID)) 155 156 # Since there is only one match, server should include 157 # service info in additional section of its response. 158 browsed_services = ed1.dns_browse('_ed2._tcp.default.service.arpa') 159 self.assertEqual(len(browsed_services), 1) 160 self.assertEqual(browsed_services['ed2']['port'], 12345) 161 self.assertEqual(browsed_services['ed2']['txt_data'], 'id=656432') 162 163 ed2.dns_set_config(br1.get_ip6_address(config.ADDRESS_TYPE.ML_EID)) 164 browsed_services = ed2.dns_browse('_ed1._tcp.default.service.arpa') 165 self.assertEqual(len(browsed_services), 1) 166 self.assertEqual(browsed_services['ed1']['port'], 12345) 167 self.assertEqual(browsed_services['ed1']['txt_data'], 'id=656431') 168 169 170if __name__ == '__main__': 171 unittest.main() 172