From 73d3ea54491ae35896f46f9951f5bf52e46c34e9 Mon Sep 17 00:00:00 2001 From: Yi Date: Tue, 16 May 2023 00:57:20 +0800 Subject: [PATCH] [nat64] check OMR prefix when selecting favored NAT64 prefix (#8995) This commit adds a check on OMR prefix before selecting AIL prefix as the favored NAT64 prefix for publishing. --- src/core/border_router/routing_manager.cpp | 14 +-- .../nat64/test_multi_border_routers.py | 11 +- .../nat64/test_with_infrastructure_prefix.py | 33 +++-- tests/toranj/openthread-core-toranj-config.h | 8 ++ tests/unit/test_routing_manager.cpp | 118 ++++++++++++++++++ 5 files changed, 167 insertions(+), 17 deletions(-) diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index 24669f5bf..0c436c242 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -2869,16 +2869,14 @@ void RoutingManager::Nat64PrefixManager::GenerateLocalPrefix(const Ip6::Prefix & const Ip6::Prefix &RoutingManager::Nat64PrefixManager::GetFavoredPrefix(RoutePreference &aPreference) const { - const Ip6::Prefix *favoredPrefix = &mInfraIfPrefix; + const Ip6::Prefix *favoredPrefix = &mLocalPrefix; - if (mInfraIfPrefix.IsValidNat64()) + aPreference = NetworkData::kRoutePreferenceLow; + + if (mInfraIfPrefix.IsValidNat64() && Get().mFavoredOmrPrefix.IsInfrastructureDerived()) { - aPreference = NetworkData::kRoutePreferenceMedium; - } - else - { - favoredPrefix = &mLocalPrefix; - aPreference = NetworkData::kRoutePreferenceLow; + favoredPrefix = &mInfraIfPrefix; + aPreference = NetworkData::kRoutePreferenceMedium; } return *favoredPrefix; diff --git a/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py b/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py index 7a4791d44..46896bc50 100755 --- a/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py +++ b/tests/scripts/thread-cert/border_router/nat64/test_multi_border_routers.py @@ -49,6 +49,8 @@ ROUTER = 2 BR2 = 3 HOST = 4 +OMR_PREFIX = "2000:0:1111:4444::/64" + NAT64_PREFIX_REFRESH_DELAY = 305 NAT64_STATE_DISABLED = 'disabled' @@ -118,9 +120,15 @@ class Nat64MultiBorderRouter(thread_cert.TestCase): self.simulator.go(config.BORDER_ROUTER_STARTUP_DELAY) self.assertEqual('router', br2.get_state()) + br2.add_prefix(OMR_PREFIX) + br2.register_netdata() + self.simulator.go(10) + self.simulator.go(10) self.assertNotEqual(br1.get_br_favored_nat64_prefix(), br2.get_br_favored_nat64_prefix()) br1_local_nat64_prefix = br1.get_br_nat64_prefix() + br2_local_nat64_prefix = br2.get_br_nat64_prefix() + self.assertNotEqual(br2_local_nat64_prefix, br2.get_br_favored_nat64_prefix()) br2_infra_nat64_prefix = br2.get_br_favored_nat64_prefix() self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1) @@ -164,8 +172,7 @@ class Nat64MultiBorderRouter(thread_cert.TestCase): br2.nat64_set_enabled(True) self.simulator.go(10) - self.assertNotEqual(br2_infra_nat64_prefix, br2.get_br_favored_nat64_prefix()) - br2_local_nat64_prefix = br2.get_br_nat64_prefix() + self.assertEqual(br2_local_nat64_prefix, br2.get_br_favored_nat64_prefix()) self.assertEqual(len(br1.get_netdata_nat64_prefix()), 1) nat64_prefix = br1.get_netdata_nat64_prefix()[0] diff --git a/tests/scripts/thread-cert/border_router/nat64/test_with_infrastructure_prefix.py b/tests/scripts/thread-cert/border_router/nat64/test_with_infrastructure_prefix.py index 465b5a7a1..905e6f259 100755 --- a/tests/scripts/thread-cert/border_router/nat64/test_with_infrastructure_prefix.py +++ b/tests/scripts/thread-cert/border_router/nat64/test_with_infrastructure_prefix.py @@ -47,6 +47,7 @@ import thread_cert BR = 1 ROUTER = 2 +OMR_PREFIX = "2000:0:1111:4444::/64" # The prefix is set smaller than the default infrastructure NAT64 prefix. SMALL_NAT64_PREFIX = "2000:0:0:1:0:0::/96" @@ -90,8 +91,26 @@ class Nat64SingleBorderRouter(thread_cert.TestCase): self.simulator.go(config.ROUTER_STARTUP_DELAY) self.assertEqual('router', router.get_state()) - # Case 1 BR advertise the infrastructure prefix - infra_nat64_prefix = br.get_br_favored_nat64_prefix() + # Case 1 No infra-derived OMR prefix. BR publishes its local prefix. + 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) + + self.assertDictIncludes(br.nat64_state, { + 'PrefixManager': NAT64_STATE_ACTIVE, + 'Translator': NAT64_STATE_ACTIVE + }) + + # Case 2 Add OMR prefix. BR publishes the infrastructure nat64 prefix + br.add_prefix(OMR_PREFIX) + br.register_netdata() + self.simulator.go(10) + + favored_nat64_prefix = br.get_br_favored_nat64_prefix() + self.assertNotEqual(favored_nat64_prefix, local_nat64_prefix) + infra_nat64_prefix = favored_nat64_prefix self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) nat64_prefix = br.get_netdata_nat64_prefix()[0] @@ -101,7 +120,7 @@ class Nat64SingleBorderRouter(thread_cert.TestCase): 'Translator': NAT64_STATE_NOT_RUNNING }) - # Case 2 Withdraw infrastructure prefix when a smaller prefix in medium + # Case 3 Unpublish infrastructure prefix when a smaller prefix in medium # preference is present br.add_route(SMALL_NAT64_PREFIX, stable=False, nat64=True, prf='med') br.register_netdata() @@ -121,7 +140,7 @@ class Nat64SingleBorderRouter(thread_cert.TestCase): self.assertEqual(len(br.get_netdata_nat64_prefix()), 1) self.assertEqual(nat64_prefix, infra_nat64_prefix) - # Case 3 No change when a smaller prefix in low preference is present + # Case 4 No change when a smaller prefix in low preference is present br.add_route(SMALL_NAT64_PREFIX, stable=False, nat64=True, prf='low') br.register_netdata() self.simulator.go(5) @@ -137,7 +156,7 @@ class Nat64SingleBorderRouter(thread_cert.TestCase): br.register_netdata() self.simulator.go(5) - # Case 4 Infrastructure nat64 prefix no longer presents + # Case 5 Infrastructure nat64 prefix no longer presents br.bash("service bind9 stop") self.simulator.go(NAT64_PREFIX_REFRESH_DELAY) @@ -150,7 +169,7 @@ class Nat64SingleBorderRouter(thread_cert.TestCase): 'Translator': NAT64_STATE_ACTIVE }) - # Case 5 Infrastructure nat64 prefix is recovered + # Case 6 Infrastructure nat64 prefix is recovered br.bash("service bind9 start") self.simulator.go(NAT64_PREFIX_REFRESH_DELAY) @@ -162,7 +181,7 @@ class Nat64SingleBorderRouter(thread_cert.TestCase): 'Translator': NAT64_STATE_NOT_RUNNING }) - # Case 6 Change infrastructure nat64 prefix + # Case 7 Change infrastructure nat64 prefix br.bash("sed -i 's/dns64 /\/\/dns64 /' /etc/bind/named.conf.options") br.bash("sed -i '/\/\/dns64 /a dns64 " + SMALL_NAT64_PREFIX + " {};' /etc/bind/named.conf.options") br.bash("service bind9 restart") diff --git a/tests/toranj/openthread-core-toranj-config.h b/tests/toranj/openthread-core-toranj-config.h index 1812c81a4..6f34920d4 100644 --- a/tests/toranj/openthread-core-toranj-config.h +++ b/tests/toranj/openthread-core-toranj-config.h @@ -75,6 +75,14 @@ */ #define OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + * + * Define to 1 to enable NAT64 support in Border Routing Manager. + * + */ +#define OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1 + /** * @def OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE * diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index bd1174b13..0177b1903 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -158,6 +158,7 @@ void ValidateRouterAdvert(const Icmp6Packet &aPacket); const char *PreferenceToString(int8_t aPreference); void SendRouterAdvert(const Ip6::Address &aAddress, const Icmp6Packet &aPacket); void SendNeighborAdvert(const Ip6::Address &aAddress, const Ip6::Nd::NeighborAdvertMessage &aNaMessage); +void DiscoverNat64Prefix(const Ip6::Prefix &aPrefix); #if OPENTHREAD_CONFIG_LOG_OUTPUT == OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) @@ -502,6 +503,13 @@ void SendNeighborAdvert(const Ip6::Address &aAddress, const Ip6::Nd::NeighborAdv sizeof(aNaMessage)); } +void DiscoverNat64Prefix(const Ip6::Prefix &aPrefix) +{ + Log("Discovered NAT64 prefix %s", aPrefix.ToString().AsCString()); + + otPlatInfraIfDiscoverNat64PrefixDone(sInstance, kInfraIfIndex, &aPrefix); +} + Ip6::Prefix PrefixFromString(const char *aString, uint8_t aPrefixLength) { Ip6::Prefix prefix; @@ -589,6 +597,31 @@ void VerifyExternalRouteInNetData(ExternalRouteMode aMode) } } +void VerifyNat64PrefixInNetData(const Ip6::Prefix &aNat64Prefix) +{ + otNetworkDataIterator iterator = OT_NETWORK_DATA_ITERATOR_INIT; + NetworkData::ExternalRouteConfig routeConfig; + bool didFind = false; + + Log("VerifyNat64PrefixInNetData()"); + + while (otNetDataGetNextRoute(sInstance, &iterator, &routeConfig) == kErrorNone) + { + if (!routeConfig.mNat64 || !routeConfig.GetPrefix().IsValidNat64()) + { + continue; + } + + Log(" nat64 prefix:%s, prf:%s", routeConfig.GetPrefix().ToString().AsCString(), + PreferenceToString(routeConfig.mPreference)); + + VerifyOrQuit(routeConfig.GetPrefix() == aNat64Prefix); + didFind = true; + } + + VerifyOrQuit(didFind); +} + struct Pio { Pio(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime) @@ -3003,6 +3036,88 @@ void TestAutoEnableOfSrpServer(void) } #endif // OPENTHREAD_CONFIG_SRP_SERVER_ENABLE +#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE +void TestNat64PrefixSelection(void) +{ + Ip6::Prefix localNat64; + Ip6::Prefix ailNat64 = PrefixFromString("2000:0:0:1:0:0::", 96); + Ip6::Prefix localOmr; + Ip6::Prefix omrPrefix = PrefixFromString("2000:0000:1111:4444::", 64); + NetworkData::OnMeshPrefixConfig prefixConfig; + + Log("--------------------------------------------------------------------------------------------"); + Log("TestNat64PrefixSelection"); + + InitTest(); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Start Routing Manager. Check local NAT64 prefix generation. + + SuccessOrQuit(sInstance->Get().SetEnabled(true)); + SuccessOrQuit(sInstance->Get().GetNat64Prefix(localNat64)); + SuccessOrQuit(sInstance->Get().GetOmrPrefix(localOmr)); + + Log("Local nat64 prefix is %s", localNat64.ToString().AsCString()); + Log("Local OMR prefix is %s", localOmr.ToString().AsCString()); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Enable Nat64 Prefix Manager. Check local NAT64 prefix in Network Data. + + sInstance->Get().SetNat64PrefixManagerEnabled(true); + + AdvanceTime(20000); + + VerifyOmrPrefixInNetData(localOmr); + VerifyNat64PrefixInNetData(localNat64); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // AIL NAT64 prefix discovered. No infra-derived OMR prefix in Network Data. + // Check local NAT64 prefix in Network Data. + + DiscoverNat64Prefix(ailNat64); + + AdvanceTime(20000); + + VerifyNat64PrefixInNetData(localNat64); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // Add a medium preference OMR prefix into Network Data. + // Check AIL NAT64 prefix published in Network Data. + + prefixConfig.Clear(); + prefixConfig.mPrefix = omrPrefix; + prefixConfig.mStable = true; + prefixConfig.mSlaac = true; + prefixConfig.mPreferred = true; + prefixConfig.mOnMesh = true; + prefixConfig.mDefaultRoute = false; + prefixConfig.mPreference = NetworkData::kRoutePreferenceMedium; + + SuccessOrQuit(otBorderRouterAddOnMeshPrefix(sInstance, &prefixConfig)); + SuccessOrQuit(otBorderRouterRegister(sInstance)); + + AdvanceTime(20000); + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyNat64PrefixInNetData(ailNat64); + + //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // AIL NAT64 prefix removed. + // Check local NAT64 prefix in Network Data. + + ailNat64.Clear(); + DiscoverNat64Prefix(ailNat64); + + AdvanceTime(20000); + + VerifyOmrPrefixInNetData(omrPrefix); + VerifyNat64PrefixInNetData(localNat64); + + Log("End of TestNat64PrefixSelection"); + FinalizeTest(); +} +#endif // OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + #endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE int main(void) @@ -3025,6 +3140,9 @@ int main(void) #if OPENTHREAD_CONFIG_SRP_SERVER_ENABLE TestAutoEnableOfSrpServer(); #endif +#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE + TestNat64PrefixSelection(); +#endif printf("All tests passed\n"); #else