[mle] expedite recovery from temporary router link quality mismatch (#10906)

This commit adds a mechanism to expedite recovery from temporary
router link quality mismatches. If a received `RouteTlv` (from a
received Advertisement) indicates that the neighboring router claims
no link to us by setting its `GetLinkQualityOut()` towards us as `0`,
and our two-way link quality to this router is at least Link Quality
2, we schedule a unicast MLE Advertisement to be sent to this
neighbor. This advertisement is sent after a randomly selected delay
within a one-second window using `Mle::DelayedSender`.

This helps with link recovery on the neighboring router, which
otherwise may take longer due to reliance on the next trickle
timer-triggered Advertisement transmission, which can be up to 32
seconds later and, being multicast, may be missed.
This commit is contained in:
Abtin Keshavarzian
2025-01-09 10:26:15 -08:00
committed by GitHub
parent a877341b3b
commit e7f8f75320
5 changed files with 68 additions and 10 deletions
+13
View File
@@ -4574,6 +4574,15 @@ void Mle::DelayedSender::ScheduleParentResponse(const ParentResponseInfo &aInfo,
AddSchedule(kTypeParentResponse, destination, aDelay, &aInfo, sizeof(aInfo));
}
void Mle::DelayedSender::ScheduleAdvertisement(const Ip6::Address &aDestination, uint16_t aDelay)
{
VerifyOrExit(!HasMatchingSchedule(kTypeAdvertisement, aDestination));
AddSchedule(kTypeAdvertisement, aDestination, aDelay, nullptr, 0);
exit:
return;
}
void Mle::DelayedSender::ScheduleMulticastDataResponse(uint16_t aDelay)
{
Ip6::Address destination;
@@ -4717,6 +4726,10 @@ void Mle::DelayedSender::Execute(const Schedule &aSchedule)
break;
}
case kTypeAdvertisement:
Get<MleRouter>().SendAdvertisement(header.mDestination);
break;
case kTypeDataResponse:
Get<MleRouter>().SendMulticastDataResponse();
break;
+1
View File
@@ -1139,6 +1139,7 @@ private:
void ScheduleChildUpdateRequestToParent(uint16_t aDelay);
#if OPENTHREAD_FTD
void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay);
void ScheduleAdvertisement(const Ip6::Address &aDestination, uint16_t aDelay);
void ScheduleMulticastDataResponse(uint16_t aDelay);
void ScheduleLinkRequest(const Router &aRouter, uint16_t aDelay);
void ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay);
+24 -9
View File
@@ -486,7 +486,7 @@ void MleRouter::HandleAdvertiseTrickleTimer(void)
{
VerifyOrExit(IsRouterEligible(), mAdvertiseTrickleTimer.Stop());
SendAdvertisement();
SendMulticastAdvertisement();
exit:
return;
@@ -534,11 +534,27 @@ exit:
return;
}
void MleRouter::SendAdvertisement(void)
void MleRouter::SendMulticastAdvertisement(void)
{
Error error = kErrorNone;
Ip6::Address destination;
TxMessage *message = nullptr;
destination.SetToLinkLocalAllNodesMulticast();
SendAdvertisement(destination);
}
void MleRouter::ScheduleUnicastAdvertisementTo(const Router &aRouter)
{
Ip6::Address destination;
destination.SetToLinkLocalAddress(aRouter.GetExtAddress());
mDelayedSender.ScheduleAdvertisement(destination,
Random::NonCrypto::GetUint32InRange(0, kMaxUnicastAdvertisementDelay));
}
void MleRouter::SendAdvertisement(const Ip6::Address &aDestination)
{
Error error = kErrorNone;
TxMessage *message = nullptr;
// Suppress MLE Advertisements when trying to attach to a better
// partition. Without this, a candidate parent might incorrectly
@@ -574,10 +590,9 @@ void MleRouter::SendAdvertisement(void)
OT_ASSERT(false);
}
destination.SetToLinkLocalAllNodesMulticast();
SuccessOrExit(error = message->SendTo(destination));
SuccessOrExit(error = message->SendTo(aDestination));
Log(kMessageSend, kTypeAdvertisement, destination);
Log(kMessageSend, kTypeAdvertisement, aDestination);
exit:
FreeMessageOnError(message, error);
@@ -1604,7 +1619,7 @@ void MleRouter::HandleTimeTick(void)
if (!mAdvertiseTrickleTimer.IsRunning())
{
SendAdvertisement();
SendMulticastAdvertisement();
mAdvertiseTrickleTimer.Start(TrickleTimer::kModePlainTimer, kReedAdvIntervalMin, kReedAdvIntervalMax);
}
@@ -3464,7 +3479,7 @@ void MleRouter::HandleAddressSolicitResponse(Coap::Message *aMessage,
// up the dissemination of the new Router ID to other routers.
// This can also help with quicker link establishment with our
// former parent and other routers.
SendAdvertisement();
SendMulticastAdvertisement();
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateChildIdRequest))
{
+11 -1
View File
@@ -362,6 +362,14 @@ public:
*/
void FillConnectivityTlv(ConnectivityTlv &aTlv);
/**
* Schedule tx of MLE Advertisement message (unicast) to the given neighboring router after a random delay.
*
* @param[in] aRouter The router to send the Advertisement to.
*
*/
void ScheduleUnicastAdvertisementTo(const Router &aRouter);
#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE
/**
* Sets steering data out of band
@@ -494,6 +502,7 @@ private:
static constexpr uint32_t kAdvIntervalMaxLogRoutes = 5000;
#endif
static constexpr uint32_t kMaxUnicastAdvertisementDelay = 1000; // Max random delay for unciast Adv tx
static constexpr uint32_t kMaxNeighborAge = 100000; // Max neighbor age (in msec)
static constexpr uint32_t kMaxLeaderToRouterTimeout = 90000; // (in msec)
static constexpr uint8_t kMinDowngradeNeighbors = 7;
@@ -616,7 +625,8 @@ private:
const Router *aRouter,
const Ip6::MessageInfo &aMessageInfo);
void SendAddressRelease(void);
void SendAdvertisement(void);
void SendMulticastAdvertisement(void);
void SendAdvertisement(const Ip6::Address &aDestination);
void SendLinkRequest(Router *aRouter);
Error SendLinkAccept(const LinkAcceptInfo &aInfo);
void SendParentResponse(const ParentResponseInfo &aInfo);
+19
View File
@@ -596,6 +596,25 @@ void RouterTable::UpdateRoutes(const Mle::RouteTlv &aRouteTlv, uint8_t aNeighbor
neighbor->SetLinkQualityOut(linkQuality);
SignalTableChanged();
}
// If the `aRouteTlv` indicates that the neighboring
// router claims to have no link to us (by setting its
// `GetLinkQualityOut()` towards us as `kLinkQuality0`),
// and we have previously established a link with it, and
// our two-way link quality to this router is at least
// `kLinkQuality2`, we schedule a unicast Advertisement to
// be sent to this neighbor. This helps expedite recovery
// from any temporary router link quality mismatch.
// Otherwise, the neighboring router will continue to
// advertise that it has no link to us until our next
// trickle timer-triggered Advertisement transmission
// (which can be up to 32 seconds later).
if (neighbor->IsStateValid() && (aRouteTlv.GetLinkQualityOut(index) == kLinkQuality0) &&
(neighbor->GetTwoWayLinkQuality() >= kLinkQuality2))
{
Get<Mle::MleRouter>().ScheduleUnicastAdvertisementTo(*neighbor);
}
}
break;