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 unittest 30 31import config 32import thread_cert 33 34# Test description: 35# This test verifies publishing infrastructure NAT64 prefix in Thread network. 36# 37# 38# Topology: 39# 40# ----------------(eth)-------------------- 41# | 42# BR (with DNS64 on infrastructure interface) 43# | 44# ROUTER 45# 46 47BR = 1 48ROUTER = 2 49 50OMR_PREFIX = "2000:0:1111:4444::/64" 51# The prefix is set smaller than the default infrastructure NAT64 prefix. 52SMALL_NAT64_PREFIX = "2000:0:0:1:0:0::/96" 53 54NAT64_PREFIX_REFRESH_DELAY = 305 55 56NAT64_STATE_DISABLED = 'disabled' 57NAT64_STATE_NOT_RUNNING = 'not_running' 58NAT64_STATE_IDLE = 'idle' 59NAT64_STATE_ACTIVE = 'active' 60 61 62class Nat64SingleBorderRouter(thread_cert.TestCase): 63 USE_MESSAGE_FACTORY = False 64 65 TOPOLOGY = { 66 BR: { 67 'name': 'BR', 68 'allowlist': [ROUTER], 69 'is_otbr': True, 70 'version': '1.2', 71 }, 72 ROUTER: { 73 'name': 'Router', 74 'allowlist': [BR], 75 'version': '1.2', 76 }, 77 } 78 79 def test(self): 80 br = self.nodes[BR] 81 router = self.nodes[ROUTER] 82 83 br.start() 84 # When feature flag is enabled, NAT64 might be disabled by default. So 85 # ensure NAT64 is enabled here. 86 br.nat64_set_enabled(True) 87 self.simulator.go(config.LEADER_STARTUP_DELAY) 88 self.assertEqual('leader', br.get_state()) 89 90 router.start() 91 self.simulator.go(config.ROUTER_STARTUP_DELAY) 92 self.assertEqual('router', router.get_state()) 93 94 # Case 1 No infra-derived OMR prefix. BR publishes its local prefix. 95 local_nat64_prefix = br.get_br_nat64_prefix() 96 97 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 98 nat64_prefix = br.get_netdata_nat64_routes()[0] 99 self.assertEqual(nat64_prefix, local_nat64_prefix) 100 101 self.assertDictIncludes(br.nat64_state, { 102 'PrefixManager': NAT64_STATE_ACTIVE, 103 'Translator': NAT64_STATE_ACTIVE 104 }) 105 106 # Case 2 Add OMR prefix. BR publishes the infrastructure nat64 prefix 107 br.add_prefix(OMR_PREFIX) 108 br.register_netdata() 109 self.simulator.go(10) 110 111 favored_nat64_prefix = br.get_br_favored_nat64_prefix() 112 self.assertNotEqual(favored_nat64_prefix, local_nat64_prefix) 113 infra_nat64_prefix = favored_nat64_prefix 114 115 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 116 nat64_prefix = br.get_netdata_nat64_routes()[0] 117 self.assertEqual(nat64_prefix, infra_nat64_prefix) 118 self.assertDictIncludes(br.nat64_state, { 119 'PrefixManager': NAT64_STATE_ACTIVE, 120 'Translator': NAT64_STATE_NOT_RUNNING 121 }) 122 123 # Case 3 Unpublish infrastructure prefix when a smaller prefix in medium 124 # preference is present 125 br.add_route(SMALL_NAT64_PREFIX, stable=False, nat64=True, prf='med') 126 br.register_netdata() 127 self.simulator.go(5) 128 129 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 130 self.assertNotEqual(infra_nat64_prefix, br.get_netdata_nat64_routes()[0]) 131 self.assertDictIncludes(br.nat64_state, { 132 'PrefixManager': NAT64_STATE_IDLE, 133 'Translator': NAT64_STATE_NOT_RUNNING 134 }) 135 136 br.remove_route(SMALL_NAT64_PREFIX) 137 br.register_netdata() 138 self.simulator.go(10) 139 140 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 141 self.assertEqual(nat64_prefix, infra_nat64_prefix) 142 143 # Case 4 No change when a smaller prefix in low preference is present 144 br.add_route(SMALL_NAT64_PREFIX, stable=False, nat64=True, prf='low') 145 br.register_netdata() 146 self.simulator.go(5) 147 148 self.assertEqual(len(br.get_netdata_nat64_routes()), 2) 149 self.assertEqual(br.get_netdata_nat64_routes(), [infra_nat64_prefix, SMALL_NAT64_PREFIX]) 150 self.assertDictIncludes(br.nat64_state, { 151 'PrefixManager': NAT64_STATE_ACTIVE, 152 'Translator': NAT64_STATE_NOT_RUNNING 153 }) 154 155 br.remove_route(SMALL_NAT64_PREFIX) 156 br.register_netdata() 157 self.simulator.go(5) 158 159 # Case 5 Infrastructure nat64 prefix no longer presents 160 br.bash("service bind9 stop") 161 self.simulator.go(NAT64_PREFIX_REFRESH_DELAY) 162 163 local_nat64_prefix = br.get_br_nat64_prefix() 164 self.assertNotEqual(local_nat64_prefix, infra_nat64_prefix) 165 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 166 self.assertEqual(br.get_netdata_nat64_routes()[0], local_nat64_prefix) 167 self.assertDictIncludes(br.nat64_state, { 168 'PrefixManager': NAT64_STATE_ACTIVE, 169 'Translator': NAT64_STATE_ACTIVE 170 }) 171 172 # Case 6 Infrastructure nat64 prefix is recovered 173 br.bash("service bind9 start") 174 self.simulator.go(NAT64_PREFIX_REFRESH_DELAY) 175 176 self.assertEqual(br.get_br_favored_nat64_prefix(), infra_nat64_prefix) 177 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 178 self.assertEqual(br.get_netdata_nat64_routes()[0], infra_nat64_prefix) 179 self.assertDictIncludes(br.nat64_state, { 180 'PrefixManager': NAT64_STATE_ACTIVE, 181 'Translator': NAT64_STATE_NOT_RUNNING 182 }) 183 184 # Case 7 Change infrastructure nat64 prefix 185 br.bash("sed -i 's/dns64 /\/\/dns64 /' /etc/bind/named.conf.options") 186 br.bash("sed -i '/\/\/dns64 /a dns64 " + SMALL_NAT64_PREFIX + " {};' /etc/bind/named.conf.options") 187 br.bash("service bind9 restart") 188 self.simulator.go(NAT64_PREFIX_REFRESH_DELAY) 189 190 self.assertEqual(br.get_br_favored_nat64_prefix(), SMALL_NAT64_PREFIX) 191 self.assertEqual(len(br.get_netdata_nat64_routes()), 1) 192 self.assertEqual(br.get_netdata_nat64_routes()[0], SMALL_NAT64_PREFIX) 193 self.assertDictIncludes(br.nat64_state, { 194 'PrefixManager': NAT64_STATE_ACTIVE, 195 'Translator': NAT64_STATE_NOT_RUNNING 196 }) 197 198 199if __name__ == '__main__': 200 unittest.main() 201