From 36b9ecbf114e9270efdca6b8c41f2c4d7d6265b9 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Fri, 31 Jul 2020 13:41:12 -0700 Subject: [PATCH] [neighbor-table] add 'NeighborTable' class (#5354) This commit adds a `NeighborTable` class which provides helper methods dealing with neighbor, e.g., finding a `Neighbor` (i.e., a `Child` from `ChildTable`, a `Router` from `RouterTable`, or parent or parent candidate entries), or iterating through all neighbors. These methods use the newly added `Neighbor::AddressMacther` to simplify the implementation. The `NeighborTable` methods replace the similar ones in `Mle` and `MleRouter`. --- Android.mk | 1 + BUILD.gn | 1 + src/core/CMakeLists.txt | 1 + src/core/Makefile.am | 2 + src/core/api/thread_api.cpp | 2 +- src/core/common/instance.hpp | 5 + src/core/mac/mac.cpp | 6 +- src/core/thread/child_table.hpp | 1 + src/core/thread/mesh_forwarder.cpp | 2 +- src/core/thread/mesh_forwarder_ftd.cpp | 21 +- src/core/thread/mle.cpp | 82 +------- src/core/thread/mle.hpp | 46 +---- src/core/thread/mle_router.cpp | 210 +------------------- src/core/thread/mle_router.hpp | 70 ------- src/core/thread/neighbor_table.cpp | 256 +++++++++++++++++++++++++ src/core/thread/neighbor_table.hpp | 171 +++++++++++++++++ src/core/thread/router_table.cpp | 5 + src/core/thread/router_table.hpp | 11 ++ src/core/utils/child_supervision.cpp | 2 +- 19 files changed, 479 insertions(+), 416 deletions(-) create mode 100644 src/core/thread/neighbor_table.cpp create mode 100644 src/core/thread/neighbor_table.hpp diff --git a/Android.mk b/Android.mk index 259e3b075..ff9a6754d 100644 --- a/Android.mk +++ b/Android.mk @@ -256,6 +256,7 @@ LOCAL_SRC_FILES := \ src/core/thread/mle_router.cpp \ src/core/thread/mle_types.cpp \ src/core/thread/mlr_manager.cpp \ + src/core/thread/neighbor_table.cpp \ src/core/thread/network_data.cpp \ src/core/thread/network_data_leader.cpp \ src/core/thread/network_data_leader_ftd.cpp \ diff --git a/BUILD.gn b/BUILD.gn index 7fa3f39c8..fbb752e00 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -151,6 +151,7 @@ static_library("lib-ot-core") { "src/core/thread/mle_router.cpp", "src/core/thread/mle_types.cpp", "src/core/thread/mlr_manager.cpp", + "src/core/thread/neighbor_table.cpp", "src/core/thread/network_data.cpp", "src/core/thread/network_data_leader.cpp", "src/core/thread/network_data_leader_ftd.cpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6cb90642b..431f61cbd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -187,6 +187,7 @@ set(COMMON_SOURCES thread/mle_router.cpp thread/mle_types.cpp thread/mlr_manager.cpp + thread/neighbor_table.cpp thread/network_data.cpp thread/network_data_leader.cpp thread/network_data_leader_ftd.cpp diff --git a/src/core/Makefile.am b/src/core/Makefile.am index de53d8062..e7a3ad5b5 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -229,6 +229,7 @@ SOURCES_COMMON = \ thread/mle_router.cpp \ thread/mle_types.cpp \ thread/mlr_manager.cpp \ + thread/neighbor_table.cpp \ thread/network_data.cpp \ thread/network_data_leader.cpp \ thread/network_data_leader_ftd.cpp \ @@ -445,6 +446,7 @@ HEADERS_COMMON = \ thread/mle_types.hpp \ thread/mlr_manager.hpp \ thread/mlr_types.hpp \ + thread/neighbor_table.hpp \ thread/network_data.hpp \ thread/network_data_leader.hpp \ thread/network_data_leader_ftd.hpp \ diff --git a/src/core/api/thread_api.cpp b/src/core/api/thread_api.cpp index ffd5600db..2a2607c2e 100644 --- a/src/core/api/thread_api.cpp +++ b/src/core/api/thread_api.cpp @@ -304,7 +304,7 @@ otError otThreadGetNextNeighborInfo(otInstance *aInstance, otNeighborInfoIterato OT_ASSERT((aInfo != nullptr) && (aIterator != nullptr)); - return instance.Get().GetNextNeighborInfo(*aIterator, *static_cast(aInfo)); + return instance.Get().GetNextNeighborInfo(*aIterator, *static_cast(aInfo)); } otDeviceRole otThreadGetDeviceRole(otInstance *aInstance) diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index e6fc16ae2..b31ea2c1f 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -443,6 +443,11 @@ template <> inline Mle::DiscoverScanner &Instance::Get(void) return mThreadNetif.mDiscoverScanner; } +template <> inline NeighborTable &Instance::Get(void) +{ + return mThreadNetif.mMleRouter.mNeighborTable; +} + #if OPENTHREAD_FTD template <> inline ChildTable &Instance::Get(void) { diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 30a77d5b4..d4d5b4836 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -1152,7 +1152,7 @@ void Mac::RecordFrameTransmitStatus(const TxFrame &aFrame, VerifyOrExit(!aFrame.IsEmpty(), OT_NOOP); IgnoreError(aFrame.GetDstAddr(dstAddr)); - neighbor = Get().GetNeighbor(dstAddr); + neighbor = Get().FindNeighbor(dstAddr); // Record frame transmission success/failure state (for a neighbor). @@ -1565,7 +1565,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, otError aError) IgnoreError(aFrame->GetSrcAddr(srcaddr)); IgnoreError(aFrame->GetDstAddr(dstaddr)); - neighbor = Get().GetNeighbor(srcaddr); + neighbor = Get().FindNeighbor(srcaddr); // Destination Address Filtering switch (dstaddr.GetType()) @@ -1583,7 +1583,7 @@ void Mac::HandleReceivedFrame(RxFrame *aFrame, otError aError) // Allow multicasts from neighbor routers if FTD if (neighbor == nullptr && dstaddr.IsBroadcast() && Get().IsFullThreadDevice()) { - neighbor = Get().GetRxOnlyNeighborRouter(srcaddr); + neighbor = Get().FindRxOnlyNeighborRouter(srcaddr); } #endif diff --git a/src/core/thread/child_table.hpp b/src/core/thread/child_table.hpp index 9963553e2..e0a476062 100644 --- a/src/core/thread/child_table.hpp +++ b/src/core/thread/child_table.hpp @@ -49,6 +49,7 @@ namespace ot { */ class ChildTable : public InstanceLocator { + friend class NeighborTable; class IteratorBuilder; public: diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 9cd2108ba..934456c7e 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -740,7 +740,7 @@ Neighbor *MeshForwarder::UpdateNeighborOnSentFrame(Mac::TxFrame &aFrame, otError VerifyOrExit(mEnabled, OT_NOOP); - neighbor = Get().GetNeighbor(aMacDest); + neighbor = Get().FindNeighbor(aMacDest); VerifyOrExit(neighbor != nullptr, OT_NOOP); VerifyOrExit(aFrame.GetAckRequest(), OT_NOOP); diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 144708a56..d9037bc42 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -101,8 +101,8 @@ otError MeshForwarder::SendMessage(Message &aMessage) } } } - else if ((neighbor = mle.GetNeighbor(ip6Header.GetDestination())) != nullptr && !neighbor->IsRxOnWhenIdle() && - !aMessage.GetDirectTransmission()) + else if ((neighbor = Get().FindNeighbor(ip6Header.GetDestination())) != nullptr && + !neighbor->IsRxOnWhenIdle() && !aMessage.GetDirectTransmission()) { // destined for a sleepy child Child &child = *static_cast(neighbor); @@ -246,8 +246,7 @@ exit: void MeshForwarder::RemoveMessages(Child &aChild, Message::SubType aSubType) { - Mle::MleRouter &mle = Get(); - Message * nextMessage; + Message *nextMessage; for (Message *message = mSendQueue.GetHead(); message; message = nextMessage) { @@ -268,7 +267,7 @@ void MeshForwarder::RemoveMessages(Child &aChild, Message::SubType aSubType) IgnoreReturnValue(message->Read(0, sizeof(ip6header), &ip6header)); - if (&aChild == static_cast(mle.GetNeighbor(ip6header.GetDestination()))) + if (&aChild == static_cast(Get().FindNeighbor(ip6header.GetDestination()))) { message->ClearDirectTransmission(); } @@ -282,7 +281,7 @@ void MeshForwarder::RemoveMessages(Child &aChild, Message::SubType aSubType) IgnoreError(meshHeader.ParseFrom(*message)); - if (&aChild == static_cast(mle.GetNeighbor(meshHeader.GetDestination()))) + if (&aChild == static_cast(Get().FindNeighbor(meshHeader.GetDestination()))) { message->ClearDirectTransmission(); } @@ -375,11 +374,11 @@ otError MeshForwarder::UpdateMeshRoute(Message &aMessage) if (nextHop != Mac::kShortAddrInvalid) { - neighbor = Get().GetNeighbor(nextHop); + neighbor = Get().FindNeighbor(nextHop); } else { - neighbor = Get().GetNeighbor(meshHeader.GetDestination()); + neighbor = Get().FindNeighbor(meshHeader.GetDestination()); } if (neighbor == nullptr) @@ -465,7 +464,7 @@ otError MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessa ExitNow(error = OT_ERROR_DROP); } } - else if ((neighbor = mle.GetNeighbor(ip6Header.GetDestination())) != nullptr) + else if ((neighbor = Get().FindNeighbor(ip6Header.GetDestination())) != nullptr) { mMeshDest = neighbor->GetRloc16(); } @@ -715,7 +714,7 @@ void MeshForwarder::UpdateRoutes(const uint8_t * aFrame, } } - neighbor = Get().GetNeighbor(ip6Header.GetSource()); + neighbor = Get().FindNeighbor(ip6Header.GetSource()); VerifyOrExit(neighbor != nullptr && !neighbor->IsFullThreadDevice(), OT_NOOP); if (!Mle::Mle::RouterIdMatch(aMeshSource.GetShort(), Get().GetShortAddress())) @@ -907,7 +906,7 @@ otError MeshForwarder::GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, ui } // Cost if the server is direct neighbor. - neighbor = Get().GetNeighbor(server16); + neighbor = Get().FindNeighbor(server16); if (neighbor != nullptr && neighbor->IsStateValid()) { diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 5ed9d22cb..eb1effa37 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -65,6 +65,7 @@ Mle::Mle(Instance &aInstance) , Notifier::Receiver(aInstance, Mle::HandleNotifierEvents) , mRetrieveNewNetworkData(false) , mRole(kRoleDisabled) + , mNeighborTable(aInstance) , mDeviceMode(DeviceMode::kModeRxOnWhenIdle | DeviceMode::kModeSecureDataRequest) , mAttachState(kAttachStateIdle) , mReattachState(kReattachStop) @@ -2001,7 +2002,7 @@ otError Mle::SendChildIdRequest(void) // // Parent state is not normally invalidated after becoming a Router/Leader (see #1875). When trying to // attach to a better partition, invalidating old parent state (especially when in kStateRestored) ensures - // that GetNeighbor() returns mParentCandidate when processing the Child ID Response. + // that FindNeighbor() returns mParentCandidate when processing the Child ID Response. mParent.SetState(Neighbor::kStateInvalid); } } @@ -2628,30 +2629,8 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn aMessage.Read(aMessage.GetOffset(), sizeof(command), &command); aMessage.MoveOffset(sizeof(command)); - switch (mRole) - { - case kRoleDetached: - case kRoleChild: - neighbor = GetNeighbor(extAddr); - break; - - case kRoleRouter: - case kRoleLeader: - if (command == Header::kCommandChildIdResponse) - { - neighbor = GetNeighbor(extAddr); - } - else - { - neighbor = Get().GetNeighbor(extAddr); - } - - break; - - default: - neighbor = nullptr; - break; - } + neighbor = (command == Header::kCommandChildIdResponse) ? mNeighborTable.FindParent(extAddr) + : mNeighborTable.FindNeighbor(extAddr); if (neighbor != nullptr && neighbor->IsStateValid()) { @@ -3773,59 +3752,6 @@ void Mle::ProcessAnnounce(void) IgnoreError(Start(/* aAnnounceAttach */ true)); } -Neighbor *Mle::GetNeighbor(uint16_t aAddress) -{ - Neighbor *rval = nullptr; - - if (mParent.IsStateValidOrRestoring() && (mParent.GetRloc16() == aAddress)) - { - rval = &mParent; - } - else if (mParentCandidate.IsStateValid() && (mParentCandidate.GetRloc16() == aAddress)) - { - rval = &mParentCandidate; - } - - return rval; -} - -Neighbor *Mle::GetNeighbor(const Mac::ExtAddress &aAddress) -{ - Neighbor *rval = nullptr; - - if (mParent.IsStateValidOrRestoring() && (mParent.GetExtAddress() == aAddress)) - { - rval = &mParent; - } - else if (mParentCandidate.IsStateValid() && (mParentCandidate.GetExtAddress() == aAddress)) - { - rval = &mParentCandidate; - } - - return rval; -} - -Neighbor *Mle::GetNeighbor(const Mac::Address &aAddress) -{ - Neighbor *neighbor = nullptr; - - switch (aAddress.GetType()) - { - case Mac::Address::kTypeShort: - neighbor = GetNeighbor(aAddress.GetShort()); - break; - - case Mac::Address::kTypeExtended: - neighbor = GetNeighbor(aAddress.GetExtended()); - break; - - default: - break; - } - - return neighbor; -} - uint16_t Mle::GetNextHop(uint16_t aDestination) const { OT_UNUSED_VARIABLE(aDestination); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index d3c137021..4038d4bca 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -45,6 +45,7 @@ #include "net/udp6.hpp" #include "thread/mle_tlvs.hpp" #include "thread/mle_types.hpp" +#include "thread/neighbor_table.hpp" #include "thread/topology.hpp" namespace ot { @@ -1381,50 +1382,6 @@ protected: */ otError CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header); - /** - * This method returns a pointer to the neighbor object. - * - * @param[in] aAddress A reference to the MAC address. - * - * @returns A pointer to the neighbor object. - * - */ - Neighbor *GetNeighbor(const Mac::Address &aAddress); - - /** - * This method returns a pointer to the neighbor object. - * - * @param[in] aAddress A reference to the MAC short address. - * - * @returns A pointer to the neighbor object. - * - */ - Neighbor *GetNeighbor(Mac::ShortAddress aAddress); - - /** - * This method returns a pointer to the neighbor object. - * - * @param[in] aAddress A reference to the MAC extended address. - * - * @returns A pointer to the neighbor object. - * - */ - Neighbor *GetNeighbor(const Mac::ExtAddress &aAddress); - - /** - * This method returns a pointer to the neighbor object. - * - * @param[in] aAddress A reference to the IPv6 address. - * - * @returns A pointer to the neighbor object. - * - */ - Neighbor *GetNeighbor(const Ip6::Address &aAddress) - { - OT_UNUSED_VARIABLE(aAddress); - return nullptr; - } - /** * This method returns the next hop towards an RLOC16 destination. * @@ -1605,6 +1562,7 @@ protected: DeviceRole mRole; ///< Current Thread role. Router mParent; ///< Parent information. Router mParentCandidate; ///< Parent candidate information. + NeighborTable mNeighborTable; ///< The neighbor table. DeviceMode mDeviceMode; ///< Device mode setting. AttachState mAttachState; ///< The parent request state. ReattachState mReattachState; ///< Reattach state diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 70085abe4..81d726d78 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -3286,7 +3286,7 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination, switch (aTlvs[i]) { case Tlv::kNetworkData: - neighbor = GetNeighbor(aDestination); + neighbor = mNeighborTable.FindNeighbor(aDestination); stableOnly = neighbor != nullptr ? !neighbor->IsFullNetworkData() : false; SuccessOrExit(error = AppendNetworkData(*message, stableOnly)); break; @@ -3339,7 +3339,7 @@ bool MleRouter::IsMinimalChild(uint16_t aRloc16) { Neighbor *neighbor; - neighbor = GetNeighbor(aRloc16); + neighbor = mNeighborTable.FindNeighbor(aRloc16); rval = (neighbor != nullptr) && (!neighbor->IsFullThreadDevice()); } @@ -3419,156 +3419,6 @@ exit: return; } -Neighbor *MleRouter::GetNeighbor(uint16_t aAddress) -{ - Neighbor *rval = nullptr; - - if (aAddress == Mac::kShortAddrBroadcast || aAddress == Mac::kShortAddrInvalid) - { - ExitNow(); - } - - switch (mRole) - { - case kRoleDisabled: - break; - - case kRoleDetached: - case kRoleChild: - rval = Mle::GetNeighbor(aAddress); - break; - - case kRoleRouter: - case kRoleLeader: - rval = mChildTable.FindChild(aAddress, Child::kInStateValidOrRestoring); - VerifyOrExit(rval == nullptr, OT_NOOP); - - rval = mRouterTable.GetNeighbor(aAddress); - break; - } - -exit: - return rval; -} - -Neighbor *MleRouter::GetNeighbor(const Mac::ExtAddress &aAddress) -{ - Neighbor *rval = nullptr; - - switch (mRole) - { - case kRoleDisabled: - break; - - case kRoleDetached: - case kRoleChild: - rval = Mle::GetNeighbor(aAddress); - break; - - case kRoleRouter: - case kRoleLeader: - rval = mChildTable.FindChild(aAddress, Child::kInStateValidOrRestoring); - VerifyOrExit(rval == nullptr, OT_NOOP); - - rval = mRouterTable.GetNeighbor(aAddress); - - if (rval != nullptr) - { - ExitNow(); - } - - if (IsAttaching()) - { - rval = Mle::GetNeighbor(aAddress); - } - - break; - } - -exit: - return rval; -} - -Neighbor *MleRouter::GetNeighbor(const Mac::Address &aAddress) -{ - Neighbor *rval = nullptr; - - switch (aAddress.GetType()) - { - case Mac::Address::kTypeShort: - rval = GetNeighbor(aAddress.GetShort()); - break; - - case Mac::Address::kTypeExtended: - rval = GetNeighbor(aAddress.GetExtended()); - break; - - default: - break; - } - - return rval; -} - -Neighbor *MleRouter::GetNeighbor(const Ip6::Address &aAddress) -{ - Neighbor *rval = nullptr; - - if (aAddress.IsLinkLocal()) - { - Mac::Address macAddr; - - aAddress.GetIid().ConvertToMacAddress(macAddr); - ExitNow(rval = GetNeighbor(macAddr)); - } - - if (IsRoutingLocator(aAddress)) - { - uint16_t rloc16 = aAddress.GetIid().GetLocator(); - - rval = mChildTable.FindChild(rloc16, Child::kInStateValidOrRestoring); - VerifyOrExit(rval == nullptr, OT_NOOP); - - rval = mRouterTable.GetNeighbor(rloc16); - ExitNow(); - } - - for (Child &child : Get().Iterate(Child::kInStateValidOrRestoring)) - { - if (child.HasIp6Address(aAddress)) - { - ExitNow(rval = &child); - } - } - -exit: - return rval; -} - -Neighbor *MleRouter::GetRxOnlyNeighborRouter(const Mac::Address &aAddress) -{ - Neighbor *rval = nullptr; - - VerifyOrExit(IsChild(), rval = nullptr); - - switch (aAddress.GetType()) - { - case Mac::Address::kTypeShort: - rval = mRouterTable.GetNeighbor(aAddress.GetShort()); - break; - - case Mac::Address::kTypeExtended: - rval = mRouterTable.GetNeighbor(aAddress.GetExtended()); - break; - - default: - break; - } - -exit: - return rval; -} - uint16_t MleRouter::GetNextHop(uint16_t aDestination) { uint8_t destinationId = RouterIdFromRloc16(aDestination); @@ -3663,60 +3513,6 @@ void MleRouter::SetRouterId(uint8_t aRouterId) mPreviousRouterId = mRouterId; } -otError MleRouter::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo) -{ - otError error = OT_ERROR_NONE; - int16_t index; - - // Non-negative iterator value gives the Child index into child table - - if (aIterator >= 0) - { - for (index = aIterator;; index++) - { - Child *child = mChildTable.GetChildAtIndex(static_cast(index)); - - if (child == nullptr) - { - break; - } - - if (child->IsStateValid()) - { - aNeighInfo.SetFrom(*child); - aNeighInfo.mIsChild = true; - index++; - aIterator = index; - ExitNow(); - } - } - - aIterator = 0; - } - - // Negative iterator value gives the current index into mRouters array - - for (index = -aIterator; index <= kMaxRouterId; index++) - { - Router *router = mRouterTable.GetRouter(static_cast(index)); - - if (router != nullptr && router->IsStateValid()) - { - aNeighInfo.SetFrom(*router); - aNeighInfo.mIsChild = false; - index++; - aIterator = -index; - ExitNow(); - } - } - - aIterator = -index; - error = OT_ERROR_NOT_FOUND; - -exit: - return error; -} - void MleRouter::ResolveRoutingLoops(uint16_t aSourceMac, uint16_t aDestRloc16) { Router *router; @@ -3756,7 +3552,7 @@ otError MleRouter::CheckReachability(uint16_t aMeshDest, Ip6::Header &aIp6Header // IPv6 destination is this device ExitNow(); } - else if (GetNeighbor(aIp6Header.GetDestination()) != nullptr) + else if (mNeighborTable.FindNeighbor(aIp6Header.GetDestination()) != nullptr) { // IPv6 destination is an RFD child ExitNow(); diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 004fbb175..ec75f1bee 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -344,57 +344,6 @@ public: */ void RemoveRouterLink(Router &aRouter); - /** - * This method returns a pointer to a Neighbor object. - * - * @param[in] aAddress The address of the Neighbor. - * - * @returns A pointer to the Neighbor corresponding to @p aAddress, nullptr otherwise. - * - */ - Neighbor *GetNeighbor(uint16_t aAddress); - - /** - * This method returns a pointer to a Neighbor object. - * - * @param[in] aAddress The address of the Neighbor. - * - * @returns A pointer to the Neighbor corresponding to @p aAddress, nullptr otherwise. - * - */ - Neighbor *GetNeighbor(const Mac::ExtAddress &aAddress); - - /** - * This method returns a pointer to a Neighbor object. - * - * @param[in] aAddress The address of the Neighbor. - * - * @returns A pointer to the Neighbor corresponding to @p aAddress, nullptr otherwise. - * - */ - Neighbor *GetNeighbor(const Mac::Address &aAddress); - - /** - * This method returns a pointer to a Neighbor object. - * - * @param[in] aAddress The address of the Neighbor. - * - * @returns A pointer to the Neighbor corresponding to @p aAddress, nullptr otherwise. - * - */ - Neighbor *GetNeighbor(const Ip6::Address &aAddress); - - /** - * This method returns a pointer to a Neighbor object if a one-way link is maintained - * as in the instance of an FTD child with neighbor routers. - * - * @param[in] aAddress The address of the Neighbor. - * - * @returns A pointer to the Neighbor corresponding to @p aAddress, nullptr otherwise. - * - */ - Neighbor *GetRxOnlyNeighborRouter(const Mac::Address &aAddress); - /** * This method indicates whether or not the RLOC16 is an MTD child of this device. * @@ -406,20 +355,6 @@ public: */ bool IsMinimalChild(uint16_t aRloc16); - /** - * This method gets the next neighbor information. It is used to iterate through the entries of - * the neighbor table. - * - * @param[inout] aIterator A reference to the iterator context. To get the first neighbor entry - it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT. - * @param[out] aNeighInfo The neighbor information. - * - * @retval OT_ERROR_NONE Successfully found the next neighbor entry in table. - * @retval OT_ERROR_NOT_FOUND No subsequent neighbor entry exists in the table. - * - */ - otError GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo); - /** * This method indicates whether or not the given Thread partition attributes are preferred. * @@ -797,11 +732,6 @@ public: otError RemoveNeighbor(Neighbor &) { return BecomeDetached(); } void RemoveRouterLink(Router &) { IgnoreError(BecomeDetached()); } - Neighbor *GetNeighbor(const Mac::ExtAddress &aAddress) { return Mle::GetNeighbor(aAddress); } - Neighbor *GetNeighbor(const Mac::Address &aAddress) { return Mle::GetNeighbor(aAddress); } - - otError GetNextNeighborInfo(otNeighborInfoIterator &, otNeighborInfo &) { return OT_ERROR_NOT_IMPLEMENTED; } - static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; } otError SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); } diff --git a/src/core/thread/neighbor_table.cpp b/src/core/thread/neighbor_table.cpp new file mode 100644 index 000000000..a5184a4e3 --- /dev/null +++ b/src/core/thread/neighbor_table.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-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 Thread neighbor table. + */ + +#include "neighbor_table.hpp" + +#include "common/code_utils.hpp" +#include "common/instance.hpp" +#include "common/locator-getters.hpp" + +namespace ot { + +NeighborTable::NeighborTable(Instance &aInstance) + : InstanceLocator(aInstance) +{ +} + +Neighbor *NeighborTable::FindParent(const Neighbor::AddressMatcher &aMatcher) +{ + Neighbor *neighbor = nullptr; + Mle::Mle &mle = Get(); + + if (mle.GetParent().Matches(aMatcher)) + { + neighbor = &mle.GetParent(); + } + else if (mle.GetParentCandidate().Matches(aMatcher)) + { + neighbor = &mle.GetParentCandidate(); + } + + return neighbor; +} + +Neighbor *NeighborTable::FindParent(Mac::ShortAddress aShortAddress) +{ + return FindParent(Neighbor::AddressMatcher(aShortAddress, Neighbor::kInStateValidOrRestoring)); +} + +Neighbor *NeighborTable::FindParent(const Mac::ExtAddress &aExtAddress) +{ + return FindParent(Neighbor::AddressMatcher(aExtAddress, Neighbor::kInStateValidOrRestoring)); +} + +Neighbor *NeighborTable::FindParent(const Mac::Address &aMacAddress) +{ + return FindParent(Neighbor::AddressMatcher(aMacAddress, Neighbor::kInStateValidOrRestoring)); +} + +Neighbor *NeighborTable::FindNeighbor(const Neighbor::AddressMatcher &aMatcher) +{ + Neighbor *neighbor = nullptr; + +#if OPENTHREAD_FTD + if (Get().IsRouterOrLeader()) + { + neighbor = FindChildOrRouter(aMatcher); + } + + if (neighbor == nullptr) +#endif + { + neighbor = FindParent(aMatcher); + } + + return neighbor; +} + +Neighbor *NeighborTable::FindNeighbor(Mac::ShortAddress aShortAddress) +{ + Neighbor *neighbor = nullptr; + + VerifyOrExit((aShortAddress != Mac::kShortAddrBroadcast) && (aShortAddress != Mac::kShortAddrInvalid), OT_NOOP); + neighbor = FindNeighbor(Neighbor::AddressMatcher(aShortAddress, Neighbor::kInStateValidOrRestoring)); + +exit: + return neighbor; +} + +Neighbor *NeighborTable::FindNeighbor(const Mac::ExtAddress &aExtAddress) +{ + return FindNeighbor(Neighbor::AddressMatcher(aExtAddress, Neighbor::kInStateValidOrRestoring)); +} + +Neighbor *NeighborTable::FindNeighbor(const Mac::Address &aMacAddress) +{ + return FindNeighbor(Neighbor::AddressMatcher(aMacAddress, Neighbor::kInStateValidOrRestoring)); +} + +#if OPENTHREAD_FTD + +Neighbor *NeighborTable::FindChildOrRouter(const Neighbor::AddressMatcher &aMatcher) +{ + Neighbor *neighbor; + + neighbor = Get().FindChild(aMatcher); + + if (neighbor == nullptr) + { + neighbor = Get().FindRouter(aMatcher); + } + + return neighbor; +} + +Neighbor *NeighborTable::FindNeighbor(const Ip6::Address &aIp6Address) +{ + Neighbor * neighbor = nullptr; + Mac::Address macAddresss; + + if (aIp6Address.IsLinkLocal()) + { + aIp6Address.GetIid().ConvertToMacAddress(macAddresss); + } + + if (Get().IsRoutingLocator(aIp6Address)) + { + macAddresss.SetShort(aIp6Address.GetIid().GetLocator()); + } + + if (!macAddresss.IsNone()) + { + neighbor = FindChildOrRouter(Neighbor::AddressMatcher(macAddresss, Neighbor::kInStateValidOrRestoring)); + ExitNow(); + } + + for (Child &child : Get().Iterate(Child::kInStateValidOrRestoring)) + { + if (child.HasIp6Address(aIp6Address)) + { + ExitNow(neighbor = &child); + } + } + +exit: + return neighbor; +} + +Neighbor *NeighborTable::FindRxOnlyNeighborRouter(const Mac::Address &aMacAddress) +{ + Neighbor *neighbor = nullptr; + + VerifyOrExit(Get().IsChild(), OT_NOOP); + neighbor = Get().GetNeighbor(aMacAddress); + +exit: + return neighbor; +} + +otError NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo) +{ + otError error = OT_ERROR_NONE; + int16_t index; + + // Non-negative iterator value gives the Child index into child table + + if (aIterator >= 0) + { + for (index = aIterator;; index++) + { + Child *child = Get().GetChildAtIndex(static_cast(index)); + + if (child == nullptr) + { + break; + } + + if (child->IsStateValid()) + { + aNeighInfo.SetFrom(*child); + aNeighInfo.mIsChild = true; + index++; + aIterator = index; + ExitNow(); + } + } + + aIterator = 0; + } + + // Negative iterator value gives the current index into mRouters array + + for (index = -aIterator; index <= Mle::kMaxRouterId; index++) + { + Router *router = Get().GetRouter(static_cast(index)); + + if (router != nullptr && router->IsStateValid()) + { + aNeighInfo.SetFrom(*router); + aNeighInfo.mIsChild = false; + index++; + aIterator = -index; + ExitNow(); + } + } + + aIterator = -index; + error = OT_ERROR_NOT_FOUND; + +exit: + return error; +} + +#endif // OPENTHREAD_FTD + +#if OPENTHREAD_MTD + +otError NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo) +{ + otError error = OT_ERROR_NOT_FOUND; + + VerifyOrExit(aIterator == OT_NEIGHBOR_INFO_ITERATOR_INIT, OT_NOOP); + + aIterator++; + VerifyOrExit(Get().GetParent().IsStateValid(), OT_NOOP); + + aNeighInfo.SetFrom(Get().GetParent()); + aNeighInfo.mIsChild = false; + error = OT_ERROR_NONE; + +exit: + return error; +} + +#endif + +} // namespace ot diff --git a/src/core/thread/neighbor_table.hpp b/src/core/thread/neighbor_table.hpp new file mode 100644 index 000000000..24452a45c --- /dev/null +++ b/src/core/thread/neighbor_table.hpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2016-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 Thread neighbor table. + */ + +#ifndef NEIGHBOR_TABLE_HPP_ +#define NEIGHBOR_TABLE_HPP_ + +#include "openthread-core-config.h" + +#include "common/locator.hpp" +#include "thread/topology.hpp" + +namespace ot { + +/** + * This class represents the Thread neighbor table. + * + */ +class NeighborTable : public InstanceLocator +{ +public: + /** + * This constructor initializes the `NeighborTable` instance. + * + * @param[in] aInstance A reference to the OpenThread instance. + * + */ + explicit NeighborTable(Instance &aInstance); + + /** + * This method searches among parent and parent candidate to find a `Neighbor` corresponding to a given short + * address. + * + * @param[in] aShortAddress A short address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aShortAddress, nullptr otherwise. + * + */ + Neighbor *FindParent(Mac::ShortAddress aShortAddress); + + /** + * This method searches in parent and parent candidate to find a `Neighbor` corresponding to a given MAC Extended + * Address. + * + * @param[in] aExtAddress A MAC Extended Address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aExtAddress, nullptr otherwise. + * + */ + Neighbor *FindParent(const Mac::ExtAddress &aExtAddress); + + /** + * This method searches among parent and parent candidate to find a `Neighbor` object corresponding to a given MAC + * address. + * + * @param[in] aMacAddress A MAC address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aMacAddress, nullptr otherwise. + * + */ + Neighbor *FindParent(const Mac::Address &aMacAddress); + + /** + * This method searches in the neighbor table to find a `Neighbor` corresponding to a given short address. + * + * @param[in] aShortAddress A short address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aShortAddress, nullptr otherwise. + * + */ + Neighbor *FindNeighbor(Mac::ShortAddress aShortAddress); + + /** + * This method searches in the neighbor table to find a `Neighbor` corresponding to a given MAC Extended Address. + * + * @param[in] aExtAddress A MAC Extended Address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aExtAddress, nullptr otherwise. + * + */ + Neighbor *FindNeighbor(const Mac::ExtAddress &aExtAddress); + + /** + * This method searches in the neighbor table to find a `Neighbor` object corresponding to a given MAC address. + * + * @param[in] aMacAddress A MAC address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aMacAddress, nullptr otherwise. + * + */ + Neighbor *FindNeighbor(const Mac::Address &aMacAddress); + +#if OPENTHREAD_FTD + + /** + * This method searches in the neighbor table to find a `Neighbor` object corresponding to a given IPv6 address. + * + * @param[in] aIp6Address An IPv6 address. + * + * @returns A pointer to the `Neighbor` corresponding to @p aIp6Address, nullptr otherwise. + * + */ + Neighbor *FindNeighbor(const Ip6::Address &aIp6Address); + + /** + * This method searches in the neighbor table to find a `Neighbor` for which a one-way link is maintained (as in the + * case of an FTD child with neighbor routers). + * + * @param[in] aMacAddress A MAC address. + * + * @returns A pointer to the Neighbor corresponding to @p aMacAddress, nullptr otherwise. + * + */ + Neighbor *FindRxOnlyNeighborRouter(const Mac::Address &aMacAddress); + +#endif // OPENTHREAD_FTD + + /** + * This method gets the next neighbor information. It is used to iterate through the entries of + * the neighbor table. + * + * @param[inout] aIterator A reference to the iterator context. To get the first neighbor entry + it should be set to OT_NEIGHBOR_INFO_ITERATOR_INIT. + * @param[out] aNeighInfo The neighbor information. + * + * @retval OT_ERROR_NONE Successfully found the next neighbor entry in table. + * @retval OT_ERROR_NOT_FOUND No subsequent neighbor entry exists in the table. + * + */ + otError GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo); + +private: + Neighbor *FindParent(const Neighbor::AddressMatcher &aMatcher); + Neighbor *FindNeighbor(const Neighbor::AddressMatcher &aMatcher); +#if OPENTHREAD_FTD + Neighbor *FindChildOrRouter(const Neighbor::AddressMatcher &aMatcher); +#endif +}; + +} // namespace ot + +#endif // NEIGHBOR_TABLE_HPP_ diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp index 27aaab65b..478519b20 100644 --- a/src/core/thread/router_table.cpp +++ b/src/core/thread/router_table.cpp @@ -373,6 +373,11 @@ Router *RouterTable::GetNeighbor(const Mac::ExtAddress &aExtAddress) return FindRouter(Router::AddressMatcher(aExtAddress, Router::kInStateValid)); } +Router *RouterTable::GetNeighbor(const Mac::Address &aMacAddress) +{ + return FindRouter(Router::AddressMatcher(aMacAddress, Router::kInStateValid)); +} + const Router *RouterTable::GetRouter(uint8_t aRouterId) const { const Router *router = nullptr; diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp index 2fb06a6d3..9ceb53635 100644 --- a/src/core/thread/router_table.hpp +++ b/src/core/thread/router_table.hpp @@ -44,6 +44,7 @@ namespace ot { class RouterTable : public InstanceLocator { + friend class NeighborTable; class IteratorBuilder; public: @@ -271,6 +272,16 @@ public: */ Router *GetNeighbor(const Mac::ExtAddress &aExtAddress); + /** + * This method returns the neighbor for a given MAC address. + * + * @param[in] aMacAddress A MAC address + * + * @returns A pointer to the router or nullptr if the router could not be found. + * + */ + Router *GetNeighbor(const Mac::Address &aMacAddress); + /** * This method returns the router for a given router id. * diff --git a/src/core/utils/child_supervision.cpp b/src/core/utils/child_supervision.cpp index 16c35d931..238ce0488 100644 --- a/src/core/utils/child_supervision.cpp +++ b/src/core/utils/child_supervision.cpp @@ -207,7 +207,7 @@ void SupervisionListener::UpdateOnReceive(const Mac::Address &aSourceAddress, bo // If listener is enabled and device is a child and it received a secure frame from its parent, restart the timer. VerifyOrExit(mTimer.IsRunning() && aIsSecure && Get().IsChild() && - (Get().GetNeighbor(aSourceAddress) == &Get().GetParent()), + (Get().FindNeighbor(aSourceAddress) == &Get().GetParent()), OT_NOOP); RestartTimer();