mirror of
https://github.com/espressif/openthread.git
synced 2026-09-06 17:20:09 +00:00
Separate route cost from link cost to allow routing when the link is lost. (#1187)
This commit is contained in:
@@ -1254,15 +1254,27 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
// initialize Mesh header
|
||||
if (mAddMeshHeader)
|
||||
{
|
||||
// Calculate the number of predicted hops.
|
||||
hopsLeft = mNetif.GetMle().GetRouteCost(mMeshDest);
|
||||
hopsLeft += mNetif.GetMle().GetLinkCost(mNetif.GetMle().GetRouterId(mNetif.GetMle().GetNextHop(mMeshDest)));
|
||||
|
||||
// The hopsLft field MUST be incremented by one if the device is not
|
||||
// an active Router.
|
||||
if (!mNetif.GetMle().IsActiveRouter(mMeshSource))
|
||||
if (mNetif.GetMle().GetDeviceState() == Mle::kDeviceStateChild)
|
||||
{
|
||||
hopsLeft += 1;
|
||||
// REED sets hopsLeft to max (16) + 1. It does not know the route cost.
|
||||
hopsLeft = Mle::kMaxRouteCost + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate the number of predicted hops.
|
||||
hopsLeft = mNetif.GetMle().GetRouteCost(mMeshDest);
|
||||
|
||||
if (hopsLeft != Mle::kMaxRouteCost)
|
||||
{
|
||||
hopsLeft += mNetif.GetMle().GetLinkCost(
|
||||
mNetif.GetMle().GetRouterId(mNetif.GetMle().GetNextHop(mMeshDest)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// In case there is no route to the destination router (only link).
|
||||
hopsLeft = mNetif.GetMle().GetLinkCost(mNetif.GetMle().GetRouterId(mMeshDest));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The hopsLft field MUST be incremented by one if the destination RLOC16
|
||||
|
||||
@@ -988,7 +988,6 @@ ThreadError MleRouter::HandleLinkAccept(const Message &aMessage, const Ip6::Mess
|
||||
// update routing table
|
||||
if (routerId != mRouterId && !IsRouterIdValid(router->mNextHop))
|
||||
{
|
||||
router->mNextHop = routerId;
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
|
||||
@@ -1404,10 +1403,12 @@ ThreadError MleRouter::HandleAdvertisement(const Message &aMessage, const Ip6::M
|
||||
if (route.GetRouteCost(routeCount) > 0)
|
||||
{
|
||||
mRouters[GetLeaderId()].mNextHop = routerId;
|
||||
mRouters[GetLeaderId()].mCost = route.GetRouteCost(routeCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
mRouters[GetLeaderId()].mNextHop = kInvalidRouterId;
|
||||
mRouters[GetLeaderId()].mCost = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1542,35 +1543,31 @@ void MleRouter::UpdateRoutes(const RouteTlv &aRoute, uint8_t aRouterId)
|
||||
|
||||
if (!IsRouterIdValid(mRouters[i].mNextHop) || mRouters[i].mNextHop == aRouterId)
|
||||
{
|
||||
// route has no nexthop or nexthop is neighbor
|
||||
newCost = cost + GetLinkCost(aRouterId);
|
||||
// route has no nexthop or nexthop is neighbor (sender)
|
||||
|
||||
if (i == aRouterId)
|
||||
if (i != aRouterId)
|
||||
{
|
||||
if (!IsRouterIdValid(mRouters[i].mNextHop))
|
||||
if (cost + GetLinkCost(aRouterId) <= kMaxRouteCost)
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
if (!IsRouterIdValid(mRouters[i].mNextHop) && GetLinkCost(i) >= kMaxRouteCost)
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
|
||||
mRouters[i].mNextHop = aRouterId;
|
||||
mRouters[i].mCost = 0;
|
||||
}
|
||||
else if (newCost <= kMaxRouteCost)
|
||||
{
|
||||
if (!IsRouterIdValid(mRouters[i].mNextHop))
|
||||
mRouters[i].mNextHop = aRouterId;
|
||||
mRouters[i].mCost = cost;
|
||||
}
|
||||
else if (mRouters[i].mNextHop == aRouterId)
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
if (GetLinkCost(i) >= kMaxRouteCost)
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
|
||||
mRouters[i].mNextHop = aRouterId;
|
||||
mRouters[i].mCost = cost;
|
||||
}
|
||||
else if (IsRouterIdValid(mRouters[i].mNextHop))
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
mRouters[i].mNextHop = kInvalidRouterId;
|
||||
mRouters[i].mCost = 0;
|
||||
mRouters[i].mLastHeard = Timer::GetNow();
|
||||
mRouters[i].mNextHop = kInvalidRouterId;
|
||||
mRouters[i].mCost = 0;
|
||||
mRouters[i].mLastHeard = Timer::GetNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1578,7 +1575,7 @@ void MleRouter::UpdateRoutes(const RouteTlv &aRoute, uint8_t aRouterId)
|
||||
curCost = mRouters[i].mCost + GetLinkCost(mRouters[i].mNextHop);
|
||||
newCost = cost + GetLinkCost(aRouterId);
|
||||
|
||||
if (newCost < curCost || (newCost == curCost && i == aRouterId))
|
||||
if (newCost < curCost && i != aRouterId)
|
||||
{
|
||||
mRouters[i].mNextHop = aRouterId;
|
||||
mRouters[i].mCost = cost;
|
||||
@@ -1637,7 +1634,11 @@ ThreadError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::M
|
||||
VerifyOrExit(GetLeaderAge() < mNetworkIdTimeout, error = kThreadError_Drop);
|
||||
|
||||
// 3. Its current routing path cost to the Leader is infinite.
|
||||
VerifyOrExit(IsRouterIdValid(mRouters[GetLeaderId()].mNextHop), error = kThreadError_Drop);
|
||||
VerifyOrExit(GetDeviceState() == kDeviceStateLeader ||
|
||||
GetLinkCost(GetLeaderId()) < kMaxRouteCost ||
|
||||
(GetDeviceState() == kDeviceStateChild && mRouters[GetLeaderId()].mCost + 1 < kMaxRouteCost) ||
|
||||
(mRouters[GetLeaderId()].mCost + GetLinkCost(mRouters[GetLeaderId()].mNextHop) < kMaxRouteCost),
|
||||
error = kThreadError_Drop);
|
||||
|
||||
macAddr.Set(aMessageInfo.GetPeerAddr());
|
||||
|
||||
@@ -1808,9 +1809,13 @@ void MleRouter::HandleStateUpdateTimer(void)
|
||||
{
|
||||
mRouters[i].mState = Neighbor::kStateInvalid;
|
||||
mRouters[i].mLinkInfo.Clear();
|
||||
mRouters[i].mNextHop = kInvalidRouterId;
|
||||
mRouters[i].mLinkQualityOut = 0;
|
||||
mRouters[i].mLastHeard = Timer::GetNow();
|
||||
|
||||
if (mRouters[i].mNextHop == kInvalidRouterId)
|
||||
{
|
||||
ResetAdvertiseInterval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1819,6 +1824,7 @@ void MleRouter::HandleStateUpdateTimer(void)
|
||||
if (mRouters[i].mAllocated)
|
||||
{
|
||||
if (!IsRouterIdValid(mRouters[i].mNextHop) &&
|
||||
GetLinkCost(i) >= kMaxRouteCost &&
|
||||
(Timer::GetNow() - mRouters[i].mLastHeard) >= Timer::SecToMsec(kMaxLeaderToRouterTimeout))
|
||||
{
|
||||
ReleaseRouterId(i);
|
||||
@@ -3209,23 +3215,43 @@ exit:
|
||||
return rval;
|
||||
}
|
||||
|
||||
uint16_t MleRouter::GetNextHop(uint16_t aDestination) const
|
||||
uint16_t MleRouter::GetNextHop(uint16_t aDestination)
|
||||
{
|
||||
uint8_t destinationId = GetRouterId(aDestination);
|
||||
uint8_t routeCost;
|
||||
uint8_t linkCost;
|
||||
uint16_t rval = Mac::kShortAddrInvalid;
|
||||
const Router *router;
|
||||
const Router *nextHop;
|
||||
|
||||
if (mDeviceState == kDeviceStateChild)
|
||||
{
|
||||
ExitNow(rval = Mle::GetNextHop(aDestination));
|
||||
}
|
||||
|
||||
router = GetRouter(GetRouterId(aDestination));
|
||||
// The frame is destined to a child
|
||||
if (destinationId == mRouterId)
|
||||
{
|
||||
ExitNow(rval = aDestination);
|
||||
}
|
||||
|
||||
router = GetRouter(destinationId);
|
||||
VerifyOrExit(router != NULL,);
|
||||
|
||||
router = GetRouter(router->mNextHop);
|
||||
VerifyOrExit(router != NULL && router->mState != Neighbor::kStateInvalid,);
|
||||
linkCost = GetLinkCost(destinationId);
|
||||
routeCost = GetRouteCost(aDestination);
|
||||
|
||||
rval = GetRloc16(router->mNextHop);
|
||||
if ((routeCost + GetLinkCost(router->mNextHop)) < linkCost)
|
||||
{
|
||||
nextHop = GetRouter(router->mNextHop);
|
||||
VerifyOrExit(nextHop != NULL && nextHop->mState != Neighbor::kStateInvalid,);
|
||||
|
||||
rval = GetRloc16(router->mNextHop);
|
||||
}
|
||||
else if (linkCost < kMaxRouteCost)
|
||||
{
|
||||
rval = GetRloc16(destinationId);
|
||||
}
|
||||
|
||||
exit:
|
||||
return rval;
|
||||
@@ -4088,6 +4114,12 @@ void MleRouter::FillConnectivityTlv(ConnectivityTlv &aTlv)
|
||||
|
||||
case kDeviceStateRouter:
|
||||
cost += GetLinkCost(mRouters[GetLeaderId()].mNextHop);
|
||||
|
||||
if (!IsRouterIdValid(mRouters[GetLeaderId()].mNextHop) || GetLinkCost(GetLeaderId()) < cost)
|
||||
{
|
||||
cost = GetLinkCost(GetLeaderId());
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case kDeviceStateLeader:
|
||||
@@ -4198,6 +4230,7 @@ exit:
|
||||
void MleRouter::FillRouteTlv(RouteTlv &tlv)
|
||||
{
|
||||
uint8_t routeCount = 0;
|
||||
uint8_t linkCost;
|
||||
uint8_t cost;
|
||||
|
||||
tlv.SetRouterIdSequence(mRouterIdSequence);
|
||||
@@ -4220,20 +4253,27 @@ void MleRouter::FillRouteTlv(RouteTlv &tlv)
|
||||
}
|
||||
else
|
||||
{
|
||||
linkCost = GetLinkCost(i);
|
||||
|
||||
if (!IsRouterIdValid(mRouters[i].mNextHop))
|
||||
{
|
||||
cost = 0;
|
||||
cost = linkCost;
|
||||
}
|
||||
else
|
||||
{
|
||||
cost = mRouters[i].mCost + GetLinkCost(mRouters[i].mNextHop);
|
||||
|
||||
if (cost >= kMaxRouteCost)
|
||||
if (linkCost < cost)
|
||||
{
|
||||
cost = 0;
|
||||
cost = linkCost;
|
||||
}
|
||||
}
|
||||
|
||||
if (cost >= kMaxRouteCost)
|
||||
{
|
||||
cost = 0;
|
||||
}
|
||||
|
||||
tlv.SetRouteCost(routeCount, cost);
|
||||
tlv.SetLinkQualityOut(routeCount, mRouters[i].mLinkQualityOut);
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ public:
|
||||
* @returns A RLOC16 of the next hop if a route is known, kInvalidRloc16 otherwise.
|
||||
*
|
||||
*/
|
||||
uint16_t GetNextHop(uint16_t aDestination) const;
|
||||
uint16_t GetNextHop(uint16_t aDestination);
|
||||
|
||||
/**
|
||||
* This method returns the NETWORK_ID_TIMEOUT value.
|
||||
|
||||
@@ -123,7 +123,7 @@ class Router : public Neighbor
|
||||
public:
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user