From 7ff1b5c6618ffe5290ec0bd931ddad307dec142f Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 27 May 2026 11:36:59 -0700 Subject: [PATCH] [child-table] move max child IP addresses logic from `Mle` (#13159) This commit moves the state and logic for managing the maximum number of IP addresses per child from `Mle` to `ChildTable`. The logic for checking the limit is also moved to the `Child` class itself. This change better encapsulates the child table properties. --- src/core/api/thread_ftd_api.cpp | 4 +-- src/core/thread/child.cpp | 10 +++++++ src/core/thread/child_table.cpp | 18 +++++++++++++ src/core/thread/child_table.hpp | 41 +++++++++++++++++++++++++++- src/core/thread/mle.cpp | 3 --- src/core/thread/mle.hpp | 47 +++++++++------------------------ src/core/thread/mle_ftd.cpp | 44 +----------------------------- 7 files changed, 83 insertions(+), 84 deletions(-) diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index d54396e97..464b0ebdf 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -51,13 +51,13 @@ otError otThreadSetMaxAllowedChildren(otInstance *aInstance, uint16_t aMaxChildr uint8_t otThreadGetMaxChildIpAddresses(otInstance *aInstance) { - return AsCoreType(aInstance).Get().GetMaxChildIpAddresses(); + return AsCoreType(aInstance).Get().GetMaxChildIpAddresses(); } #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE otError otThreadSetMaxChildIpAddresses(otInstance *aInstance, uint8_t aMaxIpAddresses) { - return AsCoreType(aInstance).Get().SetMaxChildIpAddresses(aMaxIpAddresses); + return AsCoreType(aInstance).Get().OverrideMaxChildIpAddresses(aMaxIpAddresses); } #endif diff --git a/src/core/thread/child.cpp b/src/core/thread/child.cpp index 42ba0cc74..a3e049e1b 100644 --- a/src/core/thread/child.cpp +++ b/src/core/thread/child.cpp @@ -164,6 +164,16 @@ Error Child::AddIp6Address(const Ip6::Address &aAddress) VerifyOrExit(!aAddress.IsUnspecified(), error = kErrorInvalidArgs); +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + if (Get().IsMaxChildIpAddressesOverridden()) + { + uint8_t num = mMeshLocalIid.IsUnspecified() ? 0 : 1; + + num += mIp6Addresses.GetLength(); + VerifyOrExit(num < Get().GetMaxChildIpAddresses(), error = kErrorNoBufs); + } +#endif + if (Get().IsMeshLocalAddress(aAddress)) { VerifyOrExit(mMeshLocalIid.IsUnspecified(), error = kErrorAlready); diff --git a/src/core/thread/child_table.cpp b/src/core/thread/child_table.cpp index e8360491d..d95c10dc5 100644 --- a/src/core/thread/child_table.cpp +++ b/src/core/thread/child_table.cpp @@ -79,6 +79,9 @@ exit: ChildTable::ChildTable(Instance &aInstance) : InstanceLocator(aInstance) +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + , mMaxChildIpAddresses(0) +#endif , mNextChildId(Mle::kMaxChildId) , mMaxChildrenAllowed(kMaxChildren) { @@ -373,6 +376,21 @@ bool ChildTable::HasSleepyChildWithAddress(const Ip6::Address &aIp6Address) cons return hasChild; } +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + +Error ChildTable::OverrideMaxChildIpAddresses(uint8_t aMaxIpAddresses) +{ + Error error = kErrorNone; + + VerifyOrExit(aMaxIpAddresses <= kMaxChildIpAddresses, error = kErrorInvalidArgs); + mMaxChildIpAddresses = aMaxIpAddresses; + +exit: + return error; +} + +#endif + } // namespace ot #endif // OPENTHREAD_FTD diff --git a/src/core/thread/child_table.hpp b/src/core/thread/child_table.hpp index f6b3abf88..ac2d547ee 100644 --- a/src/core/thread/child_table.hpp +++ b/src/core/thread/child_table.hpp @@ -313,8 +313,44 @@ public: return (mChildren <= child) && (child < GetArrayEnd(mChildren)); } + /** + * Gets the maximum number of IP addresses that each MTD child may register with this device as parent. + * + * @returns The maximum number of IP addresses that each MTD child may register with this device as parent. + */ + uint8_t GetMaxChildIpAddresses(void) const + { + return +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + IsMaxChildIpAddressesOverridden() ? mMaxChildIpAddresses : +#endif + kMaxChildIpAddresses; + } + +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + /** + * Indicates whether the maximum number of IP addresses is overridden. + * + * @retval TRUE If the maximum number of IP addresses is overridden. + * @retval FALSE If the maximum number of IP addresses is not overridden. + */ + bool IsMaxChildIpAddressesOverridden(void) const { return (mMaxChildIpAddresses != 0); } + + /** + * Overrides the maximum number of IP addresses that each MTD child may register with this device as parent. + * + * @param[in] aMaxIpAddresses The maximum number of IP addresses that each MTD child may register with this + * device as parent. Zero to clear the setting and restore the default. + * + * @retval kErrorNone Successfully set/cleared the number. + * @retval kErrorInvalidArgs If exceeds the allowed maximum number. + */ + Error OverrideMaxChildIpAddresses(uint8_t aMaxIpAddresses); +#endif + private: - static constexpr uint16_t kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN; + static constexpr uint16_t kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN; + static constexpr uint8_t kMaxChildIpAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD; class IteratorBuilder : public InstanceLocator { @@ -337,6 +373,9 @@ private: const Child *FindChild(const Child::AddressMatcher &aMatcher) const; void RefreshStoredChildren(void); +#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE + uint8_t mMaxChildIpAddresses; +#endif uint16_t mNextChildId; uint16_t mMaxChildrenAllowed; Child mChildren[kMaxChildren]; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index affa8d337..f560c098f 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -87,9 +87,6 @@ Mle::Mle(Instance &aInstance) , mPreviousPartitionIdTimeout(0) , mChildRouterLinks(kChildRouterLinks) , mAlternateRloc16Timeout(0) -#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - , mMaxChildIpAddresses(0) -#endif , mParentPriority(kParentPriorityUnspecified) , mPreviousPartitionIdRouter(0) , mPreviousPartitionId(0) diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 981ea194e..a43ee6409 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1153,27 +1153,8 @@ public: Error SendTimeSync(void); #endif - /** - * Gets the maximum number of IP addresses that each MTD child may register with this device as parent. - * - * @returns The maximum number of IP addresses that each MTD child may register with this device as parent. - */ - uint8_t GetMaxChildIpAddresses(void) const; - #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - /** - * Sets/restores the maximum number of IP addresses that each MTD child may register with this - * device as parent. - * - * @param[in] aMaxIpAddresses The maximum number of IP addresses that each MTD child may register with this - * device as parent. 0 to clear the setting and restore the default. - * - * @retval kErrorNone Successfully set/cleared the number. - * @retval kErrorInvalidArgs If exceeds the allowed maximum number. - */ - Error SetMaxChildIpAddresses(uint8_t aMaxIpAddresses); - /** * Sets whether the device was commissioned using CCM. * @@ -1361,7 +1342,6 @@ private: static constexpr uint8_t kLinkRequestMinMargin = OPENTHREAD_CONFIG_MLE_LINK_REQUEST_MARGIN_MIN; static constexpr uint8_t kPartitionMergeMinMargin = OPENTHREAD_CONFIG_MLE_PARTITION_MERGE_MARGIN_MIN; static constexpr uint8_t kChildRouterLinks = OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS; - static constexpr uint8_t kMaxChildIpAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD; // Constants for gradual router link establishment (on FTD child) struct GradualChildRouterLink @@ -2575,21 +2555,18 @@ private: #if OPENTHREAD_FTD - bool mAddressSolicitPending : 1; - bool mAddressSolicitRejected : 1; - uint8_t mRouterId; - uint8_t mPreviousRouterId; - uint8_t mNetworkIdTimeout; - uint8_t mRouterUpgradeThreshold; - uint8_t mRouterDowngradeThreshold; - uint8_t mLeaderWeight; - uint8_t mPreviousPartitionRouterIdSequence; - uint8_t mPreviousPartitionIdTimeout; - uint8_t mChildRouterLinks; - uint8_t mAlternateRloc16Timeout; -#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - uint8_t mMaxChildIpAddresses; -#endif + bool mAddressSolicitPending : 1; + bool mAddressSolicitRejected : 1; + uint8_t mRouterId; + uint8_t mPreviousRouterId; + uint8_t mNetworkIdTimeout; + uint8_t mRouterUpgradeThreshold; + uint8_t mRouterDowngradeThreshold; + uint8_t mLeaderWeight; + uint8_t mPreviousPartitionRouterIdSequence; + uint8_t mPreviousPartitionIdTimeout; + uint8_t mChildRouterLinks; + uint8_t mAlternateRloc16Timeout; 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 fc0e47445..7d277cae8 100644 --- a/src/core/thread/mle_ftd.cpp +++ b/src/core/thread/mle_ftd.cpp @@ -1820,34 +1820,6 @@ exit: LogSendError(kTypeParentResponse, error); } -uint8_t Mle::GetMaxChildIpAddresses(void) const -{ - uint8_t num = kMaxChildIpAddresses; - -#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - if (mMaxChildIpAddresses != 0) - { - num = mMaxChildIpAddresses; - } -#endif - - return num; -} - -#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE -Error Mle::SetMaxChildIpAddresses(uint8_t aMaxIpAddresses) -{ - Error error = kErrorNone; - - VerifyOrExit(aMaxIpAddresses <= kMaxChildIpAddresses, error = kErrorInvalidArgs); - - mMaxChildIpAddresses = aMaxIpAddresses; - -exit: - return error; -} -#endif - Error Mle::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild) { Error error; @@ -1927,21 +1899,7 @@ Error Mle::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild) IgnoreError(aRxInfo.mMessage.ReadAndAdvance(offsetRange, address)); } -#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - if (mMaxChildIpAddresses > 0 && storedCount >= mMaxChildIpAddresses) - { - // Skip remaining address registration entries but keep logging - // skipped addresses. - error = kErrorNoBufs; - } - else -#endif - { - // We try to accept/add as many IPv6 addresses as possible. - // "Child ID/Update Response" will indicate the accepted - // addresses. - error = aChild.AddIp6Address(address); - } + error = aChild.AddIp6Address(address); if (error == kErrorNone) {