diff --git a/src/core/border_router/routing_manager.cpp b/src/core/border_router/routing_manager.cpp index eabf9f4ac..5f1884e38 100644 --- a/src/core/border_router/routing_manager.cpp +++ b/src/core/border_router/routing_manager.cpp @@ -47,6 +47,7 @@ #include "common/log.hpp" #include "common/random.hpp" #include "common/settings.hpp" +#include "meshcop/extended_panid.hpp" #include "net/ip6.hpp" #include "thread/network_data_leader.hpp" #include "thread/network_data_local.hpp" @@ -101,7 +102,7 @@ Error RoutingManager::Init(uint32_t aInfraIfIndex, bool aInfraIfIsRunning) #if OPENTHREAD_CONFIG_BORDER_ROUTING_NAT64_ENABLE GenerateNat64Prefix(); #endif - SuccessOrExit(error = LoadOrGenerateRandomOnLinkPrefix()); + GenerateOnLinkPrefix(); mInfraIfIndex = aInfraIfIndex; @@ -222,37 +223,18 @@ void RoutingManager::GenerateNat64Prefix(void) } #endif -Error RoutingManager::LoadOrGenerateRandomOnLinkPrefix(void) +void RoutingManager::GenerateOnLinkPrefix(void) { - Error error = kErrorNone; - bool generated = false; + MeshCoP::ExtendedPanId extPanId = Get().GetExtPanId(); - if (Get().Read(mLocalOnLinkPrefix) != kErrorNone || - !mLocalOnLinkPrefix.IsUniqueLocal()) - { - Ip6::NetworkPrefix randomOnLinkPrefix; + mLocalOnLinkPrefix.mPrefix.mFields.m8[0] = 0xfd; + // Global ID: 40 most significant bits of Extended PAN ID + memcpy(mLocalOnLinkPrefix.mPrefix.mFields.m8 + 1, extPanId.m8, 5); + // Subnet ID: 16 least significant bits of Extended PAN ID + memcpy(mLocalOnLinkPrefix.mPrefix.mFields.m8 + 6, extPanId.m8 + 6, 2); + mLocalOnLinkPrefix.SetLength(kOnLinkPrefixLength); - error = randomOnLinkPrefix.GenerateRandomUla(); - if (error != kErrorNone) - { - LogCrit("Failed to generate random on-link prefix"); - ExitNow(); - } - - mLocalOnLinkPrefix.Set(randomOnLinkPrefix); - mLocalOnLinkPrefix.SetSubnetId(0); - - IgnoreError(Get().Save(mLocalOnLinkPrefix)); - generated = true; - } - - OT_UNUSED_VARIABLE(generated); - - LogNote("Local on-link prefix: %s (%s)", mLocalOnLinkPrefix.ToString().AsCString(), - generated ? "generated" : "loaded"); - -exit: - return error; + LogNote("Local on-link prefix: %s", mLocalOnLinkPrefix.ToString().AsCString()); } void RoutingManager::EvaluateState(void) @@ -397,6 +379,24 @@ void RoutingManager::HandleNotifierEvents(Events aEvents) StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter); } + if (aEvents.Contains(kEventThreadExtPanIdChanged)) + { + if (mIsAdvertisingLocalOnLinkPrefix) + { + RemoveExternalRoute(mLocalOnLinkPrefix); + // TODO: consider deprecating/invalidating existing + // on-link prefix + mIsAdvertisingLocalOnLinkPrefix = false; + } + + GenerateOnLinkPrefix(); + + if (mIsRunning) + { + StartRoutingPolicyEvaluationJitter(kRoutingPolicyEvaluationJitter); + } + } + exit: return; } diff --git a/src/core/border_router/routing_manager.hpp b/src/core/border_router/routing_manager.hpp index 0023e9e65..c601370ef 100644 --- a/src/core/border_router/routing_manager.hpp +++ b/src/core/border_router/routing_manager.hpp @@ -317,7 +317,7 @@ private: bool IsEnabled(void) const { return mIsEnabled; } Error LoadOrGenerateRandomBrUlaPrefix(void); void GenerateOmrPrefix(void); - Error LoadOrGenerateRandomOnLinkPrefix(void); + void GenerateOnLinkPrefix(void); const Ip6::Prefix *EvaluateOnLinkPrefix(void); 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 73dc85f9c..5e4eeabd7 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 @@ -191,12 +191,13 @@ class MultiBorderRouters(thread_cert.TestCase): 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_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) + # There should be no changes to the external route for the + # on-link prefix, given that the on-link prefix is derived + # from the Extended PAN ID. + self.assertEqual(len(br1.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router1.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(br2.get_netdata_non_nat64_prefixes()), 1) + self.assertEqual(len(router2.get_netdata_non_nat64_prefixes()), 1) br2_on_link_prefix = br2.get_br_on_link_prefix() self.assertEqual(set(map(IPv6Network, br2.get_netdata_non_nat64_prefixes())), 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 24ba05f43..4776fefbe 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 @@ -28,6 +28,7 @@ # import logging import unittest +from ipaddress import IPv6Network import config import thread_cert @@ -326,6 +327,25 @@ class SingleBorderRouter(thread_cert.TestCase): self.assertTrue(router.ping(host.get_ip6_address(config.ADDRESS_TYPE.ONLINK_ULA)[0])) self.assertTrue(host.ping(router.get_ip6_address(config.ADDRESS_TYPE.OMR)[0], backbone=True)) + # + # Case 7. Test if Border Router changes on-link prefix when + # Extended PAN ID changes. + # + + prefixA = br.get_br_on_link_prefix() + + router.commissioner_start() + self.simulator.go(5) + + router.send_mgmt_active_set( + active_timestamp=100, + extended_panid='0001020304050607', + ) + self.simulator.go(10) + + prefixB = br.get_br_on_link_prefix() + self.assertNotEqual(IPv6Network(prefixA), IPv6Network(prefixB)) + if __name__ == '__main__': unittest.main() 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 7c09f9601..5c1e55847 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 @@ -67,6 +67,7 @@ class MultiThreadNetworks(thread_cert.TestCase): 'version': '1.2', 'channel': CHANNEL1, 'router_selection_jitter': 1, + 'extended_panid': '0001020304050607' }, ROUTER1: { 'name': 'Router_1', @@ -74,6 +75,7 @@ class MultiThreadNetworks(thread_cert.TestCase): 'version': '1.2', 'channel': CHANNEL1, 'router_selection_jitter': 1, + 'extended_panid': '0001020304050607' }, BR2: { 'name': 'BR_2', @@ -82,6 +84,7 @@ class MultiThreadNetworks(thread_cert.TestCase): 'version': '1.2', 'channel': CHANNEL2, 'router_selection_jitter': 1, + 'extended_panid': '08090a0b0c0d0e0f' }, ROUTER2: { 'name': 'Router_2', @@ -89,6 +92,7 @@ class MultiThreadNetworks(thread_cert.TestCase): 'version': '1.2', 'channel': CHANNEL2, 'router_selection_jitter': 1, + 'extended_panid': '08090a0b0c0d0e0f' }, HOST: { 'name': 'Host', diff --git a/tests/scripts/thread-cert/thread_cert.py b/tests/scripts/thread-cert/thread_cert.py index 0dacebd12..fdbdacec4 100755 --- a/tests/scripts/thread-cert/thread_cert.py +++ b/tests/scripts/thread-cert/thread_cert.py @@ -183,6 +183,8 @@ class TestCase(NcpSupportMixin, unittest.TestCase): self.nodes[i].set_panid(params['panid']) self.nodes[i].set_mode(params['mode']) + if 'extended_panid' in params: + self.nodes[i].set_extpanid(params['extended_panid']) if 'partition_id' in params: self.nodes[i].set_preferred_partition_id(params['partition_id']) if 'channel' in params: