diff --git a/include/openthread/thread_ftd.h b/include/openthread/thread_ftd.h index 2095092f5..28bdac9b7 100644 --- a/include/openthread/thread_ftd.h +++ b/include/openthread/thread_ftd.h @@ -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); /** * @} diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 76f9943a4..dc7e27398 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -380,18 +380,11 @@ otError otThreadSetParentPriority(otInstance *aInstance, const int8_t aParentPri return instance.Get().SetAssignParentPriority(aParentPriority); } -otThreadChildTableCallback otThreadGetChildTableCallback(otInstance *aInstance) +void otThreadRegisterNeighborTableCallback(otInstance *aInstance, otNeighborTableCallback aCallback) { Instance &instance = *static_cast(aInstance); - return instance.Get().GetChildTableChangedCallback(); -} - -void otThreadSetChildTableCallback(otInstance *aInstance, otThreadChildTableCallback aCallback) -{ - Instance &instance = *static_cast(aInstance); - - instance.Get().SetChildTableChangedCallback(aCallback); + instance.Get().RegisterNeighborTableChangedCallback(aCallback); } #endif // OPENTHREAD_FTD diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 423eb4ecb..fe927162e 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -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(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(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(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().Signal(OT_CHANGED_THREAD_CHILD_ADDED); break; - case OT_THREAD_CHILD_TABLE_EVENT_CHILD_REMOVED: + case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED: Get().Signal(OT_CHANGED_THREAD_CHILD_REMOVED); break; + + default: + break; } } diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index 5dfe611a3..33c658338 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -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]; diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp index 7cdfde974..7b50ea19d 100644 --- a/src/core/thread/router_table.cpp +++ b/src/core/thread/router_table.cpp @@ -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().Signal(OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED, router); + } + + router.SetState(Neighbor::kStateInvalid); } } diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 3f960ede5..d45646727 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -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 diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 340de70d6..0a248b90a 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -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); diff --git a/src/ncp/ncp_base_ftd.cpp b/src/ncp/ncp_base_ftd.cpp index 7b8cff10c..2a8a7ad5f 100644 --- a/src/ncp/ncp_base_ftd.cpp +++ b/src/ncp/ncp_base_ftd.cpp @@ -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: