diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 439e95f32..a3720fb56 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -4937,7 +4937,7 @@ Error Mle::TxMessage::AppendRouteTlv(Neighbor *aNeighbor) RouteTlv tlv; tlv.Init(); - Get().FillRouteTlv(tlv, aNeighbor); + Get().FillRouteTlv(tlv, aNeighbor); return tlv.AppendTo(*this); } diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index cb5bc2c7d..981ca2cf3 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -4151,107 +4151,6 @@ void MleRouter::FillConnectivityTlv(ConnectivityTlv &aTlv) aTlv.SetSedDatagramCount(OPENTHREAD_CONFIG_DEFAULT_SED_DATAGRAM_COUNT); } -void MleRouter::FillRouteTlv(RouteTlv &aTlv, Neighbor *aNeighbor) -{ - uint8_t routerIdSequence = mRouterTable.GetRouterIdSequence(); - RouterIdSet routerIdSet = mRouterTable.GetRouterIdSet(); - uint8_t routerCount; - - if (aNeighbor && IsActiveRouter(aNeighbor->GetRloc16())) - { - // Sending a Link Accept message that may require truncation - // of Route64 TLV - - routerCount = mRouterTable.GetActiveRouterCount(); - - if (routerCount > kLinkAcceptMaxRouters) - { - for (uint8_t routerId = 0; routerId <= kMaxRouterId; routerId++) - { - if (routerCount <= kLinkAcceptMaxRouters) - { - break; - } - - if ((routerId == RouterIdFromRloc16(GetRloc16())) || (routerId == aNeighbor->GetRouterId()) || - (routerId == GetLeaderId())) - { - // Route64 TLV must contain this device and the - // neighboring router to ensure that at least this - // link can be established. - continue; - } - - if (routerIdSet.Contains(routerId)) - { - routerIdSet.Remove(routerId); - routerCount--; - } - } - - // Ensure that the neighbor will process the current - // Route64 TLV in a subsequent message exchange - routerIdSequence -= kLinkAcceptSequenceRollback; - } - } - - aTlv.SetRouterIdSequence(routerIdSequence); - aTlv.SetRouterIdMask(routerIdSet); - - routerCount = 0; - - for (Router &router : Get().Iterate()) - { - if (!routerIdSet.Contains(router.GetRouterId())) - { - continue; - } - - if (router.GetRloc16() == GetRloc16()) - { - aTlv.SetLinkQualityIn(routerCount, kLinkQuality0); - aTlv.SetLinkQualityOut(routerCount, kLinkQuality0); - aTlv.SetRouteCost(routerCount, 1); - } - else - { - Router *nextHop; - uint8_t linkCost; - uint8_t routeCost; - - linkCost = mRouterTable.GetLinkCost(router); - nextHop = mRouterTable.FindNextHopOf(router); - - if (nextHop == nullptr) - { - routeCost = linkCost; - } - else - { - routeCost = router.GetCost() + mRouterTable.GetLinkCost(*nextHop); - - if (linkCost < routeCost) - { - routeCost = linkCost; - } - } - - if (routeCost >= kMaxRouteCost) - { - routeCost = 0; - } - - aTlv.SetRouteCost(routerCount, routeCost); - aTlv.SetLinkQualityOut(routerCount, router.GetLinkQualityOut()); - aTlv.SetLinkQualityIn(routerCount, router.GetLinkQualityIn()); - } - - routerCount++; - } - - aTlv.SetRouteDataLength(routerCount); -} - bool MleRouter::HasMinDowngradeNeighborRouters(void) { uint8_t routerCount = 0; diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index 811f1a005..c8e70f783 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -419,14 +419,6 @@ public: */ void FillConnectivityTlv(ConnectivityTlv &aTlv); - /** - * This method fills an RouteTlv. - * - * @param[out] aTlv A reference to the tlv to be filled. - * - */ - void FillRouteTlv(RouteTlv &aTlv, Neighbor *aNeighbor = nullptr); - /** * This method generates an MLE Child Update Request message to be sent to the parent. * diff --git a/src/core/thread/network_diagnostic.cpp b/src/core/thread/network_diagnostic.cpp index 9e927ae9f..d598be8e7 100644 --- a/src/core/thread/network_diagnostic.cpp +++ b/src/core/thread/network_diagnostic.cpp @@ -343,7 +343,7 @@ Error NetworkDiagnostic::FillRequestedTlvs(const Message & aRequest, RouteTlv tlv; tlv.Init(); - Get().FillRouteTlv(tlv); + Get().FillRouteTlv(tlv); SuccessOrExit(error = tlv.AppendTo(aResponse)); break; } diff --git a/src/core/thread/router_table.cpp b/src/core/thread/router_table.cpp index a09d481be..9cd38089a 100644 --- a/src/core/thread/router_table.cpp +++ b/src/core/thread/router_table.cpp @@ -483,7 +483,7 @@ void RouterTable::UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::Router // If was allocated but removed in new Router Id Set if (IsAllocated(routerId) && !aRouterIdSet.Contains(routerId)) { - Router *router = FindRouterForId(routerId); + Router *router = FindRouterById(routerId); OT_ASSERT(router != nullptr); router->SetNextHop(Mle::kInvalidRouterId); @@ -501,6 +501,104 @@ exit: return; } +void RouterTable::FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighbor) const +{ + uint8_t routerIdSequence = mRouterIdSequence; + Mle::RouterIdSet routerIdSet = mAllocatedRouterIds; + uint8_t routerCount; + + if ((aNeighbor != nullptr) && Mle::IsActiveRouter(aNeighbor->GetRloc16())) + { + // Sending a Link Accept message that may require truncation + // of Route64 TLV. + + routerCount = mActiveRouterCount; + + if (routerCount > Mle::kLinkAcceptMaxRouters) + { + for (uint8_t routerId = 0; routerId <= Mle::kMaxRouterId; routerId++) + { + if (routerCount <= Mle::kLinkAcceptMaxRouters) + { + break; + } + + if ((routerId == Mle::RouterIdFromRloc16(Get().GetRloc16())) || + (routerId == aNeighbor->GetRouterId()) || (routerId == Get().GetLeaderId())) + { + // Route64 TLV must contain this device and the + // neighboring router to ensure that at least this + // link can be established. + continue; + } + + if (routerIdSet.Contains(routerId)) + { + routerIdSet.Remove(routerId); + routerCount--; + } + } + + // Ensure that the neighbor will process the current + // Route64 TLV in a subsequent message exchange + routerIdSequence -= Mle::kLinkAcceptSequenceRollback; + } + } + + aRouteTlv.SetRouterIdSequence(routerIdSequence); + aRouteTlv.SetRouterIdMask(routerIdSet); + + routerCount = 0; + + for (const Router *router = GetFirstEntry(); router != nullptr; router = GetNextEntry(router)) + { + if (!routerIdSet.Contains(router->GetRouterId())) + { + continue; + } + + if (router->GetRloc16() == Get().GetRloc16()) + { + aRouteTlv.SetLinkQualityIn(routerCount, kLinkQuality0); + aRouteTlv.SetLinkQualityOut(routerCount, kLinkQuality0); + aRouteTlv.SetRouteCost(routerCount, 1); + } + else + { + const Router *nextHop = FindNextHopOf(*router); + uint8_t linkCost = GetLinkCost(*router); + uint8_t routeCost; + + if (nextHop == nullptr) + { + routeCost = linkCost; + } + else + { + routeCost = router->GetCost() + GetLinkCost(*nextHop); + + if (linkCost < routeCost) + { + routeCost = linkCost; + } + } + + if (routeCost >= Mle::kMaxRouteCost) + { + routeCost = 0; + } + + aRouteTlv.SetRouteCost(routerCount, routeCost); + aRouteTlv.SetLinkQualityOut(routerCount, router->GetLinkQualityOut()); + aRouteTlv.SetLinkQualityIn(routerCount, router->GetLinkQualityIn()); + } + + routerCount++; + } + + aRouteTlv.SetRouteDataLength(routerCount); +} + void RouterTable::HandleTimeTick(void) { Mle::MleRouter &mle = Get(); diff --git a/src/core/thread/router_table.hpp b/src/core/thread/router_table.hpp index c935bb436..801a7ec0c 100644 --- a/src/core/thread/router_table.hpp +++ b/src/core/thread/router_table.hpp @@ -39,6 +39,7 @@ #include "common/locator.hpp" #include "common/non_copyable.hpp" #include "mac/mac_types.hpp" +#include "thread/mle_tlvs.hpp" #include "thread/mle_types.hpp" #include "thread/thread_tlvs.hpp" #include "thread/topology.hpp" @@ -326,6 +327,19 @@ public: */ const Mle::RouterIdSet &GetRouterIdSet(void) const { return mAllocatedRouterIds; } + /** + * This method fills a Route TLV. + * + * When @p aNeighbor is not `nullptr`, we limit the number of router entries to `Mle::kLinkAcceptMaxRouters` when + * populating `aRouteTlv`, so that the TLV can be appended in a Link Accept message. In this case, we ensure to + * include router entries associated with @p aNeighbor, leader, and this device itself. + * + * @param[out] aRouteTlv A Route TLV to be filled. + * @param[in] aNeighbor A pointer to the receiver (in case TLV is for a Link Accept message). + * + */ + void FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighbor = nullptr) const; + /** * This method updates the router table and must be called with a one second period. *