[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:
Abtin Keshavarzian
2022-11-08 19:14:46 +01:00
committed by GitHub
parent f4d7f1a719
commit 537002352f
8 changed files with 126 additions and 148 deletions
-36
View File
@@ -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;
-17
View File
@@ -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.
-35
View File
@@ -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
+5 -18
View File
@@ -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
+108 -2
View File
@@ -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))
+13 -4
View File
@@ -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