[mle] add DelayedSender class to manage delayed msg tx (#10733)

This commit introduces the `DelayedSender` nested class within `Mle`
to handle delayed MLE message transmissions, such as delayed
responses. Existing methods related to delayed message handling have
been refactored into this new class.
This commit is contained in:
Abtin Keshavarzian
2024-09-25 10:52:56 -07:00
committed by GitHub
parent 3913e0de61
commit b42be4cff1
3 changed files with 147 additions and 121 deletions
+113 -100
View File
@@ -82,12 +82,12 @@ Mle::Mle(Instance &aInstance)
#endif
, mAlternateTimestamp(0)
, mNeighborTable(aInstance)
, mDelayedSender(aInstance)
, mSocket(aInstance, *this)
#if OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
, mParentSearch(aInstance)
#endif
, mAttachTimer(aInstance)
, mDelayedResponseTimer(aInstance)
, mMessageTransmissionTimer(aInstance)
, mDetachGracefullyTimer(aInstance)
{
@@ -1563,88 +1563,6 @@ exit:
return delay;
}
void Mle::HandleDelayedResponseTimer(void)
{
NextFireTime nextSendTime;
for (Message &message : mDelayedResponses)
{
DelayedResponseMetadata metadata;
metadata.ReadFrom(message);
if (nextSendTime.GetNow() < metadata.mSendTime)
{
nextSendTime.UpdateIfEarlier(metadata.mSendTime);
}
else
{
mDelayedResponses.Dequeue(message);
SendDelayedResponse(static_cast<TxMessage &>(message), metadata);
}
}
mDelayedResponseTimer.FireAt(nextSendTime);
}
void Mle::SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata)
{
Error error = kErrorNone;
aMetadata.RemoveFrom(aMessage);
if (aMessage.GetSubType() == Message::kSubTypeMleDataRequest)
{
SuccessOrExit(error = aMessage.AppendActiveAndPendingTimestampTlvs());
}
SuccessOrExit(error = aMessage.SendTo(aMetadata.mDestination));
Log(kMessageSend, kTypeGenericDelayed, aMetadata.mDestination);
if (!IsRxOnWhenIdle())
{
// Start fast poll mode, assuming enqueued msg is MLE Data Request.
// Note: Finer-grade check may be required when deciding whether or
// not to enter fast poll mode for other type of delayed message.
Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
}
exit:
if (error != kErrorNone)
{
aMessage.Free();
}
}
void Mle::RemoveDelayedDataResponseMessage(void)
{
RemoveDelayedMessage(Message::kSubTypeMleDataResponse, kTypeDataResponse, nullptr);
}
void Mle::RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination)
{
RemoveDelayedMessage(Message::kSubTypeMleDataRequest, kTypeDataRequest, &aDestination);
}
void Mle::RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination)
{
for (Message &message : mDelayedResponses)
{
DelayedResponseMetadata metadata;
metadata.ReadFrom(message);
if ((message.GetSubType() == aSubType) &&
((aDestination == nullptr) || (metadata.mDestination == *aDestination)))
{
mDelayedResponses.DequeueAndFree(message);
Log(kMessageRemoveDelayed, aMessageType, metadata.mDestination);
}
}
}
void Mle::SendParentRequest(ParentRequestType aType)
{
Error error = kErrorNone;
@@ -1821,7 +1739,7 @@ Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlv
Error error = kErrorNone;
TxMessage *message;
RemoveDelayedDataRequestMessage(aDestination);
mDelayedSender.RemoveDataRequestMessage(aDestination);
VerifyOrExit((message = NewMleMessage(kCommandDataRequest)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->AppendTlvRequestTlv(aTlvs, aTlvsLength));
@@ -4386,9 +4304,116 @@ void Mle::TlvList::AddElementsFrom(const TlvList &aTlvList)
}
//---------------------------------------------------------------------------------------------------------------------
// DelayedResponseMetadata
// DelayedSender
void Mle::DelayedResponseMetadata::ReadFrom(const Message &aMessage)
Mle::DelayedSender::DelayedSender(Instance &aInstance)
: InstanceLocator(aInstance)
, mTimer(aInstance)
{
}
Error Mle::DelayedSender::SendMessage(TxMessage &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
{
Error error = kErrorNone;
Metadata metadata;
metadata.mSendTime = TimerMilli::GetNow() + aDelay;
metadata.mDestination = aDestination;
SuccessOrExit(error = metadata.AppendTo(aMessage));
mQueue.Enqueue(aMessage);
mTimer.FireAtIfEarlier(metadata.mSendTime);
exit:
return error;
}
void Mle::DelayedSender::HandleTimer(void)
{
NextFireTime nextSendTime;
for (Message &message : mQueue)
{
Metadata metadata;
metadata.ReadFrom(message);
if (nextSendTime.GetNow() < metadata.mSendTime)
{
nextSendTime.UpdateIfEarlier(metadata.mSendTime);
}
else
{
mQueue.Dequeue(message);
Send(static_cast<TxMessage &>(message), metadata);
}
}
mTimer.FireAt(nextSendTime);
}
void Mle::DelayedSender::Send(TxMessage &aMessage, const Metadata &aMetadata)
{
Error error = kErrorNone;
aMetadata.RemoveFrom(aMessage);
if (aMessage.GetSubType() == Message::kSubTypeMleDataRequest)
{
SuccessOrExit(error = aMessage.AppendActiveAndPendingTimestampTlvs());
}
SuccessOrExit(error = aMessage.SendTo(aMetadata.mDestination));
Log(kMessageSend, kTypeGenericDelayed, aMetadata.mDestination);
if (!Get<Mle>().IsRxOnWhenIdle())
{
// Start fast poll mode, assuming enqueued msg is MLE Data Request.
// Note: Finer-grade check may be required when deciding whether or
// not to enter fast poll mode for other type of delayed message.
Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
}
exit:
if (error != kErrorNone)
{
aMessage.Free();
}
}
void Mle::DelayedSender::RemoveDataResponseMessage(void)
{
RemoveMessage(Message::kSubTypeMleDataResponse, kTypeDataResponse, nullptr);
}
void Mle::DelayedSender::RemoveDataRequestMessage(const Ip6::Address &aDestination)
{
RemoveMessage(Message::kSubTypeMleDataRequest, kTypeDataRequest, &aDestination);
}
void Mle::DelayedSender::RemoveMessage(Message::SubType aSubType,
MessageType aMessageType,
const Ip6::Address *aDestination)
{
for (Message &message : mQueue)
{
Metadata metadata;
metadata.ReadFrom(message);
if ((message.GetSubType() == aSubType) &&
((aDestination == nullptr) || (metadata.mDestination == *aDestination)))
{
mQueue.DequeueAndFree(message);
Log(kMessageRemoveDelayed, aMessageType, metadata.mDestination);
}
}
}
void Mle::DelayedSender::Metadata::ReadFrom(const Message &aMessage)
{
uint16_t length = aMessage.GetLength();
@@ -4396,7 +4421,7 @@ void Mle::DelayedResponseMetadata::ReadFrom(const Message &aMessage)
IgnoreError(aMessage.Read(length - sizeof(*this), *this));
}
void Mle::DelayedResponseMetadata::RemoveFrom(Message &aMessage) const { aMessage.RemoveFooter(sizeof(*this)); }
void Mle::DelayedSender::Metadata::RemoveFrom(Message &aMessage) const { aMessage.RemoveFooter(sizeof(*this)); }
//---------------------------------------------------------------------------------------------------------------------
// TxMessage
@@ -4852,19 +4877,7 @@ exit:
Error Mle::TxMessage::SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay)
{
Error error = kErrorNone;
DelayedResponseMetadata metadata;
metadata.mSendTime = TimerMilli::GetNow() + aDelay;
metadata.mDestination = aDestination;
SuccessOrExit(error = metadata.AppendTo(*this));
Get<Mle>().mDelayedResponses.Enqueue(*this);
Get<Mle>().mDelayedResponseTimer.FireAtIfEarlier(metadata.mSendTime);
exit:
return error;
return Get<Mle>().mDelayedSender.SendMessage(*this, aDestination, aDelay);
}
#if OPENTHREAD_FTD
+33 -20
View File
@@ -586,12 +586,7 @@ public:
*
* @returns A reference to the send queue.
*/
const MessageQueue &GetMessageQueue(void) const { return mDelayedResponses; }
/**
* Frees multicast MLE Data Response from Delayed Message Queue if any.
*/
void RemoveDelayedDataResponseMessage(void);
const MessageQueue &GetMessageQueue(void) const { return mDelayedSender.GetQueue(); }
/**
* Gets the MLE counters.
@@ -1093,14 +1088,38 @@ private:
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct DelayedResponseMetadata
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
void RemoveFrom(Message &aMessage) const;
void HandleDelayedSenderTimer(void) { mDelayedSender.HandleTimer(); }
Ip6::Address mDestination; // IPv6 address of the message destination.
TimeMilli mSendTime; // Time when the message shall be sent.
class DelayedSender : public InstanceLocator
{
public:
explicit DelayedSender(Instance &aInstance);
Error SendMessage(TxMessage &aMessage, const Ip6::Address &aDestination, uint16_t aDelay);
void RemoveDataRequestMessage(const Ip6::Address &aDestination);
void RemoveDataResponseMessage(void);
void HandleTimer(void);
const MessageQueue &GetQueue(void) const { return mQueue; }
private:
struct Metadata
{
Error AppendTo(Message &aMessage) const { return aMessage.Append(*this); }
void ReadFrom(const Message &aMessage);
void RemoveFrom(Message &aMessage) const;
Ip6::Address mDestination;
TimeMilli mSendTime;
};
void Send(TxMessage &aMessage, const Metadata &aMetadata);
void RemoveMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination);
using DelayTimer = TimerMilliIn<Mle, &Mle::HandleDelayedSenderTimer>;
MessageQueue mQueue;
DelayTimer mTimer;
};
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1223,7 +1242,6 @@ private:
void ClearParentCandidate(void) { mParentCandidate.Clear(); }
Error SendDataRequest(const Ip6::Address &aDestination);
void HandleNotifierEvents(Events aEvents);
void SendDelayedResponse(TxMessage &aMessage, const DelayedResponseMetadata &aMetadata);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ReestablishLinkWithNeighbor(Neighbor &aNeighbor);
void HandleDetachGracefullyTimer(void);
@@ -1243,7 +1261,6 @@ private:
bool IsAnnounceAttach(void) const { return mAlternatePanId != Mac::kPanIdBroadcast; }
void ScheduleMessageTransmissionTimer(void);
void HandleAttachTimer(void);
void HandleDelayedResponseTimer(void);
void HandleMessageTransmissionTimer(void);
void ProcessKeySequence(RxInfo &aRxInfo);
void HandleAdvertisement(RxInfo &aRxInfo);
@@ -1280,8 +1297,6 @@ private:
const Ip6::MessageInfo &aMessageInfo,
uint16_t aCmdOffset,
const SecurityHeader &aHeader);
void RemoveDelayedMessage(Message::SubType aSubType, MessageType aMessageType, const Ip6::Address *aDestination);
void RemoveDelayedDataRequestMessage(const Ip6::Address &aDestination);
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
void InformPreviousParent(void);
@@ -1352,7 +1367,6 @@ private:
using DetachGracefullyTimer = TimerMilliIn<Mle, &Mle::HandleDetachGracefullyTimer>;
using AttachTimer = TimerMilliIn<Mle, &Mle::HandleAttachTimer>;
using DelayTimer = TimerMilliIn<Mle, &Mle::HandleDelayedResponseTimer>;
using MsgTxTimer = TimerMilliIn<Mle, &Mle::HandleMessageTransmissionTimer>;
using MleSocket = Ip6::Udp::SocketIn<Mle, &Mle::HandleUdpReceive>;
@@ -1402,7 +1416,7 @@ private:
LeaderData mLeaderData;
Parent mParent;
NeighborTable mNeighborTable;
MessageQueue mDelayedResponses;
DelayedSender mDelayedSender;
TxChallenge mParentRequestChallenge;
ParentCandidate mParentCandidate;
MleSocket mSocket;
@@ -1418,7 +1432,6 @@ private:
Callback<otThreadParentResponseCallback> mParentResponseCallback;
#endif
AttachTimer mAttachTimer;
DelayTimer mDelayedResponseTimer;
MsgTxTimer mMessageTransmissionTimer;
DetachGracefullyTimer mDetachGracefullyTimer;
Ip6::NetworkPrefix mMeshLocalPrefix;
+1 -1
View File
@@ -3116,7 +3116,7 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
{
Get<MeshForwarder>().RemoveDataResponseMessages();
RemoveDelayedDataResponseMessage();
mDelayedSender.RemoveDataResponseMessage();
SuccessOrExit(error = message->SendAfterDelay(aDestination, aDelay));
Log(kMessageDelay, kTypeDataResponse, aDestination);