diff --git a/Android.mk b/Android.mk index 2ae5accf7..33005e1de 100644 --- a/Android.mk +++ b/Android.mk @@ -238,6 +238,7 @@ LOCAL_SRC_FILES := \ src/core/thread/network_data_leader.cpp \ src/core/thread/network_data_leader_ftd.cpp \ src/core/thread/network_data_local.cpp \ + src/core/thread/network_data_notifier.cpp \ src/core/thread/network_diagnostic.cpp \ src/core/thread/panid_query_server.cpp \ src/core/thread/router_table.cpp \ diff --git a/BUILD.gn b/BUILD.gn index 3cc17fb9e..4c904e22b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -151,6 +151,7 @@ static_library("lib-ot-core") { "src/core/thread/network_data_leader.cpp", "src/core/thread/network_data_leader_ftd.cpp", "src/core/thread/network_data_local.cpp", + "src/core/thread/network_data_notifier.cpp", "src/core/thread/network_diagnostic.cpp", "src/core/thread/panid_query_server.cpp", "src/core/thread/router_table.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1cd6edf01..29bd34493 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -191,6 +191,7 @@ set(COMMON_SOURCES thread/network_data_leader.cpp thread/network_data_leader_ftd.cpp thread/network_data_local.cpp + thread/network_data_notifier.cpp thread/network_diagnostic.cpp thread/panid_query_server.cpp thread/router_table.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index a58760e3c..5266d38d6 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -229,6 +229,7 @@ SOURCES_COMMON = \ thread/network_data_leader.cpp \ thread/network_data_leader_ftd.cpp \ thread/network_data_local.cpp \ + thread/network_data_notifier.cpp \ thread/network_diagnostic.cpp \ thread/panid_query_server.cpp \ thread/router_table.cpp \ @@ -431,6 +432,7 @@ HEADERS_COMMON = \ thread/network_data_leader.hpp \ thread/network_data_leader_ftd.hpp \ thread/network_data_local.hpp \ + thread/network_data_notifier.hpp \ thread/network_data_tlvs.hpp \ thread/network_diagnostic.hpp \ thread/network_diagnostic_tlvs.hpp \ diff --git a/src/core/api/border_router_api.cpp b/src/core/api/border_router_api.cpp index 09187da25..79658a141 100644 --- a/src/core/api/border_router_api.cpp +++ b/src/core/api/border_router_api.cpp @@ -147,7 +147,9 @@ otError otBorderRouterRegister(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); - return instance.Get().SendServerDataNotification(); + instance.Get().HandleServerDataUpdated(); + + return OT_ERROR_NONE; } #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE diff --git a/src/core/api/server_api.cpp b/src/core/api/server_api.cpp index 94dbf9384..42391dc56 100644 --- a/src/core/api/server_api.cpp +++ b/src/core/api/server_api.cpp @@ -88,7 +88,9 @@ otError otServerRegister(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); - return instance.Get().SendServerDataNotification(); + instance.Get().HandleServerDataUpdated(); + + return OT_ERROR_NONE; } #endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE diff --git a/src/core/backbone_router/local.cpp b/src/core/backbone_router/local.cpp index 0b4373684..003ea33a8 100644 --- a/src/core/backbone_router/local.cpp +++ b/src/core/backbone_router/local.cpp @@ -158,7 +158,7 @@ otError Local::AddService(bool aForce) reinterpret_cast(&serverData), sizeof(serverData))); mIsServiceAdded = true; - Get().SendServerDataNotification(); + Get().HandleServerDataUpdated(); otLogInfoNetData("BBR Service added: seqno (%d), delay (%ds), timeout (%ds)", mSequenceNumber, mReregistrationDelay, mMlrTimeout); @@ -177,11 +177,7 @@ otError Local::RemoveService(void) error = Get().RemoveService(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData))); mIsServiceAdded = false; - - if (Get().IsAttached()) - { - Get().SendServerDataNotification(); - } + Get().HandleServerDataUpdated(); exit: otLogInfoNetData("Remove BBR Service %s", otThreadErrorToString(error)); diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index 0d62ed0ce..e3e754bc0 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -551,6 +551,13 @@ template <> inline NetworkData::Leader &Instance::Get(void) return mThreadNetif.mNetworkDataLeader; } +#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE +template <> inline NetworkData::Notifier &Instance::Get(void) +{ + return mThreadNetif.mNetworkDataNotifier; +} +#endif + template <> inline Ip6::Udp &Instance::Get(void) { return mIp6.mUdp; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 86f5c6a06..93d5b03d1 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -830,9 +830,6 @@ void Mle::SetStateChild(uint16_t aRloc16) } #endif -#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - Get().ClearResubmitDelayTimer(); -#endif Get().SetForwardingEnabled(false); #if OPENTHREAD_FTD Get().SetTimerExpirations(kMplChildDataMessageTimerExpirations); @@ -1617,12 +1614,9 @@ void Mle::HandleStateChanged(otChangedFlags aFlags) #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) Get().Update(); #endif -#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - Get().SendServerDataNotification(); #if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE this->UpdateServiceAlocs(); #endif -#endif #if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE Get().UpdateService(); @@ -3002,12 +2996,6 @@ otError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay); SendDataRequest(aMessageInfo.GetPeerAddr(), tlvs, sizeof(tlvs), delay); } -#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE - else - { - Get().SendServerDataNotification(); - } -#endif exit: diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 6853f3074..61a25f1d0 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -2722,8 +2722,6 @@ void MleRouter::SynchronizeChildNetworkData(void) { VerifyOrExit(mRole == OT_DEVICE_ROLE_ROUTER || mRole == OT_DEVICE_ROLE_LEADER); - Get().RemoveStaleChildEntries(); - for (ChildTable::Iterator iter(GetInstance(), Child::kInStateValid); !iter.IsDone(); iter++) { Child & child = *iter.GetChild(); @@ -3333,7 +3331,6 @@ void MleRouter::RemoveNeighbor(Neighbor &aNeighbor) } Get().ClearAllMessagesForSleepyChild(static_cast(aNeighbor)); - Get().SendServerDataNotification(aNeighbor.GetRloc16()); if (aNeighbor.IsFullThreadDevice()) { @@ -3923,11 +3920,6 @@ otError MleRouter::CheckReachability(uint16_t aMeshSource, uint16_t aMeshDest, I { ExitNow(); } - else if (IsAnycastLocator(aIp6Header.GetDestination())) - { - // Proactively notify Leader of the expired child to de-register the stale service if any. - Get().SendServerDataNotification(aMeshDest); - } } else if (GetNextHop(aMeshDest) != Mac::kShortAddrInvalid) { diff --git a/src/core/thread/network_data.cpp b/src/core/thread/network_data.cpp index a2a069962..cdf4782d2 100644 --- a/src/core/thread/network_data.cpp +++ b/src/core/thread/network_data.cpp @@ -50,7 +50,6 @@ namespace NetworkData { NetworkData::NetworkData(Instance &aInstance, Type aType) : InstanceLocator(aInstance) , mType(aType) - , mLastAttempt(0) { mLength = 0; } @@ -754,21 +753,12 @@ void NetworkData::RemoveTlv(NetworkDataTlv *aTlv) NetworkData::RemoveTlv(mTlvs, mLength, aTlv); } -otError NetworkData::SendServerDataNotification(uint16_t aRloc16) +otError NetworkData::SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext) { otError error = OT_ERROR_NONE; Coap::Message * message = NULL; Ip6::MessageInfo messageInfo; - if (mLastAttempt.GetValue() != 0) - { - uint32_t diff = TimerMilli::GetNow() - mLastAttempt; - - VerifyOrExit(((mType == kTypeLocal) && (diff > kDataResubmitDelay)) || - ((mType == kTypeLeader) && (diff > kProxyResubmitDelay)), - error = OT_ERROR_ALREADY); - } - VerifyOrExit((message = Get().NewMessage()) != NULL, error = OT_ERROR_NO_BUFS); SuccessOrExit(error = message->Init(OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST, OT_URI_PATH_SERVER_DATA)); @@ -791,16 +781,7 @@ otError NetworkData::SendServerDataNotification(uint16_t aRloc16) Get().GetLeaderAloc(messageInfo.GetPeerAddr()); messageInfo.SetSockAddr(Get().GetMeshLocal16()); messageInfo.SetPeerPort(kCoapUdpPort); - SuccessOrExit(error = Get().SendMessage(*message, messageInfo)); - - mLastAttempt = TimerMilli::GetNow(); - - // `0` is a special value to indicate no delay limitation on sending SRV_DATA.ntf. - // Here avoids possible impact in rate limitation of SRV_DATA.ntf in case of wrap. - if (mLastAttempt.GetValue() == 0) - { - mLastAttempt.SetValue(1); - } + SuccessOrExit(error = Get().SendMessage(*message, messageInfo, aHandler, aContext)); otLogInfoNetData("Sent server data notification"); @@ -875,10 +856,5 @@ exit: return error; } -void NetworkData::ClearResubmitDelayTimer(void) -{ - mLastAttempt.SetValue(0); -} - } // namespace NetworkData } // namespace ot diff --git a/src/core/thread/network_data.hpp b/src/core/thread/network_data.hpp index f19d7aaf9..8bb0cb12a 100644 --- a/src/core/thread/network_data.hpp +++ b/src/core/thread/network_data.hpp @@ -316,12 +316,6 @@ public: */ otError GetNextServer(Iterator &aIterator, uint16_t &aRloc16); - /** - * This method cancels the data resubmit delay timer. - * - */ - void ClearResubmitDelayTimer(void); - protected: /** * This method returns a pointer to the start of Network Data TLV sequence. @@ -532,13 +526,15 @@ protected: /** * This method sends a Server Data Notification message to the Leader. * - * @param[in] aRloc16 The old RLOC16 value that was previously registered. + * @param[in] aRloc16 The old RLOC16 value that was previously registered. + * @param[in] aHandler A function pointer that is called when the transaction ends. + * @param[in] aContext A pointer to arbitrary context information. * * @retval OT_ERROR_NONE Successfully enqueued the notification message. * @retval OT_ERROR_NO_BUFS Insufficient message buffers to generate the notification message. * */ - otError SendServerDataNotification(uint16_t aRloc16); + otError SendServerDataNotification(uint16_t aRloc16, Coap::ResponseHandler aHandler, void *aContext); /** * This static method searches in a given sequence of TLVs to find the first TLV with a given TLV Type. @@ -696,7 +692,6 @@ private: } const Type mType; - TimeMilli mLastAttempt; }; } // namespace NetworkData diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 83d54bc8b..820c063de 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -64,7 +64,7 @@ void LeaderBase::Reset(void) mVersion = Random::NonCrypto::GetUint8(); mStableVersion = Random::NonCrypto::GetUint8(); mLength = 0; - Get().Signal(OT_CHANGED_THREAD_NETDATA); + Get().Signal(OT_CHANGED_THREAD_NETDATA); } otError LeaderBase::GetServiceId(uint32_t aEnterpriseNumber, @@ -444,7 +444,7 @@ otError LeaderBase::SetNetworkData(uint8_t aVersion, otDumpDebgNetData("set network data", mTlvs, mLength); - Get().Signal(OT_CHANGED_THREAD_NETDATA); + Get().Signal(OT_CHANGED_THREAD_NETDATA); exit: return error; @@ -470,7 +470,7 @@ otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLe } mVersion++; - Get().Signal(OT_CHANGED_THREAD_NETDATA); + Get().Signal(OT_CHANGED_THREAD_NETDATA); exit: return error; diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index 809308ec8..650e5c3a1 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -114,7 +114,7 @@ void Leader::IncrementVersions(bool aIncludeStable) } mVersion++; - Get().Signal(OT_CHANGED_THREAD_NETDATA); + Get().Signal(OT_CHANGED_THREAD_NETDATA); } void Leader::RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode) @@ -1129,22 +1129,6 @@ void Leader::StopContextReuseTimer(uint8_t aContextId) mContextLastUsed[aContextId - kMinContextId].SetValue(0); } -otError Leader::SendServerDataNotification(uint16_t aRloc16) -{ - otError error = OT_ERROR_NONE; - bool rlocIn; - bool rlocStable; - - RlocLookup(aRloc16, rlocIn, rlocStable, mTlvs, mLength, kMatchModeRloc16); - - VerifyOrExit(rlocIn, error = OT_ERROR_NOT_FOUND); - - SuccessOrExit(error = NetworkData::SendServerDataNotification(aRloc16)); - -exit: - return error; -} - void Leader::RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode) { NetworkDataTlv *cur = GetTlvsStart(); @@ -1407,10 +1391,14 @@ void Leader::HandleTimer(void) } } -void Leader::RemoveStaleChildEntries(void) +otError Leader::RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext) { - Iterator iterator = kIteratorInit; - uint16_t rloc16; + otError error = OT_ERROR_NOT_FOUND; + Iterator iterator = kIteratorInit; + otDeviceRole role = Get().GetRole(); + uint16_t rloc16; + + VerifyOrExit((role == OT_DEVICE_ROLE_ROUTER) || (role == OT_DEVICE_ROLE_LEADER)); while (GetNextServer(iterator, rloc16) == OT_ERROR_NONE) { @@ -1418,10 +1406,13 @@ void Leader::RemoveStaleChildEntries(void) Get().FindChild(rloc16, Child::kInStateValid) == NULL) { // In Thread 1.1 Specification 5.15.6.1, only one RLOC16 TLV entry may appear in SRV_DATA.ntf. - SendServerDataNotification(rloc16); - break; + error = NetworkData::SendServerDataNotification(rloc16, aHandler, aContext); + ExitNow(); } } + +exit: + return error; } } // namespace NetworkData diff --git a/src/core/thread/network_data_leader_ftd.hpp b/src/core/thread/network_data_leader_ftd.hpp index 8aa9f7fd1..4e15e420c 100644 --- a/src/core/thread/network_data_leader_ftd.hpp +++ b/src/core/thread/network_data_leader_ftd.hpp @@ -140,17 +140,6 @@ public: */ void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode); - /** - * This method sends a Server Data Notification message to the Leader indicating an invalid RLOC16. - * - * @param[in] aRloc16 The invalid RLOC16 to notify. - * - * @retval OT_ERROR_NONE Successfully enqueued the notification message. - * @retval OT_ERROR_NO_BUFS Insufficient message buffers to generate the notification message. - * - */ - otError SendServerDataNotification(uint16_t aRloc16); - /** * This method synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data. * @@ -171,8 +160,15 @@ public: /** * 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 OT_ERROR_NONE A stale child entry was found and successfully enqueued a SVR_DATA.ntf message. + * @retval OT_ERROR_NO_BUFS A stale child entry was found, but insufficient message buffers were available. + * @retval OT_ERROR_NOT_FOUND No stale child entries were found. + * */ - void RemoveStaleChildEntries(void); + otError RemoveStaleChildEntries(Coap::ResponseHandler aHandler, void *aContext); private: static void HandleServerData(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo); diff --git a/src/core/thread/network_data_local.cpp b/src/core/thread/network_data_local.cpp index d3b3b888d..79a630a90 100644 --- a/src/core/thread/network_data_local.cpp +++ b/src/core/thread/network_data_local.cpp @@ -138,8 +138,6 @@ otError Local::AddPrefix(const uint8_t * aPrefix, prefixTlv->GetSubTlvs()->SetStable(); } - ClearResubmitDelayTimer(); - otDumpDebgNetData("add prefix done", mTlvs, mLength); exit: @@ -154,7 +152,6 @@ otError Local::RemovePrefix(const uint8_t *aPrefix, uint8_t aPrefixLength, Netwo VerifyOrExit((tlv = FindPrefix(aPrefix, aPrefixLength)) != NULL, error = OT_ERROR_NOT_FOUND); VerifyOrExit(FindTlv(tlv->GetSubTlvs(), tlv->GetNext(), aSubTlvType) != NULL, error = OT_ERROR_NOT_FOUND); RemoveTlv(tlv); - ClearResubmitDelayTimer(); exit: otDumpDebgNetData("remove done", mTlvs, mLength); @@ -241,8 +238,6 @@ otError Local::AddService(uint32_t aEnterpriseNumber, serverTlv->SetServer16(Get().GetRloc16()); serverTlv->SetServerData(aServerData, aServerDataLength); - ClearResubmitDelayTimer(); - otDumpDebgNetData("add service done", mTlvs, mLength); exit: @@ -257,7 +252,6 @@ otError Local::RemoveService(uint32_t aEnterpriseNumber, const uint8_t *aService VerifyOrExit((tlv = FindService(aEnterpriseNumber, aServiceData, aServiceDataLength)) != NULL, error = OT_ERROR_NOT_FOUND); RemoveTlv(tlv); - ClearResubmitDelayTimer(); exit: otDumpDebgNetData("remove service done", mTlvs, mLength); @@ -317,7 +311,7 @@ void Local::UpdateRloc(void) } } -otError Local::SendServerDataNotification(void) +otError Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext) { otError error = OT_ERROR_NONE; uint16_t rloc = Get().GetRloc16(); @@ -343,14 +337,14 @@ otError Local::SendServerDataNotification(void) isConsistent = isConsistent && IsServiceConsistent(); #endif - VerifyOrExit(!isConsistent, ClearResubmitDelayTimer()); + VerifyOrExit(!isConsistent, error = OT_ERROR_NOT_FOUND); if (mOldRloc == rloc) { mOldRloc = Mac::kShortAddrInvalid; } - SuccessOrExit(error = NetworkData::SendServerDataNotification(mOldRloc)); + SuccessOrExit(error = NetworkData::SendServerDataNotification(mOldRloc, aHandler, aContext)); mOldRloc = rloc; exit: diff --git a/src/core/thread/network_data_local.hpp b/src/core/thread/network_data_local.hpp index 5d6c801d1..5024da6bd 100644 --- a/src/core/thread/network_data_local.hpp +++ b/src/core/thread/network_data_local.hpp @@ -164,11 +164,16 @@ public: /** * This method sends a Server Data Notification message to the Leader. * - * @retval OT_ERROR_NONE Successfully enqueued the notification message. - * @retval OT_ERROR_NO_BUFS Insufficient message buffers to generate the notification message. + * @param[in] aHandler A function pointer that is called when the transaction ends. + * @param[in] aContext A pointer to arbitrary context information. + * + * @retval OT_ERROR_NONE Successfully enqueued the notification message. + * @retval OT_ERROR_NO_BUFS Insufficient message buffers to generate the notification message. + * @retval OT_ERROR_INVALID_STATE Device is a REED and is in the process of becoming a Router. + * @retval OT_ERROR_NOT_FOUND Server Data is already consistent with network data. * */ - otError SendServerDataNotification(void); + otError UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext); private: void UpdateRloc(void); diff --git a/src/core/thread/network_data_notifier.cpp b/src/core/thread/network_data_notifier.cpp new file mode 100644 index 000000000..ec97dd8b1 --- /dev/null +++ b/src/core/thread/network_data_notifier.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file implements transmissions of SVR_DATA.ntf messages to the Leader. + */ + +#include "network_data_notifier.hpp" + +#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + +#include "common/code_utils.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" +#include "thread/network_data_leader.hpp" +#include "thread/network_data_local.hpp" + +namespace ot { +namespace NetworkData { + +Notifier::Notifier(Instance &aInstance) + : InstanceLocator(aInstance) + , mNotifierCallback(aInstance, &Notifier::HandleStateChanged, this) + , mTimer(aInstance, &Notifier::HandleTimer, this) + , mNextDelay(0) + , mWaitingForResponse(false) +{ +} + +void Notifier::HandleServerDataUpdated(void) +{ + mNextDelay = 0; + SynchronizeServerData(); +} + +void Notifier::SynchronizeServerData(void) +{ + otError error = OT_ERROR_NOT_FOUND; + + VerifyOrExit(Get().IsAttached() && !mWaitingForResponse); + + VerifyOrExit((mNextDelay == 0) || !mTimer.IsRunning()); + +#if OPENTHREAD_FTD + mNextDelay = kDelayRemoveStaleChildren; + error = Get().RemoveStaleChildEntries(&Notifier::HandleCoapResponse, this); + VerifyOrExit(error == OT_ERROR_NOT_FOUND); +#endif + +#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + mNextDelay = kDelaySynchronizeServerData; + error = Get().UpdateInconsistentServerData(&Notifier::HandleCoapResponse, this); + VerifyOrExit(error == OT_ERROR_NOT_FOUND); +#endif + +exit: + switch (error) + { + case OT_ERROR_NONE: + mWaitingForResponse = true; + break; + case OT_ERROR_NO_BUFS: + mTimer.Start(kDelayNoBufs); + break; +#if OPENTHREAD_FTD + case OT_ERROR_INVALID_STATE: + mTimer.Start(Time::SecToMsec(Get().GetRouterSelectionJitterTimeout() + 1)); + break; +#endif + case OT_ERROR_NOT_FOUND: + break; + default: + OT_ASSERT(false); + break; + } +} + +void Notifier::HandleStateChanged(ot::Notifier::Callback &aCallback, otChangedFlags aFlags) +{ + aCallback.GetOwner().HandleStateChanged(aFlags); +} + +void Notifier::HandleStateChanged(otChangedFlags aFlags) +{ + if (aFlags & (OT_CHANGED_THREAD_ROLE | OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED)) + { + mNextDelay = 0; + } + + if (aFlags & (OT_CHANGED_THREAD_NETDATA | OT_CHANGED_THREAD_ROLE | OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED)) + { + SynchronizeServerData(); + } +} + +void Notifier::HandleTimer(Timer &aTimer) +{ + aTimer.GetOwner().HandleTimer(); +} + +void Notifier::HandleTimer(void) +{ + SynchronizeServerData(); +} + +void Notifier::HandleCoapResponse(void * aContext, + otMessage * aMessage, + const otMessageInfo *aMessageInfo, + otError aResult) +{ + OT_UNUSED_VARIABLE(aMessage); + OT_UNUSED_VARIABLE(aMessageInfo); + + static_cast(aContext)->HandleCoapResponse(aResult); +} + +void Notifier::HandleCoapResponse(otError aResult) +{ + mWaitingForResponse = false; + + switch (aResult) + { + case OT_ERROR_NONE: + mTimer.Start(mNextDelay + 1); + break; + + case OT_ERROR_RESPONSE_TIMEOUT: + case OT_ERROR_ABORT: + SynchronizeServerData(); + break; + + default: + OT_ASSERT(false); + break; + } +} + +} // namespace NetworkData +} // namespace ot + +#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE diff --git a/src/core/thread/network_data_notifier.hpp b/src/core/thread/network_data_notifier.hpp new file mode 100644 index 000000000..3c9ac36f1 --- /dev/null +++ b/src/core/thread/network_data_notifier.hpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2020, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * This file includes definitions for transmitting SVR_DATA.ntf messages. + */ + +#ifndef NETWORK_DATA_NOTIFIER_HPP_ +#define NETWORK_DATA_NOTIFIER_HPP_ + +#include "openthread-core-config.h" + +#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + +#include "coap/coap.hpp" +#include "common/message.hpp" +#include "common/notifier.hpp" + +namespace ot { +namespace NetworkData { + +/** + * This class implements the SVR_DATA.ntf transmission logic. + * + */ +class Notifier : public InstanceLocator +{ +public: + /** + * Constructor. + * + * @param[in] aInstance The OpenThread instance. + * + */ + Notifier(Instance &aInstance); + + /** + * Call this method to inform the notifier that new server data is available. + * + */ + void HandleServerDataUpdated(void); + +private: + enum + { + kDelayNoBufs = 1000, ///< milliseconds + kDelayRemoveStaleChildren = 5000, ///< milliseconds + kDelaySynchronizeServerData = 300000, ///< milliseconds + }; + + static void HandleStateChanged(ot::Notifier::Callback &aCallback, otChangedFlags aFlags); + void HandleStateChanged(otChangedFlags aFlags); + + static void HandleTimer(Timer &aTimer); + void HandleTimer(void); + + static void HandleCoapResponse(void * aContext, + otMessage * aMessage, + const otMessageInfo *aMessageInfo, + otError aResult); + void HandleCoapResponse(otError aResult); + + void SynchronizeServerData(void); + + ot::Notifier::Callback mNotifierCallback; + TimerMilli mTimer; + uint32_t mNextDelay; + bool mWaitingForResponse; +}; + +} // namespace NetworkData +} // namespace ot + +#endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + +#endif // NETWORK_DATA_NOTIFIER_HPP_ diff --git a/src/core/thread/thread_netif.cpp b/src/core/thread/thread_netif.cpp index ee8f2ce75..9973dbebe 100644 --- a/src/core/thread/thread_netif.cpp +++ b/src/core/thread/thread_netif.cpp @@ -76,6 +76,9 @@ ThreadNetif::ThreadNetif(Instance &aInstance) , mNetworkDataLocal(aInstance) #endif , mNetworkDataLeader(aInstance) +#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + , mNetworkDataNotifier(aInstance) +#endif #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE , mNetworkDiagnostic(aInstance) #endif diff --git a/src/core/thread/thread_netif.hpp b/src/core/thread/thread_netif.hpp index 4cf28e825..2a6ffec1c 100644 --- a/src/core/thread/thread_netif.hpp +++ b/src/core/thread/thread_netif.hpp @@ -76,6 +76,7 @@ #include "thread/mle.hpp" #include "thread/mle_router.hpp" #include "thread/network_data_local.hpp" +#include "thread/network_data_notifier.hpp" #include "thread/network_diagnostic.hpp" #include "thread/panid_query_server.hpp" #include "thread/time_sync_service.hpp" @@ -197,6 +198,9 @@ private: NetworkData::Local mNetworkDataLocal; #endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE NetworkData::Leader mNetworkDataLeader; +#if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE + NetworkData::Notifier mNetworkDataNotifier; +#endif #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE NetworkDiagnostic::NetworkDiagnostic mNetworkDiagnostic; #endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE