mirror of
https://github.com/espressif/openthread.git
synced 2026-09-05 16:50:05 +00:00
[mle] use DelayedSender to delay & aggregate Child Update Requests (#10853)
This commit refines the Child Update Request mechanism within the MLE module. The `DelayedSender` class is now used to schedule these requests, enabling the aggregation of multiple updates into a single transmission. The previous implementation, which relied on `mMessageTransmissionTimer` and a state variable, has been replaced with the `DelayedSender` mechanism. This change aligns the Child Update Request process with the scheduling of other MLE messages, ensuring consistency. Additionally, the `mMessageTransmissionTimer` is now exclusively dedicated to retransmission handling, simplifying the logic and improving code readability. The introduction of two boolean variables, `mWaitingForChildUpdateResponse` and `mWaitingForDataResponse`, further streamlines retransmission handling by clearly tracking the waiting state for specific responses.
This commit is contained in:
committed by
Jonathan Hui
parent
169ac65e93
commit
bf6d74d098
+47
-54
@@ -53,15 +53,15 @@ Mle::Mle(Instance &aInstance)
|
||||
, mReceivedResponseFromParent(false)
|
||||
, mDetachingGracefully(false)
|
||||
, mInitiallyAttachedAsSleepy(false)
|
||||
, mWaitingForChildUpdateResponse(false)
|
||||
, mWaitingForDataResponse(false)
|
||||
, mRole(kRoleDisabled)
|
||||
, mLastSavedRole(kRoleDisabled)
|
||||
, mDeviceMode(DeviceMode::kModeRxOnWhenIdle)
|
||||
, mAttachState(kAttachStateIdle)
|
||||
, mReattachState(kReattachStop)
|
||||
, mAttachMode(kAnyPartition)
|
||||
, mDataRequestState(kDataRequestNone)
|
||||
, mAddressRegistrationMode(kAppendAllAddresses)
|
||||
, mChildUpdateRequestState(kChildUpdateRequestNone)
|
||||
, mParentRequestCounter(0)
|
||||
, mChildUpdateAttempts(0)
|
||||
, mDataRequestAttempts(0)
|
||||
@@ -134,11 +134,7 @@ exit:
|
||||
|
||||
void Mle::ScheduleChildUpdateRequest(void)
|
||||
{
|
||||
if (mChildUpdateRequestState != kChildUpdateRequestPending)
|
||||
{
|
||||
mChildUpdateRequestState = kChildUpdateRequestPending;
|
||||
ScheduleMessageTransmissionTimer();
|
||||
}
|
||||
mDelayedSender.ScheduleChildUpdateRequestToParent(kChildUpdateRequestDelay);
|
||||
}
|
||||
|
||||
Error Mle::Disable(void)
|
||||
@@ -685,12 +681,13 @@ void Mle::SetStateDetached(void)
|
||||
SetRole(kRoleDetached);
|
||||
SetAttachState(kAttachStateIdle);
|
||||
mAttachTimer.Stop();
|
||||
mDelayedSender.RemoveScheduledChildUpdateRequestToParent();
|
||||
mMessageTransmissionTimer.Stop();
|
||||
mChildUpdateRequestState = kChildUpdateRequestNone;
|
||||
mChildUpdateAttempts = 0;
|
||||
mDataRequestState = kDataRequestNone;
|
||||
mDataRequestAttempts = 0;
|
||||
mInitiallyAttachedAsSleepy = false;
|
||||
mWaitingForChildUpdateResponse = false;
|
||||
mChildUpdateAttempts = 0;
|
||||
mWaitingForDataResponse = false;
|
||||
mDataRequestAttempts = 0;
|
||||
mInitiallyAttachedAsSleepy = false;
|
||||
Get<MeshForwarder>().SetRxOnWhenIdle(true);
|
||||
Get<Mac::Mac>().SetBeaconEnabled(false);
|
||||
#if OPENTHREAD_FTD
|
||||
@@ -1752,9 +1749,9 @@ Error Mle::SendDataRequest(const Ip6::Address &aDestination)
|
||||
|
||||
if (IsChild() && !IsRxOnWhenIdle())
|
||||
{
|
||||
mDataRequestState = kDataRequestActive;
|
||||
mWaitingForDataResponse = true;
|
||||
|
||||
if (mChildUpdateRequestState == kChildUpdateRequestNone)
|
||||
if (!mWaitingForChildUpdateResponse)
|
||||
{
|
||||
ScheduleMessageTransmissionTimer();
|
||||
}
|
||||
@@ -1813,15 +1810,8 @@ void Mle::ScheduleMessageTransmissionTimer(void)
|
||||
{
|
||||
uint32_t interval = 0;
|
||||
|
||||
switch (mChildUpdateRequestState)
|
||||
if (mWaitingForChildUpdateResponse)
|
||||
{
|
||||
case kChildUpdateRequestNone:
|
||||
break;
|
||||
|
||||
case kChildUpdateRequestPending:
|
||||
ExitNow(interval = kChildUpdateRequestPendingDelay);
|
||||
|
||||
case kChildUpdateRequestActive:
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
|
||||
if (Get<Mac::Mac>().IsCslEnabled())
|
||||
{
|
||||
@@ -1834,12 +1824,8 @@ void Mle::ScheduleMessageTransmissionTimer(void)
|
||||
}
|
||||
}
|
||||
|
||||
switch (mDataRequestState)
|
||||
if (mWaitingForDataResponse)
|
||||
{
|
||||
case kDataRequestNone:
|
||||
break;
|
||||
|
||||
case kDataRequestActive:
|
||||
ExitNow(interval = kUnicastRetxDelay);
|
||||
}
|
||||
|
||||
@@ -1863,15 +1849,13 @@ void Mle::HandleMessageTransmissionTimer(void)
|
||||
{
|
||||
// The `mMessageTransmissionTimer` is used for:
|
||||
//
|
||||
// - Delaying kEvent notification triggered "Child Update Request" transmission (to allow aggregation),
|
||||
// - Retransmission of "Child Update Request",
|
||||
// - Retransmission of "Data Request" on a child,
|
||||
// - Sending periodic keep-alive "Child Update Request" messages on a non-sleepy (rx-on) child.
|
||||
|
||||
switch (mChildUpdateRequestState)
|
||||
if (!mWaitingForChildUpdateResponse)
|
||||
{
|
||||
case kChildUpdateRequestNone:
|
||||
if (mDataRequestState == kDataRequestActive)
|
||||
if (mWaitingForDataResponse)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
|
||||
@@ -1889,22 +1873,6 @@ void Mle::HandleMessageTransmissionTimer(void)
|
||||
|
||||
// Keep-alive "Child Update Request" only on a non-sleepy child
|
||||
VerifyOrExit(IsChild() && IsRxOnWhenIdle());
|
||||
break;
|
||||
|
||||
case kChildUpdateRequestPending:
|
||||
if (Get<Notifier>().IsPending())
|
||||
{
|
||||
// Add another delay to ensures the Child Update Request is sent
|
||||
// only after all pending changes are incorporated.
|
||||
ScheduleMessageTransmissionTimer();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mChildUpdateAttempts = 0;
|
||||
break;
|
||||
|
||||
case kChildUpdateRequestActive:
|
||||
break;
|
||||
}
|
||||
|
||||
VerifyOrExit(mChildUpdateAttempts < kMaxChildKeepAliveAttempts, IgnoreError(BecomeDetached()));
|
||||
@@ -1938,7 +1906,8 @@ Error Mle::SendChildUpdateRequestToParent(ChildUpdateRequestMode aMode)
|
||||
{
|
||||
// Enable MLE retransmissions on all Child Update Request
|
||||
// messages, except when actively detaching.
|
||||
mChildUpdateRequestState = kChildUpdateRequestActive;
|
||||
mWaitingForChildUpdateResponse = true;
|
||||
mDelayedSender.RemoveScheduledChildUpdateRequestToParent();
|
||||
ScheduleMessageTransmissionTimer();
|
||||
}
|
||||
|
||||
@@ -2743,7 +2712,7 @@ void Mle::HandleDataResponse(RxInfo &aRxInfo)
|
||||
|
||||
error = HandleLeaderData(aRxInfo);
|
||||
|
||||
if (mDataRequestState == kDataRequestNone && !IsRxOnWhenIdle())
|
||||
if (!mWaitingForDataResponse && !IsRxOnWhenIdle())
|
||||
{
|
||||
// Stop fast data poll request by MLE since we received
|
||||
// the response.
|
||||
@@ -2903,8 +2872,8 @@ exit:
|
||||
}
|
||||
else if (error == kErrorNone)
|
||||
{
|
||||
mDataRequestAttempts = 0;
|
||||
mDataRequestState = kDataRequestNone;
|
||||
mDataRequestAttempts = 0;
|
||||
mWaitingForDataResponse = false;
|
||||
|
||||
// Here the `mMessageTransmissionTimer` is intentionally not canceled
|
||||
// so that when it fires from its callback a "Child Update" is sent
|
||||
@@ -3560,10 +3529,10 @@ exit:
|
||||
|
||||
if (error == kErrorNone)
|
||||
{
|
||||
if (mChildUpdateRequestState == kChildUpdateRequestActive)
|
||||
if (mWaitingForChildUpdateResponse)
|
||||
{
|
||||
mChildUpdateAttempts = 0;
|
||||
mChildUpdateRequestState = kChildUpdateRequestNone;
|
||||
mChildUpdateAttempts = 0;
|
||||
mWaitingForChildUpdateResponse = false;
|
||||
ScheduleMessageTransmissionTimer();
|
||||
}
|
||||
}
|
||||
@@ -4331,6 +4300,26 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::ScheduleChildUpdateRequestToParent(uint16_t aDelay)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
|
||||
destination.SetToLinkLocalAddress(Get<Mle>().mParent.GetExtAddress());
|
||||
VerifyOrExit(!HasMatchingSchedule(kTypeChildUpdateRequestAsChild, destination));
|
||||
AddSchedule(kTypeChildUpdateRequestAsChild, destination, aDelay, nullptr, 0);
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::RemoveScheduledChildUpdateRequestToParent(void)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
|
||||
destination.SetToLinkLocalAddress(Get<Mle>().mParent.GetExtAddress());
|
||||
RemoveMatchingSchedules(kTypeChildUpdateRequestAsChild, destination);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
void Mle::DelayedSender::ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay)
|
||||
@@ -4449,6 +4438,10 @@ void Mle::DelayedSender::Execute(const Schedule &aSchedule)
|
||||
IgnoreError(Get<Mle>().SendDataRequest(header.mDestination));
|
||||
break;
|
||||
|
||||
case kTypeChildUpdateRequestAsChild:
|
||||
IgnoreError(Get<Mle>().SendChildUpdateRequestToParent());
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
case kTypeParentResponse:
|
||||
{
|
||||
|
||||
+24
-34
@@ -731,25 +731,25 @@ private:
|
||||
// Constants
|
||||
|
||||
// All time intervals are in milliseconds
|
||||
static constexpr uint32_t kParentRequestRouterTimeout = 750; // Wait time after tx of Parent Req to routers
|
||||
static constexpr uint32_t kParentRequestReedTimeout = 1250; // Wait timer after tx of Parent Req to REEDs
|
||||
static constexpr uint32_t kParentRequestDuplicateMargin = 50; // Margin to detect duplicate received Parent Req
|
||||
static constexpr uint32_t kChildIdResponseTimeout = 1250; // Wait time to receive Child ID Response
|
||||
static constexpr uint32_t kAttachStartJitter = 50; // Max jitter time added to start of attach
|
||||
static constexpr uint32_t kAnnounceProcessTimeout = 250; // Delay after Announce rx before processing
|
||||
static constexpr uint32_t kAnnounceTimeout = 1400; // Total timeout for sending Announce messages
|
||||
static constexpr uint16_t kMinAnnounceDelay = 80; // Min delay between Announcement messages
|
||||
static constexpr uint32_t kParentResponseMaxDelayRouters = 500; // Max response delay for Parent Req to routers
|
||||
static constexpr uint32_t kParentResponseMaxDelayAll = 1000; // Max response delay for Parent Req to all
|
||||
static constexpr uint32_t kChildUpdateRequestPendingDelay = 100; // Delay for aggregating Child Update Req
|
||||
static constexpr uint32_t kMaxLinkAcceptDelay = 1000; // Max delay to tx Link Accept for multicast Req
|
||||
static constexpr uint32_t kChildIdRequestTimeout = 5000; // Max delay to rx a Child ID Req after Parent Res
|
||||
static constexpr uint32_t kLinkRequestTimeout = 2000; // Max delay to rx a Link Accept
|
||||
static constexpr uint32_t kDetachGracefullyTimeout = 1000; // Timeout for graceful detach
|
||||
static constexpr uint32_t kUnicastRetxDelay = 1000; // Base delay for MLE unicast retx
|
||||
static constexpr uint32_t kMulticastRetxDelay = 5000; // Base delay for MLE multicast retx
|
||||
static constexpr uint32_t kMulticastRetxDelayMin = kMulticastRetxDelay * 9 / 10; // 0.9 * base delay
|
||||
static constexpr uint32_t kMulticastRetxDelayMax = kMulticastRetxDelay * 11 / 10; // 1.1 * base delay
|
||||
static constexpr uint32_t kParentRequestRouterTimeout = 750; // Wait time after tx of Parent Req to routers
|
||||
static constexpr uint32_t kParentRequestReedTimeout = 1250; // Wait timer after tx of Parent Req to REEDs
|
||||
static constexpr uint32_t kParentRequestDuplicateMargin = 50; // Margin to detect duplicate received Parent Req
|
||||
static constexpr uint32_t kChildIdResponseTimeout = 1250; // Wait time to receive Child ID Response
|
||||
static constexpr uint32_t kAttachStartJitter = 50; // Max jitter time added to start of attach
|
||||
static constexpr uint32_t kAnnounceProcessTimeout = 250; // Delay after Announce rx before processing
|
||||
static constexpr uint32_t kAnnounceTimeout = 1400; // Total timeout for sending Announce messages
|
||||
static constexpr uint16_t kMinAnnounceDelay = 80; // Min delay between Announcement messages
|
||||
static constexpr uint32_t kParentResponseMaxDelayRouters = 500; // Max response delay for Parent Req to routers
|
||||
static constexpr uint32_t kParentResponseMaxDelayAll = 1000; // Max response delay for Parent Req to all
|
||||
static constexpr uint32_t kChildUpdateRequestDelay = 100; // Delay for aggregating Child Update Req
|
||||
static constexpr uint32_t kMaxLinkAcceptDelay = 1000; // Max delay to tx Link Accept for multicast Req
|
||||
static constexpr uint32_t kChildIdRequestTimeout = 5000; // Max delay to rx a Child ID Req after Parent Res
|
||||
static constexpr uint32_t kLinkRequestTimeout = 2000; // Max delay to rx a Link Accept
|
||||
static constexpr uint32_t kDetachGracefullyTimeout = 1000; // Timeout for graceful detach
|
||||
static constexpr uint32_t kUnicastRetxDelay = 1000; // Base delay for MLE unicast retx
|
||||
static constexpr uint32_t kMulticastRetxDelay = 5000; // Base delay for MLE multicast retx
|
||||
static constexpr uint32_t kMulticastRetxDelayMin = kMulticastRetxDelay * 9 / 10; // 0.9 * base delay
|
||||
static constexpr uint32_t kMulticastRetxDelayMax = kMulticastRetxDelay * 11 / 10; // 1.1 * base delay
|
||||
static constexpr uint32_t kAnnounceBackoffForPendingDataset = 60000; // Max delay left to block Announce processing.
|
||||
|
||||
static constexpr uint8_t kMaxTxCount = 3; // Max tx count for MLE message
|
||||
@@ -859,13 +859,6 @@ private:
|
||||
kToRoutersAndReeds, // Parent Request to all routers and REEDs.
|
||||
};
|
||||
|
||||
enum ChildUpdateRequestState : uint8_t
|
||||
{
|
||||
kChildUpdateRequestNone, // No pending or active Child Update Request.
|
||||
kChildUpdateRequestPending, // Pending Child Update Request due to relative OT_CHANGED event.
|
||||
kChildUpdateRequestActive, // Child Update Request has been sent and Child Update Response is expected.
|
||||
};
|
||||
|
||||
enum ChildUpdateRequestMode : uint8_t // Used in `SendChildUpdateRequest()`
|
||||
{
|
||||
kNormalChildUpdateRequest, // Normal Child Update Request.
|
||||
@@ -873,12 +866,6 @@ private:
|
||||
kAppendZeroTimeout, // Use zero timeout when appending Timeout TLV (used for graceful detach).
|
||||
};
|
||||
|
||||
enum DataRequestState : uint8_t
|
||||
{
|
||||
kDataRequestNone, // Not waiting for a Data Response.
|
||||
kDataRequestActive, // Data Request has been sent, Data Response is expected.
|
||||
};
|
||||
|
||||
enum SecuritySuite : uint8_t
|
||||
{
|
||||
k154Security = 0, // Security suite value indicating that MLE message is not secured.
|
||||
@@ -1108,6 +1095,7 @@ private:
|
||||
void Stop(void);
|
||||
|
||||
void ScheduleDataRequest(const Ip6::Address &aDestination, uint16_t aDelay);
|
||||
void ScheduleChildUpdateRequestToParent(uint16_t aDelay);
|
||||
#if OPENTHREAD_FTD
|
||||
void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay);
|
||||
void ScheduleMulticastDataResponse(uint16_t aDelay);
|
||||
@@ -1116,6 +1104,8 @@ private:
|
||||
const DiscoveryResponseInfo &aInfo,
|
||||
uint16_t aDelay);
|
||||
#endif
|
||||
void RemoveScheduledChildUpdateRequestToParent(void);
|
||||
|
||||
void HandleTimer(void);
|
||||
const MessageQueue &GetQueue(void) const { return mSchedules; }
|
||||
|
||||
@@ -1398,6 +1388,8 @@ private:
|
||||
bool mReceivedResponseFromParent : 1;
|
||||
bool mDetachingGracefully : 1;
|
||||
bool mInitiallyAttachedAsSleepy : 1;
|
||||
bool mWaitingForChildUpdateResponse : 1;
|
||||
bool mWaitingForDataResponse : 1;
|
||||
|
||||
DeviceRole mRole;
|
||||
DeviceRole mLastSavedRole;
|
||||
@@ -1405,9 +1397,7 @@ private:
|
||||
AttachState mAttachState;
|
||||
ReattachState mReattachState;
|
||||
AttachMode mAttachMode;
|
||||
DataRequestState mDataRequestState;
|
||||
AddressRegistrationMode mAddressRegistrationMode;
|
||||
ChildUpdateRequestState mChildUpdateRequestState;
|
||||
|
||||
uint8_t mParentRequestCounter;
|
||||
uint8_t mChildUpdateAttempts;
|
||||
|
||||
Reference in New Issue
Block a user