From 537002352faf934f353af30021b689e75fb7aa78 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 8 Nov 2022 10:14:46 -0800 Subject: [PATCH] [netdata] update `Notifier` to prepare and send SVR_DATA.ntf msg (#8376) This class moves all the related code for preparing and sending `kUriServerData` message to `NetworkData::Notifier`. In particular, `RemoveStaleChildEntries()` and `UpdateInconsistentData()` are moved to the `Notifier` class. --- src/core/thread/network_data.cpp | 36 ------- src/core/thread/network_data.hpp | 17 --- src/core/thread/network_data_leader_ftd.cpp | 23 ---- src/core/thread/network_data_leader_ftd.hpp | 13 --- src/core/thread/network_data_local.cpp | 35 ------- src/core/thread/network_data_local.hpp | 23 +--- src/core/thread/network_data_notifier.cpp | 110 +++++++++++++++++++- src/core/thread/network_data_notifier.hpp | 17 ++- 8 files changed, 126 insertions(+), 148 deletions(-) diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index f505aec52..38b537cac 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -635,42 +635,6 @@ void MutableNetworkData::RemoveTlv(NetworkDataTlv *aTlv) Remove(aTlv, aTlv->GetSize()); } -Error NetworkData::SendServerDataNotification(uint16_t aRloc16, - bool aAppendNetDataTlv, - Coap::ResponseHandler aHandler, - void * aContext) const -{ - Error error = kErrorNone; - Coap::Message * message; - Tmf::MessageInfo messageInfo(GetInstance()); - - message = Get().NewPriorityConfirmablePostMessage(kUriServerData); - VerifyOrExit(message != nullptr, error = kErrorNoBufs); - - if (aAppendNetDataTlv) - { - ThreadTlv tlv; - tlv.SetType(ThreadTlv::kThreadNetworkData); - tlv.SetLength(mLength); - SuccessOrExit(error = message->Append(tlv)); - SuccessOrExit(error = message->AppendBytes(mTlvs, mLength)); - } - - if (aRloc16 != Mac::kShortAddrInvalid) - { - SuccessOrExit(error = Tlv::Append(*message, aRloc16)); - } - - IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc()); - SuccessOrExit(error = Get().SendMessage(*message, messageInfo, aHandler, aContext)); - - LogInfo("Sent server data notification"); - -exit: - FreeMessageOnError(message, error); - return error; -} - Error NetworkData::GetNextServer(Iterator &aIterator, uint16_t &aRloc16) const { Error error; diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index cbe513305..340cac8ff 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -488,23 +488,6 @@ protected: const ServiceData &aServiceData, ServiceMatchMode aServiceMatchMode) const; - /** - * This method sends a Server Data Notification message to the Leader. - * - * @param[in] aRloc16 The old RLOC16 value that was previously registered. - * @param[in] aAppendNetDataTlv Indicates whether or not to append Thread Network Data TLV to the message. - * @param[in] aHandler A function pointer that is called when the transaction ends. - * @param[in] aContext A pointer to arbitrary context information. - * - * @retval kErrorNone Successfully enqueued the notification message. - * @retval kErrorNoBufs Insufficient message buffers to generate the notification message. - * - */ - Error SendServerDataNotification(uint16_t aRloc16, - bool aAppendNetDataTlv, - Coap::ResponseHandler aHandler, - void * aContext) const; - private: class NetworkDataIterator { diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index e8b3afad9..8e00a4cad 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -1352,29 +1352,6 @@ exit: return; } -Error Leader::RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext) -{ - Error error = kErrorNotFound; - Iterator iterator = kIteratorInit; - uint16_t rloc16; - - VerifyOrExit(Get().IsRouterOrLeader()); - - while (GetNextServer(iterator, rloc16) == kErrorNone) - { - if (!Mle::IsActiveRouter(rloc16) && Mle::RouterIdMatch(Get().GetRloc16(), rloc16) && - Get().FindChild(rloc16, Child::kInStateValid) == nullptr) - { - // In Thread 1.1 Specification 5.15.6.1, only one RLOC16 TLV entry may appear in SRV_DATA.ntf. - error = SendServerDataNotification(rloc16, /* aAppendNetDataTlv */ false, aHandler, aContext); - ExitNow(); - } - } - -exit: - return error; -} - #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE bool Leader::ContainsOmrPrefix(const Ip6::Prefix &aPrefix) { diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp index 4ae30d84d..1b7827005 100644 --- a/src/core/thread/network_data_leader_ftd.hpp +++ b/src/core/thread/network_data_leader_ftd.hpp @@ -163,19 +163,6 @@ public: */ const ServiceTlv *FindServiceById(uint8_t aServiceId) const; - /** - * This method sends SVR_DATA.ntf message for any stale child entries that exist in the network data. - * - * @param[in] aHandler A function pointer that is called when the transaction ends. - * @param[in] aContext A pointer to arbitrary context information. - * - * @retval kErrorNone A stale child entry was found and successfully enqueued a SVR_DATA.ntf message. - * @retval kErrorNoBufs A stale child entry was found, but insufficient message buffers were available. - * @retval kErrorNotFound No stale child entries were found. - * - */ - Error RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext); - #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE /** * This method indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data. diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp index 49651fdcf..10d63be37 100644 --- a/src/core/thread/network_data_local.cpp +++ b/src/core/thread/network_data_local.cpp @@ -273,41 +273,6 @@ void Local::UpdateRloc(void) } } -bool Local::IsConsistent(void) const -{ - return Get().ContainsEntriesFrom(*this, Get().GetRloc16()) && - ContainsEntriesFrom(Get(), Get().GetRloc16()); -} - -Error Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext) -{ - Error error = kErrorNone; - uint16_t rloc = Get().GetRloc16(); - -#if OPENTHREAD_FTD - // Don't send this Server Data Notification if the device is going to upgrade to Router - if (Get().IsExpectedToBecomeRouterSoon()) - { - ExitNow(error = kErrorInvalidState); - } -#endif - - UpdateRloc(); - - VerifyOrExit(!IsConsistent(), error = kErrorNotFound); - - if (mOldRloc == rloc) - { - mOldRloc = Mac::kShortAddrInvalid; - } - - SuccessOrExit(error = SendServerDataNotification(mOldRloc, /* aAppendNetDataTlv */ true, aHandler, aContext)); - mOldRloc = rloc; - -exit: - return error; -} - } // namespace NetworkData } // namespace ot diff --git a/src/core/thread/network_data_local.hpp b/src/core/thread/network_data_local.hpp index ec274d1dd..7d2dbbb68 100644 --- a/src/core/thread/network_data_local.hpp +++ b/src/core/thread/network_data_local.hpp @@ -54,12 +54,16 @@ namespace ot { namespace NetworkData { +class Notifier; + /** * This class implements the Thread Network Data contributed by the local device. * */ class Local : public MutableNetworkData, private NonCopyable { + friend class Notifier; + public: /** * This constructor initializes the local Network Data. @@ -69,7 +73,6 @@ public: */ explicit Local(Instance &aInstance) : MutableNetworkData(aInstance, mTlvBuffer, 0, sizeof(mTlvBuffer)) - , mOldRloc(Mac::kShortAddrInvalid) { } @@ -163,23 +166,8 @@ public: Error RemoveService(uint32_t aEnterpriseNumber, const ServiceData &aServiceData); #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - /** - * This method sends a Server Data Notification message to the Leader. - * - * @param[in] aHandler A function pointer that is called when the transaction ends. - * @param[in] aContext A pointer to arbitrary context information. - * - * @retval kErrorNone Successfully enqueued the notification message. - * @retval kErrorNoBufs Insufficient message buffers to generate the notification message. - * @retval kErrorInvalidState Device is a REED and is in the process of becoming a Router. - * @retval kErrorNotFound Server Data is already consistent with network data. - * - */ - Error UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext); - private: void UpdateRloc(void); - bool IsConsistent(void) const; #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE Error AddPrefix(const Ip6::Prefix &aPrefix, NetworkDataTlv::Type aSubTlvType, uint16_t aFlags, bool aStable); @@ -191,8 +179,7 @@ private: void UpdateRloc(ServiceTlv &aService); #endif - uint8_t mTlvBuffer[kMaxSize]; - uint16_t mOldRloc; + uint8_t mTlvBuffer[kMaxSize]; }; } // namespace NetworkData diff --git a/src/core/thread/network_data_notifier.cpp b/src/core/thread/network_data_notifier.cpp index f7900f2f9..7755864e7 100644 --- a/src/core/thread/network_data_notifier.cpp +++ b/src/core/thread/network_data_notifier.cpp @@ -41,6 +41,8 @@ #include "common/log.hpp" #include "thread/network_data_leader.hpp" #include "thread/network_data_local.hpp" +#include "thread/tmf.hpp" +#include "thread/uri_paths.hpp" namespace ot { namespace NetworkData { @@ -52,6 +54,7 @@ Notifier::Notifier(Instance &aInstance) , mTimer(aInstance) , mSynchronizeDataTask(aInstance) , mNextDelay(0) + , mOldRloc(Mac::kShortAddrInvalid) , mWaitingForResponse(false) #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE , mDidRequestRouterRoleUpgrade(false) @@ -81,13 +84,13 @@ void Notifier::SynchronizeServerData(void) #if OPENTHREAD_FTD mNextDelay = kDelayRemoveStaleChildren; - error = Get().RemoveStaleChildEntries(&Notifier::HandleCoapResponse, this); + error = RemoveStaleChildEntries(); VerifyOrExit(error == kErrorNotFound); #endif #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE mNextDelay = kDelaySynchronizeServerData; - error = Get().UpdateInconsistentServerData(&Notifier::HandleCoapResponse, this); + error = UpdateInconsistentData(); VerifyOrExit(error == kErrorNotFound); #endif @@ -112,6 +115,109 @@ exit: } } +#if OPENTHREAD_FTD +Error Notifier::RemoveStaleChildEntries(void) +{ + // Check if there is any stale child entry in network data and send + // a "Server Data" notification to leader to remove it. + // + // - `kErrorNone` when a stale child entry was found and successfully + // sent a "Server Data" notification to leader. + // - `kErrorNoBufs` if could not allocate message to send message. + // - `kErrorNotFound` if no stale child entries were found. + + Error error = kErrorNotFound; + Iterator iterator = kIteratorInit; + uint16_t rloc16; + + VerifyOrExit(Get().IsRouterOrLeader()); + + while (Get().GetNextServer(iterator, rloc16) == kErrorNone) + { + if (!Mle::IsActiveRouter(rloc16) && Mle::RouterIdMatch(Get().GetRloc16(), rloc16) && + Get().FindChild(rloc16, Child::kInStateValid) == nullptr) + { + error = SendServerDataNotification(rloc16); + ExitNow(); + } + } + +exit: + return error; +} +#endif // OPENTHREAD_FTD + +#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE +Error Notifier::UpdateInconsistentData(void) +{ + Error error = kErrorNone; + uint16_t deviceRloc = Get().GetRloc16(); + +#if OPENTHREAD_FTD + // Don't send this Server Data Notification if the device is going + // to upgrade to Router. + + if (Get().IsExpectedToBecomeRouterSoon()) + { + ExitNow(error = kErrorInvalidState); + } +#endif + + Get().UpdateRloc(); + + if (Get().ContainsEntriesFrom(Get(), deviceRloc) && + Get().ContainsEntriesFrom(Get(), deviceRloc)) + { + ExitNow(error = kErrorNotFound); + } + + if (mOldRloc == deviceRloc) + { + mOldRloc = Mac::kShortAddrInvalid; + } + + SuccessOrExit(error = SendServerDataNotification(mOldRloc, &Get())); + mOldRloc = deviceRloc; + +exit: + return error; +} +#endif // #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + +Error Notifier::SendServerDataNotification(uint16_t aOldRloc16, const NetworkData *aNetworkData) +{ + Error error = kErrorNone; + Coap::Message * message; + Tmf::MessageInfo messageInfo(GetInstance()); + + message = Get().NewPriorityConfirmablePostMessage(kUriServerData); + VerifyOrExit(message != nullptr, error = kErrorNoBufs); + + if (aNetworkData != nullptr) + { + ThreadTlv tlv; + + tlv.SetType(ThreadTlv::kThreadNetworkData); + tlv.SetLength(aNetworkData->GetLength()); + SuccessOrExit(error = message->Append(tlv)); + SuccessOrExit(error = message->AppendBytes(aNetworkData->GetBytes(), aNetworkData->GetLength())); + } + + if (aOldRloc16 != Mac::kShortAddrInvalid) + { + SuccessOrExit(error = Tlv::Append(*message, aOldRloc16)); + } + + IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc()); + SuccessOrExit(error = Get().SendMessage(*message, messageInfo, HandleCoapResponse, this)); + + LogInfo("Sent server data notification"); + +exit: + FreeMessageOnError(message, error); + return error; +} + void Notifier::HandleNotifierEvents(Events aEvents) { if (aEvents.ContainsAny(kEventThreadRoleChanged | kEventThreadChildRemoved)) diff --git a/src/core/thread/network_data_notifier.hpp b/src/core/thread/network_data_notifier.hpp index ad4af46f2..82bd3c04c 100644 --- a/src/core/thread/network_data_notifier.hpp +++ b/src/core/thread/network_data_notifier.hpp @@ -48,6 +48,8 @@ namespace ot { namespace NetworkData { +class NetworkData; + /** * This class implements the SVR_DATA.ntf transmission logic. * @@ -104,17 +106,23 @@ private: static constexpr uint32_t kDelaySynchronizeServerData = 300000; // in msec static constexpr uint8_t kRouterRoleUpgradeMaxTimeout = 10; // in sec - void HandleNotifierEvents(Events aEvents); - - void HandleTimer(void); + void SynchronizeServerData(void); + Error SendServerDataNotification(uint16_t aOldRloc16, const NetworkData *aNetworkData = nullptr); +#if OPENTHREAD_FTD + Error RemoveStaleChildEntries(void); +#endif +#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + Error UpdateInconsistentData(void); +#endif + void HandleNotifierEvents(Events aEvents); + void HandleTimer(void); static void HandleCoapResponse(void * aContext, otMessage * aMessage, const otMessageInfo *aMessageInfo, Error aResult); void HandleCoapResponse(Error aResult); - void SynchronizeServerData(void); #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE void ScheduleRouterRoleUpgradeIfEligible(void); void HandleTimeTick(void); @@ -126,6 +134,7 @@ private: DelayTimer mTimer; SynchronizeDataTask mSynchronizeDataTask; uint32_t mNextDelay; + uint16_t mOldRloc; bool mWaitingForResponse : 1; #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE