mirror of
https://github.com/espressif/openthread.git
synced 2026-08-29 05:19:54 +00:00
[router-table] move cost calc and related methods to RouterTable (#8623)
This commit moves existing methods for cost and next hop calculation and updating router table entries to `RouterTable` class from `MleRouter`.
This commit is contained in:
@@ -962,7 +962,7 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
switch (error = ProcessRouteTlv(aRxInfo, routeTlv))
|
||||
{
|
||||
case kErrorNone:
|
||||
UpdateRoutes(routeTlv, routerId);
|
||||
mRouterTable.UpdateRoutes(routeTlv, routerId);
|
||||
// Need to update router after ProcessRouteTlv
|
||||
router = mRouterTable.FindRouterById(routerId);
|
||||
OT_ASSERT(router != nullptr);
|
||||
@@ -1035,22 +1035,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t MleRouter::GetLinkCost(uint8_t aRouterId) const
|
||||
{
|
||||
uint8_t rval = kMaxRouteCost;
|
||||
const Router *router;
|
||||
|
||||
router = mRouterTable.FindRouterById(aRouterId);
|
||||
|
||||
// `nullptr` aRouterId indicates non-existing next hop, hence return kMaxRouteCost for it.
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
rval = mRouterTable.GetLinkCost(*router);
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
Error MleRouter::SetRouterSelectionJitter(uint8_t aRouterJitter)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -1394,7 +1378,7 @@ Error MleRouter::HandleAdvertisement(RxInfo &aRxInfo)
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateRoutes(routeTlv, routerId);
|
||||
mRouterTable.UpdateRoutes(routeTlv, routerId);
|
||||
|
||||
exit:
|
||||
if (aRxInfo.mNeighbor && aRxInfo.mNeighbor->GetRloc16() != sourceAddress)
|
||||
@@ -1406,150 +1390,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::UpdateRoutes(const RouteTlv &aRouteTlv, uint8_t aRouterId)
|
||||
{
|
||||
Router *neighbor;
|
||||
bool resetAdvInterval = false;
|
||||
bool changed = false;
|
||||
|
||||
neighbor = mRouterTable.FindRouterById(aRouterId);
|
||||
VerifyOrExit(neighbor != nullptr);
|
||||
|
||||
// update link quality out to neighbor
|
||||
changed = UpdateLinkQualityOut(aRouteTlv, *neighbor, resetAdvInterval);
|
||||
|
||||
// update routes
|
||||
for (uint8_t routerId = 0, routeCount = 0; routerId <= kMaxRouterId; routerId++)
|
||||
{
|
||||
Router *router;
|
||||
Router *nextHop;
|
||||
uint8_t cost;
|
||||
|
||||
if (!aRouteTlv.IsRouterIdSet(routerId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
router = mRouterTable.FindRouterById(routerId);
|
||||
|
||||
if (router == nullptr || router->GetRloc16() == GetRloc16() || router == neighbor)
|
||||
{
|
||||
routeCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
nextHop = mRouterTable.FindNextHopOf(*router);
|
||||
|
||||
cost = aRouteTlv.GetRouteCost(routeCount);
|
||||
|
||||
if (cost == 0)
|
||||
{
|
||||
cost = kMaxRouteCost;
|
||||
}
|
||||
|
||||
if (nextHop == nullptr || nextHop == neighbor)
|
||||
{
|
||||
// router has no next hop or next hop is neighbor (sender)
|
||||
|
||||
if (cost + mRouterTable.GetLinkCost(*neighbor) < kMaxRouteCost)
|
||||
{
|
||||
if (nextHop == nullptr && mRouterTable.GetLinkCost(*router) >= kMaxRouteCost)
|
||||
{
|
||||
resetAdvInterval = true;
|
||||
}
|
||||
|
||||
if (router->GetNextHop() != aRouterId)
|
||||
{
|
||||
router->SetNextHop(aRouterId);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (router->GetCost() != cost)
|
||||
{
|
||||
router->SetCost(cost);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (nextHop == neighbor)
|
||||
{
|
||||
if (mRouterTable.GetLinkCost(*router) >= kMaxRouteCost)
|
||||
{
|
||||
resetAdvInterval = true;
|
||||
}
|
||||
|
||||
router->SetNextHop(kInvalidRouterId);
|
||||
router->SetCost(0);
|
||||
router->SetLastHeard(TimerMilli::GetNow());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t curCost = router->GetCost() + mRouterTable.GetLinkCost(*nextHop);
|
||||
uint8_t newCost = cost + mRouterTable.GetLinkCost(*neighbor);
|
||||
|
||||
if (newCost < curCost)
|
||||
{
|
||||
router->SetNextHop(aRouterId);
|
||||
router->SetCost(cost);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
routeCount++;
|
||||
}
|
||||
|
||||
if (resetAdvInterval)
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
Get<RouterTable>().LogRouteTable();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
bool MleRouter::UpdateLinkQualityOut(const RouteTlv &aRouteTlv, Router &aNeighbor, bool &aResetAdvInterval)
|
||||
{
|
||||
bool changed = false;
|
||||
LinkQuality linkQuality;
|
||||
uint8_t myRouterId;
|
||||
uint8_t myRouteCount;
|
||||
uint8_t oldLinkCost;
|
||||
Router *nextHop;
|
||||
|
||||
myRouterId = RouterIdFromRloc16(GetRloc16());
|
||||
VerifyOrExit(aRouteTlv.IsRouterIdSet(myRouterId));
|
||||
|
||||
myRouteCount = 0;
|
||||
for (uint8_t routerId = 0; routerId < myRouterId; routerId++)
|
||||
{
|
||||
myRouteCount += aRouteTlv.IsRouterIdSet(routerId);
|
||||
}
|
||||
|
||||
linkQuality = aRouteTlv.GetLinkQualityIn(myRouteCount);
|
||||
VerifyOrExit(aNeighbor.GetLinkQualityOut() != linkQuality);
|
||||
|
||||
oldLinkCost = mRouterTable.GetLinkCost(aNeighbor);
|
||||
|
||||
aNeighbor.SetLinkQualityOut(linkQuality);
|
||||
nextHop = mRouterTable.FindNextHopOf(aNeighbor);
|
||||
|
||||
// reset MLE advertisement timer if neighbor route cost changed to or from infinite
|
||||
if (nextHop == nullptr && (oldLinkCost >= kMaxRouteCost) != (mRouterTable.GetLinkCost(aNeighbor) >= kMaxRouteCost))
|
||||
{
|
||||
aResetAdvInterval = true;
|
||||
}
|
||||
changed = true;
|
||||
|
||||
exit:
|
||||
return changed;
|
||||
}
|
||||
|
||||
void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -1584,9 +1424,9 @@ void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
leader = mRouterTable.GetLeader();
|
||||
OT_ASSERT(leader != nullptr);
|
||||
|
||||
VerifyOrExit(IsLeader() || GetLinkCost(GetLeaderId()) < kMaxRouteCost ||
|
||||
VerifyOrExit(IsLeader() || mRouterTable.GetLinkCost(GetLeaderId()) < kMaxRouteCost ||
|
||||
(IsChild() && leader->GetCost() + 1 < kMaxRouteCost) ||
|
||||
(leader->GetCost() + GetLinkCost(leader->GetNextHop()) < kMaxRouteCost),
|
||||
(leader->GetCost() + mRouterTable.GetLinkCost(leader->GetNextHop()) < kMaxRouteCost),
|
||||
error = kErrorDrop);
|
||||
|
||||
// 4. It is a REED and there are already `kMaxRouters` active routers in
|
||||
@@ -3441,128 +3281,6 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t MleRouter::GetNextHop(uint16_t aDestination)
|
||||
{
|
||||
uint8_t destinationId = RouterIdFromRloc16(aDestination);
|
||||
uint8_t routeCost;
|
||||
uint8_t linkCost;
|
||||
uint16_t rval = Mac::kShortAddrInvalid;
|
||||
const Router *router;
|
||||
const Router *nextHop;
|
||||
|
||||
if (IsChild())
|
||||
{
|
||||
ExitNow(rval = Mle::GetNextHop(aDestination));
|
||||
}
|
||||
|
||||
// The frame is destined to a child
|
||||
if (destinationId == mRouterId)
|
||||
{
|
||||
ExitNow(rval = aDestination);
|
||||
}
|
||||
|
||||
router = mRouterTable.FindRouterById(destinationId);
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
linkCost = GetLinkCost(destinationId);
|
||||
routeCost = GetRouteCost(aDestination);
|
||||
|
||||
if ((routeCost + GetLinkCost(router->GetNextHop())) < linkCost)
|
||||
{
|
||||
nextHop = mRouterTable.FindNextHopOf(*router);
|
||||
VerifyOrExit(nextHop != nullptr && !nextHop->IsStateInvalid());
|
||||
|
||||
rval = Rloc16FromRouterId(router->GetNextHop());
|
||||
}
|
||||
else if (linkCost < kMaxRouteCost)
|
||||
{
|
||||
rval = Rloc16FromRouterId(destinationId);
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint8_t MleRouter::GetPathCost(uint16_t aDestRloc16) const
|
||||
{
|
||||
uint8_t cost = kMaxRouteCost;
|
||||
uint8_t destRouterId;
|
||||
const Router *router;
|
||||
const Router *nextHop;
|
||||
|
||||
if (aDestRloc16 == GetRloc16())
|
||||
{
|
||||
// Destination is this device, return cost as zero.
|
||||
// This is also valid when device is a child.
|
||||
ExitNow(cost = 0);
|
||||
}
|
||||
|
||||
if (IsChild())
|
||||
{
|
||||
// If device is a child, then check if destination is our parent
|
||||
// and determine cost based on the link quality to parent.
|
||||
// Otherwise we cannot determine the cost.
|
||||
|
||||
VerifyOrExit(aDestRloc16 == GetParent().GetRloc16());
|
||||
cost = CostForLinkQuality(GetParent().GetLinkQualityIn());
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
destRouterId = RouterIdFromRloc16(aDestRloc16);
|
||||
|
||||
if (destRouterId == RouterIdFromRloc16(GetRloc16()))
|
||||
{
|
||||
// `aDestRloc16` is a one of device's children. We know the
|
||||
// device is not a child from `IsChild()` check above and
|
||||
// that the destination is not device itself (from first `if`
|
||||
// check above).
|
||||
|
||||
const Child *child = Get<ChildTable>().FindChild(aDestRloc16, Child::kInStateValid);
|
||||
|
||||
VerifyOrExit(child != nullptr);
|
||||
ExitNow(cost = CostForLinkQuality(child->GetLinkQualityIn()));
|
||||
}
|
||||
|
||||
router = mRouterTable.FindRouterById(destRouterId);
|
||||
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
cost = mRouterTable.GetLinkCost(*router);
|
||||
|
||||
nextHop = mRouterTable.FindNextHopOf(*router);
|
||||
|
||||
if (nextHop != nullptr)
|
||||
{
|
||||
// Determine whether direct link or forwarding hop link
|
||||
// has a lower cost.
|
||||
cost = Min(cost, static_cast<uint8_t>(router->GetCost() + mRouterTable.GetLinkCost(*nextHop)));
|
||||
}
|
||||
|
||||
if (!IsActiveRouter(aDestRloc16))
|
||||
{
|
||||
// Destination is a child. we assume best link quality
|
||||
// between destination and its parent router.
|
||||
cost += kCostForLinkQuality3;
|
||||
}
|
||||
|
||||
exit:
|
||||
return cost;
|
||||
}
|
||||
|
||||
uint8_t MleRouter::GetRouteCost(uint16_t aRloc16) const
|
||||
{
|
||||
uint8_t rval = kMaxRouteCost;
|
||||
const Router *router;
|
||||
|
||||
router = mRouterTable.FindRouterByRloc16(aRloc16);
|
||||
VerifyOrExit(router != nullptr && mRouterTable.FindNextHopOf(*router) != nullptr);
|
||||
|
||||
rval = router->GetCost();
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
Error MleRouter::SetPreferredRouterId(uint8_t aRouterId)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -4054,11 +3772,11 @@ void MleRouter::FillConnectivityTlv(ConnectivityTlv &aTlv)
|
||||
case kRoleRouter:
|
||||
if (leader != nullptr)
|
||||
{
|
||||
cost += GetLinkCost(leader->GetNextHop());
|
||||
cost += mRouterTable.GetLinkCost(leader->GetNextHop());
|
||||
|
||||
if (!IsRouterIdValid(leader->GetNextHop()) || GetLinkCost(GetLeaderId()) < cost)
|
||||
if (!IsRouterIdValid(leader->GetNextHop()) || mRouterTable.GetLinkCost(GetLeaderId()) < cost)
|
||||
{
|
||||
cost = GetLinkCost(GetLeaderId());
|
||||
cost = mRouterTable.GetLinkCost(GetLeaderId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
* @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
|
||||
*
|
||||
*/
|
||||
uint16_t GetNextHop(uint16_t aDestination);
|
||||
uint16_t GetNextHop(uint16_t aDestination) { return mRouterTable.GetNextHop(aDestination); }
|
||||
|
||||
/**
|
||||
* This method returns the NETWORK_ID_TIMEOUT value.
|
||||
@@ -240,26 +240,6 @@ public:
|
||||
*/
|
||||
void SetNetworkIdTimeout(uint8_t aTimeout) { mNetworkIdTimeout = aTimeout; }
|
||||
|
||||
/**
|
||||
* This method returns the route cost to a RLOC16.
|
||||
*
|
||||
* @param[in] aRloc16 The RLOC16 of the destination.
|
||||
*
|
||||
* @returns The route cost to a RLOC16.
|
||||
*
|
||||
*/
|
||||
uint8_t GetRouteCost(uint16_t aRloc16) const;
|
||||
|
||||
/**
|
||||
* This method returns the link cost to the given Router.
|
||||
*
|
||||
* @param[in] aRouterId The Router ID.
|
||||
*
|
||||
* @returns The link cost to the Router.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLinkCost(uint8_t aRouterId) const;
|
||||
|
||||
/**
|
||||
* This method returns the minimum mesh path cost to the given RLOC16
|
||||
*
|
||||
@@ -268,7 +248,7 @@ public:
|
||||
* @returns The minimum mesh path cost to @p aDestRloc16 (via direct link or forwarding).
|
||||
*
|
||||
*/
|
||||
uint8_t GetPathCost(uint16_t aDestRloc16) const;
|
||||
uint8_t GetPathCost(uint16_t aDestRloc16) const { return mRouterTable.GetPathCost(aDestRloc16); }
|
||||
|
||||
/**
|
||||
* This method returns the ROUTER_SELECTION_JITTER value.
|
||||
@@ -617,8 +597,6 @@ private:
|
||||
void StopLeader(void);
|
||||
void SynchronizeChildNetworkData(void);
|
||||
Error UpdateChildAddresses(const Message &aMessage, uint16_t aOffset, uint16_t aLength, Child &aChild);
|
||||
void UpdateRoutes(const RouteTlv &aRouteTlv, uint8_t aRouterId);
|
||||
bool UpdateLinkQualityOut(const RouteTlv &aRouteTlv, Router &aNeighbor, bool &aResetAdvInterval);
|
||||
bool HasNeighborWithGoodLinkQuality(void) const;
|
||||
|
||||
static void HandleAddressSolicitResponse(void *aContext,
|
||||
|
||||
@@ -358,6 +358,147 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint8_t RouterTable::GetLinkCost(uint8_t aRouterId) const
|
||||
{
|
||||
uint8_t rval = Mle::kMaxRouteCost;
|
||||
const Router *router;
|
||||
|
||||
router = FindRouterById(aRouterId);
|
||||
|
||||
// `nullptr` aRouterId indicates non-existing next hop, hence return kMaxRouteCost for it.
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
rval = GetLinkCost(*router);
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint8_t RouterTable::GetPathCost(uint16_t aDestRloc16) const
|
||||
{
|
||||
uint8_t cost = Mle::kMaxRouteCost;
|
||||
uint8_t destRouterId;
|
||||
const Router *router;
|
||||
const Router *nextHop;
|
||||
|
||||
if (aDestRloc16 == Get<Mle::Mle>().GetRloc16())
|
||||
{
|
||||
// Destination is this device, return cost as zero.
|
||||
// This is also valid when device is a child.
|
||||
ExitNow(cost = 0);
|
||||
}
|
||||
|
||||
if (Get<Mle::MleRouter>().IsChild())
|
||||
{
|
||||
// If device is a child, then check if destination is our parent
|
||||
// and determine cost based on the link quality to parent.
|
||||
// Otherwise we cannot determine the cost.
|
||||
|
||||
VerifyOrExit(aDestRloc16 == Get<Mle::Mle>().GetParent().GetRloc16());
|
||||
cost = CostForLinkQuality(Get<Mle::Mle>().GetParent().GetLinkQualityIn());
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
destRouterId = Mle::RouterIdFromRloc16(aDestRloc16);
|
||||
|
||||
if (destRouterId == Mle::RouterIdFromRloc16(Get<Mle::Mle>().GetRloc16()))
|
||||
{
|
||||
// `aDestRloc16` is a one of device's children. We know the
|
||||
// device is not a child from `IsChild()` check above and
|
||||
// that the destination is not device itself (from first `if`
|
||||
// check above).
|
||||
|
||||
const Child *child = Get<ChildTable>().FindChild(aDestRloc16, Child::kInStateValid);
|
||||
|
||||
VerifyOrExit(child != nullptr);
|
||||
ExitNow(cost = CostForLinkQuality(child->GetLinkQualityIn()));
|
||||
}
|
||||
|
||||
router = FindRouterById(destRouterId);
|
||||
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
cost = GetLinkCost(*router);
|
||||
|
||||
nextHop = FindNextHopOf(*router);
|
||||
|
||||
if (nextHop != nullptr)
|
||||
{
|
||||
// Determine whether direct link or forwarding hop link
|
||||
// has a lower cost.
|
||||
cost = Min(cost, static_cast<uint8_t>(router->GetCost() + GetLinkCost(*nextHop)));
|
||||
}
|
||||
|
||||
if (!Mle::IsActiveRouter(aDestRloc16))
|
||||
{
|
||||
// Destination is a child. we assume best link quality
|
||||
// between destination and its parent router.
|
||||
cost += kCostForLinkQuality3;
|
||||
}
|
||||
|
||||
exit:
|
||||
return cost;
|
||||
}
|
||||
|
||||
uint16_t RouterTable::GetNextHop(uint16_t aDestination) const
|
||||
{
|
||||
uint8_t destinationId = Mle::RouterIdFromRloc16(aDestination);
|
||||
uint8_t routeCost;
|
||||
uint8_t linkCost;
|
||||
uint16_t rval = Mac::kShortAddrInvalid;
|
||||
const Router *router;
|
||||
const Router *nextHop;
|
||||
|
||||
if (Get<Mle::Mle>().IsChild())
|
||||
{
|
||||
const Router &parent = Get<Mle::Mle>().GetParent();
|
||||
|
||||
VerifyOrExit(parent.IsStateValid());
|
||||
ExitNow(rval = parent.GetRloc16());
|
||||
}
|
||||
|
||||
// The frame is destined to a child
|
||||
if (destinationId == Mle::RouterIdFromRloc16(Get<Mle::Mle>().GetRloc16()))
|
||||
{
|
||||
ExitNow(rval = aDestination);
|
||||
}
|
||||
|
||||
router = FindRouterById(destinationId);
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
linkCost = GetLinkCost(destinationId);
|
||||
routeCost = GetRouteCost(aDestination);
|
||||
|
||||
if ((routeCost + GetLinkCost(router->GetNextHop())) < linkCost)
|
||||
{
|
||||
nextHop = FindNextHopOf(*router);
|
||||
VerifyOrExit(nextHop != nullptr && !nextHop->IsStateInvalid());
|
||||
|
||||
rval = Mle::Rloc16FromRouterId(router->GetNextHop());
|
||||
}
|
||||
else if (linkCost < Mle::kMaxRouteCost)
|
||||
{
|
||||
rval = Mle::Rloc16FromRouterId(destinationId);
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint8_t RouterTable::GetRouteCost(uint16_t aRloc16) const
|
||||
{
|
||||
uint8_t rval = Mle::kMaxRouteCost;
|
||||
const Router *router;
|
||||
|
||||
router = FindRouterByRloc16(aRloc16);
|
||||
VerifyOrExit(router != nullptr && FindNextHopOf(*router) != nullptr);
|
||||
|
||||
rval = router->GetCost();
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
void RouterTable::UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::RouterIdSet &aRouterIdSet)
|
||||
{
|
||||
bool shouldAdd = false;
|
||||
@@ -408,6 +549,151 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RouterTable::UpdateRoutes(const Mle::RouteTlv &aRouteTlv, uint8_t aRouterId)
|
||||
{
|
||||
Router *neighbor;
|
||||
bool resetAdvInterval = false;
|
||||
bool changed = false;
|
||||
|
||||
neighbor = FindRouterById(aRouterId);
|
||||
VerifyOrExit(neighbor != nullptr);
|
||||
|
||||
// update link quality out to neighbor
|
||||
changed = UpdateLinkQualityOut(aRouteTlv, *neighbor, resetAdvInterval);
|
||||
|
||||
// update routes
|
||||
for (uint8_t routerId = 0, routeCount = 0; routerId <= Mle::kMaxRouterId; routerId++)
|
||||
{
|
||||
Router *router;
|
||||
Router *nextHop;
|
||||
uint8_t cost;
|
||||
|
||||
if (!aRouteTlv.IsRouterIdSet(routerId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
router = FindRouterById(routerId);
|
||||
|
||||
if (router == nullptr || router->GetRloc16() == Get<Mle::Mle>().GetRloc16() || router == neighbor)
|
||||
{
|
||||
routeCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
nextHop = FindNextHopOf(*router);
|
||||
|
||||
cost = aRouteTlv.GetRouteCost(routeCount);
|
||||
|
||||
if (cost == 0)
|
||||
{
|
||||
cost = Mle::kMaxRouteCost;
|
||||
}
|
||||
|
||||
if (nextHop == nullptr || nextHop == neighbor)
|
||||
{
|
||||
// router has no next hop or next hop is neighbor (sender)
|
||||
|
||||
if (cost + GetLinkCost(*neighbor) < Mle::kMaxRouteCost)
|
||||
{
|
||||
if (nextHop == nullptr && GetLinkCost(*router) >= Mle::kMaxRouteCost)
|
||||
{
|
||||
resetAdvInterval = true;
|
||||
}
|
||||
|
||||
if (router->GetNextHop() != aRouterId)
|
||||
{
|
||||
router->SetNextHop(aRouterId);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (router->GetCost() != cost)
|
||||
{
|
||||
router->SetCost(cost);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (nextHop == neighbor)
|
||||
{
|
||||
if (GetLinkCost(*router) >= Mle::kMaxRouteCost)
|
||||
{
|
||||
resetAdvInterval = true;
|
||||
}
|
||||
|
||||
router->SetNextHop(Mle::kInvalidRouterId);
|
||||
router->SetCost(0);
|
||||
router->SetLastHeard(TimerMilli::GetNow());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t curCost = router->GetCost() + GetLinkCost(*nextHop);
|
||||
uint8_t newCost = cost + GetLinkCost(*neighbor);
|
||||
|
||||
if (newCost < curCost)
|
||||
{
|
||||
router->SetNextHop(aRouterId);
|
||||
router->SetCost(cost);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
routeCount++;
|
||||
}
|
||||
|
||||
if (resetAdvInterval)
|
||||
{
|
||||
Get<Mle::MleRouter>().ResetAdvertiseInterval();
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
LogRouteTable();
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
bool RouterTable::UpdateLinkQualityOut(const Mle::RouteTlv &aRouteTlv, Router &aNeighbor, bool &aResetAdvInterval)
|
||||
{
|
||||
bool changed = false;
|
||||
LinkQuality linkQuality;
|
||||
uint8_t myRouterId;
|
||||
uint8_t myRouteCount;
|
||||
uint8_t oldLinkCost;
|
||||
Router *nextHop;
|
||||
|
||||
myRouterId = Mle::RouterIdFromRloc16(Get<Mle::Mle>().GetRloc16());
|
||||
VerifyOrExit(aRouteTlv.IsRouterIdSet(myRouterId));
|
||||
|
||||
myRouteCount = 0;
|
||||
for (uint8_t routerId = 0; routerId < myRouterId; routerId++)
|
||||
{
|
||||
myRouteCount += aRouteTlv.IsRouterIdSet(routerId);
|
||||
}
|
||||
|
||||
linkQuality = aRouteTlv.GetLinkQualityIn(myRouteCount);
|
||||
VerifyOrExit(aNeighbor.GetLinkQualityOut() != linkQuality);
|
||||
|
||||
oldLinkCost = GetLinkCost(aNeighbor);
|
||||
|
||||
aNeighbor.SetLinkQualityOut(linkQuality);
|
||||
nextHop = FindNextHopOf(aNeighbor);
|
||||
|
||||
// reset MLE advertisement timer if neighbor route cost changed to or from infinite
|
||||
if (nextHop == nullptr && (oldLinkCost >= Mle::kMaxRouteCost) != (GetLinkCost(aNeighbor) >= Mle::kMaxRouteCost))
|
||||
{
|
||||
aResetAdvInterval = true;
|
||||
}
|
||||
|
||||
changed = true;
|
||||
|
||||
exit:
|
||||
return changed;
|
||||
}
|
||||
|
||||
void RouterTable::FillRouteTlv(Mle::RouteTlv &aRouteTlv, const Neighbor *aNeighbor) const
|
||||
{
|
||||
uint8_t routerIdSequence = mRouterIdSequence;
|
||||
|
||||
@@ -144,6 +144,36 @@ public:
|
||||
*/
|
||||
uint8_t GetLinkCost(const Router &aRouter) const;
|
||||
|
||||
/**
|
||||
* This method returns the link cost to the given Router.
|
||||
*
|
||||
* @param[in] aRouterId The Router ID.
|
||||
*
|
||||
* @returns The link cost to the Router.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLinkCost(uint8_t aRouterId) const;
|
||||
|
||||
/**
|
||||
* This method returns the minimum mesh path cost to the given RLOC16
|
||||
*
|
||||
* @param[in] aDestRloc16 The RLOC16 of destination
|
||||
*
|
||||
* @returns The minimum mesh path cost to @p aDestRloc16 (via direct link or forwarding).
|
||||
*
|
||||
*/
|
||||
uint8_t GetPathCost(uint16_t aDestRloc16) const;
|
||||
|
||||
/**
|
||||
* This method returns the next hop towards an RLOC16 destination.
|
||||
*
|
||||
* @param[in] aDestination The RLOC16 of the destination.
|
||||
*
|
||||
* @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
|
||||
*
|
||||
*/
|
||||
uint16_t GetNextHop(uint16_t aDestination) const;
|
||||
|
||||
/**
|
||||
* This method finds the router for a given Router ID.
|
||||
*
|
||||
@@ -286,6 +316,15 @@ public:
|
||||
*/
|
||||
void UpdateRouterIdSet(uint8_t aRouterIdSequence, const Mle::RouterIdSet &aRouterIdSet);
|
||||
|
||||
/**
|
||||
* This method updates the routes based on a received `RouteTlv` from a neighboring router.
|
||||
*
|
||||
* @param[in] aRouteTlv The received `RouteTlv`
|
||||
* @param[in] aRouterId The router ID of neighboring router from which @p aRouteTlv is received.
|
||||
*
|
||||
*/
|
||||
void UpdateRoutes(const Mle::RouteTlv &aRouteTlv, uint8_t aRouterId);
|
||||
|
||||
/**
|
||||
* This method gets the allocated Router ID set.
|
||||
*
|
||||
@@ -371,6 +410,9 @@ private:
|
||||
return AsNonConst(AsConst(this)->FindRouter(aMatcher));
|
||||
}
|
||||
|
||||
bool UpdateLinkQualityOut(const Mle::RouteTlv &aRouteTlv, Router &aNeighbor, bool &aResetAdvInterval);
|
||||
uint8_t GetRouteCost(uint16_t aRloc16) const;
|
||||
|
||||
class RouterIdMap
|
||||
{
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user