From 98292673fbdcf9b78e14128ac2010503c4e6effe Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 29 Aug 2023 08:47:11 -0700 Subject: [PATCH] [core] add separate `neighbor.hpp`, `child.hpp`, and `router.hpp` (#9376) This commit adds separate files for `Neighbor`, `Child`, and `Router` classes. --- src/core/BUILD.gn | 8 +- src/core/CMakeLists.txt | 4 +- src/core/mac/data_poll_sender.hpp | 2 +- src/core/mac/mac.cpp | 3 +- src/core/mac/mac_filter.cpp | 2 +- src/core/thread/{topology.cpp => child.cpp} | 295 +------- src/core/thread/child.hpp | 550 ++++++++++++++ src/core/thread/child_supervision.hpp | 3 +- src/core/thread/child_table.hpp | 2 +- src/core/thread/dua_manager.hpp | 2 +- src/core/thread/indirect_sender.cpp | 2 +- src/core/thread/mesh_forwarder.hpp | 2 +- src/core/thread/mle.hpp | 3 +- src/core/thread/mle_router.hpp | 3 +- src/core/thread/mlr_manager.hpp | 2 +- src/core/thread/neighbor.cpp | 261 +++++++ .../thread/{topology.hpp => neighbor.hpp} | 708 +----------------- src/core/thread/neighbor_table.hpp | 2 +- src/core/thread/network_diagnostic_tlvs.hpp | 3 +- src/core/thread/router.cpp | 120 +++ src/core/thread/router.hpp | 240 ++++++ src/core/thread/router_table.hpp | 2 +- src/core/thread/src_match_controller.cpp | 2 +- src/core/utils/otns.hpp | 2 +- tests/unit/test_child.cpp | 2 +- tests/unit/test_toolchain.cpp | 2 +- 26 files changed, 1208 insertions(+), 1019 deletions(-) rename src/core/thread/{topology.cpp => child.cpp} (52%) create mode 100644 src/core/thread/child.hpp create mode 100644 src/core/thread/neighbor.cpp rename src/core/thread/{topology.hpp => neighbor.hpp} (56%) create mode 100644 src/core/thread/router.cpp create mode 100644 src/core/thread/router.hpp diff --git a/src/core/BUILD.gn b/src/core/BUILD.gn index 1b3297074..eb07520ce 100644 --- a/src/core/BUILD.gn +++ b/src/core/BUILD.gn @@ -604,6 +604,8 @@ openthread_core_files = [ "thread/announce_sender.hpp", "thread/anycast_locator.cpp", "thread/anycast_locator.hpp", + "thread/child.cpp", + "thread/child.hpp", "thread/child_mask.hpp", "thread/child_supervision.cpp", "thread/child_supervision.hpp", @@ -646,6 +648,8 @@ openthread_core_files = [ "thread/mlr_manager.cpp", "thread/mlr_manager.hpp", "thread/mlr_types.hpp", + "thread/neighbor.cpp", + "thread/neighbor.hpp", "thread/neighbor_table.cpp", "thread/neighbor_table.hpp", "thread/network_data.cpp", @@ -674,6 +678,8 @@ openthread_core_files = [ "thread/panid_query_server.hpp", "thread/radio_selector.cpp", "thread/radio_selector.hpp", + "thread/router.cpp", + "thread/router.hpp", "thread/router_table.cpp", "thread/router_table.hpp", "thread/src_match_controller.cpp", @@ -685,8 +691,6 @@ openthread_core_files = [ "thread/time_sync_service.hpp", "thread/tmf.cpp", "thread/tmf.hpp", - "thread/topology.cpp", - "thread/topology.hpp", "thread/uri_paths.cpp", "thread/uri_paths.hpp", "thread/version.hpp", diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e77b576e1..e6b86f005 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -195,6 +195,7 @@ set(COMMON_SOURCES thread/announce_begin_server.cpp thread/announce_sender.cpp thread/anycast_locator.cpp + thread/child.cpp thread/child_supervision.cpp thread/child_table.cpp thread/csl_tx_scheduler.cpp @@ -215,6 +216,7 @@ set(COMMON_SOURCES thread/mle_tlvs.cpp thread/mle_types.cpp thread/mlr_manager.cpp + thread/neighbor.cpp thread/neighbor_table.cpp thread/network_data.cpp thread/network_data_leader.cpp @@ -229,12 +231,12 @@ set(COMMON_SOURCES thread/network_diagnostic_tlvs.cpp thread/panid_query_server.cpp thread/radio_selector.cpp + thread/router.cpp thread/router_table.cpp thread/src_match_controller.cpp thread/thread_netif.cpp thread/time_sync_service.cpp thread/tmf.cpp - thread/topology.cpp thread/uri_paths.cpp utils/channel_manager.cpp utils/channel_monitor.cpp diff --git a/src/core/mac/data_poll_sender.hpp b/src/core/mac/data_poll_sender.hpp index edb66b806..5780042fd 100644 --- a/src/core/mac/data_poll_sender.hpp +++ b/src/core/mac/data_poll_sender.hpp @@ -42,7 +42,7 @@ #include "common/timer.hpp" #include "mac/mac.hpp" #include "mac/mac_frame.hpp" -#include "thread/topology.hpp" +#include "thread/neighbor.hpp" namespace ot { diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 5ef871961..71634147d 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -48,11 +48,12 @@ #include "crypto/sha256.hpp" #include "mac/mac_frame.hpp" #include "radio/radio.hpp" +#include "thread/child.hpp" #include "thread/child_table.hpp" #include "thread/link_quality.hpp" #include "thread/mle_router.hpp" +#include "thread/neighbor.hpp" #include "thread/thread_netif.hpp" -#include "thread/topology.hpp" namespace ot { namespace Mac { diff --git a/src/core/mac/mac_filter.cpp b/src/core/mac/mac_filter.cpp index 97604a33c..e0cddf3ad 100644 --- a/src/core/mac/mac_filter.cpp +++ b/src/core/mac/mac_filter.cpp @@ -38,7 +38,7 @@ #include "common/array.hpp" #include "common/as_core_type.hpp" #include "common/code_utils.hpp" -#include "thread/topology.hpp" +#include "thread/neighbor.hpp" namespace ot { namespace Mac { diff --git a/src/core/thread/topology.cpp b/src/core/thread/child.cpp similarity index 52% rename from src/core/thread/topology.cpp rename to src/core/thread/child.cpp index 68b58006e..7dbec0c40 100644 --- a/src/core/thread/topology.cpp +++ b/src/core/thread/child.cpp @@ -28,10 +28,10 @@ /** * @file - * This file includes definitions for maintaining Thread network topologies. + * This file includes definitions for a Thread `Child`. */ -#include "topology.hpp" +#include "child.hpp" #include "common/array.hpp" #include "common/code_utils.hpp" @@ -42,222 +42,6 @@ namespace ot { -void Neighbor::SetState(State aState) -{ - VerifyOrExit(mState != aState); - mState = static_cast(aState); - -#if OPENTHREAD_CONFIG_UPTIME_ENABLE - if (mState == kStateValid) - { - mConnectionStart = Uptime::MsecToSec(Get().GetUptime()); - } -#endif - -exit: - return; -} - -#if OPENTHREAD_CONFIG_UPTIME_ENABLE -uint32_t Neighbor::GetConnectionTime(void) const -{ - return IsStateValid() ? Uptime::MsecToSec(Get().GetUptime()) - mConnectionStart : 0; -} -#endif - -bool Neighbor::AddressMatcher::Matches(const Neighbor &aNeighbor) const -{ - bool matches = false; - - VerifyOrExit(aNeighbor.MatchesFilter(mStateFilter)); - - if (mShortAddress != Mac::kShortAddrInvalid) - { - VerifyOrExit(mShortAddress == aNeighbor.GetRloc16()); - } - - if (mExtAddress != nullptr) - { - VerifyOrExit(*mExtAddress == aNeighbor.GetExtAddress()); - } - - matches = true; - -exit: - return matches; -} - -void Neighbor::Info::SetFrom(const Neighbor &aNeighbor) -{ - Clear(); - - mExtAddress = aNeighbor.GetExtAddress(); - mAge = Time::MsecToSec(TimerMilli::GetNow() - aNeighbor.GetLastHeard()); - mRloc16 = aNeighbor.GetRloc16(); - mLinkFrameCounter = aNeighbor.GetLinkFrameCounters().GetMaximum(); - mMleFrameCounter = aNeighbor.GetMleFrameCounter(); - mLinkQualityIn = aNeighbor.GetLinkQualityIn(); - mAverageRssi = aNeighbor.GetLinkInfo().GetAverageRss(); - mLastRssi = aNeighbor.GetLinkInfo().GetLastRss(); - mLinkMargin = aNeighbor.GetLinkInfo().GetLinkMargin(); - mFrameErrorRate = aNeighbor.GetLinkInfo().GetFrameErrorRate(); - mMessageErrorRate = aNeighbor.GetLinkInfo().GetMessageErrorRate(); - mRxOnWhenIdle = aNeighbor.IsRxOnWhenIdle(); - mFullThreadDevice = aNeighbor.IsFullThreadDevice(); - mFullNetworkData = (aNeighbor.GetNetworkDataType() == NetworkData::kFullSet); - mVersion = aNeighbor.GetVersion(); -#if OPENTHREAD_CONFIG_UPTIME_ENABLE - mConnectionTime = aNeighbor.GetConnectionTime(); -#endif -} - -void Neighbor::Init(Instance &aInstance) -{ - InstanceLocatorInit::Init(aInstance); - mLinkInfo.Init(aInstance); - SetState(kStateInvalid); -} - -bool Neighbor::IsStateValidOrAttaching(void) const -{ - bool rval = false; - - switch (GetState()) - { - case kStateInvalid: - case kStateParentRequest: - case kStateParentResponse: - break; - - case kStateRestored: - case kStateChildIdRequest: - case kStateLinkRequest: - case kStateChildUpdateRequest: - case kStateValid: - rval = true; - break; - } - - return rval; -} - -bool Neighbor::MatchesFilter(StateFilter aFilter) const -{ - bool matches = false; - - switch (aFilter) - { - case kInStateValid: - matches = IsStateValid(); - break; - - case kInStateValidOrRestoring: - matches = IsStateValidOrRestoring(); - break; - - case kInStateChildIdRequest: - matches = IsStateChildIdRequest(); - break; - - case kInStateValidOrAttaching: - matches = IsStateValidOrAttaching(); - break; - - case kInStateInvalid: - matches = IsStateInvalid(); - break; - - case kInStateAnyExceptInvalid: - matches = !IsStateInvalid(); - break; - - case kInStateAnyExceptValidOrRestoring: - matches = !IsStateValidOrRestoring(); - break; - - case kInStateAny: - matches = true; - break; - } - - return matches; -} - -#if OPENTHREAD_CONFIG_MULTI_RADIO -void Neighbor::SetLastRxFragmentTag(uint16_t aTag) -{ - mLastRxFragmentTag = (aTag == 0) ? 0xffff : aTag; - mLastRxFragmentTagTime = TimerMilli::GetNow(); -} - -bool Neighbor::IsLastRxFragmentTagSet(void) const -{ - return (mLastRxFragmentTag != 0) && (TimerMilli::GetNow() <= mLastRxFragmentTagTime + kLastRxFragmentTagTimeout); -} -#endif - -#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE -void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss) -{ - for (LinkMetrics::SeriesInfo &entry : mLinkMetricsSeriesInfoList) - { - if (aSeriesId == 0 || aSeriesId == entry.GetSeriesId()) - { - entry.AggregateLinkMetrics(aFrameType, aLqi, aRss); - } - } -} - -LinkMetrics::SeriesInfo *Neighbor::GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId) -{ - return mLinkMetricsSeriesInfoList.FindMatching(aSeriesId); -} - -void Neighbor::AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo) -{ - mLinkMetricsSeriesInfoList.Push(aSeriesInfo); -} - -LinkMetrics::SeriesInfo *Neighbor::RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId) -{ - return mLinkMetricsSeriesInfoList.RemoveMatching(aSeriesId); -} - -void Neighbor::RemoveAllForwardTrackingSeriesInfo(void) -{ - while (!mLinkMetricsSeriesInfoList.IsEmpty()) - { - LinkMetrics::SeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop(); - Get().Free(*seriesInfo); - } -} -#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE - -const char *Neighbor::StateToString(State aState) -{ - static const char *const kStateStrings[] = { - "Invalid", // (0) kStateInvalid - "Restored", // (1) kStateRestored - "ParentReq", // (2) kStateParentRequest - "ParentRes", // (3) kStateParentResponse - "ChildIdReq", // (4) kStateChildIdRequest - "LinkReq", // (5) kStateLinkRequest - "ChildUpdateReq", // (6) kStateChildUpdateRequest - "Valid", // (7) kStateValid - }; - - static_assert(0 == kStateInvalid, "kStateInvalid value is incorrect"); - static_assert(1 == kStateRestored, "kStateRestored value is incorrect"); - static_assert(2 == kStateParentRequest, "kStateParentRequest value is incorrect"); - static_assert(3 == kStateParentResponse, "kStateParentResponse value is incorrect"); - static_assert(4 == kStateChildIdRequest, "kStateChildIdRequest value is incorrect"); - static_assert(5 == kStateLinkRequest, "kStateLinkRequest value is incorrect"); - static_assert(6 == kStateChildUpdateRequest, "kStateChildUpdateRequest value is incorrect"); - static_assert(7 == kStateValid, "kStateValid value is incorrect"); - - return kStateStrings[aState]; -} - #if OPENTHREAD_FTD void Child::Info::SetFrom(const Child &aChild) @@ -533,79 +317,4 @@ void Child::SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState) #endif // OPENTHREAD_FTD -void Router::Info::SetFrom(const Router &aRouter) -{ - Clear(); - mRloc16 = aRouter.GetRloc16(); - mRouterId = Mle::RouterIdFromRloc16(mRloc16); - mExtAddress = aRouter.GetExtAddress(); - mAllocated = true; - mNextHop = aRouter.GetNextHop(); - mLinkEstablished = aRouter.IsStateValid(); - mPathCost = aRouter.GetCost(); - mLinkQualityIn = aRouter.GetLinkQualityIn(); - mLinkQualityOut = aRouter.GetLinkQualityOut(); - mAge = static_cast(Time::MsecToSec(TimerMilli::GetNow() - aRouter.GetLastHeard())); - mVersion = ClampToUint8(aRouter.GetVersion()); -} - -void Router::Info::SetFrom(const Parent &aParent) -{ - SetFrom(static_cast(aParent)); -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - mCslClockAccuracy = aParent.GetCslAccuracy().GetClockAccuracy(); - mCslUncertainty = aParent.GetCslAccuracy().GetUncertainty(); -#endif -} - -void Router::Clear(void) -{ - Instance &instance = GetInstance(); - - memset(reinterpret_cast(this), 0, sizeof(Router)); - Init(instance); -} - -LinkQuality Router::GetTwoWayLinkQuality(void) const { return Min(GetLinkQualityIn(), GetLinkQualityOut()); } - -void Router::SetFrom(const Parent &aParent) -{ - // We use an intermediate pointer to copy `aParent` to silence - // code checkers warning about object slicing (assigning a - // sub-class to base class instance). - - const Router *parentAsRouter = &aParent; - - *this = *parentAsRouter; -} - -void Parent::Clear(void) -{ - Instance &instance = GetInstance(); - - memset(reinterpret_cast(this), 0, sizeof(Parent)); - Init(instance); -} - -bool Router::SetNextHopAndCost(uint8_t aNextHop, uint8_t aCost) -{ - bool changed = false; - - if (mNextHop != aNextHop) - { - mNextHop = aNextHop; - changed = true; - } - - if (mCost != aCost) - { - mCost = aCost; - changed = true; - } - - return changed; -} - -bool Router::SetNextHopToInvalid(void) { return SetNextHopAndCost(Mle::kInvalidRouterId, 0); } - } // namespace ot diff --git a/src/core/thread/child.hpp b/src/core/thread/child.hpp new file mode 100644 index 000000000..452cd4da8 --- /dev/null +++ b/src/core/thread/child.hpp @@ -0,0 +1,550 @@ +/* + * Copyright (c) 2016, 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 a Thread `Child`. + */ + +#ifndef CHILD_HPP_ +#define CHILD_HPP_ + +#include "openthread-core-config.h" + +#include "thread/neighbor.hpp" + +namespace ot { + +#if OPENTHREAD_FTD + +/** + * Represents a Thread Child. + * + */ +class Child : public Neighbor, + public IndirectSender::ChildInfo, + public DataPollHandler::ChildInfo +#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE + , + public CslTxScheduler::ChildInfo +#endif +{ + class AddressIteratorBuilder; + +public: + static constexpr uint8_t kMaxRequestTlvs = 6; + + /** + * Represents diagnostic information for a Thread Child. + * + */ + class Info : public otChildInfo, public Clearable + { + public: + /** + * Sets the `Info` instance from a given `Child`. + * + * @param[in] aChild A neighbor. + * + */ + void SetFrom(const Child &aChild); + }; + + /** + * Defines an iterator used to go through IPv6 address entries of a child. + * + */ + class AddressIterator : public Unequatable + { + friend class AddressIteratorBuilder; + + public: + /** + * Represents an index indicating the current IPv6 address entry to which the iterator is pointing. + * + */ + typedef otChildIp6AddressIterator Index; + + /** + * Initializes the iterator associated with a given `Child` starting from beginning of the + * IPv6 address list. + * + * @param[in] aChild A reference to a child entry. + * @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses. + * + */ + explicit AddressIterator(const Child &aChild, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) + : AddressIterator(aChild, 0, aFilter) + { + } + + /** + * Initializes the iterator associated with a given `Child` starting from a given index + * + * @param[in] aChild A reference to the child entry. + * @param[in] aIndex An index (`Index`) with which to initialize the iterator. + * @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses. + * + */ + AddressIterator(const Child &aChild, Index aIndex, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) + : mChild(aChild) + , mFilter(aFilter) + , mIndex(aIndex) + { + Update(); + } + + /** + * Converts the iterator into an index. + * + * @returns An index corresponding to the iterator. + * + */ + Index GetAsIndex(void) const { return mIndex; } + + /** + * Gets the iterator's associated `Child` entry. + * + * @returns The associated child entry. + * + */ + const Child &GetChild(void) const { return mChild; } + + /** + * Gets the current `Child` IPv6 Address to which the iterator is pointing. + * + * @returns A pointer to the associated IPv6 Address, or `nullptr` if iterator is done. + * + */ + const Ip6::Address *GetAddress(void) const; + + /** + * Indicates whether the iterator has reached end of the list. + * + * @retval TRUE There are no more entries in the list (reached end of the list). + * @retval FALSE The current entry is valid. + * + */ + bool IsDone(void) const { return (mIndex >= kMaxIndex); } + + /** + * Overloads `++` operator (pre-increment) to advance the iterator. + * + * The iterator is moved to point to the next `Address` entry. If there are no more `Ip6::Address` entries + * `IsDone()` returns `true`. + * + */ + void operator++(void) { mIndex++, Update(); } + + /** + * Overloads `++` operator (post-increment) to advance the iterator. + * + * The iterator is moved to point to the next `Address` entry. If there are no more `Ip6::Address` entries + * `IsDone()` returns `true`. + * + */ + void operator++(int) { mIndex++, Update(); } + + /** + * Overloads the `*` dereference operator and gets a reference to `Ip6::Address` to which the + * iterator is currently pointing. + * + * MUST be used when the iterator is not done (i.e., `IsDone()` returns `false`). + * + * @returns A reference to the `Ip6::Address` entry currently pointed by the iterator. + * + */ + const Ip6::Address &operator*(void) const { return *GetAddress(); } + + /** + * Overloads operator `==` to evaluate whether or not two `Iterator` instances are equal. + * + * MUST be used when the two iterators are associated with the same `Child` entry. + * + * @param[in] aOther The other `Iterator` to compare with. + * + * @retval TRUE If the two `Iterator` objects are equal. + * @retval FALSE If the two `Iterator` objects are not equal. + * + */ + bool operator==(const AddressIterator &aOther) const { return (mIndex == aOther.mIndex); } + + private: + enum IteratorType : uint8_t + { + kEndIterator, + }; + + static constexpr uint16_t kMaxIndex = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD; + + AddressIterator(const Child &aChild, IteratorType) + : mChild(aChild) + , mIndex(kMaxIndex) + { + } + + void Update(void); + + const Child &mChild; + Ip6::Address::TypeFilter mFilter; + Index mIndex; + Ip6::Address mMeshLocalAddress; + }; + + /** + * Initializes the `Child` object. + * + * @param[in] aInstance A reference to OpenThread instance. + * + */ + void Init(Instance &aInstance) { Neighbor::Init(aInstance); } + + /** + * Clears the child entry. + * + */ + void Clear(void); + + /** + * Clears the IPv6 address list for the child. + * + */ + void ClearIp6Addresses(void); + + /** + * Sets the device mode flags. + * + * @param[in] aMode The device mode flags. + * + */ + void SetDeviceMode(Mle::DeviceMode aMode); + + /** + * Gets the mesh-local IPv6 address. + * + * @param[out] aAddress A reference to an IPv6 address to provide address (if any). + * + * @retval kErrorNone Successfully found the mesh-local address and updated @p aAddress. + * @retval kErrorNotFound No mesh-local IPv6 address in the IPv6 address list. + * + */ + Error GetMeshLocalIp6Address(Ip6::Address &aAddress) const; + + /** + * Returns the Mesh Local Interface Identifier. + * + * @returns The Mesh Local Interface Identifier. + * + */ + const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; } + + /** + * Enables range-based `for` loop iteration over all (or a subset of) IPv6 addresses. + * + * Should be used as follows: to iterate over all addresses + * + * for (const Ip6::Address &address : child.IterateIp6Addresses()) { ... } + * + * or to iterate over a subset of IPv6 addresses determined by a given address type filter + * + * for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticast)) { ... } + * + * @param[in] aFilter An IPv6 address type filter restricting iteration to certain type of addresses (default is + * to accept any address type). + * + * @returns An IteratorBuilder instance. + * + */ + AddressIteratorBuilder IterateIp6Addresses(Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) const + { + return AddressIteratorBuilder(*this, aFilter); + } + + /** + * Adds an IPv6 address to the list. + * + * @param[in] aAddress A reference to IPv6 address to be added. + * + * @retval kErrorNone Successfully added the new address. + * @retval kErrorAlready Address is already in the list. + * @retval kErrorNoBufs Already at maximum number of addresses. No entry available to add the new address. + * @retval kErrorInvalidArgs Address is invalid (it is the Unspecified Address). + * + */ + Error AddIp6Address(const Ip6::Address &aAddress); + + /** + * Removes an IPv6 address from the list. + * + * @param[in] aAddress A reference to IPv6 address to be removed. + * + * @retval kErrorNone Successfully removed the address. + * @retval kErrorNotFound Address was not found in the list. + * @retval kErrorInvalidArgs Address is invalid (it is the Unspecified Address). + * + */ + Error RemoveIp6Address(const Ip6::Address &aAddress); + + /** + * Indicates whether an IPv6 address is in the list of IPv6 addresses of the child. + * + * @param[in] aAddress A reference to IPv6 address. + * + * @retval TRUE The address exists on the list. + * @retval FALSE Address was not found in the list. + * + */ + bool HasIp6Address(const Ip6::Address &aAddress) const; + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE + /** + * Retrieves the Domain Unicast Address registered by the child. + * + * @returns A pointer to Domain Unicast Address registered by the child if there is. + * + */ + const Ip6::Address *GetDomainUnicastAddress(void) const; +#endif + + /** + * Gets the child timeout. + * + * @returns The child timeout. + * + */ + uint32_t GetTimeout(void) const { return mTimeout; } + + /** + * Sets the child timeout. + * + * @param[in] aTimeout The child timeout. + * + */ + void SetTimeout(uint32_t aTimeout) { mTimeout = aTimeout; } + + /** + * Gets the network data version. + * + * @returns The network data version. + * + */ + uint8_t GetNetworkDataVersion(void) const { return mNetworkDataVersion; } + + /** + * Sets the network data version. + * + * @param[in] aVersion The network data version. + * + */ + void SetNetworkDataVersion(uint8_t aVersion) { mNetworkDataVersion = aVersion; } + + /** + * Generates a new challenge value to use during a child attach. + * + */ + void GenerateChallenge(void) { mAttachChallenge.GenerateRandom(); } + + /** + * Gets the current challenge value used during attach. + * + * @returns The current challenge value. + * + */ + const Mle::TxChallenge &GetChallenge(void) const { return mAttachChallenge; } + + /** + * Clears the requested TLV list. + * + */ + void ClearRequestTlvs(void) { memset(mRequestTlvs, Mle::Tlv::kInvalid, sizeof(mRequestTlvs)); } + + /** + * Returns the requested TLV at index @p aIndex. + * + * @param[in] aIndex The index into the requested TLV list. + * + * @returns The requested TLV at index @p aIndex. + * + */ + uint8_t GetRequestTlv(uint8_t aIndex) const { return mRequestTlvs[aIndex]; } + + /** + * Sets the requested TLV at index @p aIndex. + * + * @param[in] aIndex The index into the requested TLV list. + * @param[in] aType The TLV type. + * + */ + void SetRequestTlv(uint8_t aIndex, uint8_t aType) { mRequestTlvs[aIndex] = aType; } + + /** + * Returns the supervision interval (in seconds). + * + * @returns The supervision interval (in seconds). + * + */ + uint16_t GetSupervisionInterval(void) const { return mSupervisionInterval; } + + /** + * Sets the supervision interval. + * + * @param[in] aInterval The supervision interval (in seconds). + * + */ + void SetSupervisionInterval(uint16_t aInterval) { mSupervisionInterval = aInterval; } + + /** + * Increments the number of seconds since last supervision of the child. + * + */ + void IncrementSecondsSinceLastSupervision(void) { mSecondsSinceSupervision++; } + + /** + * Returns the number of seconds since last supervision of the child (last message to the child) + * + * @returns Number of seconds since last supervision of the child. + * + */ + uint16_t GetSecondsSinceLastSupervision(void) const { return mSecondsSinceSupervision; } + + /** + * Resets the number of seconds since last supervision of the child to zero. + * + */ + void ResetSecondsSinceLastSupervision(void) { mSecondsSinceSupervision = 0; } + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE + /** + * Returns MLR state of an IPv6 multicast address. + * + * @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`. + * + * @param[in] aAddress The IPv6 multicast address. + * + * @returns MLR state of the IPv6 multicast address. + * + */ + MlrState GetAddressMlrState(const Ip6::Address &aAddress) const; + + /** + * Sets MLR state of an IPv6 multicast address. + * + * @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`. + * + * @param[in] aAddress The IPv6 multicast address. + * @param[in] aState The target MLR state. + * + */ + void SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState); + + /** + * Returns if the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`. + * + * @param[in] aAddress The IPv6 address. + * + * @retval true If the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`. + * @retval false If the Child does not have IPv6 address @p aAddress of MLR state `kMlrStateRegistered`. + * + */ + bool HasMlrRegisteredAddress(const Ip6::Address &aAddress) const; + + /** + * Returns if the Child has any IPv6 address of MLR state `kMlrStateRegistered`. + * + * @retval true If the Child has any IPv6 address of MLR state `kMlrStateRegistered`. + * @retval false If the Child does not have any IPv6 address of MLR state `kMlrStateRegistered`. + * + */ + bool HasAnyMlrRegisteredAddress(void) const { return mMlrRegisteredMask.HasAny(); } + + /** + * Returns if the Child has any IPv6 address of MLR state `kMlrStateToRegister`. + * + * @retval true If the Child has any IPv6 address of MLR state `kMlrStateToRegister`. + * @retval false If the Child does not have any IPv6 address of MLR state `kMlrStateToRegister`. + * + */ + bool HasAnyMlrToRegisterAddress(void) const { return mMlrToRegisterMask.HasAny(); } +#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE + +private: +#if OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD < 2 +#error OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD should be at least set to 2. +#endif + + static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1; + + typedef BitVector ChildIp6AddressMask; + + class AddressIteratorBuilder + { + public: + AddressIteratorBuilder(const Child &aChild, Ip6::Address::TypeFilter aFilter) + : mChild(aChild) + , mFilter(aFilter) + { + } + + AddressIterator begin(void) { return AddressIterator(mChild, mFilter); } + AddressIterator end(void) { return AddressIterator(mChild, AddressIterator::kEndIterator); } + + private: + const Child &mChild; + Ip6::Address::TypeFilter mFilter; + }; + + Ip6::InterfaceIdentifier mMeshLocalIid; ///< IPv6 address IID for mesh-local address + Ip6::Address mIp6Address[kNumIp6Addresses]; ///< Registered IPv6 addresses + uint32_t mTimeout; ///< Child timeout + +#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE + ChildIp6AddressMask mMlrToRegisterMask; + ChildIp6AddressMask mMlrRegisteredMask; +#endif + + uint8_t mNetworkDataVersion; ///< Current Network Data version + + union + { + uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs + Mle::TxChallenge mAttachChallenge; ///< The challenge value + }; + + uint16_t mSupervisionInterval; // Supervision interval for the child (in sec). + uint16_t mSecondsSinceSupervision; // Number of seconds since last supervision of the child. + + static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < 8192, "mQueuedMessageCount cannot fit max required!"); +}; + +DefineCoreType(otChildInfo, Child::Info); + +#endif // OPENTHREAD_FTD + +} // namespace ot + +#endif // CHILD_HPP_ diff --git a/src/core/thread/child_supervision.hpp b/src/core/thread/child_supervision.hpp index 637e5ff88..ae72f55d1 100644 --- a/src/core/thread/child_supervision.hpp +++ b/src/core/thread/child_supervision.hpp @@ -46,12 +46,11 @@ #include "common/time_ticker.hpp" #include "common/timer.hpp" #include "mac/mac_types.hpp" -#include "thread/topology.hpp" +#include "thread/child.hpp" namespace ot { class ThreadNetif; -class Child; /** * diff --git a/src/core/thread/child_table.hpp b/src/core/thread/child_table.hpp index e02313661..61d930742 100644 --- a/src/core/thread/child_table.hpp +++ b/src/core/thread/child_table.hpp @@ -42,7 +42,7 @@ #include "common/iterator_utils.hpp" #include "common/locator.hpp" #include "common/non_copyable.hpp" -#include "thread/topology.hpp" +#include "thread/child.hpp" namespace ot { diff --git a/src/core/thread/dua_manager.hpp b/src/core/thread/dua_manager.hpp index 383111566..cf454a065 100644 --- a/src/core/thread/dua_manager.hpp +++ b/src/core/thread/dua_manager.hpp @@ -56,9 +56,9 @@ #include "common/time_ticker.hpp" #include "common/timer.hpp" #include "net/netif.hpp" +#include "thread/child.hpp" #include "thread/thread_tlvs.hpp" #include "thread/tmf.hpp" -#include "thread/topology.hpp" namespace ot { diff --git a/src/core/thread/indirect_sender.cpp b/src/core/thread/indirect_sender.cpp index 00931364c..7549702ff 100644 --- a/src/core/thread/indirect_sender.cpp +++ b/src/core/thread/indirect_sender.cpp @@ -39,9 +39,9 @@ #include "common/instance.hpp" #include "common/locator_getters.hpp" #include "common/message.hpp" +#include "thread/child.hpp" #include "thread/mesh_forwarder.hpp" #include "thread/mle_tlvs.hpp" -#include "thread/topology.hpp" namespace ot { diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 5730d87a3..ffa8af2c4 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -50,10 +50,10 @@ #include "mac/mac_frame.hpp" #include "net/ip6.hpp" #include "thread/address_resolver.hpp" +#include "thread/child.hpp" #include "thread/indirect_sender.hpp" #include "thread/lowpan.hpp" #include "thread/network_data_leader.hpp" -#include "thread/topology.hpp" namespace ot { diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index da792d3b7..5e21a8dff 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -48,13 +48,14 @@ #include "meshcop/joiner_router.hpp" #include "meshcop/meshcop.hpp" #include "net/udp6.hpp" +#include "thread/child.hpp" #include "thread/link_metrics.hpp" #include "thread/link_metrics_tlvs.hpp" #include "thread/mle_tlvs.hpp" #include "thread/mle_types.hpp" #include "thread/neighbor_table.hpp" #include "thread/network_data_types.hpp" -#include "thread/topology.hpp" +#include "thread/router.hpp" namespace ot { diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 1ac8d195e..4264648c8 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -47,13 +47,14 @@ #include "meshcop/meshcop_tlvs.hpp" #include "net/icmp6.hpp" #include "net/udp6.hpp" +#include "thread/child.hpp" #include "thread/child_table.hpp" #include "thread/mle.hpp" #include "thread/mle_tlvs.hpp" +#include "thread/router.hpp" #include "thread/router_table.hpp" #include "thread/thread_tlvs.hpp" #include "thread/tmf.hpp" -#include "thread/topology.hpp" namespace ot { namespace Mle { diff --git a/src/core/thread/mlr_manager.hpp b/src/core/thread/mlr_manager.hpp index 65df2afad..03ea44709 100644 --- a/src/core/thread/mlr_manager.hpp +++ b/src/core/thread/mlr_manager.hpp @@ -51,8 +51,8 @@ #include "common/time_ticker.hpp" #include "common/timer.hpp" #include "net/netif.hpp" +#include "thread/child.hpp" #include "thread/thread_tlvs.hpp" -#include "thread/topology.hpp" namespace ot { diff --git a/src/core/thread/neighbor.cpp b/src/core/thread/neighbor.cpp new file mode 100644 index 000000000..868c762d5 --- /dev/null +++ b/src/core/thread/neighbor.cpp @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2016-2017, 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 a Thread `Neighbor`. + */ + +#include "neighbor.hpp" + +#include "common/array.hpp" +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/instance.hpp" +#include "common/locator_getters.hpp" +#include "common/num_utils.hpp" + +namespace ot { + +void Neighbor::SetState(State aState) +{ + VerifyOrExit(mState != aState); + mState = static_cast(aState); + +#if OPENTHREAD_CONFIG_UPTIME_ENABLE + if (mState == kStateValid) + { + mConnectionStart = Uptime::MsecToSec(Get().GetUptime()); + } +#endif + +exit: + return; +} + +#if OPENTHREAD_CONFIG_UPTIME_ENABLE +uint32_t Neighbor::GetConnectionTime(void) const +{ + return IsStateValid() ? Uptime::MsecToSec(Get().GetUptime()) - mConnectionStart : 0; +} +#endif + +bool Neighbor::AddressMatcher::Matches(const Neighbor &aNeighbor) const +{ + bool matches = false; + + VerifyOrExit(aNeighbor.MatchesFilter(mStateFilter)); + + if (mShortAddress != Mac::kShortAddrInvalid) + { + VerifyOrExit(mShortAddress == aNeighbor.GetRloc16()); + } + + if (mExtAddress != nullptr) + { + VerifyOrExit(*mExtAddress == aNeighbor.GetExtAddress()); + } + + matches = true; + +exit: + return matches; +} + +void Neighbor::Info::SetFrom(const Neighbor &aNeighbor) +{ + Clear(); + + mExtAddress = aNeighbor.GetExtAddress(); + mAge = Time::MsecToSec(TimerMilli::GetNow() - aNeighbor.GetLastHeard()); + mRloc16 = aNeighbor.GetRloc16(); + mLinkFrameCounter = aNeighbor.GetLinkFrameCounters().GetMaximum(); + mMleFrameCounter = aNeighbor.GetMleFrameCounter(); + mLinkQualityIn = aNeighbor.GetLinkQualityIn(); + mAverageRssi = aNeighbor.GetLinkInfo().GetAverageRss(); + mLastRssi = aNeighbor.GetLinkInfo().GetLastRss(); + mLinkMargin = aNeighbor.GetLinkInfo().GetLinkMargin(); + mFrameErrorRate = aNeighbor.GetLinkInfo().GetFrameErrorRate(); + mMessageErrorRate = aNeighbor.GetLinkInfo().GetMessageErrorRate(); + mRxOnWhenIdle = aNeighbor.IsRxOnWhenIdle(); + mFullThreadDevice = aNeighbor.IsFullThreadDevice(); + mFullNetworkData = (aNeighbor.GetNetworkDataType() == NetworkData::kFullSet); + mVersion = aNeighbor.GetVersion(); +#if OPENTHREAD_CONFIG_UPTIME_ENABLE + mConnectionTime = aNeighbor.GetConnectionTime(); +#endif +} + +void Neighbor::Init(Instance &aInstance) +{ + InstanceLocatorInit::Init(aInstance); + mLinkInfo.Init(aInstance); + SetState(kStateInvalid); +} + +bool Neighbor::IsStateValidOrAttaching(void) const +{ + bool rval = false; + + switch (GetState()) + { + case kStateInvalid: + case kStateParentRequest: + case kStateParentResponse: + break; + + case kStateRestored: + case kStateChildIdRequest: + case kStateLinkRequest: + case kStateChildUpdateRequest: + case kStateValid: + rval = true; + break; + } + + return rval; +} + +bool Neighbor::MatchesFilter(StateFilter aFilter) const +{ + bool matches = false; + + switch (aFilter) + { + case kInStateValid: + matches = IsStateValid(); + break; + + case kInStateValidOrRestoring: + matches = IsStateValidOrRestoring(); + break; + + case kInStateChildIdRequest: + matches = IsStateChildIdRequest(); + break; + + case kInStateValidOrAttaching: + matches = IsStateValidOrAttaching(); + break; + + case kInStateInvalid: + matches = IsStateInvalid(); + break; + + case kInStateAnyExceptInvalid: + matches = !IsStateInvalid(); + break; + + case kInStateAnyExceptValidOrRestoring: + matches = !IsStateValidOrRestoring(); + break; + + case kInStateAny: + matches = true; + break; + } + + return matches; +} + +#if OPENTHREAD_CONFIG_MULTI_RADIO +void Neighbor::SetLastRxFragmentTag(uint16_t aTag) +{ + mLastRxFragmentTag = (aTag == 0) ? 0xffff : aTag; + mLastRxFragmentTagTime = TimerMilli::GetNow(); +} + +bool Neighbor::IsLastRxFragmentTagSet(void) const +{ + return (mLastRxFragmentTag != 0) && (TimerMilli::GetNow() <= mLastRxFragmentTagTime + kLastRxFragmentTagTimeout); +} +#endif + +#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +void Neighbor::AggregateLinkMetrics(uint8_t aSeriesId, uint8_t aFrameType, uint8_t aLqi, int8_t aRss) +{ + for (LinkMetrics::SeriesInfo &entry : mLinkMetricsSeriesInfoList) + { + if (aSeriesId == 0 || aSeriesId == entry.GetSeriesId()) + { + entry.AggregateLinkMetrics(aFrameType, aLqi, aRss); + } + } +} + +LinkMetrics::SeriesInfo *Neighbor::GetForwardTrackingSeriesInfo(const uint8_t &aSeriesId) +{ + return mLinkMetricsSeriesInfoList.FindMatching(aSeriesId); +} + +void Neighbor::AddForwardTrackingSeriesInfo(LinkMetrics::SeriesInfo &aSeriesInfo) +{ + mLinkMetricsSeriesInfoList.Push(aSeriesInfo); +} + +LinkMetrics::SeriesInfo *Neighbor::RemoveForwardTrackingSeriesInfo(const uint8_t &aSeriesId) +{ + return mLinkMetricsSeriesInfoList.RemoveMatching(aSeriesId); +} + +void Neighbor::RemoveAllForwardTrackingSeriesInfo(void) +{ + while (!mLinkMetricsSeriesInfoList.IsEmpty()) + { + LinkMetrics::SeriesInfo *seriesInfo = mLinkMetricsSeriesInfoList.Pop(); + Get().Free(*seriesInfo); + } +} +#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE + +const char *Neighbor::StateToString(State aState) +{ + static const char *const kStateStrings[] = { + "Invalid", // (0) kStateInvalid + "Restored", // (1) kStateRestored + "ParentReq", // (2) kStateParentRequest + "ParentRes", // (3) kStateParentResponse + "ChildIdReq", // (4) kStateChildIdRequest + "LinkReq", // (5) kStateLinkRequest + "ChildUpdateReq", // (6) kStateChildUpdateRequest + "Valid", // (7) kStateValid + }; + + static_assert(0 == kStateInvalid, "kStateInvalid value is incorrect"); + static_assert(1 == kStateRestored, "kStateRestored value is incorrect"); + static_assert(2 == kStateParentRequest, "kStateParentRequest value is incorrect"); + static_assert(3 == kStateParentResponse, "kStateParentResponse value is incorrect"); + static_assert(4 == kStateChildIdRequest, "kStateChildIdRequest value is incorrect"); + static_assert(5 == kStateLinkRequest, "kStateLinkRequest value is incorrect"); + static_assert(6 == kStateChildUpdateRequest, "kStateChildUpdateRequest value is incorrect"); + static_assert(7 == kStateValid, "kStateValid value is incorrect"); + + return kStateStrings[aState]; +} + +} // namespace ot diff --git a/src/core/thread/topology.hpp b/src/core/thread/neighbor.hpp similarity index 56% rename from src/core/thread/topology.hpp rename to src/core/thread/neighbor.hpp index e91670438..903715d44 100644 --- a/src/core/thread/topology.hpp +++ b/src/core/thread/neighbor.hpp @@ -28,11 +28,11 @@ /** * @file - * This file includes definitions for maintaining Thread network topologies. + * This file includes definitions for a Thread `Neighbor`. */ -#ifndef TOPOLOGY_HPP_ -#define TOPOLOGY_HPP_ +#ifndef NEIGHBOR_HPP_ +#define NEIGHBOR_HPP_ #include "openthread-core-config.h" @@ -848,708 +848,8 @@ private: #endif }; -#if OPENTHREAD_FTD - -/** - * Represents a Thread Child. - * - */ -class Child : public Neighbor, - public IndirectSender::ChildInfo, - public DataPollHandler::ChildInfo -#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - , - public CslTxScheduler::ChildInfo -#endif -{ - class AddressIteratorBuilder; - -public: - static constexpr uint8_t kMaxRequestTlvs = 6; - - /** - * Represents diagnostic information for a Thread Child. - * - */ - class Info : public otChildInfo, public Clearable - { - public: - /** - * Sets the `Info` instance from a given `Child`. - * - * @param[in] aChild A neighbor. - * - */ - void SetFrom(const Child &aChild); - }; - - /** - * Defines an iterator used to go through IPv6 address entries of a child. - * - */ - class AddressIterator : public Unequatable - { - friend class AddressIteratorBuilder; - - public: - /** - * Represents an index indicating the current IPv6 address entry to which the iterator is pointing. - * - */ - typedef otChildIp6AddressIterator Index; - - /** - * Initializes the iterator associated with a given `Child` starting from beginning of the - * IPv6 address list. - * - * @param[in] aChild A reference to a child entry. - * @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses. - * - */ - explicit AddressIterator(const Child &aChild, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) - : AddressIterator(aChild, 0, aFilter) - { - } - - /** - * Initializes the iterator associated with a given `Child` starting from a given index - * - * @param[in] aChild A reference to the child entry. - * @param[in] aIndex An index (`Index`) with which to initialize the iterator. - * @param[in] aFilter An IPv6 address type filter restricting iterator to certain type of addresses. - * - */ - AddressIterator(const Child &aChild, Index aIndex, Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) - : mChild(aChild) - , mFilter(aFilter) - , mIndex(aIndex) - { - Update(); - } - - /** - * Converts the iterator into an index. - * - * @returns An index corresponding to the iterator. - * - */ - Index GetAsIndex(void) const { return mIndex; } - - /** - * Gets the iterator's associated `Child` entry. - * - * @returns The associated child entry. - * - */ - const Child &GetChild(void) const { return mChild; } - - /** - * Gets the current `Child` IPv6 Address to which the iterator is pointing. - * - * @returns A pointer to the associated IPv6 Address, or `nullptr` if iterator is done. - * - */ - const Ip6::Address *GetAddress(void) const; - - /** - * Indicates whether the iterator has reached end of the list. - * - * @retval TRUE There are no more entries in the list (reached end of the list). - * @retval FALSE The current entry is valid. - * - */ - bool IsDone(void) const { return (mIndex >= kMaxIndex); } - - /** - * Overloads `++` operator (pre-increment) to advance the iterator. - * - * The iterator is moved to point to the next `Address` entry. If there are no more `Ip6::Address` entries - * `IsDone()` returns `true`. - * - */ - void operator++(void) { mIndex++, Update(); } - - /** - * Overloads `++` operator (post-increment) to advance the iterator. - * - * The iterator is moved to point to the next `Address` entry. If there are no more `Ip6::Address` entries - * `IsDone()` returns `true`. - * - */ - void operator++(int) { mIndex++, Update(); } - - /** - * Overloads the `*` dereference operator and gets a reference to `Ip6::Address` to which the - * iterator is currently pointing. - * - * MUST be used when the iterator is not done (i.e., `IsDone()` returns `false`). - * - * @returns A reference to the `Ip6::Address` entry currently pointed by the iterator. - * - */ - const Ip6::Address &operator*(void) const { return *GetAddress(); } - - /** - * Overloads operator `==` to evaluate whether or not two `Iterator` instances are equal. - * - * MUST be used when the two iterators are associated with the same `Child` entry. - * - * @param[in] aOther The other `Iterator` to compare with. - * - * @retval TRUE If the two `Iterator` objects are equal. - * @retval FALSE If the two `Iterator` objects are not equal. - * - */ - bool operator==(const AddressIterator &aOther) const { return (mIndex == aOther.mIndex); } - - private: - enum IteratorType : uint8_t - { - kEndIterator, - }; - - static constexpr uint16_t kMaxIndex = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD; - - AddressIterator(const Child &aChild, IteratorType) - : mChild(aChild) - , mIndex(kMaxIndex) - { - } - - void Update(void); - - const Child &mChild; - Ip6::Address::TypeFilter mFilter; - Index mIndex; - Ip6::Address mMeshLocalAddress; - }; - - /** - * Initializes the `Child` object. - * - * @param[in] aInstance A reference to OpenThread instance. - * - */ - void Init(Instance &aInstance) { Neighbor::Init(aInstance); } - - /** - * Clears the child entry. - * - */ - void Clear(void); - - /** - * Clears the IPv6 address list for the child. - * - */ - void ClearIp6Addresses(void); - - /** - * Sets the device mode flags. - * - * @param[in] aMode The device mode flags. - * - */ - void SetDeviceMode(Mle::DeviceMode aMode); - - /** - * Gets the mesh-local IPv6 address. - * - * @param[out] aAddress A reference to an IPv6 address to provide address (if any). - * - * @retval kErrorNone Successfully found the mesh-local address and updated @p aAddress. - * @retval kErrorNotFound No mesh-local IPv6 address in the IPv6 address list. - * - */ - Error GetMeshLocalIp6Address(Ip6::Address &aAddress) const; - - /** - * Returns the Mesh Local Interface Identifier. - * - * @returns The Mesh Local Interface Identifier. - * - */ - const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; } - - /** - * Enables range-based `for` loop iteration over all (or a subset of) IPv6 addresses. - * - * Should be used as follows: to iterate over all addresses - * - * for (const Ip6::Address &address : child.IterateIp6Addresses()) { ... } - * - * or to iterate over a subset of IPv6 addresses determined by a given address type filter - * - * for (const Ip6::Address &address : child.IterateIp6Addresses(Ip6::Address::kTypeMulticast)) { ... } - * - * @param[in] aFilter An IPv6 address type filter restricting iteration to certain type of addresses (default is - * to accept any address type). - * - * @returns An IteratorBuilder instance. - * - */ - AddressIteratorBuilder IterateIp6Addresses(Ip6::Address::TypeFilter aFilter = Ip6::Address::kTypeAny) const - { - return AddressIteratorBuilder(*this, aFilter); - } - - /** - * Adds an IPv6 address to the list. - * - * @param[in] aAddress A reference to IPv6 address to be added. - * - * @retval kErrorNone Successfully added the new address. - * @retval kErrorAlready Address is already in the list. - * @retval kErrorNoBufs Already at maximum number of addresses. No entry available to add the new address. - * @retval kErrorInvalidArgs Address is invalid (it is the Unspecified Address). - * - */ - Error AddIp6Address(const Ip6::Address &aAddress); - - /** - * Removes an IPv6 address from the list. - * - * @param[in] aAddress A reference to IPv6 address to be removed. - * - * @retval kErrorNone Successfully removed the address. - * @retval kErrorNotFound Address was not found in the list. - * @retval kErrorInvalidArgs Address is invalid (it is the Unspecified Address). - * - */ - Error RemoveIp6Address(const Ip6::Address &aAddress); - - /** - * Indicates whether an IPv6 address is in the list of IPv6 addresses of the child. - * - * @param[in] aAddress A reference to IPv6 address. - * - * @retval TRUE The address exists on the list. - * @retval FALSE Address was not found in the list. - * - */ - bool HasIp6Address(const Ip6::Address &aAddress) const; - -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE - /** - * Retrieves the Domain Unicast Address registered by the child. - * - * @returns A pointer to Domain Unicast Address registered by the child if there is. - * - */ - const Ip6::Address *GetDomainUnicastAddress(void) const; -#endif - - /** - * Gets the child timeout. - * - * @returns The child timeout. - * - */ - uint32_t GetTimeout(void) const { return mTimeout; } - - /** - * Sets the child timeout. - * - * @param[in] aTimeout The child timeout. - * - */ - void SetTimeout(uint32_t aTimeout) { mTimeout = aTimeout; } - - /** - * Gets the network data version. - * - * @returns The network data version. - * - */ - uint8_t GetNetworkDataVersion(void) const { return mNetworkDataVersion; } - - /** - * Sets the network data version. - * - * @param[in] aVersion The network data version. - * - */ - void SetNetworkDataVersion(uint8_t aVersion) { mNetworkDataVersion = aVersion; } - - /** - * Generates a new challenge value to use during a child attach. - * - */ - void GenerateChallenge(void) { mAttachChallenge.GenerateRandom(); } - - /** - * Gets the current challenge value used during attach. - * - * @returns The current challenge value. - * - */ - const Mle::TxChallenge &GetChallenge(void) const { return mAttachChallenge; } - - /** - * Clears the requested TLV list. - * - */ - void ClearRequestTlvs(void) { memset(mRequestTlvs, Mle::Tlv::kInvalid, sizeof(mRequestTlvs)); } - - /** - * Returns the requested TLV at index @p aIndex. - * - * @param[in] aIndex The index into the requested TLV list. - * - * @returns The requested TLV at index @p aIndex. - * - */ - uint8_t GetRequestTlv(uint8_t aIndex) const { return mRequestTlvs[aIndex]; } - - /** - * Sets the requested TLV at index @p aIndex. - * - * @param[in] aIndex The index into the requested TLV list. - * @param[in] aType The TLV type. - * - */ - void SetRequestTlv(uint8_t aIndex, uint8_t aType) { mRequestTlvs[aIndex] = aType; } - - /** - * Returns the supervision interval (in seconds). - * - * @returns The supervision interval (in seconds). - * - */ - uint16_t GetSupervisionInterval(void) const { return mSupervisionInterval; } - - /** - * Sets the supervision interval. - * - * @param[in] aInterval The supervision interval (in seconds). - * - */ - void SetSupervisionInterval(uint16_t aInterval) { mSupervisionInterval = aInterval; } - - /** - * Increments the number of seconds since last supervision of the child. - * - */ - void IncrementSecondsSinceLastSupervision(void) { mSecondsSinceSupervision++; } - - /** - * Returns the number of seconds since last supervision of the child (last message to the child) - * - * @returns Number of seconds since last supervision of the child. - * - */ - uint16_t GetSecondsSinceLastSupervision(void) const { return mSecondsSinceSupervision; } - - /** - * Resets the number of seconds since last supervision of the child to zero. - * - */ - void ResetSecondsSinceLastSupervision(void) { mSecondsSinceSupervision = 0; } - -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE - /** - * Returns MLR state of an IPv6 multicast address. - * - * @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`. - * - * @param[in] aAddress The IPv6 multicast address. - * - * @returns MLR state of the IPv6 multicast address. - * - */ - MlrState GetAddressMlrState(const Ip6::Address &aAddress) const; - - /** - * Sets MLR state of an IPv6 multicast address. - * - * @note The @p aAddress reference MUST be from `IterateIp6Addresses()` or `AddressIterator`. - * - * @param[in] aAddress The IPv6 multicast address. - * @param[in] aState The target MLR state. - * - */ - void SetAddressMlrState(const Ip6::Address &aAddress, MlrState aState); - - /** - * Returns if the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`. - * - * @param[in] aAddress The IPv6 address. - * - * @retval true If the Child has IPv6 address @p aAddress of MLR state `kMlrStateRegistered`. - * @retval false If the Child does not have IPv6 address @p aAddress of MLR state `kMlrStateRegistered`. - * - */ - bool HasMlrRegisteredAddress(const Ip6::Address &aAddress) const; - - /** - * Returns if the Child has any IPv6 address of MLR state `kMlrStateRegistered`. - * - * @retval true If the Child has any IPv6 address of MLR state `kMlrStateRegistered`. - * @retval false If the Child does not have any IPv6 address of MLR state `kMlrStateRegistered`. - * - */ - bool HasAnyMlrRegisteredAddress(void) const { return mMlrRegisteredMask.HasAny(); } - - /** - * Returns if the Child has any IPv6 address of MLR state `kMlrStateToRegister`. - * - * @retval true If the Child has any IPv6 address of MLR state `kMlrStateToRegister`. - * @retval false If the Child does not have any IPv6 address of MLR state `kMlrStateToRegister`. - * - */ - bool HasAnyMlrToRegisterAddress(void) const { return mMlrToRegisterMask.HasAny(); } -#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE - -private: -#if OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD < 2 -#error OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD should be at least set to 2. -#endif - - static constexpr uint16_t kNumIp6Addresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1; - - typedef BitVector ChildIp6AddressMask; - - class AddressIteratorBuilder - { - public: - AddressIteratorBuilder(const Child &aChild, Ip6::Address::TypeFilter aFilter) - : mChild(aChild) - , mFilter(aFilter) - { - } - - AddressIterator begin(void) { return AddressIterator(mChild, mFilter); } - AddressIterator end(void) { return AddressIterator(mChild, AddressIterator::kEndIterator); } - - private: - const Child &mChild; - Ip6::Address::TypeFilter mFilter; - }; - - Ip6::InterfaceIdentifier mMeshLocalIid; ///< IPv6 address IID for mesh-local address - Ip6::Address mIp6Address[kNumIp6Addresses]; ///< Registered IPv6 addresses - uint32_t mTimeout; ///< Child timeout - -#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE - ChildIp6AddressMask mMlrToRegisterMask; - ChildIp6AddressMask mMlrRegisteredMask; -#endif - - uint8_t mNetworkDataVersion; ///< Current Network Data version - - union - { - uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs - Mle::TxChallenge mAttachChallenge; ///< The challenge value - }; - - uint16_t mSupervisionInterval; // Supervision interval for the child (in sec). - uint16_t mSecondsSinceSupervision; // Number of seconds since last supervision of the child. - - static_assert(OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS < 8192, "mQueuedMessageCount cannot fit max required!"); -}; - -#endif // OPENTHREAD_FTD - -class Parent; - -/** - * Represents a Thread Router - * - */ -class Router : public Neighbor -{ -public: - /** - * Represents diagnostic information for a Thread Router. - * - */ - class Info : public otRouterInfo, public Clearable - { - public: - /** - * Sets the `Info` instance from a given `Router`. - * - * @param[in] aRouter A router. - * - */ - void SetFrom(const Router &aRouter); - - /** - * Sets the `Info` instance from a given `Parent`. - * - * @param[in] aParent A parent. - * - */ - void SetFrom(const Parent &aParent); - }; - - /** - * Initializes the `Router` object. - * - * @param[in] aInstance A reference to OpenThread instance. - * - */ - void Init(Instance &aInstance) { Neighbor::Init(aInstance); } - - /** - * Clears the router entry. - * - */ - void Clear(void); - - /** - * Sets the `Router` entry from a `Parent` - * - */ - void SetFrom(const Parent &aParent); - - /** - * Gets the router ID of the next hop to this router. - * - * @returns The router ID of the next hop to this router. - * - */ - uint8_t GetNextHop(void) const { return mNextHop; } - - /** - * Gets the link quality out value for this router. - * - * @returns The link quality out value for this router. - * - */ - LinkQuality GetLinkQualityOut(void) const { return static_cast(mLinkQualityOut); } - - /** - * Sets the link quality out value for this router. - * - * @param[in] aLinkQuality The link quality out value for this router. - * - */ - void SetLinkQualityOut(LinkQuality aLinkQuality) { mLinkQualityOut = aLinkQuality; } - - /** - * Gets the two-way link quality value (minimum of link quality in and out). - * - * @returns The two-way link quality value. - * - */ - LinkQuality GetTwoWayLinkQuality(void) const; - - /** - * Get the route cost to this router. - * - * @returns The route cost to this router. - * - */ - uint8_t GetCost(void) const { return mCost; } - - /** - * Sets the next hop and cost to this router. - * - * @param[in] aNextHop The Router ID of the next hop to this router. - * @param[in] aCost The cost to this router. - * - * @retval TRUE If there was a change, i.e., @p aNextHop or @p aCost were different from their previous values. - * @retval FALSE If no change to next hop and cost values (new values are the same as before). - * - */ - bool SetNextHopAndCost(uint8_t aNextHop, uint8_t aCost); - - /** - * Sets the next hop to this router as invalid and clears the cost. - * - * @retval TRUE If there was a change (next hop was valid before). - * @retval FALSE No change to next hop (next hop was invalid before). - * - */ - bool SetNextHopToInvalid(void); - -private: - uint8_t mNextHop; ///< The next hop towards this router - uint8_t mLinkQualityOut : 2; ///< The link quality out for this router - -#if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE - uint8_t mCost; ///< The cost to this router via neighbor router -#else - uint8_t mCost : 4; ///< The cost to this router via neighbor router -#endif -}; - -/** - * Represent parent of a child node. - * - */ -class Parent : public Router -{ -public: - /** - * Initializes the `Parent`. - * - * @param[in] aInstance A reference to OpenThread instance. - * - */ - void Init(Instance &aInstance) - { - Neighbor::Init(aInstance); -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - mCslAccuracy.Init(); -#endif - } - - /** - * Clears the parent entry. - * - */ - void Clear(void); - - /** - * Gets route cost from parent to leader. - * - * @returns The route cost from parent to leader - * - */ - uint8_t GetLeaderCost(void) const { return mLeaderCost; } - - /** - * Sets route cost from parent to leader. - * - * @param[in] aLaderConst The route cost. - * - */ - void SetLeaderCost(uint8_t aLeaderCost) { mLeaderCost = aLeaderCost; } - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - /** - * Gets the CSL accuracy (clock accuracy and uncertainty). - * - * @returns The CSL accuracy. - * - */ - const Mac::CslAccuracy &GetCslAccuracy(void) const { return mCslAccuracy; } - - /** - * Sets CSL accuracy. - * - * @param[in] aCslAccuracy The CSL accuracy. - * - */ - void SetCslAccuracy(const Mac::CslAccuracy &aCslAccuracy) { mCslAccuracy = aCslAccuracy; } -#endif - -private: - uint8_t mLeaderCost; -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - Mac::CslAccuracy mCslAccuracy; // CSL accuracy (clock accuracy in ppm and uncertainty). -#endif -}; - DefineCoreType(otNeighborInfo, Neighbor::Info); -#if OPENTHREAD_FTD -DefineCoreType(otChildInfo, Child::Info); -#endif -DefineCoreType(otRouterInfo, Router::Info); } // namespace ot -#endif // TOPOLOGY_HPP_ +#endif // NEIGHBOR_HPP_ diff --git a/src/core/thread/neighbor_table.hpp b/src/core/thread/neighbor_table.hpp index 2600d62ae..321983d45 100644 --- a/src/core/thread/neighbor_table.hpp +++ b/src/core/thread/neighbor_table.hpp @@ -38,7 +38,7 @@ #include "common/locator.hpp" #include "common/non_copyable.hpp" -#include "thread/topology.hpp" +#include "thread/neighbor.hpp" namespace ot { diff --git a/src/core/thread/network_diagnostic_tlvs.hpp b/src/core/thread/network_diagnostic_tlvs.hpp index 8a98fd525..184aaf7b1 100644 --- a/src/core/thread/network_diagnostic_tlvs.hpp +++ b/src/core/thread/network_diagnostic_tlvs.hpp @@ -45,10 +45,11 @@ #include "common/tlvs.hpp" #include "net/ip6_address.hpp" #include "radio/radio.hpp" +#include "thread/child.hpp" #include "thread/link_quality.hpp" #include "thread/mle_tlvs.hpp" #include "thread/mle_types.hpp" -#include "thread/topology.hpp" +#include "thread/router.hpp" namespace ot { namespace NetworkDiagnostic { diff --git a/src/core/thread/router.cpp b/src/core/thread/router.cpp new file mode 100644 index 000000000..c99fec132 --- /dev/null +++ b/src/core/thread/router.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016-2017, 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 `Router` and `Parent`. + */ + +#include "router.hpp" + +#include "common/array.hpp" +#include "common/code_utils.hpp" +#include "common/debug.hpp" +#include "common/instance.hpp" +#include "common/locator_getters.hpp" +#include "common/num_utils.hpp" + +namespace ot { + +void Router::Info::SetFrom(const Router &aRouter) +{ + Clear(); + mRloc16 = aRouter.GetRloc16(); + mRouterId = Mle::RouterIdFromRloc16(mRloc16); + mExtAddress = aRouter.GetExtAddress(); + mAllocated = true; + mNextHop = aRouter.GetNextHop(); + mLinkEstablished = aRouter.IsStateValid(); + mPathCost = aRouter.GetCost(); + mLinkQualityIn = aRouter.GetLinkQualityIn(); + mLinkQualityOut = aRouter.GetLinkQualityOut(); + mAge = static_cast(Time::MsecToSec(TimerMilli::GetNow() - aRouter.GetLastHeard())); + mVersion = ClampToUint8(aRouter.GetVersion()); +} + +void Router::Info::SetFrom(const Parent &aParent) +{ + SetFrom(static_cast(aParent)); +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + mCslClockAccuracy = aParent.GetCslAccuracy().GetClockAccuracy(); + mCslUncertainty = aParent.GetCslAccuracy().GetUncertainty(); +#endif +} + +void Router::Clear(void) +{ + Instance &instance = GetInstance(); + + memset(reinterpret_cast(this), 0, sizeof(Router)); + Init(instance); +} + +LinkQuality Router::GetTwoWayLinkQuality(void) const { return Min(GetLinkQualityIn(), GetLinkQualityOut()); } + +void Router::SetFrom(const Parent &aParent) +{ + // We use an intermediate pointer to copy `aParent` to silence + // code checkers warning about object slicing (assigning a + // sub-class to base class instance). + + const Router *parentAsRouter = &aParent; + + *this = *parentAsRouter; +} + +void Parent::Clear(void) +{ + Instance &instance = GetInstance(); + + memset(reinterpret_cast(this), 0, sizeof(Parent)); + Init(instance); +} + +bool Router::SetNextHopAndCost(uint8_t aNextHop, uint8_t aCost) +{ + bool changed = false; + + if (mNextHop != aNextHop) + { + mNextHop = aNextHop; + changed = true; + } + + if (mCost != aCost) + { + mCost = aCost; + changed = true; + } + + return changed; +} + +bool Router::SetNextHopToInvalid(void) { return SetNextHopAndCost(Mle::kInvalidRouterId, 0); } + +} // namespace ot diff --git a/src/core/thread/router.hpp b/src/core/thread/router.hpp new file mode 100644 index 000000000..e75e89059 --- /dev/null +++ b/src/core/thread/router.hpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016, 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 Thread `Router` and `Parent`. + */ + +#ifndef ROUTER_HPP_ +#define ROUTER_HPP_ + +#include "openthread-core-config.h" + +#include "thread/neighbor.hpp" + +namespace ot { + +class Parent; + +/** + * Represents a Thread Router + * + */ +class Router : public Neighbor +{ +public: + /** + * Represents diagnostic information for a Thread Router. + * + */ + class Info : public otRouterInfo, public Clearable + { + public: + /** + * Sets the `Info` instance from a given `Router`. + * + * @param[in] aRouter A router. + * + */ + void SetFrom(const Router &aRouter); + + /** + * Sets the `Info` instance from a given `Parent`. + * + * @param[in] aParent A parent. + * + */ + void SetFrom(const Parent &aParent); + }; + + /** + * Initializes the `Router` object. + * + * @param[in] aInstance A reference to OpenThread instance. + * + */ + void Init(Instance &aInstance) { Neighbor::Init(aInstance); } + + /** + * Clears the router entry. + * + */ + void Clear(void); + + /** + * Sets the `Router` entry from a `Parent` + * + */ + void SetFrom(const Parent &aParent); + + /** + * Gets the router ID of the next hop to this router. + * + * @returns The router ID of the next hop to this router. + * + */ + uint8_t GetNextHop(void) const { return mNextHop; } + + /** + * Gets the link quality out value for this router. + * + * @returns The link quality out value for this router. + * + */ + LinkQuality GetLinkQualityOut(void) const { return static_cast(mLinkQualityOut); } + + /** + * Sets the link quality out value for this router. + * + * @param[in] aLinkQuality The link quality out value for this router. + * + */ + void SetLinkQualityOut(LinkQuality aLinkQuality) { mLinkQualityOut = aLinkQuality; } + + /** + * Gets the two-way link quality value (minimum of link quality in and out). + * + * @returns The two-way link quality value. + * + */ + LinkQuality GetTwoWayLinkQuality(void) const; + + /** + * Get the route cost to this router. + * + * @returns The route cost to this router. + * + */ + uint8_t GetCost(void) const { return mCost; } + + /** + * Sets the next hop and cost to this router. + * + * @param[in] aNextHop The Router ID of the next hop to this router. + * @param[in] aCost The cost to this router. + * + * @retval TRUE If there was a change, i.e., @p aNextHop or @p aCost were different from their previous values. + * @retval FALSE If no change to next hop and cost values (new values are the same as before). + * + */ + bool SetNextHopAndCost(uint8_t aNextHop, uint8_t aCost); + + /** + * Sets the next hop to this router as invalid and clears the cost. + * + * @retval TRUE If there was a change (next hop was valid before). + * @retval FALSE No change to next hop (next hop was invalid before). + * + */ + bool SetNextHopToInvalid(void); + +private: + uint8_t mNextHop; ///< The next hop towards this router + uint8_t mLinkQualityOut : 2; ///< The link quality out for this router + +#if OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE + uint8_t mCost; ///< The cost to this router via neighbor router +#else + uint8_t mCost : 4; ///< The cost to this router via neighbor router +#endif +}; + +/** + * Represent parent of a child node. + * + */ +class Parent : public Router +{ +public: + /** + * Initializes the `Parent`. + * + * @param[in] aInstance A reference to OpenThread instance. + * + */ + void Init(Instance &aInstance) + { + Neighbor::Init(aInstance); +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + mCslAccuracy.Init(); +#endif + } + + /** + * Clears the parent entry. + * + */ + void Clear(void); + + /** + * Gets route cost from parent to leader. + * + * @returns The route cost from parent to leader + * + */ + uint8_t GetLeaderCost(void) const { return mLeaderCost; } + + /** + * Sets route cost from parent to leader. + * + * @param[in] aLeaderCost The route cost. + * + */ + void SetLeaderCost(uint8_t aLeaderCost) { mLeaderCost = aLeaderCost; } + +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + /** + * Gets the CSL accuracy (clock accuracy and uncertainty). + * + * @returns The CSL accuracy. + * + */ + const Mac::CslAccuracy &GetCslAccuracy(void) const { return mCslAccuracy; } + + /** + * Sets CSL accuracy. + * + * @param[in] aCslAccuracy The CSL accuracy. + * + */ + void SetCslAccuracy(const Mac::CslAccuracy &aCslAccuracy) { mCslAccuracy = aCslAccuracy; } +#endif + +private: + uint8_t mLeaderCost; +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + Mac::CslAccuracy mCslAccuracy; // CSL accuracy (clock accuracy in ppm and uncertainty). +#endif +}; + +DefineCoreType(otRouterInfo, Router::Info); + +} // namespace ot + +#endif // ROUTER_HPP_ diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp index b3721c69c..6ad32bb28 100644 --- a/src/core/thread/router_table.hpp +++ b/src/core/thread/router_table.hpp @@ -44,8 +44,8 @@ #include "mac/mac_types.hpp" #include "thread/mle_tlvs.hpp" #include "thread/mle_types.hpp" +#include "thread/router.hpp" #include "thread/thread_tlvs.hpp" -#include "thread/topology.hpp" namespace ot { diff --git a/src/core/thread/src_match_controller.cpp b/src/core/thread/src_match_controller.cpp index 371405f7a..2d73ce923 100644 --- a/src/core/thread/src_match_controller.cpp +++ b/src/core/thread/src_match_controller.cpp @@ -42,9 +42,9 @@ #include "common/log.hpp" #include "mac/mac_types.hpp" #include "radio/radio.hpp" +#include "thread/child.hpp" #include "thread/mesh_forwarder.hpp" #include "thread/thread_netif.hpp" -#include "thread/topology.hpp" namespace ot { diff --git a/src/core/utils/otns.hpp b/src/core/utils/otns.hpp index c949fd8bf..2ece56452 100644 --- a/src/core/utils/otns.hpp +++ b/src/core/utils/otns.hpp @@ -49,8 +49,8 @@ #include "mac/mac_frame.hpp" #include "mac/mac_types.hpp" #include "net/ip6_address.hpp" +#include "thread/neighbor.hpp" #include "thread/neighbor_table.hpp" -#include "thread/topology.hpp" namespace ot { namespace Utils { diff --git a/tests/unit/test_child.cpp b/tests/unit/test_child.cpp index 2a796a333..45fe65a80 100644 --- a/tests/unit/test_child.cpp +++ b/tests/unit/test_child.cpp @@ -33,7 +33,7 @@ #include "test_util.h" #include "common/code_utils.hpp" #include "common/instance.hpp" -#include "thread/topology.hpp" +#include "thread/child.hpp" namespace ot { diff --git a/tests/unit/test_toolchain.cpp b/tests/unit/test_toolchain.cpp index def163462..ead3b1e42 100644 --- a/tests/unit/test_toolchain.cpp +++ b/tests/unit/test_toolchain.cpp @@ -33,7 +33,7 @@ #include #include "test_util.h" -#include "thread/topology.hpp" +#include "thread/neighbor.hpp" extern "C" { uint32_t otNetifAddress_Size_c();