[router-table] reduce router allocation from 63 to 32 (#2678)

The existing router table allocated a router entry for every possible router
id value (63).  Beacuse Thread only allows at most 32 active routers in a
given network, allocating 63 router entries is wasteful.  This commit
allocates only 32 router entries and dynamically manages the pool of router
entries.
This commit is contained in:
Jonathan Hui
2018-05-10 15:47:36 -07:00
committed by GitHub
parent e4f5f240eb
commit 585080e3a0
22 changed files with 1420 additions and 872 deletions
+2
View File
@@ -141,6 +141,7 @@
<ClCompile Include="..\..\src\core\thread\network_data_local.cpp" />
<ClCompile Include="..\..\src\core\thread\network_diagnostic.cpp" />
<ClCompile Include="..\..\src\core\thread\panid_query_server.cpp" />
<ClCompile Include="..\..\src\core\thread\router_table.cpp" />
<ClCompile Include="..\..\src\core\thread\src_match_controller.cpp" />
<ClCompile Include="..\..\src\core\thread\thread_netif.cpp" />
<ClCompile Include="..\..\src\core\thread\topology.cpp" />
@@ -226,6 +227,7 @@
<ClInclude Include="..\..\src\core\thread\network_diagnostic.hpp" />
<ClInclude Include="..\..\src\core\thread\network_diagnostic_tlvs.hpp" />
<ClInclude Include="..\..\src\core\thread\panid_query_server.hpp" />
<ClInclude Include="..\..\src\core\thread\router_table.hpp" />
<ClInclude Include="..\..\src\core\thread\src_match_controller.hpp" />
<ClInclude Include="..\..\src\core\thread\thread_netif.hpp" />
<ClInclude Include="..\..\src\core\thread\thread_tlvs.hpp" />
@@ -252,6 +252,9 @@
<ClCompile Include="..\..\src\core\thread\panid_query_server.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\router_table.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\src_match_controller.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
@@ -503,6 +506,9 @@
<ClInclude Include="..\..\src\core\thread\panid_query_server.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\thread\router_table.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\thread\src_match_controller.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
@@ -149,6 +149,7 @@
<ClCompile Include="..\..\src\core\thread\network_data_local.cpp" />
<ClCompile Include="..\..\src\core\thread\network_diagnostic.cpp" />
<ClCompile Include="..\..\src\core\thread\panid_query_server.cpp" />
<ClCompile Include="..\..\src\core\thread\router_table.cpp" />
<ClCompile Include="..\..\src\core\thread\src_match_controller.cpp" />
<ClCompile Include="..\..\src\core\thread\thread_netif.cpp" />
<ClCompile Include="..\..\src\core\thread\topology.cpp" />
@@ -260,6 +261,7 @@
<ClInclude Include="..\..\src\core\thread\network_diagnostic.hpp" />
<ClInclude Include="..\..\src\core\thread\network_diagnostic_tlvs.hpp" />
<ClInclude Include="..\..\src\core\thread\panid_query_server.hpp" />
<ClInclude Include="..\..\src\core\thread\router_table.hpp" />
<ClInclude Include="..\..\src\core\thread\src_match_controller.hpp" />
<ClInclude Include="..\..\src\core\thread\thread_netif.hpp" />
<ClInclude Include="..\..\src\core\thread\thread_tlvs.hpp" />
@@ -255,6 +255,9 @@
<ClCompile Include="..\..\src\core\thread\panid_query_server.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\router_table.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\thread\src_match_controller.cpp">
<Filter>Source Files\thread</Filter>
</ClCompile>
@@ -506,6 +509,9 @@
<ClInclude Include="..\..\src\core\thread\panid_query_server.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\thread\router_table.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\thread\src_match_controller.hpp">
<Filter>Header Files\thread</Filter>
</ClInclude>
+3 -2
View File
@@ -266,8 +266,9 @@ OTAPI void OTCALL otThreadSetRouterUpgradeThreshold(otInstance *aInstance, uint8
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aRouterId The Router ID to release. Valid range is [0, 62].
*
* @retval OT_ERROR_NONE Successfully released the Router ID specified by aRouterId.
* @retval OT_ERROR_INVALID_STATE The Router ID was not allocated.
* @retval OT_ERROR_NONE Successfully released the router id.
* @retval OT_ERROR_INVALID_STATE The device is not currently operating as a leader.
* @retval OT_ERROR_NOT_FOUND The router id is not currently allocated.
*
*/
OTAPI otError OTCALL otThreadReleaseRouterId(otInstance *aInstance, uint8_t aRouterId);
+2
View File
@@ -188,6 +188,7 @@ SOURCES_COMMON = \
thread/network_data_local.cpp \
thread/network_diagnostic.cpp \
thread/panid_query_server.cpp \
thread/router_table.cpp \
thread/src_match_controller.cpp \
thread/thread_netif.cpp \
thread/tmf_proxy.cpp \
@@ -313,6 +314,7 @@ HEADERS_COMMON = \
thread/panid_query_server.hpp \
thread/network_diagnostic.hpp \
thread/network_diagnostic_tlvs.hpp \
thread/router_table.hpp \
thread/src_match_controller.hpp \
thread/thread_netif.hpp \
thread/thread_tlvs.hpp \
+1 -1
View File
@@ -364,7 +364,7 @@ otError otThreadGetParentInfo(otInstance *aInstance, otRouterInfo *aParentInfo)
aParentInfo->mLinkQualityIn = parent->GetLinkInfo().GetLinkQuality();
aParentInfo->mLinkQualityOut = parent->GetLinkQualityOut();
aParentInfo->mAge = static_cast<uint8_t>(TimerMilli::MsecToSec(TimerMilli::GetNow() - parent->GetLastHeard()));
aParentInfo->mAllocated = parent->IsAllocated();
aParentInfo->mAllocated = true;
aParentInfo->mLinkEstablished = parent->GetState() == Neighbor::kStateValid;
exit:
+3 -3
View File
@@ -168,7 +168,7 @@ otError otThreadReleaseRouterId(otInstance *aInstance, uint8_t aRouterId)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetThreadNetif().GetMle().ReleaseRouterId(aRouterId);
return instance.GetThreadNetif().GetMle().GetRouterTable().Release(aRouterId);
}
otError otThreadBecomeRouter(otInstance *aInstance)
@@ -283,7 +283,7 @@ uint8_t otThreadGetRouterIdSequence(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.GetThreadNetif().GetMle().GetRouterIdSequence();
return instance.GetThreadNetif().GetMle().GetRouterTable().GetRouterIdSequence();
}
uint8_t otThreadGetMaxRouterId(otInstance *aInstance)
@@ -299,7 +299,7 @@ otError otThreadGetRouterInfo(otInstance *aInstance, uint16_t aRouterId, otRoute
VerifyOrExit(aRouterInfo != NULL, error = OT_ERROR_INVALID_ARGS);
error = instance.GetThreadNetif().GetMle().GetRouterInfo(aRouterId, *aRouterInfo);
error = instance.GetThreadNetif().GetMle().GetRouterTable().GetRouterInfo(aRouterId, *aRouterInfo);
exit:
return error;
+6
View File
@@ -39,6 +39,7 @@
#include "common/logging.hpp"
#include "common/new.hpp"
#include "thread/router_table.hpp"
namespace ot {
@@ -251,6 +252,11 @@ template <> ChildTable &Instance::Get(void)
return GetThreadNetif().GetMle().GetChildTable();
}
template <> RouterTable &Instance::Get(void)
{
return GetThreadNetif().GetMle().GetRouterTable();
}
template <> Ip6::Netif &Instance::Get(void)
{
return GetThreadNetif();
+13
View File
@@ -261,6 +261,19 @@
#define OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE 1024
#endif
/**
* @def OPENTHREAD_CONFIG_MAX_ROUTERS
*
* The maximum number of routers in a Thread network.
*
* @note Thread specifies this value to be 32. Changing this value may cause interoperability issues with standard
* Thread 1.1 devices.
*
*/
#ifndef OPENTHREAD_CONFIG_MAX_ROUTERS
#define OPENTHREAD_CONFIG_MAX_ROUTERS 32
#endif
/**
* @def OPENTHREAD_CONFIG_MAX_CHILDREN
*
+1 -1
View File
@@ -119,7 +119,7 @@ public:
*
* The iterator is moved to point to the next `Child` entry matching the given state filter in the constructor.
* If there are no more `Child` entries matching the given filter, the iterator becomes empty (i.e.,
* `GetChild()` returns `NULL` and `IsDone()` returns `true`.
* `GetChild()` returns `NULL` and `IsDone()` returns `true`).
*
*/
void Advance(void);
+8 -10
View File
@@ -119,9 +119,9 @@ const otMasterKey &KeyManager::GetMasterKey(void) const
otError KeyManager::SetMasterKey(const otMasterKey &aKey)
{
otError error = OT_ERROR_NONE;
Router *routers;
uint8_t num;
Mle::MleRouter &mle = GetNetif().GetMle();
otError error = OT_ERROR_NONE;
Router * routers;
VerifyOrExit(memcmp(&mMasterKey, &aKey, sizeof(mMasterKey)) != 0);
@@ -130,19 +130,17 @@ otError KeyManager::SetMasterKey(const otMasterKey &aKey)
ComputeKey(mKeySequence, mKey);
// reset parent frame counters
routers = GetNetif().GetMle().GetParent();
routers = mle.GetParent();
routers->SetKeySequence(0);
routers->SetLinkFrameCounter(0);
routers->SetMleFrameCounter(0);
// reset router frame counters
routers = GetNetif().GetMle().GetRouters(&num);
for (uint8_t i = 0; i < num; i++)
for (RouterTable::Iterator iter(GetInstance()); !iter.IsDone(); iter.Advance())
{
routers[i].SetKeySequence(0);
routers[i].SetLinkFrameCounter(0);
routers[i].SetMleFrameCounter(0);
iter.GetRouter()->SetKeySequence(0);
iter.GetRouter()->SetLinkFrameCounter(0);
iter.GetRouter()->SetMleFrameCounter(0);
}
// reset child frame counters
+6 -4
View File
@@ -2764,7 +2764,6 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
MleFrameCounterTlv mleFrameCounter;
ChallengeTlv challenge;
Mac::ExtAddress extAddress;
int8_t diff;
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
@@ -2808,9 +2807,11 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kConnectivity, sizeof(connectivity), connectivity));
VerifyOrExit(connectivity.IsValid(), error = OT_ERROR_PARSE);
#if OPENTHREAD_FTD
if ((mDeviceMode & ModeTlv::kModeFFD) && (mRole != OT_DEVICE_ROLE_DETACHED))
{
diff = static_cast<int8_t>(connectivity.GetIdSequence() - netif.GetMle().GetRouterIdSequence());
int8_t diff =
static_cast<int8_t>(connectivity.GetIdSequence() - netif.GetMle().GetRouterTable().GetRouterIdSequence());
switch (mParentRequestMode)
{
@@ -2821,8 +2822,8 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
case kAttachSame1:
case kAttachSame2:
VerifyOrExit(leaderData.GetPartitionId() == mLeaderData.GetPartitionId());
VerifyOrExit(diff > 0 ||
(diff == 0 && netif.GetMle().GetLeaderAge() < netif.GetMle().GetNetworkIdTimeout()));
VerifyOrExit(diff > 0 || (diff == 0 && netif.GetMle().GetRouterTable().GetLeaderAge() <
netif.GetMle().GetNetworkIdTimeout()));
break;
case kAttachBetter:
@@ -2832,6 +2833,7 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
break;
}
}
#endif
// if already have a candidate parent, only seek a better parent
if (mParentCandidate.GetState() == Neighbor::kStateParentResponse)
+21 -21
View File
@@ -86,27 +86,27 @@ enum
*/
enum
{
kAdvertiseIntervalMin = 1, ///< ADVERTISEMENT_I_MIN (seconds)
kAdvertiseIntervalMax = 32, ///< ADVERTISEMENT_I_MAX (seconds)
kFailedRouterTransmissions = 4, ///< FAILED_ROUTER_TRANSMISSIONS
kRouterIdReuseDelay = 100, ///< ID_REUSE_DELAY (seconds)
kRouterIdSequencePeriod = 10, ///< ID_SEQUENCE_PERIOD (seconds)
kMaxNeighborAge = 100, ///< MAX_NEIGHBOR_AGE (seconds)
kMaxRouteCost = 16, ///< MAX_ROUTE_COST
kMaxRouterId = 62, ///< MAX_ROUTER_ID
kInvalidRouterId = kMaxRouterId + 1, ///< Value indicating incorrect Router Id
kMaxRouters = 32, ///< MAX_ROUTERS
kMinDowngradeNeighbors = 7, ///< MIN_DOWNGRADE_NEIGHBORS
kNetworkIdTimeout = 120, ///< NETWORK_ID_TIMEOUT (seconds)
kParentRouteToLeaderTimeout = 20, ///< PARENT_ROUTE_TO_LEADER_TIMEOUT (seconds)
kRouterSelectionJitter = 120, ///< ROUTER_SELECTION_JITTER (seconds)
kRouterDowngradeThreshold = 23, ///< ROUTER_DOWNGRADE_THRESHOLD (routers)
kRouterUpgradeThreshold = 16, ///< ROUTER_UPGRADE_THRESHOLD (routers)
kMaxLeaderToRouterTimeout = 90, ///< INFINITE_COST_TIMEOUT (seconds)
kReedAdvertiseInterval = 570, ///< REED_ADVERTISEMENT_INTERVAL (seconds)
kReedAdvertiseJitter = 60, ///< REED_ADVERTISEMENT_JITTER (seconds)
kLeaderWeight = 64, ///< Default leader weight for the Thread Network Partition
kMleEndDeviceTimeout = OPENTHREAD_CONFIG_DEFAULT_CHILD_TIMEOUT, ///< MLE_END_DEVICE_TIMEOUT (seconds)
kAdvertiseIntervalMin = 1, ///< ADVERTISEMENT_I_MIN (sec)
kAdvertiseIntervalMax = 32, ///< ADVERTISEMENT_I_MAX (sec)
kFailedRouterTransmissions = 4, ///< FAILED_ROUTER_TRANSMISSIONS
kRouterIdReuseDelay = 100, ///< ID_REUSE_DELAY (sec)
kRouterIdSequencePeriod = 10, ///< ID_SEQUENCE_PERIOD (sec)
kMaxNeighborAge = 100, ///< MAX_NEIGHBOR_AGE (sec)
kMaxRouteCost = 16, ///< MAX_ROUTE_COST
kMaxRouterId = 62, ///< MAX_ROUTER_ID
kInvalidRouterId = kMaxRouterId + 1, ///< Value indicating incorrect Router Id
kMaxRouters = OPENTHREAD_CONFIG_MAX_ROUTERS, ///< MAX_ROUTERS
kMinDowngradeNeighbors = 7, ///< MIN_DOWNGRADE_NEIGHBORS
kNetworkIdTimeout = 120, ///< NETWORK_ID_TIMEOUT (sec)
kParentRouteToLeaderTimeout = 20, ///< PARENT_ROUTE_TO_LEADER_TIMEOUT (sec)
kRouterSelectionJitter = 120, ///< ROUTER_SELECTION_JITTER (sec)
kRouterDowngradeThreshold = 23, ///< ROUTER_DOWNGRADE_THRESHOLD (routers)
kRouterUpgradeThreshold = 16, ///< ROUTER_UPGRADE_THRESHOLD (routers)
kMaxLeaderToRouterTimeout = 90, ///< INFINITE_COST_TIMEOUT (sec)
kReedAdvertiseInterval = 570, ///< REED_ADVERTISEMENT_INTERVAL (sec)
kReedAdvertiseJitter = 60, ///< REED_ADVERTISEMENT_JITTER (sec)
kLeaderWeight = 64, ///< Default leader weight
kMleEndDeviceTimeout = OPENTHREAD_CONFIG_DEFAULT_CHILD_TIMEOUT, ///< MLE_END_DEVICE_TIMEOUT (sec)
};
/**
File diff suppressed because it is too large Load Diff
+34 -106
View File
@@ -51,6 +51,7 @@
#include "thread/child_table.hpp"
#include "thread/mle.hpp"
#include "thread/mle_tlvs.hpp"
#include "thread/router_table.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/topology.hpp"
@@ -134,30 +135,6 @@ public:
*/
otError BecomeLeader(void);
/**
* This method returns the number of active routers.
*
* @returns The number of active routers.
*
*/
uint8_t GetActiveRouterCount(void) const;
/**
* This method returns the number of active neighbor routers.
*
* @returns The number of active neighbor routers.
*
*/
uint8_t GetActiveNeighborRouterCount(void) const;
/**
* This method returns the time in seconds since the last Router ID Sequence update.
*
* @returns The time in seconds since the last Router ID Sequence update.
*
*/
uint32_t GetLeaderAge(void) const;
/**
* This method returns the Leader Weighting value for this Thread interface.
*
@@ -306,14 +283,6 @@ public:
*/
uint8_t GetRouterSelectionJitterTimeout(void) { return mRouterSelectionJitterTimeout; }
/**
* This method returns the current Router ID Sequence value.
*
* @returns The current Router ID Sequence value.
*
*/
uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; }
/**
* This method returns the ROUTER_UPGRADE_THRESHOLD value.
*
@@ -346,17 +315,6 @@ public:
*/
void SetRouterDowngradeThreshold(uint8_t aThreshold) { mRouterDowngradeThreshold = aThreshold; }
/**
* This method release a given Router ID.
*
* @param[in] aRouterId The Router ID to release.
*
* @retval OT_ERROR_NONE Successfully released the Router ID.
* @retval OT_ERROR_INVALID_STATE The Router ID was not allocated.
*
*/
otError ReleaseRouterId(uint8_t aRouterId);
/**
* This method removes a link to a neighbor.
*
@@ -523,48 +481,6 @@ public:
*/
otError GetNextNeighborInfo(otNeighborInfoIterator &aIterator, otNeighborInfo &aNeighInfo);
/**
* This method returns a pointer to a Router array.
*
* @param[out] aNumRouters A pointer to output the number of routers.
*
* @returns A pointer to the Router array.
*
*/
Router *GetRouters(uint8_t *aNumRouters);
/**
* This method returns a pointer to a Router entry.
*
* @param[in] aRouterId The Router ID.
*
* @returns A pointer to a Router entry or NULL if @p aRouterId is out-of-range.
*
*/
Router *GetRouter(uint8_t aRouterId);
/**
* This method returns a pointer to a Router entry.
*
* @param[in] aRouterId The Router ID.
*
* @returns A pointer to a Router entry or NULL if @p aRouterId is out-of-range.
*
*/
const Router *GetRouter(uint8_t aRouterId) const;
/**
* This method retains diagnostic information for a given router.
*
* @param[in] aRouterId The router ID or RLOC16 for a given router.
* @param[out] aRouterInfo The router information.
*
* @retval OT_ERROR_NONE Successfully retrieved the router info for given id.
* @retval OT_ERROR_NOT_FOUND No router entry with the given id.
*
*/
otError GetRouterInfo(uint16_t aRouterId, otRouterInfo &aRouterInfo);
/**
* This method indicates whether or not the given Thread partition attributes are preferred.
*
@@ -641,6 +557,8 @@ public:
*/
otError SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
otError SendLinkRequest(Neighbor *aNeighbor);
#if OPENTHREAD_CONFIG_ENABLE_STEERING_DATA_SET_OOB
/**
* This method sets steering data out of band
@@ -729,6 +647,28 @@ public:
*/
bool IsSleepyChildSubscribed(const Ip6::Address &aAddress, Child &aChild);
/**
* This method resets the MLE Advertisement Trickle timer interval.
*
*/
void ResetAdvertiseInterval(void);
/**
* This method returns a reference to the router table object.
*
*/
RouterTable &GetRouterTable(void) { return mRouterTable; }
/**
* This static method converts link quality to route cost.
*
* @param[in] aLinkQuality The link quality.
*
* @returns The link cost corresponding to @p aLinkQuality.
*
*/
static uint8_t LinkQualityToCost(uint8_t aLinkQuality);
private:
enum
{
@@ -770,14 +710,12 @@ private:
otError ProcessRouteTlv(const RouteTlv &aRoute);
void StopAdvertiseTimer(void);
void ResetAdvertiseInterval(void);
otError SendAddressSolicit(ThreadStatusTlv::Status aStatus);
otError SendAddressRelease(void);
void SendAddressSolicitResponse(const Coap::Header & aRequest,
uint8_t aRouterId,
const Router * aRouter,
const Ip6::MessageInfo &aMessageInfo);
otError SendAdvertisement(void);
otError SendLinkRequest(Neighbor *aNeighbor);
otError SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor,
const TlvRequestTlv & aTlvRequest,
@@ -823,23 +761,16 @@ private:
const otMessageInfo *aMessageInfo);
void HandleAddressSolicit(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
static uint8_t LinkQualityToCost(uint8_t aLinkQuality);
static bool IsSingleton(const RouteTlv &aRouteTlv);
void HandlePartitionChange(void);
void SetChildStateToValid(Child &aChild);
bool HasChildren(void);
void RemoveChildren(void);
bool HasMinDowngradeNeighborRouters(void);
bool HasOneNeighborwithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId);
bool HasSmallNumberOfChildren(void);
uint8_t GetMinDowngradeNeighborRouters(void);
uint8_t AllocateRouterId(void);
uint8_t AllocateRouterId(uint8_t aRouterId);
bool InRouterIdMask(uint8_t aRouterId);
void SetChildStateToValid(Child &aChild);
bool HasChildren(void);
void RemoveChildren(void);
bool HasMinDowngradeNeighborRouters(void);
bool HasOneNeighborWithComparableConnectivity(const RouteTlv &aRoute, uint8_t aRouterId);
bool HasSmallNumberOfChildren(void);
static bool HandleAdvertiseTimer(TrickleTimer &aTimer);
bool HandleAdvertiseTimer(void);
@@ -854,11 +785,8 @@ private:
Coap::Resource mAddressSolicit;
Coap::Resource mAddressRelease;
uint8_t mRouterIdSequence;
uint32_t mRouterIdSequenceLastUpdated;
Router mRouters[kMaxRouterId + 1];
ChildTable mChildTable;
ChildTable mChildTable;
RouterTable mRouterTable;
otThreadChildTableCallback mChildTableChangedCallback;
+7 -25
View File
@@ -41,6 +41,7 @@
#include "thread/child_table.hpp"
#include "thread/mle.hpp"
#include "thread/mle_tlvs.hpp"
#include "thread/router_table.hpp"
#include "thread/thread_tlvs.hpp"
namespace ot {
@@ -54,6 +55,7 @@ public:
explicit MleRouter(Instance &aInstance)
: Mle(aInstance)
, mChildTable(aInstance)
, mRouterTable(aInstance)
{
}
@@ -62,12 +64,8 @@ public:
otError BecomeRouter(ThreadStatusTlv::Status) { return OT_ERROR_NOT_CAPABLE; }
otError BecomeLeader(void) { return OT_ERROR_NOT_CAPABLE; }
uint8_t GetActiveRouterCount(void) const { return 0; }
uint8_t GetActiveNeighborRouterCount(void) const { return 0; }
uint8_t GetRouterSelectionJitterTimeout(void) { return 0; }
uint32_t GetLeaderAge(void) const { return 0; }
uint32_t GetPreviousPartitionId(void) const { return 0; }
void SetPreviousPartitionId(uint32_t) {}
void SetRouterId(uint8_t) {}
@@ -80,12 +78,11 @@ public:
uint8_t GetLinkCost(uint16_t) { return 0; }
uint8_t GetCost(uint16_t) { return 0; }
uint8_t GetRouterIdSequence(void) const { return 0; }
otError RemoveNeighbor(const Mac::Address &) { return BecomeDetached(); }
otError RemoveNeighbor(Neighbor &) { return BecomeDetached(); }
ChildTable &GetChildTable(void) { return mChildTable; }
ChildTable & GetChildTable(void) { return mChildTable; }
RouterTable &GetRouterTable(void) { return mRouterTable; }
bool IsMinimalChild(uint16_t) { return false; }
@@ -105,16 +102,6 @@ public:
otError GetNextNeighborInfo(otNeighborInfoIterator &, otNeighborInfo &) { return OT_ERROR_NOT_IMPLEMENTED; }
Router *GetRouters(uint8_t *aNumRouters)
{
if (aNumRouters != NULL)
{
*aNumRouters = 0;
}
return NULL;
}
static int ComparePartitions(bool, const LeaderDataTlv &, bool, const LeaderDataTlv &) { return 0; }
void ResolveRoutingLoops(uint16_t, uint16_t) {}
@@ -127,7 +114,6 @@ public:
static bool IsRouterIdValid(uint8_t aRouterId) { return aRouterId <= kMaxRouterId; }
void FillConnectivityTlv(ConnectivityTlv &) {}
void FillRouteTlv(RouteTlv &) {}
otError SendChildUpdateRequest(void) { return Mle::SendChildUpdateRequest(); }
@@ -157,15 +143,11 @@ private:
otError HandleNetworkDataUpdateRouter(void) { return OT_ERROR_NONE; }
otError HandleDiscoveryRequest(const Message &, const Ip6::MessageInfo &) { return OT_ERROR_DROP; }
void HandlePartitionChange(void) {}
void StopAdvertiseTimer(void) {}
otError ProcessRouteTlv(const RouteTlv &aRoute)
{
OT_UNUSED_VARIABLE(aRoute);
return OT_ERROR_NONE;
}
otError ProcessRouteTlv(const RouteTlv &) { return OT_ERROR_NONE; }
ChildTable mChildTable;
ChildTable mChildTable;
RouterTable mRouterTable;
};
} // namespace Mle
+2 -1
View File
@@ -346,7 +346,8 @@ otError Local::SendServerDataNotification(void)
// Don't send this Server Data Notification if the device is going to upgrade to Router
if ((mle.GetDeviceMode() & Mle::ModeTlv::kModeFFD) != 0 && (mle.IsRouterRoleEnabled()) &&
(mle.GetRole() < OT_DEVICE_ROLE_ROUTER) && (mle.GetActiveRouterCount() < mle.GetRouterUpgradeThreshold()))
(mle.GetRole() < OT_DEVICE_ROLE_ROUTER) &&
(mle.GetRouterTable().GetActiveRouterCount() < mle.GetRouterUpgradeThreshold()))
{
ExitNow(error = OT_ERROR_INVALID_STATE);
}
+2
View File
@@ -338,6 +338,7 @@ otError NetworkDiagnostic::FillRequestedTlvs(Message & aRequest,
break;
}
#if OPENTHREAD_FTD
case NetworkDiagnosticTlv::kRoute:
{
RouteTlv tlv;
@@ -346,6 +347,7 @@ otError NetworkDiagnostic::FillRequestedTlvs(Message & aRequest,
SuccessOrExit(error = aResponse.Append(&tlv, tlv.GetSize()));
break;
}
#endif
case NetworkDiagnosticTlv::kLeaderData:
{
+619
View File
@@ -0,0 +1,619 @@
/*
* Copyright (c) 2018, 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.
*/
#define WPP_NAME "router_table.tmh"
#include "router_table.hpp"
#if OPENTHREAD_FTD
#include "common/code_utils.hpp"
#include "common/instance.hpp"
#include "common/logging.hpp"
#include "common/timer.hpp"
#include "thread/mle.hpp"
#include "thread/mle_router.hpp"
#include "thread/network_data_leader.hpp"
#include "thread/thread_netif.hpp"
namespace ot {
RouterTable::Iterator::Iterator(Instance &aInstance)
: InstanceLocator(aInstance)
, mRouter(NULL)
{
Reset();
}
void RouterTable::Iterator::Reset(void)
{
RouterTable &routerTable = GetInstance().Get<RouterTable>();
mRouter = &routerTable.mRouters[0];
if (mRouter->GetRloc16() == 0xffff)
{
mRouter = NULL;
}
}
void RouterTable::Iterator::Advance(void)
{
RouterTable &routerTable = GetInstance().Get<RouterTable>();
Router * listEnd = &routerTable.mRouters[Mle::kMaxRouters];
VerifyOrExit(mRouter != NULL);
mRouter++;
VerifyOrExit(mRouter < listEnd && mRouter->GetRloc16() != 0xffff, mRouter = NULL);
exit:
return;
}
RouterTable::RouterTable(Instance &aInstance)
: InstanceLocator(aInstance)
, mRouterIdSequenceLastUpdated(0)
, mRouterIdSequence(Random::GetUint8())
, mActiveRouterCount(0)
{
Clear();
}
void RouterTable::Clear(void)
{
memset(mAllocatedRouterIds, 0, sizeof(mAllocatedRouterIds));
memset(mRouterIdReuseDelay, 0, sizeof(mRouterIdReuseDelay));
UpdateAllocation();
}
void RouterTable::ClearNeighbors(void)
{
for (uint8_t i = 0; i < Mle::kMaxRouters; i++)
{
mRouters[i].SetState(Neighbor::kStateInvalid);
}
}
bool RouterTable::IsAllocated(uint8_t aRouterId) const
{
return (mAllocatedRouterIds[aRouterId / 8] & (1 << (aRouterId % 8))) != 0;
}
void RouterTable::UpdateAllocation(void)
{
uint8_t indexMap[Mle::kMaxRouterId + 1];
mActiveRouterCount = 0;
// build index map
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
if (IsAllocated(i))
{
indexMap[i] = mActiveRouterCount++;
}
else
{
indexMap[i] = Mle::kInvalidRouterId;
}
}
// shift entries forward
for (int i = Mle::kMaxRouters - 2; i >= 0; i--)
{
uint8_t routerId = mRouters[i].GetRouterId();
uint8_t newIndex;
if (routerId > Mle::kMaxRouterId || indexMap[routerId] == Mle::kInvalidRouterId)
{
continue;
}
newIndex = indexMap[routerId];
if (newIndex > i)
{
mRouters[newIndex] = mRouters[i];
}
}
// shift entries backward
for (uint8_t i = 1; i < Mle::kMaxRouters; i++)
{
uint8_t routerId = mRouters[i].GetRouterId();
uint8_t newIndex;
if (routerId > Mle::kMaxRouterId || indexMap[routerId] == Mle::kInvalidRouterId)
{
continue;
}
newIndex = indexMap[routerId];
if (newIndex < i)
{
mRouters[newIndex] = mRouters[i];
}
}
// fix replaced entries
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
uint8_t index = indexMap[i];
Router &router = mRouters[index];
if (index == Mle::kInvalidRouterId)
{
continue;
}
if (router.GetRouterId() != i)
{
memset(&router, 0, sizeof(router));
router.SetRloc16(Mle::Mle::GetRloc16(i));
router.SetNextHop(Mle::kInvalidRouterId);
}
}
// clear unused entries
for (uint8_t i = mActiveRouterCount; i < Mle::kMaxRouters; i++)
{
Router &router = mRouters[i];
memset(&router, 0, sizeof(router));
router.SetRloc16(0xffff);
}
}
Router *RouterTable::Allocate(void)
{
Router *rval = NULL;
uint8_t numAllocated = 0;
uint8_t numAvailable = 0;
uint8_t freeBit;
// count available router ids
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
if (IsAllocated(i))
{
numAllocated++;
}
else if (mRouterIdReuseDelay[i] == 0)
{
numAvailable++;
}
}
VerifyOrExit(numAllocated < Mle::kMaxRouters && numAvailable > 0);
// choose available router id at random
freeBit = Random::GetUint8InRange(0, numAvailable);
// allocate router
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
if (IsAllocated(i) || mRouterIdReuseDelay[i] > 0)
{
continue;
}
if (freeBit == 0)
{
rval = Allocate(i);
assert(rval != NULL);
ExitNow();
}
freeBit--;
}
exit:
return rval;
}
Router *RouterTable::Allocate(uint8_t aRouterId)
{
Router *rval = NULL;
VerifyOrExit(!IsAllocated(aRouterId) && mRouterIdReuseDelay[aRouterId] == 0);
mAllocatedRouterIds[aRouterId / 8] |= 1 << (aRouterId % 8);
UpdateAllocation();
rval = GetRouter(aRouterId);
rval->SetLastHeard(TimerMilli::GetNow());
mRouterIdSequence++;
mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
GetNetif().GetMle().ResetAdvertiseInterval();
otLogInfoMle(GetInstance(), "Allocate router id %d", aRouterId);
exit:
return rval;
}
otError RouterTable::Release(uint8_t aRouterId)
{
otError error = OT_ERROR_NONE;
ThreadNetif &netif = GetNetif();
uint16_t rloc16 = Mle::Mle::GetRloc16(aRouterId);
VerifyOrExit(netif.GetMle().GetRole() == OT_DEVICE_ROLE_LEADER, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(IsAllocated(aRouterId), error = OT_ERROR_NOT_FOUND);
mAllocatedRouterIds[aRouterId / 8] &= ~(1 << (aRouterId % 8));
UpdateAllocation();
mRouterIdReuseDelay[aRouterId] = Mle::kRouterIdReuseDelay;
for (int i = 0; i < Mle::kMaxRouters; i++)
{
Router &router = mRouters[i];
if (router.GetRloc16() == 0xffff)
{
break;
}
if (router.GetNextHop() == rloc16)
{
router.SetNextHop(Mle::kInvalidRouterId);
router.SetCost(0);
}
}
mRouterIdSequence++;
mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
netif.GetAddressResolver().Remove(aRouterId);
netif.GetNetworkDataLeader().RemoveBorderRouter(rloc16);
netif.GetMle().ResetAdvertiseInterval();
otLogInfoMle(GetInstance(), "Release router id %d", aRouterId);
exit:
return error;
}
void RouterTable::RemoveNeighbor(Router &aRouter)
{
ThreadNetif &netif = GetNetif();
aRouter.SetLinkQualityOut(0);
aRouter.SetLastHeard(TimerMilli::GetNow());
for (uint8_t i = 0; i < Mle::kMaxRouters; i++)
{
Router &cur = mRouters[i];
if (cur.GetRloc16() == 0xffff)
{
break;
}
if (cur.GetNextHop() == aRouter.GetRouterId())
{
cur.SetNextHop(Mle::kInvalidRouterId);
cur.SetCost(0);
if (GetLinkCost(cur) >= Mle::kMaxRouteCost)
{
netif.GetMle().ResetAdvertiseInterval();
}
}
}
if (aRouter.GetNextHop() == Mle::kInvalidRouterId)
{
netif.GetMle().ResetAdvertiseInterval();
// Clear all EID-to-RLOC entries assossiated with the router.
netif.GetAddressResolver().Remove(aRouter.GetRouterId());
}
}
Router *RouterTable::GetNeighbor(uint16_t aRloc16)
{
Router *router = NULL;
VerifyOrExit(aRloc16 != GetNetif().GetMle().GetRloc16());
for (int i = 0; i < Mle::kMaxRouters; i++)
{
if (mRouters[i].GetState() == Neighbor::kStateValid && mRouters[i].GetRloc16() == aRloc16)
{
router = &mRouters[i];
ExitNow();
}
}
exit:
return router;
}
Router *RouterTable::GetNeighbor(const Mac::ExtAddress &aExtAddress)
{
Router *router = NULL;
VerifyOrExit(aExtAddress != GetNetif().GetMac().GetExtAddress());
for (int i = 0; i < Mle::kMaxRouters; i++)
{
if (mRouters[i].GetState() == Neighbor::kStateValid && mRouters[i].GetExtAddress() == aExtAddress)
{
router = &mRouters[i];
ExitNow();
}
}
exit:
return router;
}
Router *RouterTable::GetRouter(uint8_t aRouterId)
{
Router * rval = NULL;
uint16_t rloc16 = Mle::Mle::GetRloc16(aRouterId);
for (uint8_t i = 0; i < Mle::kMaxRouters; i++)
{
if (mRouters[i].GetRloc16() == rloc16)
{
rval = &mRouters[i];
ExitNow();
}
}
exit:
return rval;
}
const Router *RouterTable::GetRouter(uint8_t aRouterId) const
{
const Router *rval = NULL;
uint16_t rloc16 = Mle::Mle::GetRloc16(aRouterId);
for (uint8_t i = 0; i < Mle::kMaxRouters; i++)
{
if (mRouters[i].GetRloc16() == rloc16)
{
rval = &mRouters[i];
ExitNow();
}
}
exit:
return rval;
}
Router *RouterTable::GetRouter(const Mac::ExtAddress &aExtAddress)
{
Router *router = NULL;
for (int i = 0; i < Mle::kMaxRouters; i++)
{
if (mRouters[i].GetRloc16() == 0xffff)
{
break;
}
if (mRouters[i].GetExtAddress() == aExtAddress)
{
router = &mRouters[i];
ExitNow();
}
}
exit:
return router;
}
otError RouterTable::GetRouterInfo(uint16_t aRouterId, otRouterInfo &aRouterInfo)
{
otError error = OT_ERROR_NONE;
Router *router;
uint8_t routerId;
if (aRouterId <= Mle::kMaxRouterId)
{
routerId = static_cast<uint8_t>(aRouterId);
}
else
{
VerifyOrExit(Mle::Mle::IsActiveRouter(aRouterId), error = OT_ERROR_INVALID_ARGS);
routerId = Mle::Mle::GetRouterId(aRouterId);
VerifyOrExit(routerId <= Mle::kMaxRouterId, error = OT_ERROR_INVALID_ARGS);
}
router = GetRouter(routerId);
VerifyOrExit(router != NULL, error = OT_ERROR_NOT_FOUND);
memset(&aRouterInfo, 0, sizeof(aRouterInfo));
aRouterInfo.mRouterId = routerId;
aRouterInfo.mRloc16 = Mle::Mle::GetRloc16(routerId);
aRouterInfo.mExtAddress = router->GetExtAddress();
aRouterInfo.mAllocated = true;
aRouterInfo.mNextHop = router->GetNextHop();
aRouterInfo.mLinkEstablished = router->GetState() == Neighbor::kStateValid;
aRouterInfo.mPathCost = router->GetCost();
aRouterInfo.mLinkQualityIn = router->GetLinkInfo().GetLinkQuality();
aRouterInfo.mLinkQualityOut = router->GetLinkQualityOut();
aRouterInfo.mAge = static_cast<uint8_t>(TimerMilli::MsecToSec(TimerMilli::GetNow() - router->GetLastHeard()));
exit:
return error;
}
Router *RouterTable::GetLeader(void)
{
return GetRouter(GetNetif().GetMle().GetLeaderId());
}
uint32_t RouterTable::GetLeaderAge(void) const
{
return TimerMilli::MsecToSec(TimerMilli::GetNow() - mRouterIdSequenceLastUpdated);
}
uint8_t RouterTable::GetNeighborCount(void) const
{
uint8_t count = 0;
for (int i = 0; i < Mle::kMaxRouters; i++)
{
if (mRouters[i].GetState() == Neighbor::kStateValid)
{
count++;
}
}
return count;
}
uint8_t RouterTable::GetLinkCost(Router &aRouter)
{
uint8_t rval = Mle::kMaxRouteCost;
VerifyOrExit(aRouter.GetRloc16() != GetNetif().GetMle().GetRloc16() && aRouter.GetState() == Neighbor::kStateValid);
rval = aRouter.GetLinkInfo().GetLinkQuality();
if (rval > aRouter.GetLinkQualityOut())
{
rval = aRouter.GetLinkQualityOut();
}
rval = Mle::MleRouter::LinkQualityToCost(rval);
exit:
return rval;
}
void RouterTable::ProcessTlv(const Mle::RouteTlv &aTlv)
{
bool allocationChanged = false;
mRouterIdSequence = aTlv.GetRouterIdSequence();
mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
if (aTlv.IsRouterIdSet(i) == IsAllocated(i))
{
continue;
}
allocationChanged = true;
if (aTlv.IsRouterIdSet(i))
{
mAllocatedRouterIds[i / 8] |= 1 << (i % 8);
}
else
{
if (IsAllocated(i))
{
Router *router = GetRouter(i);
assert(router != NULL);
router->SetNextHop(Mle::kInvalidRouterId);
RemoveNeighbor(*router);
}
mAllocatedRouterIds[i / 8] &= ~(1 << (i % 8));
}
}
if (allocationChanged)
{
UpdateAllocation();
GetNetif().GetMle().ResetAdvertiseInterval();
}
}
void RouterTable::ProcessTlv(const ThreadRouterMaskTlv &aTlv)
{
bool allocationChanged = false;
mRouterIdSequence = aTlv.GetIdSequence();
mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
if (aTlv.IsAssignedRouterIdSet(i) == IsAllocated(i))
{
continue;
}
allocationChanged = true;
if (aTlv.IsAssignedRouterIdSet(i))
{
mAllocatedRouterIds[i / 8] |= 1 << (i % 8);
}
else
{
mAllocatedRouterIds[i / 8] &= ~(1 << (i % 8));
}
}
if (allocationChanged)
{
UpdateAllocation();
GetNetif().GetMle().ResetAdvertiseInterval();
}
}
void RouterTable::ProcessTimerTick(void)
{
Mle::MleRouter &mle = GetNetif().GetMle();
if (mle.GetRole() == OT_DEVICE_ROLE_LEADER)
{
// update router id sequence
if (GetLeaderAge() >= Mle::kRouterIdSequencePeriod)
{
mRouterIdSequence++;
mRouterIdSequenceLastUpdated = TimerMilli::GetNow();
}
for (uint8_t i = 0; i <= Mle::kMaxRouterId; i++)
{
if (mRouterIdReuseDelay[i] > 0)
{
mRouterIdReuseDelay[i]--;
}
}
}
}
} // namespace ot
#endif // OPENTHREAD_FTD
+340
View File
@@ -0,0 +1,340 @@
/*
* Copyright (c) 2018, 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.
*/
#ifndef ROUTER_TABLE_HPP_
#define ROUTER_TABLE_HPP_
#include "common/encoding.hpp"
#include "common/locator.hpp"
#include "mac/mac_frame.hpp"
#include "thread/mle_constants.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/topology.hpp"
namespace ot {
#if OPENTHREAD_FTD
class RouterTable : public InstanceLocator
{
public:
/**
* This class represents an iterator for iterating through entries in the router table.
*
*/
class Iterator : public InstanceLocator
{
public:
/**
* This constructor initializes an `Iterator` instance to start from beginning of the router table.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
Iterator(Instance &aInstance);
/**
* This method resets the iterator to start over.
*
*/
void Reset(void);
/**
* This method indicates if the iterator has reached the end of the list.
*
* @retval TRUE The iterator has reached the end of the list.
* @retval FALSE The iterator currently points to a valid entry.
*
*/
bool IsDone(void) const { return (mRouter == NULL); }
/**
* This method advances the iterator.
*
* The iterator is moved to point to the next entry. If there are no more entries matching the iterator
* becomes empty (i.e., `GetRouter()` returns `NULL` and `IsDone()` returns `true`).
*
*/
void Advance(void);
/**
* This method gets the entry to which the iterator is currently pointing.
*
* @returns A pointer to the current entry, or `NULL` if the iterator is done/empty.
*
*/
Router *GetRouter(void) { return mRouter; }
private:
Router *mRouter;
};
/**
* Constructor.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
RouterTable(Instance &aInstance);
/**
* This method clears the router table.
*
*/
void Clear(void);
/**
* This method removes all neighbor links to routers.
*
*/
void ClearNeighbors(void);
/**
* This method allocates a router with a random router id.
*
* @returns A pointer to the allocated router or NULL if a router ID is not available.
*
*/
Router *Allocate(void);
/**
* This method allocates a router with a specified router id.
*
* @returns A pointer to the allocated router or NULL if the router id could not be allocated.
*
*/
Router *Allocate(uint8_t aRouterId);
/**
* This method releases a router id.
*
* @param[in] aRouterId The router id.
*
* @retval OT_ERROR_NONE Successfully released the router id.
* @retval OT_ERROR_INVALID_STATE The device is not currently operating as a leader.
* @retval OT_ERROR_NOT_FOUND The router id is not currently allocated.
*
*/
otError Release(uint8_t aRouterId);
/**
* This method removes a neighboring router link.
*
* @param[in] aRouter A reference to the router.
*
*/
void RemoveNeighbor(Router &aRouter);
/**
* This method returns the number of active routers in the Thread network.
*
* @returns The number of active routers in the Thread network.
*
*/
uint8_t GetActiveRouterCount(void) const { return mActiveRouterCount; }
/**
* This method returns the leader in the Thread network.
*
* @returns A pointer to the Leader in the Thread network.
*
*/
Router *GetLeader(void);
/**
* This method returns the time in seconds since the last Router ID Sequence update.
*
* @returns The time in seconds since the last Router ID Sequence update.
*
*/
uint32_t GetLeaderAge(void) const;
/**
* This method returns the link cost for a neighboring router.
*
* @param[in] aRouter A reference to the router.
*
* @returns The link cost.
*
*/
uint8_t GetLinkCost(Router &aRouter);
/**
* This method returns the neighbor for a given RLOC16.
*
* @param[in] aRloc16 The RLOC16 value.
*
* @returns A pointer to the router or NULL if the router could not be found.
*
*/
Router *GetNeighbor(uint16_t aRloc16);
/**
* This method returns the neighbor for a given IEEE Extended Address.
*
* @param[in] aExtAddress A reference to the IEEE Extended Address.
*
* @returns A pointer to the router or NULL if the router could not be found.
*
*/
Router *GetNeighbor(const Mac::ExtAddress &aExtAddress);
/**
* This method returns the router for a given router id.
*
* @parma[in] aRouterId The router id.
*
* @returns A pointer to the router or NULL if the router could not be found.
*
*/
Router *GetRouter(uint8_t aRouterId);
/**
* This method returns the router for a given router id.
*
* @parma[in] aRouterId The router id.
*
* @returns A pointer to the router or NULL if the router could not be found.
*
*/
const Router *GetRouter(uint8_t aRouterId) const;
/**
* This method returns the router for a given IEEE Extended Address.
*
* @param[in] aExtAddress A reference to the IEEE Extended Address.
*
* @returns A pointer to the router or NULL if the router could not be found.
*
*/
Router *GetRouter(const Mac::ExtAddress &aExtAddress);
/**
* This method retains diagnostic information for a given router.
*
* @param[in] aRouterId The router ID or RLOC16 for a given router.
* @param[out] aRouterInfo The router information.
*
* @retval OT_ERROR_NONE Successfully retrieved the router info for given id.
* @retval OT_ERROR_INVALID_ARGS @p aRouterId is not a valid value for a router.
* @retval OT_ERROR_NOT_FOUND No router entry with the given id.
*
*/
otError GetRouterInfo(uint16_t aRouterId, otRouterInfo &aRouterInfo);
/**
* This method returns the Router ID Sequence.
*
* @returns The Router ID Sequence.
*
*/
uint8_t GetRouterIdSequence(void) const { return mRouterIdSequence; }
/**
* This method returns the local time when the Router ID Sequence was last updated.
*
* @returns The local time when the Router ID Sequence was last updated.
*
*/
uint32_t GetRouterIdSequenceLastUpdated(void) const { return mRouterIdSequenceLastUpdated; }
/**
* This method returns the number of neighbor links.
*
* @returns The number of neighbor links.
*
*/
uint8_t GetNeighborCount(void) const;
/**
* This method indicates whether or not @p aRouterId is allocated.
*
* @retval TRUE if @p aRouterId is allocated.
* @retval FALSE if @p aRouterId is not allocated.
*
*/
bool IsAllocated(uint8_t aRouterId) const;
/**
* This method updates the router table with a received Route TLV.
*
* @param[in] aRoute A reference to the Route TLV.
*
*/
void ProcessTlv(const Mle::RouteTlv &aRoute);
/**
* This method updates the router table with a received Router Mask TLV.
*
* @param[in] aTlv A reference to the Router Mask TLV.
*
*/
void ProcessTlv(const ThreadRouterMaskTlv &Tlv);
/**
* This method updates the router table and must be called with a one second period.
*
*/
void ProcessTimerTick(void);
private:
void UpdateAllocation(void);
Router mRouters[Mle::kMaxRouters];
uint8_t mAllocatedRouterIds[BitVectorBytes(Mle::kMaxRouterId)];
uint8_t mRouterIdReuseDelay[Mle::kMaxRouterId + 1];
uint32_t mRouterIdSequenceLastUpdated;
uint8_t mRouterIdSequence;
uint8_t mActiveRouterCount;
};
#endif // OPENTHREAD_FTD
#if OPENTHREAD_MTD
class RouterTable
{
public:
class Iterator
{
public:
Iterator(Instance &) {}
void Reset(void) {}
bool IsDone(void) const { return true; }
void Advance(void) {}
Router *GetRouter(void) { return NULL; }
};
explicit RouterTable(Instance &) {}
};
#endif // OPENTHREAD_MTD
} // namespace ot
#endif // ROUTER_TABLE_HPP_
+8 -34
View File
@@ -254,6 +254,14 @@ public:
*/
uint16_t GetRloc16(void) const { return mRloc16; }
/**
* This method gets the Router ID value.
*
* @returns The Router ID value.
*
*/
uint8_t GetRouterId(void) const { return mRloc16 >> Mle::kRouterIdOffset; }
/**
* This method sets the RLOC16 value.
*
@@ -877,44 +885,10 @@ public:
*/
void SetCost(uint8_t aCost) { mCost = aCost; }
/**
* This method indicates whether or not this router ID has been allocated.
*
* @returns TRUE if this router ID has been allocated, FALSE otherwise.
*
*/
bool IsAllocated(void) const { return mAllocated; }
/**
* This method sets whether or not this router ID has been allocated.
*
* @param[in] aAllocated TRUE if this router ID has been allocated, FALSE otherwise.
*
*/
void SetAllocated(bool aAllocated) { mAllocated = aAllocated; }
/**
* This method indicates whether the reclaim delay is in effect for this router ID.
*
* @returns TRUE if the reclaim delay is in effect, FALSE otherwise.
*
*/
bool IsReclaimDelay(void) const { return mReclaimDelay; }
/**
* This method sets whether the reclaim delay is in effect for this router ID.
*
* @param[in] aReclaimDelay TRUE if the reclaim delay is in effect, FALSE otherwise.
*
*/
void SetReclaimDelay(bool aReclaimDelay) { mReclaimDelay = aReclaimDelay; }
private:
uint8_t mNextHop; ///< The next hop towards this router
uint8_t mLinkQualityOut : 2; ///< The link quality out for this router
uint8_t mCost : 4; ///< The cost to this router via neighbor router
bool mAllocated : 1; ///< Indicates whether or not this entry is allocated
bool mReclaimDelay : 1; ///< Indicates whether or not this entry is waiting to be reclaimed
};
} // namespace ot