[mle-router] signal child/router entry being added or removed (#3838)

This commit updates the neighbor table callback to signal when
either a child or a router neighbor entry is being added or removed.
This change replaces and enhances the previous APIs relalted to child
table callback.
This commit is contained in:
Abtin Keshavarzian
2019-05-21 21:35:39 -07:00
committed by Jonathan Hui
parent 167362130c
commit c0bc29197a
8 changed files with 114 additions and 79 deletions
+29 -21
View File
@@ -580,47 +580,55 @@ OTAPI int8_t OTCALL otThreadGetParentPriority(otInstance *aInstance);
OTAPI otError OTCALL otThreadSetParentPriority(otInstance *aInstance, int8_t aParentPriority);
/**
* This enumeration defines the constants used in `otThreadChildTableCallback` to indicate whether a child is added or
* removed.
* This enumeration defines the constants used in `otNeighborTableCallback` to indicate whether a child or router
* neighbor is being added or removed.
*
*/
typedef enum otThreadChildTableEvent
typedef enum
{
OT_THREAD_CHILD_TABLE_EVENT_CHILD_ADDED, ///< A child is being added.
OT_THREAD_CHILD_TABLE_EVENT_CHILD_REMOVED, ///< A child is being removed.
} otThreadChildTableEvent;
OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED, ///< A child is being added.
OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED, ///< A child is being removed.
OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED, ///< A router is being added.
OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED, ///< A router is being removed.
} otNeighborTableEvent;
/**
* This function pointer is called to notify that a child is being added to or removed from child table.
*
* @param[in] aEvent A event flag indicating whether a child is being added or removed.
* @param[in] aChildInfo A pointer to child information structure.
* This type represent a neighbor table entry info (child or router) and is used as a parameter in the neighbor table
* callback `otNeighborTableCallback`.
*
*/
typedef void (*otThreadChildTableCallback)(otThreadChildTableEvent aEvent, const otChildInfo *aChildInfo);
typedef struct
{
otInstance *mInstance; ///< The OpenThread instance.
union
{
otChildInfo mChild; ///< The child neighbor info.
otNeighborInfo mRouter; ///< The router neighbor info.
} mInfo;
} otNeighborTableEntryInfo;
/**
* This function gets the child table callback function.
* This function pointer is called to notify that a child or router neighbor is being added to or removed from neighbor
* table.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns The callback function pointer.
* @param[in] aEvent A event flag.
* @param[in] aEntryInfo A pointer to table entry info.
*
*/
otThreadChildTableCallback otThreadGetChildTableCallback(otInstance *aInstance);
typedef void (*otNeighborTableCallback)(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntryInfo);
/**
* This function sets the child table callback function.
* This function registers a neighbor table callback function.
*
* The provided callback (if non-NULL) will be invoked when a child entry is being added/removed to/from the child
* table. Subsequent calls to this method will overwrite the previous callback. Note that this callback in invoked
* while the child table is being updated and always before the `otStateChangedCallback`.
* The provided callback (if non-NULL) will be invoked when a child or router neighbor entry is being added/removed
* to/from the neighbor table. Subsequent calls to this method will overwrite the previous callback. Note that this
* callback in invoked while the neighbor/child table is being updated and always before the `otStateChangedCallback`.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aCallback A pointer to callback handler function.
*
*/
void otThreadSetChildTableCallback(otInstance *aInstance, otThreadChildTableCallback aCallback);
void otThreadRegisterNeighborTableCallback(otInstance *aInstance, otNeighborTableCallback aCallback);
/**
* @}
+2 -9
View File
@@ -380,18 +380,11 @@ otError otThreadSetParentPriority(otInstance *aInstance, const int8_t aParentPri
return instance.Get<Mle::MleRouter>().SetAssignParentPriority(aParentPriority);
}
otThreadChildTableCallback otThreadGetChildTableCallback(otInstance *aInstance)
void otThreadRegisterNeighborTableCallback(otInstance *aInstance, otNeighborTableCallback aCallback)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Mle::MleRouter>().GetChildTableChangedCallback();
}
void otThreadSetChildTableCallback(otInstance *aInstance, otThreadChildTableCallback aCallback)
{
Instance &instance = *static_cast<Instance *>(aInstance);
instance.Get<Mle::MleRouter>().SetChildTableChangedCallback(aCallback);
instance.Get<Mle::MleRouter>().RegisterNeighborTableChangedCallback(aCallback);
}
#endif // OPENTHREAD_FTD
+52 -28
View File
@@ -65,7 +65,7 @@ MleRouter::MleRouter(Instance &aInstance)
, mAddressRelease(OT_URI_PATH_ADDRESS_RELEASE, &MleRouter::HandleAddressRelease, this)
, mChildTable(aInstance)
, mRouterTable(aInstance)
, mChildTableChangedCallback(NULL)
, mNeighborTableChangedCallback(NULL)
, mChallengeTimeout(0)
, mNextChildId(kMaxChildId)
, mNetworkIdTimeout(kNetworkIdTimeout)
@@ -984,6 +984,8 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage,
router->SetState(Neighbor::kStateValid);
router->SetKeySequence(aKeySequence);
Signal(OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED, *router);
if (aRequest)
{
// Challenge
@@ -3157,7 +3159,7 @@ void MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
{
if (aNeighbor.IsStateValidOrRestoring())
{
SignalChildUpdated(OT_THREAD_CHILD_TABLE_EVENT_CHILD_REMOVED, static_cast<Child &>(aNeighbor));
Signal(OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED, aNeighbor);
}
aNeighbor.SetState(Neighbor::kStateInvalid);
@@ -3175,6 +3177,7 @@ void MleRouter::RemoveNeighbor(Neighbor &aNeighbor)
}
else if (aNeighbor.GetState() == Neighbor::kStateValid)
{
Signal(OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED, aNeighbor);
mRouterTable.RemoveNeighbor(static_cast<Router &>(aNeighbor));
}
@@ -3632,6 +3635,26 @@ exit:
return error;
}
void MleRouter::GetNeighborInfo(Neighbor &aNeighbor, otNeighborInfo &aNeighInfo)
{
aNeighInfo.mExtAddress = aNeighbor.GetExtAddress();
aNeighInfo.mAge = TimerMilli::MsecToSec(TimerMilli::Elapsed(aNeighbor.GetLastHeard()));
aNeighInfo.mRloc16 = aNeighbor.GetRloc16();
aNeighInfo.mLinkFrameCounter = aNeighbor.GetLinkFrameCounter();
aNeighInfo.mMleFrameCounter = aNeighbor.GetMleFrameCounter();
aNeighInfo.mLinkQualityIn = aNeighbor.GetLinkInfo().GetLinkQuality();
aNeighInfo.mAverageRssi = aNeighbor.GetLinkInfo().GetAverageRss();
aNeighInfo.mLastRssi = aNeighbor.GetLinkInfo().GetLastRss();
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
aNeighInfo.mFrameErrorRate = aNeighbor.GetLinkInfo().GetFrameErrorRate();
aNeighInfo.mMessageErrorRate = aNeighbor.GetLinkInfo().GetMessageErrorRate();
#endif
aNeighInfo.mRxOnWhenIdle = aNeighbor.IsRxOnWhenIdle();
aNeighInfo.mSecureDataRequest = aNeighbor.IsSecureDataRequest();
aNeighInfo.mFullThreadDevice = aNeighbor.IsFullThreadDevice();
aNeighInfo.mFullNetworkData = aNeighbor.IsFullNetworkData();
}
otError MleRouter::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, otNeighborInfo &aNeighInfo)
{
otError error = OT_ERROR_NONE;
@@ -3689,22 +3712,7 @@ exit:
if (neighbor != NULL)
{
aNeighInfo.mExtAddress = neighbor->GetExtAddress();
aNeighInfo.mAge = TimerMilli::MsecToSec(TimerMilli::Elapsed(neighbor->GetLastHeard()));
aNeighInfo.mRloc16 = neighbor->GetRloc16();
aNeighInfo.mLinkFrameCounter = neighbor->GetLinkFrameCounter();
aNeighInfo.mMleFrameCounter = neighbor->GetMleFrameCounter();
aNeighInfo.mLinkQualityIn = neighbor->GetLinkInfo().GetLinkQuality();
aNeighInfo.mAverageRssi = neighbor->GetLinkInfo().GetAverageRss();
aNeighInfo.mLastRssi = neighbor->GetLinkInfo().GetLastRss();
#if OPENTHREAD_CONFIG_ENABLE_TX_ERROR_RATE_TRACKING
aNeighInfo.mFrameErrorRate = neighbor->GetLinkInfo().GetFrameErrorRate();
aNeighInfo.mMessageErrorRate = neighbor->GetLinkInfo().GetMessageErrorRate();
#endif
aNeighInfo.mRxOnWhenIdle = neighbor->IsRxOnWhenIdle();
aNeighInfo.mSecureDataRequest = neighbor->IsSecureDataRequest();
aNeighInfo.mFullThreadDevice = neighbor->IsFullThreadDevice();
aNeighInfo.mFullNetworkData = neighbor->IsFullNetworkData();
GetNeighborInfo(*neighbor, aNeighInfo);
}
return error;
@@ -4547,7 +4555,7 @@ void MleRouter::SetChildStateToValid(Child &aChild)
aChild.SetState(Neighbor::kStateValid);
StoreChild(aChild);
SignalChildUpdated(OT_THREAD_CHILD_TABLE_EVENT_CHILD_ADDED, aChild);
Signal(OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED, aChild);
exit:
return;
@@ -4621,28 +4629,44 @@ exit:
return error;
}
void MleRouter::SignalChildUpdated(otThreadChildTableEvent aEvent, Child &aChild)
void MleRouter::Signal(otNeighborTableEvent aEvent, Neighbor &aNeighbor)
{
if (mChildTableChangedCallback != NULL)
if (mNeighborTableChangedCallback != NULL)
{
otChildInfo childInfo;
otError error;
otNeighborTableEntryInfo info;
otError error;
error = GetChildInfo(aChild, childInfo);
assert(error == OT_ERROR_NONE);
info.mInstance = &GetInstance();
mChildTableChangedCallback(aEvent, &childInfo);
switch (aEvent)
{
case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED:
case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED:
error = GetChildInfo(static_cast<Child &>(aNeighbor), info.mInfo.mChild);
assert(error == OT_ERROR_NONE);
break;
case OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED:
case OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED:
GetNeighborInfo(aNeighbor, info.mInfo.mRouter);
break;
}
mNeighborTableChangedCallback(aEvent, &info);
}
switch (aEvent)
{
case OT_THREAD_CHILD_TABLE_EVENT_CHILD_ADDED:
case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED:
Get<Notifier>().Signal(OT_CHANGED_THREAD_CHILD_ADDED);
break;
case OT_THREAD_CHILD_TABLE_EVENT_CHILD_REMOVED:
case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED:
Get<Notifier>().Signal(OT_CHANGED_THREAD_CHILD_REMOVED);
break;
default:
break;
}
}
+13 -10
View File
@@ -597,23 +597,27 @@ public:
otError GetMaxChildTimeout(uint32_t &aTimeout) const;
/**
* This method sets the "child table changed" callback function.
* This method register the "neighbor table changed" callback function.
*
* The provided callback (if non-NULL) will be invoked when a child entry is being added/remove to/from the child
* table. Subsequent calls to this method will overwrite the previous callback.
* The provided callback (if non-NULL) will be invoked when a child/router entry is being added/remove to/from the
* neighbor table. Subsequent calls to this method will overwrite the previous callback.
*
* @param[in] aCallback A pointer to callback handler function.
*
*/
void SetChildTableChangedCallback(otThreadChildTableCallback aCallback) { mChildTableChangedCallback = aCallback; }
void RegisterNeighborTableChangedCallback(otNeighborTableCallback aCallback)
{
mNeighborTableChangedCallback = aCallback;
}
/**
* This method gets the "child table changed" callback function.
* This method signals a "neighbor table changed" events (invoking the registered callback function).
*
* @returns The callback function pointer.
* @param[in] aEvent The event to emit (child/router added/removed).
* @param[in] aNeighbor The neighbor that is being added/removed.
*
*/
otThreadChildTableCallback GetChildTableChangedCallback(void) const { return mChildTableChangedCallback; }
void Signal(otNeighborTableEvent aEvent, Neighbor &aNeighbor);
/**
* This method returns whether the device has any sleepy children subscribed the address.
@@ -679,6 +683,7 @@ private:
otError AppendActiveDataset(Message &aMessage);
otError AppendPendingDataset(Message &aMessage);
otError GetChildInfo(Child &aChild, otChildInfo &aChildInfo);
void GetNeighborInfo(Neighbor &aNeighbor, otNeighborInfo &aNeighInfo);
otError RefreshStoredChildren(void);
void HandleDetachStart(void);
otError HandleChildStart(AttachMode aMode);
@@ -766,8 +771,6 @@ private:
static void HandleStateUpdateTimer(Timer &aTimer);
void HandleStateUpdateTimer(void);
void SignalChildUpdated(otThreadChildTableEvent aEvent, Child &aChild);
TrickleTimer mAdvertiseTimer;
TimerMilli mStateUpdateTimer;
@@ -777,7 +780,7 @@ private:
ChildTable mChildTable;
RouterTable mRouterTable;
otThreadChildTableCallback mChildTableChangedCallback;
otNeighborTableCallback mNeighborTableChangedCallback;
uint8_t mChallengeTimeout;
uint8_t mChallenge[8];
+8 -1
View File
@@ -101,7 +101,14 @@ void RouterTable::ClearNeighbors(void)
{
for (uint8_t index = 0; index < Mle::kMaxRouters; index++)
{
mRouters[index].SetState(Neighbor::kStateInvalid);
Router &router = mRouters[index];
if (router.GetState() == Neighbor::kStateValid)
{
Get<Mle::MleRouter>().Signal(OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED, router);
}
router.SetState(Neighbor::kStateInvalid);
}
}
+1 -1
View File
@@ -274,7 +274,7 @@ NcpBase::NcpBase(Instance *aInstance)
#endif
otIcmp6SetEchoMode(mInstance, OT_ICMP6_ECHO_HANDLER_DISABLED);
#if OPENTHREAD_FTD
otThreadSetChildTableCallback(mInstance, &NcpBase::HandleChildTableChanged);
otThreadRegisterNeighborTableCallback(mInstance, &NcpBase::HandleNeighborTableChanged);
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
memset(&mSteeringDataAddress, 0, sizeof(mSteeringDataAddress));
#endif
+2 -2
View File
@@ -276,8 +276,8 @@ protected:
void HandleTimeSyncUpdate(void);
#if OPENTHREAD_FTD
static void HandleChildTableChanged(otThreadChildTableEvent aEvent, const otChildInfo *aChildInfo);
void HandleChildTableChanged(otThreadChildTableEvent aEvent, const otChildInfo &aChildInfo);
static void HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntry);
void HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo &aEntry);
static void HandleParentResponseInfo(otThreadParentResponseInfo *aInfo, void *aContext);
void HandleParentResponseInfo(const otThreadParentResponseInfo &aInfo);
+7 -7
View File
@@ -115,12 +115,12 @@ exit:
return;
}
void NcpBase::HandleChildTableChanged(otThreadChildTableEvent aEvent, const otChildInfo *aChildInfo)
void NcpBase::HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntry)
{
GetNcpInstance()->HandleChildTableChanged(aEvent, *aChildInfo);
GetNcpInstance()->HandleNeighborTableChanged(aEvent, *aEntry);
}
void NcpBase::HandleChildTableChanged(otThreadChildTableEvent aEvent, const otChildInfo &aChildInfo)
void NcpBase::HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo &aEntry)
{
otError error = OT_ERROR_NONE;
uint8_t header = SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0;
@@ -128,15 +128,15 @@ void NcpBase::HandleChildTableChanged(otThreadChildTableEvent aEvent, const otCh
VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(SPINEL_PROP_THREAD_CHILD_TABLE));
VerifyOrExit(!aChildInfo.mIsStateRestoring);
VerifyOrExit(!aEntry.mInfo.mChild.mIsStateRestoring);
switch (aEvent)
{
case OT_THREAD_CHILD_TABLE_EVENT_CHILD_ADDED:
case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED:
command = SPINEL_CMD_PROP_VALUE_INSERTED;
break;
case OT_THREAD_CHILD_TABLE_EVENT_CHILD_REMOVED:
case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED:
command = SPINEL_CMD_PROP_VALUE_REMOVED;
break;
@@ -145,7 +145,7 @@ void NcpBase::HandleChildTableChanged(otThreadChildTableEvent aEvent, const otCh
}
SuccessOrExit(error = mEncoder.BeginFrame(header, command, SPINEL_PROP_THREAD_CHILD_TABLE));
SuccessOrExit(error = EncodeChildInfo(aChildInfo));
SuccessOrExit(error = EncodeChildInfo(aEntry.mInfo.mChild));
SuccessOrExit(error = mEncoder.EndFrame());
exit: