mirror of
https://github.com/espressif/openthread.git
synced 2026-08-18 16:39:52 +00:00
[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:
+113
-100
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user