diff --git a/script/test b/script/test index ef2ba7254..2c5226145 100755 --- a/script/test +++ b/script/test @@ -46,6 +46,7 @@ readonly THREAD_VERSION="${THREAD_VERSION:-1.2}" readonly INTER_OP="${INTER_OP:-0}" readonly VERBOSE="${VERBOSE:-0}" readonly BORDER_ROUTING="${BORDER_ROUTING:-1}" +readonly BORDER_ROUTING_NAT64="${BORDER_ROUTING_NAT64:-1}" readonly INTER_OP_BBR="${INTER_OP_BBR:-1}" readonly OT_COREDUMP_DIR="${PWD}/ot-core-dump" @@ -295,6 +296,12 @@ do_build_otbr_docker() otbr_options+=("-DOTBR_TREL=OFF") fi + if [[ ${BORDER_ROUTING_NAT64} == 1 ]]; then + otbr_options+=("-DOT_BORDER_ROUTING_NAT64=ON") + else + otbr_options+=("-DOT_BORDER_ROUTING_NAT64=OFF") + fi + local otbr_docker_image=${OTBR_DOCKER_IMAGE:-otbr-ot12-backbone-ci} otbrdir=$(mktemp -d -t otbr_XXXXXX) diff --git a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py index 8441ea07d..0e122d187 100755 --- a/tests/scripts/thread-cert/border_router/test_multi_border_routers.py +++ b/tests/scripts/thread-cert/border_router/test_multi_border_routers.py @@ -132,23 +132,23 @@ class MultiBorderRouters(thread_cert.TestCase): logging.info("ROUTER2 addrs: %r", router2.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br1.get_prefixes()), 1) - self.assertEqual(len(router1.get_prefixes()), 1) - self.assertEqual(len(br2.get_prefixes()), 1) - self.assertEqual(len(router2.get_prefixes()), 1) + self.assertEqual(len(br1.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router1.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br2.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router2.get_netdata_omr_prefixes()), 1) - br1_omr_prefix = br1.get_omr_prefix() - self.assertEqual(br1_omr_prefix, br1.get_prefixes()[0].split(' ')[0]) + br1_omr_prefix = br1.get_br_omr_prefix() + self.assertEqual(br1_omr_prefix, br1.get_netdata_omr_prefixes()[0]) # Each BR should independently register an external route for the on-link prefix. - self.assertEqual(len(br1.get_routes()), 2) - self.assertEqual(len(router1.get_routes()), 2) - self.assertEqual(len(br2.get_routes()), 2) - self.assertEqual(len(router2.get_routes()), 2) + self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2) - br1_on_link_prefix = br1.get_on_link_prefix() - self.assertEqual(br1_on_link_prefix, br1.get_routes()[0].split(' ')[0]) - self.assertEqual(br1_on_link_prefix, br1.get_routes()[1].split(' ')[0]) + br1_on_link_prefix = br1.get_br_on_link_prefix() + self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0]) + self.assertEqual(br1_on_link_prefix, br1.get_netdata_non_nat64_prefixes()[0]) self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) @@ -183,25 +183,23 @@ class MultiBorderRouters(thread_cert.TestCase): self.assertGreaterEqual(len(host.get_addrs()), 3) - self.assertEqual(len(br1.get_prefixes()), 1) - self.assertEqual(len(router1.get_prefixes()), 1) - self.assertEqual(len(br2.get_prefixes()), 1) - self.assertEqual(len(router2.get_prefixes()), 1) + self.assertEqual(len(br1.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router1.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br2.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router2.get_netdata_omr_prefixes()), 1) - br2_omr_prefix = br2.get_omr_prefix() - self.assertEqual(br2_omr_prefix, br2.get_prefixes()[0].split(' ')[0]) + br2_omr_prefix = br2.get_br_omr_prefix() + self.assertEqual(br2_omr_prefix, br2.get_netdata_omr_prefixes()[0]) # Only BR2 will keep the route for BR1's on-link prefix # and add route for on-link prefix of its own. - self.assertEqual(len(br1.get_routes()), 2) - self.assertEqual(len(router1.get_routes()), 2) - self.assertEqual(len(br2.get_routes()), 2) - self.assertEqual(len(router2.get_routes()), 2) + self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2) - br2_external_routes = [route.split(' ')[0] for route in br2.get_routes()] - - br2_on_link_prefix = br2.get_on_link_prefix() - self.assertEqual(set(map(IPv6Network, br2_external_routes)), + br2_on_link_prefix = br2.get_br_on_link_prefix() + self.assertEqual(set(map(IPv6Network, br2.get_netdata_non_nat64_prefixes())), set(map(IPv6Network, [br1_on_link_prefix, br2_on_link_prefix]))) self.assertEqual(len(br1.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) diff --git a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py index b0e9f92d0..c75026b69 100755 --- a/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py +++ b/tests/scripts/thread-cert/border_router/test_multi_thread_networks.py @@ -115,22 +115,22 @@ class MultiThreadNetworks(thread_cert.TestCase): logging.info("BR2 addrs: %r", br2.get_addrs()) logging.info("ROUTER2 addrs: %r", router2.get_addrs()) - self.assertTrue(len(br1.get_prefixes()) == 1) - self.assertTrue(len(router1.get_prefixes()) == 1) - self.assertTrue(len(br2.get_prefixes()) == 1) - self.assertTrue(len(router2.get_prefixes()) == 1) + self.assertTrue(len(br1.get_netdata_omr_prefixes()) == 1) + self.assertTrue(len(router1.get_netdata_omr_prefixes()) == 1) + self.assertTrue(len(br2.get_netdata_omr_prefixes()) == 1) + self.assertTrue(len(router2.get_netdata_omr_prefixes()) == 1) - br1_omr_prefix = br1.get_omr_prefix() - br2_omr_prefix = br2.get_omr_prefix() + br1_omr_prefix = br1.get_br_omr_prefix() + br2_omr_prefix = br2.get_br_omr_prefix() self.assertNotEqual(br1_omr_prefix, br2_omr_prefix) # Each BR should independently register an external route for the on-link prefix # and OMR prefix in another Thread Network. - self.assertTrue(len(br1.get_routes()) == 2) - self.assertTrue(len(router1.get_routes()) == 2) - self.assertTrue(len(br2.get_routes()) == 2) - self.assertTrue(len(router2.get_routes()) == 2) + self.assertTrue(len(br1.get_netdata_non_nat64_prefixes()) == 2) + self.assertTrue(len(router1.get_netdata_non_nat64_prefixes()) == 2) + self.assertTrue(len(br2.get_netdata_non_nat64_prefixes()) == 2) + self.assertTrue(len(router2.get_netdata_non_nat64_prefixes()) == 2) br1_external_routes = br1.get_routes() br2_external_routes = br2.get_routes() diff --git a/tests/scripts/thread-cert/border_router/test_nat64_multi_border_routers.py b/tests/scripts/thread-cert/border_router/test_nat64_multi_border_routers.py new file mode 100644 index 000000000..64e5ac8c5 --- /dev/null +++ b/tests/scripts/thread-cert/border_router/test_nat64_multi_border_routers.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022, 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 that a single NAT64 prefix is advertised when there are +# multiple Border Routers in the same Thread and infrastructure network. +# +# TODO: add checks for outbound connectivity from Thread device to IPv4 host +# after OTBR change is ready. +# +# Topology: +# ----------------(eth)-------------------------- +# | | | +# BR1 (Leader) ---- BR2 HOST +# | +# ROUTER +# + +BR1 = 1 +ROUTER = 2 +BR2 = 3 +HOST = 4 + + +class Nat64MultiBorderRouter(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + + TOPOLOGY = { + BR1: { + 'name': 'BR1', + 'allowlist': [ROUTER, BR2], + 'is_otbr': True, + 'version': '1.2', + }, + ROUTER: { + 'name': 'Router', + 'allowlist': [BR1], + 'version': '1.2', + }, + BR2: { + 'name': 'BR2', + 'allowlist': [BR1], + 'is_otbr': True, + 'version': '1.2' + }, + HOST: { + 'name': 'Host', + 'is_host': True + }, + } + + def test(self): + br1 = self.nodes[BR1] + router = self.nodes[ROUTER] + br2 = self.nodes[BR2] + host = self.nodes[HOST] + + host.start(start_radvd=False) + self.simulator.go(5) + + br1.start() + self.simulator.go(5) + self.assertEqual('leader', br1.get_state()) + + router.start() + self.simulator.go(5) + self.assertEqual('router', router.get_state()) + + # + # Case 1. BR2 joins the network later and it will not add + # its local nat64 prefix to Network Data. + # + br2.start() + self.simulator.go(5) + self.assertEqual('router', br2.get_state()) + + # Only 1 NAT64 prefix in Network Data. + self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1) + self.assertEqual(len(br2.get_netdata_nat64_prefix()), 1) + self.assertEqual(br1.get_netdata_nat64_prefix()[0], br2.get_netdata_nat64_prefix()[0]) + nat64_prefix = br1.get_netdata_nat64_prefix()[0] + + # The NAT64 prefix in Network Data is same as BR1's local NAT64 prefix. + br1_nat64_prefix = br1.get_br_nat64_prefix() + br2_nat64_prefix = br2.get_br_nat64_prefix() + self.assertEqual(nat64_prefix, br1_nat64_prefix) + self.assertNotEqual(nat64_prefix, br2_nat64_prefix) + + # + # Case 2. Disable and re-enable border routing on BR1. + # + br1.disable_br() + self.simulator.go(5) + + # BR1 withdraws its prefix and BR2 advertises its prefix. + self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1) + self.assertEqual(br2_nat64_prefix, br1.get_netdata_nat64_prefix()[0]) + self.assertNotEqual(br1_nat64_prefix, br1.get_netdata_nat64_prefix()[0]) + + br1.enable_br() + self.simulator.go(5) + + # NAT64 prefix in Network Data is still advertised by BR2. + self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1) + self.assertEqual(br2_nat64_prefix, br1.get_netdata_nat64_prefix()[0]) + self.assertNotEqual(br1_nat64_prefix, br1.get_netdata_nat64_prefix()[0]) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/scripts/thread-cert/border_router/test_nat64_single_border_router.py b/tests/scripts/thread-cert/border_router/test_nat64_single_border_router.py new file mode 100644 index 000000000..f28158ac3 --- /dev/null +++ b/tests/scripts/thread-cert/border_router/test_nat64_single_border_router.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022, 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 the advertisement of NAT64 prefix in Thread network. +# +# TODO: add checks for outbound connectivity from Thread device to IPv4 host +# after OTBR change is ready. +# +# Topology: +# ----------------(eth)-------------------- +# | | +# BR (Leader) HOST +# | +# ROUTER +# + +BR = 1 +ROUTER = 2 +HOST = 3 + +# The prefix is set small enough that a random-generated NAT64 prefix is very +# likely greater than it. So that the BR will remove the random-generated one. +SMALL_NAT64_PREFIX = "fd00:00:00:01:00:00::/96" + + +class Nat64SingleBorderRouter(thread_cert.TestCase): + USE_MESSAGE_FACTORY = False + + TOPOLOGY = { + BR: { + 'name': 'BR', + 'allowlist': [ROUTER], + 'is_otbr': True, + 'version': '1.2', + }, + ROUTER: { + 'name': 'Router', + 'allowlist': [BR], + 'version': '1.2', + }, + HOST: { + 'name': 'Host', + 'is_host': True + }, + } + + def test(self): + br = self.nodes[BR] + router = self.nodes[ROUTER] + host = self.nodes[HOST] + + host.start(start_radvd=False) + self.simulator.go(5) + + br.start() + self.simulator.go(5) + self.assertEqual('leader', br.get_state()) + + router.start() + self.simulator.go(5) + self.assertEqual('router', router.get_state()) + + # + # Case 1. Border router advertises its local NAT64 prefix. + # + self.simulator.go(5) + local_nat64_prefix = br.get_br_nat64_prefix() + + self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) + nat64_prefix = br.get_netdata_nat64_prefix()[0] + self.assertEqual(nat64_prefix, local_nat64_prefix) + + # + # Case 2. + # User adds a smaller NAT64 prefix and the local prefix is withdrawn. + # User removes the smaller NAT64 prefix and the local prefix is re-added. + # + br.add_route(SMALL_NAT64_PREFIX, stable=False, nat64=True) + br.register_netdata() + self.simulator.go(5) + + self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) + self.assertNotEqual(local_nat64_prefix, br.get_netdata_nat64_prefix()[0]) + + br.remove_route(SMALL_NAT64_PREFIX) + br.register_netdata() + self.simulator.go(5) + + self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) + self.assertEqual(local_nat64_prefix, br.get_netdata_nat64_prefix()[0]) + + # + # Case 3. Disable and re-enable border routing on the border router. + # + br.disable_br() + self.simulator.go(5) + + # NAT64 prefix is withdrawn from Network Data. + self.assertEqual(len(br.get_netdata_nat64_prefix()), 0) + + br.enable_br() + self.simulator.go(5) + + # Same NAT64 prefix is advertised to Network Data. + self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) + self.assertEqual(nat64_prefix, br.get_netdata_nat64_prefix()[0]) + + # + # Case 4. Disable and re-enable ethernet on the border router. + # + br.disable_ether() + self.simulator.go(5) + + # NAT64 prefix is withdrawn from Network Data. + self.assertEqual(len(br.get_netdata_nat64_prefix()), 0) + + br.enable_ether() + self.simulator.go(80) + + # Same NAT64 prefix is advertised to Network Data. + self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) + self.assertEqual(nat64_prefix, br.get_netdata_nat64_prefix()[0]) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/scripts/thread-cert/border_router/test_radvd_coexist.py b/tests/scripts/thread-cert/border_router/test_radvd_coexist.py index 3c4f4845c..dde4de5fd 100755 --- a/tests/scripts/thread-cert/border_router/test_radvd_coexist.py +++ b/tests/scripts/thread-cert/border_router/test_radvd_coexist.py @@ -100,10 +100,10 @@ class SingleBorderRouter(thread_cert.TestCase): logging.info("ROUTER addrs: %r", router.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br.get_prefixes()), 1) - self.assertEqual(len(router.get_prefixes()), 1) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) @@ -120,10 +120,10 @@ class SingleBorderRouter(thread_cert.TestCase): br.stop_radvd_service() self.simulator.go(15) - self.assertEqual(len(br.get_prefixes()), 1) - self.assertEqual(len(router.get_prefixes()), 1) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) diff --git a/tests/scripts/thread-cert/border_router/test_single_border_router.py b/tests/scripts/thread-cert/border_router/test_single_border_router.py index 756786c70..cadd5d36a 100755 --- a/tests/scripts/thread-cert/border_router/test_single_border_router.py +++ b/tests/scripts/thread-cert/border_router/test_single_border_router.py @@ -102,13 +102,13 @@ class SingleBorderRouter(thread_cert.TestCase): logging.info("ROUTER addrs: %r", router.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br.get_prefixes()), 1) - self.assertEqual(len(router.get_prefixes()), 1) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) - omr_prefix = br.get_prefixes()[0] - external_route = br.get_routes()[0] + omr_prefix = br.get_br_omr_prefix() + on_link_prefix = br.get_br_on_link_prefix() self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) @@ -142,10 +142,10 @@ class SingleBorderRouter(thread_cert.TestCase): self.assertGreaterEqual(len(host.get_addrs()), 2) - self.assertEqual(len(br.get_prefixes()), 2) - self.assertEqual(len(router.get_prefixes()), 2) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 2) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 2) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 2) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 2) @@ -168,16 +168,16 @@ class SingleBorderRouter(thread_cert.TestCase): logging.info("ROUTER addrs: %r", router.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br.get_prefixes()), 1) - self.assertEqual(len(router.get_prefixes()), 1) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) # The same local OMR and on-link prefix should be re-register. - self.assertEqual(br.get_prefixes(), [omr_prefix]) - self.assertEqual(router.get_prefixes(), [omr_prefix]) - self.assertEqual(br.get_routes(), [external_route]) - self.assertEqual(router.get_routes(), [external_route]) + self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix]) + self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix]) + self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix]) + self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix]) self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) @@ -222,16 +222,16 @@ class SingleBorderRouter(thread_cert.TestCase): logging.info("ROUTER addrs: %r", router.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br.get_prefixes()), 1) - self.assertEqual(len(router.get_prefixes()), 1) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) # The same local OMR and on-link prefix should be re-registered. - self.assertEqual(br.get_prefixes(), [omr_prefix]) - self.assertEqual(router.get_prefixes(), [omr_prefix]) - self.assertEqual(br.get_routes(), [external_route]) - self.assertEqual(router.get_routes(), [external_route]) + self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix]) + self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix]) + self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix]) + self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix]) self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) @@ -276,16 +276,16 @@ class SingleBorderRouter(thread_cert.TestCase): logging.info("ROUTER addrs: %r", router.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br.get_prefixes()), 1) - self.assertEqual(len(router.get_prefixes()), 1) - self.assertEqual(len(br.get_routes()), 1) - self.assertEqual(len(router.get_routes()), 1) + self.assertEqual(len(br.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(router.get_netdata_omr_prefixes()), 1) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 1) # The same local OMR and on-link prefix should be re-registered. - self.assertEqual(br.get_prefixes(), [omr_prefix]) - self.assertEqual(router.get_prefixes(), [omr_prefix]) - self.assertEqual(br.get_routes(), [external_route]) - self.assertEqual(router.get_routes(), [external_route]) + self.assertEqual(br.get_netdata_omr_prefixes(), [omr_prefix]) + self.assertEqual(router.get_netdata_omr_prefixes(), [omr_prefix]) + self.assertEqual(br.get_netdata_non_nat64_prefixes(), [on_link_prefix]) + self.assertEqual(router.get_netdata_non_nat64_prefixes(), [on_link_prefix]) self.assertEqual(len(br.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) self.assertEqual(len(router.get_ip6_address(config.ADDRESS_TYPE.OMR)), 1) @@ -319,8 +319,8 @@ class SingleBorderRouter(thread_cert.TestCase): br.start_radvd_service(prefix=config.ONLINK_GUA_PREFIX, slaac=True) self.simulator.go(5) - self.assertEqual(len(br.get_routes()), 2) - self.assertEqual(len(router.get_routes()), 2) + self.assertEqual(len(br.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(router.get_netdata_non_nat64_prefixes()), 2) self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_GUA)[0])) self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])) diff --git a/tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py b/tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py index ee5684222..4befa1141 100755 --- a/tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py +++ b/tests/scripts/thread-cert/border_router/test_vicarious_router_solicit.py @@ -122,11 +122,11 @@ class MultiThreadNetworks(thread_cert.TestCase): logging.info("ROUTER1 addrs: %r", router1.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertEqual(len(br1.get_routes()), 1) - br1_on_link_prefix = br1.get_routes()[0].split(' ')[0] - self.assertEqual(IPv6Network(br1_on_link_prefix), IPv6Network(ON_LINK_PREFIX)) + self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1) + on_link_prefix = br1.get_netdata_non_nat64_prefixes()[0] + self.assertEqual(IPv6Network(on_link_prefix), IPv6Network(ON_LINK_PREFIX)) - host_on_link_addr = host.get_matched_ula_addresses(br1_on_link_prefix)[0] + host_on_link_addr = host.get_matched_ula_addresses(on_link_prefix)[0] self.assertTrue(router1.ping(host_on_link_addr)) self.assertTrue( host.ping(router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True, interface=host_on_link_addr)) @@ -151,29 +151,27 @@ class MultiThreadNetworks(thread_cert.TestCase): logging.info("ROUTER2 addrs: %r", router2.get_addrs()) logging.info("HOST addrs: %r", host.get_addrs()) - self.assertTrue(len(br1.get_prefixes()) == 1) - self.assertTrue(len(router1.get_prefixes()) == 1) - self.assertTrue(len(br2.get_prefixes()) == 1) - self.assertTrue(len(router2.get_prefixes()) == 1) + self.assertTrue(len(br1.get_netdata_omr_prefixes()) == 1) + self.assertTrue(len(router1.get_netdata_omr_prefixes()) == 1) + self.assertTrue(len(br2.get_netdata_omr_prefixes()) == 1) + self.assertTrue(len(router2.get_netdata_omr_prefixes()) == 1) - br1_omr_prefix = br1.get_omr_prefix() - br2_omr_prefix = br2.get_omr_prefix() + br1_omr_prefix = br1.get_br_omr_prefix() + br2_omr_prefix = br2.get_br_omr_prefix() self.assertNotEqual(br1_omr_prefix, br2_omr_prefix) # Verify that the Border Routers starts advertsing new on-link prefix # but don't remove the external routes for the radvd on-link prefix # immediately, because the SLAAC addresses are still valid. - self.assertEqual(len(br1.get_routes()), 3) - self.assertEqual(len(router1.get_routes()), 3) - self.assertEqual(len(br2.get_routes()), 2) - self.assertEqual(len(router2.get_routes()), 2) + self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 3) + self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 3) + self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 2) + self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 2) - br1_external_routes = [route.split(' ')[0] for route in br1.get_routes()] - br2_external_routes = [route.split(' ')[0] for route in br2.get_routes()] - - on_link_prefixes = list(set(br1_external_routes).intersection(br2_external_routes)) + on_link_prefixes = list( + set(br1.get_netdata_non_nat64_prefixes()).intersection(br2.get_netdata_non_nat64_prefixes())) self.assertEqual(len(on_link_prefixes), 1) - self.assertEqual(IPv6Network(on_link_prefixes[0]), IPv6Network(br2.get_on_link_prefix())) + self.assertEqual(IPv6Network(on_link_prefixes[0]), IPv6Network(br2.get_br_on_link_prefix())) router1_omr_addr = router1.get_ip6_address(config.ADDRESS_TYPE.OMR)[0] router2_omr_addr = router2.get_ip6_address(config.ADDRESS_TYPE.OMR)[0] diff --git a/tests/scripts/thread-cert/node.py b/tests/scripts/thread-cert/node.py index 3191a5027..5f2b445ca 100755 --- a/tests/scripts/thread-cert/node.py +++ b/tests/scripts/thread-cert/node.py @@ -1897,16 +1897,41 @@ class NodeImpl: self.send_command('br disable') self._expect_done() - def get_omr_prefix(self): + def get_br_omr_prefix(self): cmd = 'br omrprefix' self.send_command(cmd) return self._expect_command_output()[0] - def get_on_link_prefix(self): + def get_netdata_omr_prefixes(self): + prefixes = [prefix.split(' ')[0] for prefix in self.get_prefixes()] + return prefixes + + def get_br_on_link_prefix(self): cmd = 'br onlinkprefix' self.send_command(cmd) return self._expect_command_output()[0] + def get_netdata_non_nat64_prefixes(self): + prefixes = [] + routes = self.get_routes() + for route in routes: + if 'n' not in route.split(' ')[1]: + prefixes.append(route.split(' ')[0]) + return prefixes + + def get_br_nat64_prefix(self): + cmd = 'br nat64prefix' + self.send_command(cmd) + return self._expect_command_output()[0] + + def get_netdata_nat64_prefix(self): + prefixes = [] + routes = self.get_routes() + for route in routes: + if 'n' in route.split(' ')[1]: + prefixes.append(route.split(' ')[0]) + return prefixes + def get_prefixes(self): return self.get_netdata()['Prefixes'] @@ -1944,10 +1969,12 @@ class NodeImpl: return netdata - def add_route(self, prefix, stable=False, prf='med'): + def add_route(self, prefix, stable=False, nat64=False, prf='med'): cmd = 'route add %s ' % prefix if stable: cmd += 's' + if nat64: + cmd += 'n' cmd += ' %s' % prf self.send_command(cmd) self._expect_done()