From 1f37da29e5e4e3829d87751fee121d9cbce202a6 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Thu, 13 Mar 2025 13:27:49 +0800 Subject: [PATCH] [csl] update CSL parameters only when necessary (#11312) The current MLE and MAC layers will trigger a call to "SubMac::UpdateCsl()" when the CSL state or CSL parameters change. This will bring a lot of unnecessary interface call overhead when we make RCP support CSL receiver in the future. This PR refactors the code so that the MLE and MAC layers only trigger a call to `UpdateCsl` when a valid state or parameter change occurs. --- src/core/api/link_api.cpp | 2 +- src/core/mac/mac.cpp | 119 +++++++++++++++++++------- src/core/mac/mac.hpp | 31 +++---- src/core/mac/mac_links.hpp | 12 +-- src/core/mac/sub_mac.hpp | 15 ++-- src/core/mac/sub_mac_csl_receiver.cpp | 4 +- src/core/thread/mle.cpp | 13 ++- src/core/thread/mle.hpp | 7 ++ src/core/thread/mle_router.cpp | 4 - 9 files changed, 126 insertions(+), 81 deletions(-) diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp index 1a46d51aa..15767000f 100644 --- a/src/core/api/link_api.cpp +++ b/src/core/api/link_api.cpp @@ -421,7 +421,7 @@ uint16_t otLinkGetCcaFailureRate(otInstance *aInstance) #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE bool otLinkIsCslEnabled(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsCslEnabled(); } -bool otLinkIsCslSupported(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsCslSupported(); } +bool otLinkIsCslSupported(otInstance *aInstance) { return AsCoreType(aInstance).Get().IsCslSupported(); } uint8_t otLinkGetCslChannel(otInstance *aInstance) { return AsCoreType(aInstance).Get().GetCslChannel(); } diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index d21aeb927..4596f0855 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -83,6 +83,8 @@ Mac::Mac(Instance &aInstance) #endif #endif #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + , mIsCslEnabled(false) + , mIsCslCapable(false) , mCslChannel(0) , mCslPeriod(0) #endif @@ -423,6 +425,9 @@ exit: Error Mac::SetPanChannel(uint8_t aChannel) { Error error = kErrorNone; +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + bool isPanChannelChanged = (mPanChannel != aChannel); +#endif VerifyOrExit(mSupportedChannelMask.ContainsChannel(aChannel), error = kErrorInvalidArgs); @@ -435,7 +440,10 @@ Error Mac::SetPanChannel(uint8_t aChannel) mRadioChannel = mPanChannel; #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - UpdateCsl(); + if ((mCslChannel == 0) && isPanChannelChanged) + { + UpdateCslParameters(); + } #endif UpdateIdleMode(); @@ -2423,36 +2431,32 @@ exit: #endif #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -void Mac::UpdateCsl(void) +void Mac::SetCslCapable(bool aIsCslCapable) { - uint16_t period = IsCslEnabled() ? GetCslPeriod() : 0; - uint8_t channel = GetCslChannel() ? GetCslChannel() : mPanChannel; + VerifyOrExit(mIsCslCapable != aIsCslCapable); + mIsCslCapable = aIsCslCapable; + UpdateCslState(); - if (mLinks.UpdateCsl(period, channel, Get().GetParent().GetRloc16(), - Get().GetParent().GetExtAddress())) - { - if (Get().IsChild()) - { - Get().RecalculatePollPeriod(); - - if (period != 0) - { - Get().ScheduleChildUpdateRequest(); - } - } - - UpdateIdleMode(); - } +exit: + return; } void Mac::SetCslChannel(uint8_t aChannel) { + VerifyOrExit(mCslChannel != aChannel); mCslChannel = aChannel; - UpdateCsl(); + UpdateCslParameters(); + +exit: + return; } void Mac::SetCslPeriod(uint16_t aPeriod) { + bool shouldUpdateCslState; + + VerifyOrExit(mCslPeriod != aPeriod); + #if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE if (IsWakeupListenEnabled() && aPeriod != 0) { @@ -2461,8 +2465,70 @@ void Mac::SetCslPeriod(uint16_t aPeriod) } #endif - mCslPeriod = aPeriod; - UpdateCsl(); + // A CSL period value of 0 means that the CSL is disabled. + shouldUpdateCslState = ((mCslPeriod == 0) != (aPeriod == 0)); + mCslPeriod = aPeriod; + + if (shouldUpdateCslState) + { + UpdateCslState(); + } + else + { + UpdateCslParameters(); + } + +exit: + return; +} + +void Mac::UpdateCslState(void) +{ + // This method will enable/disable CSL when the CSL state (enabled/disabled) is changed. Otherwise, nothing to do. + bool isCslEnabled = mIsCslCapable && (mCslPeriod > 0); + + VerifyOrExit(mIsCslEnabled != isCslEnabled); + + mIsCslEnabled = isCslEnabled; + + if (mIsCslEnabled) + { + UpdateCslParameters(); + // Request the Mac to enter sleep state. + UpdateIdleMode(); + } + else + { + // The platform API `otPlatRadioEnableCsl()` description says that disable CSL by setting the CSL period to 0. + // However, this description does not say whether the parameter `aExtAddr` can be set to nullptr or how to set + // the `aExtAddr` when the CSL is disabled. Here, an empty ExtAddress is set to meet the API requirement. + ExtAddress extAddress; + + extAddress.Fill(0); + mLinks.SetCslParams(0, 0, kShortAddrInvalid, extAddress); + } + + LogInfo("CSL receiver is %s", mIsCslEnabled ? "enabled" : "disabled"); + +exit: + return; +} + +void Mac::UpdateCslParameters(void) +{ + // This method will set all CSL parameters when the CSL is enabled. Otherwise, nothing to do. + uint8_t cslChannel; + + VerifyOrExit(mIsCslEnabled); + + cslChannel = GetCslChannel() ? GetCslChannel() : mPanChannel; + mLinks.SetCslParams(GetCslPeriod(), cslChannel, Get().GetParent().GetRloc16(), + Get().GetParent().GetExtAddress()); + Get().RecalculatePollPeriod(); + Get().ScheduleChildUpdateRequest(); + +exit: + return; } uint32_t Mac::GetCslPeriodInMsec(void) const @@ -2474,15 +2540,6 @@ uint32_t Mac::CslPeriodToUsec(uint16_t aPeriodInTenSymbols) { return static_cast(aPeriodInTenSymbols) * kUsPerTenSymbols; } - -bool Mac::IsCslEnabled(void) const { return !Get().IsRxOnWhenIdle() && IsCslCapable(); } - -bool Mac::IsCslCapable(void) const { return (GetCslPeriod() > 0) && IsCslSupported(); } - -bool Mac::IsCslSupported(void) const -{ - return Get().IsChild() && Get().GetParent().IsEnhancedKeepAliveSupported(); -} #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 109bbbb65..ec79e9f69 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -581,9 +581,12 @@ public: void SetCslChannel(uint8_t aChannel); /** - * Centralizes CSL state switching conditions evaluating, configuring SubMac accordingly. + * Sets whether the MLE layer is capable of starting CSL. + * + * @retval TRUE If MLE layer is capable of starting CSL. + * @retval FALSE If MLE layer is not capable of starting CSL. */ - void UpdateCsl(void); + void SetCslCapable(bool aIsCslCapable); /** * Gets the CSL period. @@ -624,23 +627,7 @@ public: * @retval TRUE If CSL is enabled. * @retval FALSE If CSL is not enabled. */ - bool IsCslEnabled(void) const; - - /** - * Indicates whether Link is capable of starting CSL. - * - * @retval TRUE If Link is capable of starting CSL. - * @retval FALSE If link is not capable of starting CSL. - */ - bool IsCslCapable(void) const; - - /** - * Indicates whether the device is connected to a parent which supports CSL. - * - * @retval TRUE If parent supports CSL. - * @retval FALSE If parent does not support CSL. - */ - bool IsCslSupported(void) const; + bool IsCslEnabled(void) const { return mIsCslEnabled; } /** * Returns parent CSL accuracy (clock accuracy and uncertainty). @@ -870,6 +857,10 @@ private: #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE void ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr); #endif +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + void UpdateCslParameters(void); + void UpdateCslState(void); +#endif #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE void ProcessEnhAckProbing(const RxFrame &aFrame, const Neighbor &aNeighbor); #endif @@ -917,6 +908,8 @@ private: TimeMilli mCslTxFireTime; #endif #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + bool mIsCslEnabled : 1; + bool mIsCslCapable : 1; // When Mac::mCslChannel is 0, it indicates that CSL channel has not been specified by the upper layer. uint8_t mCslChannel; uint16_t mCslPeriod; diff --git a/src/core/mac/mac_links.hpp b/src/core/mac/mac_links.hpp index 592d48e0b..ac668bec3 100644 --- a/src/core/mac/mac_links.hpp +++ b/src/core/mac/mac_links.hpp @@ -461,28 +461,22 @@ public: #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE /** - * Configures CSL parameters in all radios. + * Sets CSL parameters in all radios. * * @param[in] aPeriod The CSL period. * @param[in] aChannel The CSL channel. * @param[in] aShortAddr The short source address of CSL receiver's peer. * @param[in] aExtAddr The extended source address of CSL receiver's peer. - * - * @retval TRUE if CSL Period or CSL Channel changed. - * @retval FALSE if CSL Period and CSL Channel did not change. */ - bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr) + void SetCslParams(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr) { - bool retval = false; - OT_UNUSED_VARIABLE(aPeriod); OT_UNUSED_VARIABLE(aChannel); OT_UNUSED_VARIABLE(aShortAddr); OT_UNUSED_VARIABLE(aExtAddr); #if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE - retval = mSubMac.UpdateCsl(aPeriod, aChannel, aShortAddr, aExtAddr); + mSubMac.SetCslParams(aPeriod, aChannel, aShortAddr, aExtAddr); #endif - return retval; } #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index 82fce50ef..afe9a73f9 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -295,9 +295,11 @@ public: Error Disable(void); /** - * Transitions the radio to Sleep. + * Request radio to transition to sleep state. * - * @retval kErrorNone Successfully transitioned to Sleep. + * The `SubMac` layer may enter `Receive()` state when the CSL receiver is enabled. + * + * @retval kErrorNone Successfully transitioned to Sleep or the radio is handled by the CSL receiver. * @retval kErrorBusy The radio was transmitting. * @retval kErrorInvalidState The radio was disabled. */ @@ -376,17 +378,14 @@ public: #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE /** - * Configures CSL parameters in 'SubMac'. + * Sets CSL parameters in 'SubMac'. * - * @param[in] aPeriod The CSL period (in unit of 10 symbols). + * @param[in] aPeriod The CSL period (in unit of 10 symbols), 0 for disabling CSL receiver. * @param[in] aChannel The CSL channel. * @param[in] aShortAddr The short source address of CSL receiver's peer. * @param[in] aExtAddr The extended source address of CSL receiver's peer. - * - * @retval TRUE if CSL Period or CSL Channel changed. - * @retval FALSE if CSL Period and CSL Channel did not change. */ - bool UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr); + void SetCslParams(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr); /** * Returns parent CSL accuracy (clock accuracy and uncertainty). diff --git a/src/core/mac/sub_mac_csl_receiver.cpp b/src/core/mac/sub_mac_csl_receiver.cpp index d83e7ce09..1e93e0316 100644 --- a/src/core/mac/sub_mac_csl_receiver.cpp +++ b/src/core/mac/sub_mac_csl_receiver.cpp @@ -108,7 +108,7 @@ exit: return; } -bool SubMac::UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr) +void SubMac::SetCslParams(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAddr, const ExtAddress &aExtAddr) { bool diffPeriod = aPeriod != mCslPeriod; bool diffChannel = aChannel != mCslChannel; @@ -133,7 +133,7 @@ bool SubMac::UpdateCsl(uint16_t aPeriod, uint8_t aChannel, ShortAddress aShortAd } exit: - return retval; + return; } void SubMac::HandleCslTimer(Timer &aTimer) { aTimer.Get().HandleCslTimer(); } diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 9ab034f05..d831452b7 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -349,6 +349,10 @@ void Mle::SetRole(DeviceRole aRole) mInitiallyAttachedAsSleepy = !GetDeviceMode().IsRxOnWhenIdle(); } +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + Get().SetCslCapable(IsCslSupported() && !IsRxOnWhenIdle()); +#endif + exit: return; } @@ -721,9 +725,6 @@ void Mle::SetStateDetached(void) Get().ClearAlternateRloc16(); Get().HandleDetachStart(); #endif -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - Get().UpdateCsl(); -#endif } void Mle::SetStateChild(uint16_t aRloc16) @@ -769,10 +770,6 @@ void Mle::SetStateChild(uint16_t aRloc16) } mPreviousParentRloc = mParent.GetRloc16(); - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - Get().UpdateCsl(); -#endif } void Mle::InformPreviousChannel(void) @@ -1098,6 +1095,8 @@ void Mle::SetCslTimeout(uint32_t aTimeout) exit: return; } + +bool Mle::IsCslSupported(void) const { return IsChild() && GetParent().IsThreadVersion1p2OrHigher(); } #endif void Mle::InitNeighbor(Neighbor &aNeighbor, const RxInfo &aRxInfo) diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 25683c168..7405109ec 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -730,6 +730,13 @@ public: */ uint64_t CalcParentCslMetric(const Mac::CslAccuracy &aCslAccuracy) const; + /** + * Indicates whether the device is connected to a parent which supports CSL. + * + * @retval TRUE If parent supports CSL. + * @retval FALSE If parent does not support CSL. + */ + bool IsCslSupported(void) const; #endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE #if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 7e23f5cfd..1ad57c9e4 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -470,10 +470,6 @@ void MleRouter::SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, Leade } } -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - Get().UpdateCsl(); -#endif - LogNote("Partition ID 0x%lx", ToUlong(mLeaderData.GetPartitionId())); }