mirror of
https://github.com/espressif/openthread.git
synced 2026-08-15 23:27:47 +00:00
[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.
This commit is contained in:
@@ -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<Tmf::Agent>().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<ThreadRloc16Tlv>(*message, aRloc16));
|
||||
}
|
||||
|
||||
IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
|
||||
SuccessOrExit(error = Get<Tmf::Agent>().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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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<Mle::MleRouter>().IsRouterOrLeader());
|
||||
|
||||
while (GetNextServer(iterator, rloc16) == kErrorNone)
|
||||
{
|
||||
if (!Mle::IsActiveRouter(rloc16) && Mle::RouterIdMatch(Get<Mle::MleRouter>().GetRloc16(), rloc16) &&
|
||||
Get<ChildTable>().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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -273,41 +273,6 @@ void Local::UpdateRloc(void)
|
||||
}
|
||||
}
|
||||
|
||||
bool Local::IsConsistent(void) const
|
||||
{
|
||||
return Get<Leader>().ContainsEntriesFrom(*this, Get<Mle::MleRouter>().GetRloc16()) &&
|
||||
ContainsEntriesFrom(Get<Leader>(), Get<Mle::MleRouter>().GetRloc16());
|
||||
}
|
||||
|
||||
Error Local::UpdateInconsistentServerData(Coap::ResponseHandler aHandler, void *aContext)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint16_t rloc = Get<Mle::MleRouter>().GetRloc16();
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
// Don't send this Server Data Notification if the device is going to upgrade to Router
|
||||
if (Get<Mle::MleRouter>().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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Leader>().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<Local>().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<Mle::MleRouter>().IsRouterOrLeader());
|
||||
|
||||
while (Get<Leader>().GetNextServer(iterator, rloc16) == kErrorNone)
|
||||
{
|
||||
if (!Mle::IsActiveRouter(rloc16) && Mle::RouterIdMatch(Get<Mle::MleRouter>().GetRloc16(), rloc16) &&
|
||||
Get<ChildTable>().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<Mle::MleRouter>().GetRloc16();
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
// Don't send this Server Data Notification if the device is going
|
||||
// to upgrade to Router.
|
||||
|
||||
if (Get<Mle::MleRouter>().IsExpectedToBecomeRouterSoon())
|
||||
{
|
||||
ExitNow(error = kErrorInvalidState);
|
||||
}
|
||||
#endif
|
||||
|
||||
Get<Local>().UpdateRloc();
|
||||
|
||||
if (Get<Leader>().ContainsEntriesFrom(Get<Local>(), deviceRloc) &&
|
||||
Get<Local>().ContainsEntriesFrom(Get<Leader>(), deviceRloc))
|
||||
{
|
||||
ExitNow(error = kErrorNotFound);
|
||||
}
|
||||
|
||||
if (mOldRloc == deviceRloc)
|
||||
{
|
||||
mOldRloc = Mac::kShortAddrInvalid;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = SendServerDataNotification(mOldRloc, &Get<Local>()));
|
||||
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<Tmf::Agent>().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<ThreadRloc16Tlv>(*message, aOldRloc16));
|
||||
}
|
||||
|
||||
IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc());
|
||||
SuccessOrExit(error = Get<Tmf::Agent>().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))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user