mirror of
https://github.com/espressif/openthread.git
synced 2026-08-19 17:09:51 +00:00
[mle] introduce "gradual router link establishment" on FTD children (#11025)
This commit introduces a "gradual router link establishment" mechanism for FTD children. An FTD child device communicates through its parent but can establish links with other neighboring routers to receive multicast messages (forwarded MPL) from them, improving multicast reliability. An FTD child tries to establish links with the first `ChildRouterLinks` routers quickly (sending an MLE Link Request to initiate the link upon receiving advertisements from a neighboring router). The `ChildRouterLinks` is configurable through an OT configuration option (specifying the default value) and at run-time using the `otThreadSetChildRouterLinks()` API. After the first `ChildRouterLinks`, the "gradual router link establishment" mechanism allows `kExtraChildRouterLinks` additional router links to be established slowly over a longer time. Gradual router link establishment uses the following conditions: - The link quality to the router must be 2 or better. - It is always skipped in the first 5 minutes (`kWaitDurationAfterAttach`) after the device attaches. - The child randomly decides whether to perform/skip this (with a 5% probability). - If the child decides to send a Link Request, a longer random delay window is used ([1.5-10] seconds). Even in a dense network, if 500 FTD children receive the advertisement, with a 5% selection probability, on average, 25 nodes will try to send a Link Request randomly spread over a 1.5-10 second window. With a 5% probability, on average, it takes 20 trials (20 advertisement receptions) for an FTD child to send a Link Request. Advertisements are, on average, ~32 seconds apart, so a child will try to establish a link in approximately 10 minutes (20 * 32 = 640 seconds).
This commit is contained in:
@@ -226,11 +226,37 @@
|
||||
* @def OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS
|
||||
*
|
||||
* Specifies the desired number of router links that a REED / FED attempts to maintain.
|
||||
*
|
||||
* This is default value used on an FTD child. This parameter can also be changed at run-time using the public APIs
|
||||
* `otThreadGetChildRouterLinks/otThreadSetChildRouterLinks()`.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS
|
||||
#define OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS 3
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MLE_EXTRA_CHILD_ROUTER_LINKS_GRADUAL
|
||||
*
|
||||
* Specifies the extra router links in addition to those specified by `otThreadSetChildRouterLinks()` that an FTD child
|
||||
* can try to establish gradually over a longer span of time.
|
||||
*
|
||||
* A child device communicates through its parent but can establish links with other neighboring routers so that it can
|
||||
* receive multicast messages (forwarded MPL) from other routers, thus improving multicast reliability.
|
||||
*
|
||||
* An FTD child tries to establish links with the first `CHILD_ROUTER_LINK` routers as quickly as possible
|
||||
* (sending MLE Link Request to initiate link upon receiving advertisements from a neighboring router).
|
||||
*
|
||||
* After that, the FTD child uses the "gradual router link establishment" mechanism to establish router links with
|
||||
* `OPENTHREAD_CONFIG_MLE_EXTRA_CHILD_ROUTER_LINKS_GRADUAL` additional routers. This is done slowly and over a longer
|
||||
* span of time.
|
||||
*
|
||||
* This parameter can be set to zero to disable "gradual router link establishment" fully. Alternatively, it can be set
|
||||
* to the maximum router count of 32 to allow the FTD child to establish links with all neighboring routers.
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MLE_EXTRA_CHILD_ROUTER_LINKS_GRADUAL
|
||||
#define OPENTHREAD_CONFIG_MLE_EXTRA_CHILD_ROUTER_LINKS_GRADUAL 32
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
|
||||
*
|
||||
|
||||
@@ -1298,15 +1298,7 @@ Error MleRouter::HandleAdvertisementOnFtd(RxInfo &aRxInfo, uint16_t aSourceAddre
|
||||
router = mRouterTable.FindRouterById(routerId);
|
||||
VerifyOrExit(router != nullptr);
|
||||
|
||||
if (!router->IsStateValid() && !router->IsStateLinkRequest() &&
|
||||
(mRouterTable.GetNeighborCount(kLinkQuality1) < mChildRouterLinks))
|
||||
{
|
||||
InitNeighbor(*router, aRxInfo);
|
||||
router->SetState(Neighbor::kStateLinkRequest);
|
||||
delay = Random::NonCrypto::GetUint32InRange(kMinLinkRequestDelayOnChild, kMaxLinkRequestDelayOnChild);
|
||||
mDelayedSender.ScheduleLinkRequest(*router, delay);
|
||||
ExitNow(error = kErrorNoRoute);
|
||||
}
|
||||
EstablishRouterLinkOnFtdChild(*router, aRxInfo, linkMargin);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
|
||||
@@ -1372,6 +1364,68 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void MleRouter::EstablishRouterLinkOnFtdChild(Router &aRouter, RxInfo &aRxInfo, uint8_t aLinkMargin)
|
||||
{
|
||||
// Decide on an FTD child whether to establish a link with a
|
||||
// router upon receiving an advertisement from it.
|
||||
|
||||
uint8_t neighborCount;
|
||||
uint32_t minDelay;
|
||||
uint32_t maxDelay;
|
||||
|
||||
VerifyOrExit(!aRouter.IsStateValid() && !aRouter.IsStateLinkRequest());
|
||||
|
||||
// The first `mChildRouterLinks` are established quickly. After that,
|
||||
// the "gradual router link establishment" mechanism is used, which
|
||||
// allows `kExtraChildRouterLinks` additional router links to be
|
||||
// established, but it is done slowly and over a longer span of time.
|
||||
//
|
||||
// Gradual router link establishment conditions:
|
||||
// - The maximum `neighborCount` limit is not yet reached.
|
||||
// - We see Link Quality 2 or better.
|
||||
// - Always skipped in the first 5 minutes
|
||||
// (`kWaitDurationAfterAttach`) after the device attaches.
|
||||
// - The child randomly decides whether to perform/skip this (with a 5%
|
||||
// probability, `kProbabilityPercentage`).
|
||||
// - If the child decides to send Link Request, a longer random delay
|
||||
// window is used, [1.5-10] seconds.
|
||||
//
|
||||
// Even in a dense network, if the advertisement is received by 500 FTD
|
||||
// children with a 5% selection probability, on average, 25 nodes will
|
||||
// try to send a Link Request, which will be randomly spread over a
|
||||
// [1.5-10] second window.
|
||||
//
|
||||
// With a 5% probability, on average, it takes 20 trials (20 advertisement
|
||||
// receptions for an FTD child to send a Link Request). Advertisements
|
||||
// are, on average, ~32 seconds apart, so, on average, a child will try
|
||||
// to establish a link in `20 * 32 = 640` seconds (~10 minutes).
|
||||
|
||||
neighborCount = mRouterTable.GetNeighborCount(kLinkQuality1);
|
||||
|
||||
if (neighborCount < mChildRouterLinks)
|
||||
{
|
||||
minDelay = kMinLinkRequestDelayOnChild;
|
||||
maxDelay = kMaxLinkRequestDelayOnChild;
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(neighborCount < mChildRouterLinks + GradualChildRouterLink::kExtraChildRouterLinks);
|
||||
VerifyOrExit(LinkQualityForLinkMargin(aLinkMargin) >= kLinkQuality2);
|
||||
VerifyOrExit(GetCurrentAttachDuration() > GradualChildRouterLink::kWaitDurationAfterAttach);
|
||||
VerifyOrExit(Random::NonCrypto::GetUint8InRange(0, 100) < GradualChildRouterLink::kProbabilityPercentage);
|
||||
|
||||
minDelay = GradualChildRouterLink::kMinLinkRequestDelay;
|
||||
maxDelay = GradualChildRouterLink::kMaxLinkRequestDelay;
|
||||
}
|
||||
|
||||
InitNeighbor(aRouter, aRxInfo);
|
||||
aRouter.SetState(Neighbor::kStateLinkRequest);
|
||||
mDelayedSender.ScheduleLinkRequest(aRouter, Random::NonCrypto::GetUint32InRange(minDelay, maxDelay));
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
@@ -517,6 +517,16 @@ private:
|
||||
static constexpr uint8_t kChildRouterLinks = OPENTHREAD_CONFIG_MLE_CHILD_ROUTER_LINKS;
|
||||
static constexpr uint8_t kMaxChildIpAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD;
|
||||
|
||||
// Constants for gradual router link establishment (on FTD child)
|
||||
struct GradualChildRouterLink
|
||||
{
|
||||
static constexpr uint8_t kExtraChildRouterLinks = OPENTHREAD_CONFIG_MLE_EXTRA_CHILD_ROUTER_LINKS_GRADUAL;
|
||||
static constexpr uint32_t kWaitDurationAfterAttach = 300; // in seconds (5 minutes)
|
||||
static constexpr uint32_t kMinLinkRequestDelay = 1500; // in msec
|
||||
static constexpr uint32_t kMaxLinkRequestDelay = 10000; // in msec
|
||||
static constexpr uint32_t kProbabilityPercentage = 5; // in percent
|
||||
};
|
||||
|
||||
static constexpr uint8_t kMinCriticalChildrenCount = 6;
|
||||
|
||||
static constexpr uint16_t kChildSupervisionDefaultIntervalForOlderVersion =
|
||||
@@ -595,6 +605,7 @@ private:
|
||||
void HandleDataRequest(RxInfo &aRxInfo);
|
||||
void HandleNetworkDataUpdateRouter(void);
|
||||
void HandleDiscoveryRequest(RxInfo &aRxInfo);
|
||||
void EstablishRouterLinkOnFtdChild(Router &aRouter, RxInfo &aRxInfo, uint8_t aLinkMargin);
|
||||
Error ProcessRouteTlv(const RouteTlv &aRouteTlv, RxInfo &aRxInfo);
|
||||
Error ReadAndProcessRouteTlvOnFtdChild(RxInfo &aRxInfo, uint8_t aParentId);
|
||||
void StopAdvertiseTrickleTimer(void);
|
||||
|
||||
Reference in New Issue
Block a user