diff --git a/include/openthread/instance.h b/include/openthread/instance.h index dc33b436a..bce260b5e 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (606) +#define OPENTHREAD_API_VERSION (607) /** * @addtogroup api-instance diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index 5342c9d5e..faea9a3cd 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -394,11 +394,17 @@ void otThreadSetNetworkIdTimeout(otInstance *aInstance, uint8_t aTimeout); uint8_t otThreadGetRouterUpgradeThreshold(otInstance *aInstance); /** - * Set the ROUTER_UPGRADE_THRESHOLD parameter used in the Leader role. + * Sets the ROUTER_UPGRADE_THRESHOLD parameter. * * @note This API is reserved for testing and demo purposes only. Changing settings with * this API will render a production application non-compliant with the Thread Specification. * + * This API historically set a single threshold value that was used for both local role transitions (deciding when + * the device itself should upgrade to a router) and by the leader (deciding whether to allow other devices to + * upgrade). These behaviors have now been separated into distinct router and leader thresholds. To preserve backward + * compatibility with existing applications and test scripts, this function continues to configure both thresholds + * (both the local router upgrade threshold and the leader upgrade threshold). + * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aThreshold The ROUTER_UPGRADE_THRESHOLD value. * diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 464b0ebdf..2c09a862d 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -152,6 +152,7 @@ uint8_t otThreadGetRouterUpgradeThreshold(otInstance *aInstance) void otThreadSetRouterUpgradeThreshold(otInstance *aInstance, uint8_t aThreshold) { AsCoreType(aInstance).Get().SetRouterUpgradeThreshold(aThreshold); + AsCoreType(aInstance).Get().SetLeaderUpgradeThreshold(aThreshold); } uint8_t otThreadGetChildRouterLinks(otInstance *aInstance) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index b8844b551..cf3c3904f 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -87,6 +87,7 @@ Mle::Mle(Instance &aInstance) , mPreviousPartitionIdTimeout(0) , mChildRouterLinks(kChildRouterLinks) , mAlternateRloc16Timeout(0) + , mLeaderUpgradeThreshold(kRouterUpgradeThreshold) , mParentPriority(kParentPriorityUnspecified) , mPreviousPartitionIdRouter(0) , mPreviousPartitionId(0) diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 1fb5fe5e5..35901bca1 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -987,10 +987,33 @@ public: /** * Sets the ROUTER_UPGRADE_THRESHOLD value. * + * This threshold is used by the device to decide whether to upgrade from a child (REED) to a router role. It is + * not used when the device is acting as the Leader to evaluate upgrade requests from other devices. + * * @param[in] aThreshold The ROUTER_UPGRADE_THRESHOLD value. */ void SetRouterUpgradeThreshold(uint8_t aThreshold) { mRoleTransitioner.SetUpgradeThreshold(aThreshold); } + /** + * Returns the leader upgrade threshold value. + * + * This threshold is used only when the device is operating as the Leader to decide whether to accept or reject + * an Address Solicit request from a router-eligible end device (REED) wishing to upgrade to a router. + * + * @returns The leader upgrade threshold value. + */ + uint8_t GetLeaderUpgradeThreshold(void) const { return mLeaderUpgradeThreshold; } + + /** + * Sets the leader upgrade threshold value. + * + * This threshold is used only when the device is operating as the Leader to decide whether to accept or reject + * an Address Solicit request from a router-eligible end device (REED) wishing to upgrade to a router. + * + * @param[in] aThreshold The leader upgrade threshold value. + */ + void SetLeaderUpgradeThreshold(uint8_t aThreshold) { mLeaderUpgradeThreshold = aThreshold; } + /** * Returns the ROUTER_DOWNGRADE_THRESHOLD value. * @@ -2604,6 +2627,7 @@ private: uint8_t mPreviousPartitionIdTimeout; uint8_t mChildRouterLinks; uint8_t mAlternateRloc16Timeout; + uint8_t mLeaderUpgradeThreshold; int8_t mParentPriority; uint32_t mPreviousPartitionIdRouter; uint32_t mPreviousPartitionId; diff --git a/src/core/thread/mle_ftd.cpp b/src/core/thread/mle_ftd.cpp index 1f8a0ed63..981467397 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -3457,7 +3457,7 @@ void Mle::ProcessAddressSolicit(AddrSolicitInfo &aInfo) switch (aInfo.mReason) { case kReasonTooFewRouters: - VerifyOrExit(mRoleTransitioner.IsRouterCountBelowUpgradeThreshold()); + VerifyOrExit(Get().GetActiveRouterCount() < mLeaderUpgradeThreshold); break; case kReasonHaveChildIdRequest: @@ -3465,7 +3465,7 @@ void Mle::ProcessAddressSolicit(AddrSolicitInfo &aInfo) break; case kReasonBorderRouterRequest: - if (!mRoleTransitioner.IsRouterCountBelowUpgradeThreshold() && + if ((Get().GetActiveRouterCount() >= mLeaderUpgradeThreshold) && (Get().CountBorderRouters(NetworkData::kRouterRoleOnly) >= kRouterUpgradeBorderRouterRequestThreshold)) { diff --git a/tests/nexus/test_1_1_5_2_3.cpp b/tests/nexus/test_1_1_5_2_3.cpp index 7b6c62c81..a9d19203c 100644 --- a/tests/nexus/test_1_1_5_2_3.cpp +++ b/tests/nexus/test_1_1_5_2_3.cpp @@ -89,7 +89,9 @@ void Test5_2_3(void) SuccessOrQuit(Instance::SetGlobalLogLevel(kLogLevelNote)); leader.Get().SetRouterUpgradeThreshold(kMaxRouters); + leader.Get().SetLeaderUpgradeThreshold(kMaxRouters); leader.Get().SetRouterDowngradeThreshold(kMaxRouters); + for (uint8_t i = 0; i < kMaxRouters; i++) { routers[i]->Get().SetRouterUpgradeThreshold(kMaxRouters); diff --git a/tests/nexus/test_1_1_5_2_6.cpp b/tests/nexus/test_1_1_5_2_6.cpp index 40a39214f..424cf2351 100644 --- a/tests/nexus/test_1_1_5_2_6.cpp +++ b/tests/nexus/test_1_1_5_2_6.cpp @@ -109,6 +109,7 @@ void Test_5_2_6(void) SuccessOrQuit(Instance::SetGlobalLogLevel(kLogLevelNote)); leader.Get().SetRouterUpgradeThreshold(kRouterUpgradeThreshold); + leader.Get().SetLeaderUpgradeThreshold(kRouterUpgradeThreshold); leader.Get().SetRouterDowngradeThreshold(kRouterDowngradeThreshold); for (uint16_t i = 0; i < kInitialRouterCount - 2; i++) diff --git a/tests/nexus/test_br_upgrade_router_role.cpp b/tests/nexus/test_br_upgrade_router_role.cpp index aa5140798..8a4f3627e 100644 --- a/tests/nexus/test_br_upgrade_router_role.cpp +++ b/tests/nexus/test_br_upgrade_router_role.cpp @@ -76,6 +76,8 @@ void TestBrUpgradeRouterRole(void) Log("Set the router upgrade threshold to 2 on all nodes."); leader.Get().SetRouterUpgradeThreshold(2); + leader.Get().SetLeaderUpgradeThreshold(2); + router.Get().SetRouterUpgradeThreshold(2); br1.Get().SetRouterUpgradeThreshold(2); br2.Get().SetRouterUpgradeThreshold(2); diff --git a/tests/nexus/test_compact_route_tlv.cpp b/tests/nexus/test_compact_route_tlv.cpp index d8d22b720..2acbaa37e 100644 --- a/tests/nexus/test_compact_route_tlv.cpp +++ b/tests/nexus/test_compact_route_tlv.cpp @@ -51,6 +51,7 @@ void TestCompactRouteTlv(void) Log("Form topology - leader + %u routers", kNumRouters); leader.Get().SetRouterUpgradeThreshold(32); + leader.Get().SetLeaderUpgradeThreshold(32); leader.Get().SetRouterDowngradeThreshold(33); leader.Form(); diff --git a/tests/nexus/test_reed_address_solicit_rejected.cpp b/tests/nexus/test_reed_address_solicit_rejected.cpp index b333a447d..b58f839f6 100644 --- a/tests/nexus/test_reed_address_solicit_rejected.cpp +++ b/tests/nexus/test_reed_address_solicit_rejected.cpp @@ -50,6 +50,7 @@ void TestReedAddressSolicitRejected(void) // Leader sets RouterUpgradeThreshold to 1 to reject further routers leader.Get().SetRouterUpgradeThreshold(1); + leader.Get().SetLeaderUpgradeThreshold(1); Log("Step 1: Form network and join REED"); AllowLinkBetween(leader, reed); diff --git a/tests/nexus/test_router_reattach.cpp b/tests/nexus/test_router_reattach.cpp index 44db1dfb2..07abef2c0 100644 --- a/tests/nexus/test_router_reattach.cpp +++ b/tests/nexus/test_router_reattach.cpp @@ -62,6 +62,7 @@ void TestRouterReattach(void) // Step 1: Start Leader Log("Step 1: Starting Leader"); nodes[0]->Get().SetRouterUpgradeThreshold(32); + nodes[0]->Get().SetLeaderUpgradeThreshold(32); nodes[0]->Get().SetRouterDowngradeThreshold(32); nodes[0]->Form(); nexus.AdvanceTime(kFormNetworkTime); diff --git a/tests/nexus/test_srp_server_reboot_port.cpp b/tests/nexus/test_srp_server_reboot_port.cpp index ff25105fa..1434d3da3 100644 --- a/tests/nexus/test_srp_server_reboot_port.cpp +++ b/tests/nexus/test_srp_server_reboot_port.cpp @@ -80,6 +80,7 @@ void TestSrpServerRebootPort(void) Log("0. Start the server & client devices."); client.Get().SetRouterUpgradeThreshold(2); + client.Get().SetLeaderUpgradeThreshold(2); server.Get().SetRouterUpgradeThreshold(2); client.Form();