[network-data] implement network data notifier (#4783)

This commit centralizes the timing logic for transmitting SVR_DATA.ntf
messages that are used to update network data at the leader.

This component helps ensure the following:

- At most one SVR_DATA.ntf message is outstanding at any given time.

- A timer to rety sending SVR_DATA.ntf messages if sending fails due
  to lack of memory buffers.

- A timer to rate limit SVR_DATA.ntf messages that are acknowledged
  but no corresponding change in the Thread Network Data was observed.

- Utilizes ot::Notifier to trigger logic on role, child state, and
  network data changes.
This commit is contained in:
Jonathan Hui
2020-04-06 21:27:51 -07:00
committed by GitHub
parent c6a258e3a5
commit c64d296c94
21 changed files with 337 additions and 112 deletions
+1
View File
@@ -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 \
+1
View File
@@ -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",
+1
View File
@@ -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
+2
View File
@@ -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 \
+3 -1
View File
@@ -147,7 +147,9 @@ otError otBorderRouterRegister(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<NetworkData::Local>().SendServerDataNotification();
instance.Get<NetworkData::Notifier>().HandleServerDataUpdated();
return OT_ERROR_NONE;
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
+3 -1
View File
@@ -88,7 +88,9 @@ otError otServerRegister(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<NetworkData::Local>().SendServerDataNotification();
instance.Get<NetworkData::Notifier>().HandleServerDataUpdated();
return OT_ERROR_NONE;
}
#endif // OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
+2 -6
View File
@@ -158,7 +158,7 @@ otError Local::AddService(bool aForce)
reinterpret_cast<const uint8_t *>(&serverData), sizeof(serverData)));
mIsServiceAdded = true;
Get<NetworkData::Local>().SendServerDataNotification();
Get<NetworkData::Notifier>().HandleServerDataUpdated();
otLogInfoNetData("BBR Service added: seqno (%d), delay (%ds), timeout (%ds)", mSequenceNumber, mReregistrationDelay,
mMlrTimeout);
@@ -177,11 +177,7 @@ otError Local::RemoveService(void)
error = Get<NetworkData::Local>().RemoveService(THREAD_ENTERPRISE_NUMBER, &serviceData, sizeof(serviceData)));
mIsServiceAdded = false;
if (Get<Mle::MleRouter>().IsAttached())
{
Get<NetworkData::Local>().SendServerDataNotification();
}
Get<NetworkData::Notifier>().HandleServerDataUpdated();
exit:
otLogInfoNetData("Remove BBR Service %s", otThreadErrorToString(error));
+7
View File
@@ -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;
-12
View File
@@ -830,9 +830,6 @@ void Mle::SetStateChild(uint16_t aRloc16)
}
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Get<NetworkData::Local>().ClearResubmitDelayTimer();
#endif
Get<Ip6::Ip6>().SetForwardingEnabled(false);
#if OPENTHREAD_FTD
Get<Ip6::Mpl>().SetTimerExpirations(kMplChildDataMessageTimerExpirations);
@@ -1617,12 +1614,9 @@ void Mle::HandleStateChanged(otChangedFlags aFlags)
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
Get<BackboneRouter::Leader>().Update();
#endif
#if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
Get<NetworkData::Local>().SendServerDataNotification();
#if OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
this->UpdateServiceAlocs();
#endif
#endif
#if OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
Get<Dhcp6::Dhcp6Server>().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<NetworkData::Local>().SendServerDataNotification();
}
#endif
exit:
-8
View File
@@ -2722,8 +2722,6 @@ void MleRouter::SynchronizeChildNetworkData(void)
{
VerifyOrExit(mRole == OT_DEVICE_ROLE_ROUTER || mRole == OT_DEVICE_ROLE_LEADER);
Get<NetworkData::Leader>().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<IndirectSender>().ClearAllMessagesForSleepyChild(static_cast<Child &>(aNeighbor));
Get<NetworkData::Leader>().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<NetworkData::Leader>().SendServerDataNotification(aMeshDest);
}
}
else if (GetNextHop(aMeshDest) != Mac::kShortAddrInvalid)
{
+2 -26
View File
@@ -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<Coap::Coap>().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<Mle::MleRouter>().GetLeaderAloc(messageInfo.GetPeerAddr());
messageInfo.SetSockAddr(Get<Mle::MleRouter>().GetMeshLocal16());
messageInfo.SetPeerPort(kCoapUdpPort);
SuccessOrExit(error = Get<Coap::Coap>().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<Coap::Coap>().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
+4 -9
View File
@@ -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
+3 -3
View File
@@ -64,7 +64,7 @@ void LeaderBase::Reset(void)
mVersion = Random::NonCrypto::GetUint8();
mStableVersion = Random::NonCrypto::GetUint8();
mLength = 0;
Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
Get<ot::Notifier>().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<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
Get<ot::Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
exit:
return error;
@@ -470,7 +470,7 @@ otError LeaderBase::SetCommissioningData(const uint8_t *aValue, uint8_t aValueLe
}
mVersion++;
Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
Get<ot::Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
exit:
return error;
+13 -22
View File
@@ -114,7 +114,7 @@ void Leader::IncrementVersions(bool aIncludeStable)
}
mVersion++;
Get<Notifier>().Signal(OT_CHANGED_THREAD_NETDATA);
Get<ot::Notifier>().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<Mle::MleRouter>().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<ChildTable>().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
+8 -12
View File
@@ -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);
+3 -9
View File
@@ -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<Mle::MleRouter>().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<Mle::MleRouter>().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:
+8 -3
View File
@@ -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);
+167
View File
@@ -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<Mle::MleRouter>().IsAttached() && !mWaitingForResponse);
VerifyOrExit((mNextDelay == 0) || !mTimer.IsRunning());
#if OPENTHREAD_FTD
mNextDelay = kDelayRemoveStaleChildren;
error = Get<Leader>().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<Local>().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<Mle::MleRouter>().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<Notifier>().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<Notifier>().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<Notifier *>(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
+102
View File
@@ -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_
+3
View File
@@ -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
+4
View File
@@ -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