mirror of
https://github.com/espressif/openthread.git
synced 2026-08-04 09:57:47 +00:00
[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:
@@ -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 \
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user