mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 23:57:47 +00:00
[mle] update DelayedSender to keep the tx schedule (#10846)
This commit updates how `Mle::DelayedSender` sends MLE messages after
a delay.
Previously, a delayed message was fully prepared and placed in a
queue, waiting for its delay duration to expire. In the new model, a
delayed message is prepared when the requested delay time expires and
the message transmission time is reached. The message is constructed
right before transmission. This ensures that the delayed message
includes the most up-to-date information and simplifies the methods
that prepare and send different types of MLE messages.
`DelayedSender` now keeps track of the message type and the
specific information required to construct the message later. For
example, for a delayed Parent Response to a Parent Request, the
extended address and the `RxChallenge` of the child are saved.
This new model makes it easier to implement the desired behavior when
similar messages are already scheduled to the same destination. For
example:
- For Data Request, if one is already scheduled, a new request can
be skipped, as the earlier Data Request will be valid.
- For Parent Response, Link Accept, and Data Response, a new
schedule request replaces an earlier one.
- For Discovery Response, multiple schedules are allowed.
This commit is contained in:
+176
-83
@@ -217,6 +217,7 @@ void Mle::Stop(StopMode aMode)
|
||||
|
||||
VerifyOrExit(!IsDisabled());
|
||||
|
||||
mDelayedSender.Stop();
|
||||
Get<KeyManager>().Stop();
|
||||
SetStateDetached();
|
||||
Get<ThreadNetif>().UnsubscribeMulticast(mRealmLocalAllThreadNodes);
|
||||
@@ -1737,22 +1738,17 @@ exit:
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination)
|
||||
{
|
||||
return SendDataRequestAfterDelay(aDestination, /* aDelay */ 0);
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay)
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kNetworkData, Tlv::kRoute};
|
||||
|
||||
Error error;
|
||||
Error error = kErrorNone;
|
||||
|
||||
mDelayedSender.RemoveDataRequestMessage(aDestination);
|
||||
VerifyOrExit(IsAttached());
|
||||
|
||||
// Based on `mRequestRouteTlv` include both Network Data and Route
|
||||
// TLVs or only Network Data TLV.
|
||||
|
||||
error = SendDataRequest(aDestination, kTlvs, mRequestRouteTlv ? 2 : 1, aDelay);
|
||||
error = SendDataRequest(aDestination, kTlvs, mRequestRouteTlv ? 2 : 1);
|
||||
|
||||
if (IsChild() && !IsRxOnWhenIdle())
|
||||
{
|
||||
@@ -1764,6 +1760,7 @@ Error Mle::SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1773,16 +1770,15 @@ Error Mle::SendDataRequestForLinkMetricsReport(const Ip6::Address
|
||||
{
|
||||
static const uint8_t kTlvs[] = {Tlv::kLinkMetricsReport};
|
||||
|
||||
return SendDataRequest(aDestination, kTlvs, sizeof(kTlvs), /* aDelay */ 0, &aQueryInfo);
|
||||
return SendDataRequest(aDestination, kTlvs, sizeof(kTlvs), &aQueryInfo);
|
||||
}
|
||||
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination,
|
||||
const uint8_t *aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const LinkMetrics::Initiator::QueryInfo *aQueryInfo)
|
||||
#else
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay)
|
||||
Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength)
|
||||
#endif
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
@@ -1798,22 +1794,14 @@ Error Mle::SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlv
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aDelay)
|
||||
{
|
||||
SuccessOrExit(error = message->SendAfterDelay(aDestination, aDelay));
|
||||
Log(kMessageDelay, kTypeDataRequest, aDestination);
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = message->AppendActiveAndPendingTimestampTlvs());
|
||||
SuccessOrExit(error = message->AppendActiveAndPendingTimestampTlvs());
|
||||
|
||||
SuccessOrExit(error = message->SendTo(aDestination));
|
||||
Log(kMessageSend, kTypeDataRequest, aDestination);
|
||||
SuccessOrExit(error = message->SendTo(aDestination));
|
||||
Log(kMessageSend, kTypeDataRequest, aDestination);
|
||||
|
||||
if (!IsRxOnWhenIdle())
|
||||
{
|
||||
Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
|
||||
}
|
||||
if (!IsRxOnWhenIdle())
|
||||
{
|
||||
Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -2719,8 +2707,8 @@ void Mle::HandleAdvertisement(RxInfo &aRxInfo)
|
||||
|
||||
if (mRetrieveNewNetworkData || IsNetworkDataNewer(leaderData))
|
||||
{
|
||||
delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
|
||||
IgnoreError(SendDataRequestAfterDelay(aRxInfo.mMessageInfo.GetPeerAddr(), delay));
|
||||
delay = 1 + Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
|
||||
mDelayedSender.ScheduleDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), delay);
|
||||
}
|
||||
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
@@ -2901,7 +2889,7 @@ exit:
|
||||
|
||||
if (aRxInfo.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
delay = Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
|
||||
delay = 1 + Random::NonCrypto::GetUint16InRange(0, kMleMaxResponseDelay);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2911,7 +2899,7 @@ exit:
|
||||
delay = 10;
|
||||
}
|
||||
|
||||
IgnoreError(SendDataRequestAfterDelay(aRxInfo.mMessageInfo.GetPeerAddr(), delay));
|
||||
mDelayedSender.ScheduleDataRequest(aRxInfo.mMessageInfo.GetPeerAddr(), delay);
|
||||
}
|
||||
else if (error == kErrorNone)
|
||||
{
|
||||
@@ -4328,100 +4316,210 @@ Mle::DelayedSender::DelayedSender(Instance &aInstance)
|
||||
{
|
||||
}
|
||||
|
||||
Error Mle::DelayedSender::SendMessage(TxMessage &aMessage, const Ip6::Address &aDestination, uint16_t aDelay)
|
||||
void Mle::DelayedSender::Stop(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Metadata metadata;
|
||||
mTimer.Stop();
|
||||
mSchedules.DequeueAndFreeAll();
|
||||
}
|
||||
|
||||
metadata.mSendTime = TimerMilli::GetNow() + aDelay;
|
||||
metadata.mDestination = aDestination;
|
||||
|
||||
SuccessOrExit(error = metadata.AppendTo(aMessage));
|
||||
mQueue.Enqueue(aMessage);
|
||||
|
||||
mTimer.FireAtIfEarlier(metadata.mSendTime);
|
||||
void Mle::DelayedSender::ScheduleDataRequest(const Ip6::Address &aDestination, uint16_t aDelay)
|
||||
{
|
||||
VerifyOrExit(!HasMatchingSchedule(kTypeDataRequest, aDestination));
|
||||
AddSchedule(kTypeDataRequest, aDestination, aDelay, nullptr, 0);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
return;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
void Mle::DelayedSender::ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
|
||||
destination.SetToLinkLocalAddress(aInfo.mChildExtAddress);
|
||||
|
||||
RemoveMatchingSchedules(kTypeParentResponse, destination);
|
||||
AddSchedule(kTypeParentResponse, destination, aDelay, &aInfo, sizeof(aInfo));
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::ScheduleMulticastDataResponse(uint16_t aDelay)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
|
||||
destination.SetToLinkLocalAllNodesMulticast();
|
||||
|
||||
Get<MeshForwarder>().RemoveDataResponseMessages();
|
||||
RemoveMatchingSchedules(kTypeDataResponse, destination);
|
||||
AddSchedule(kTypeDataResponse, destination, aDelay, nullptr, 0);
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
|
||||
destination.SetToLinkLocalAddress(aInfo.mExtAddress);
|
||||
|
||||
RemoveMatchingSchedules(kTypeLinkAccept, destination);
|
||||
AddSchedule(kTypeLinkAccept, destination, aDelay, &aInfo, sizeof(aInfo));
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::ScheduleDiscoveryResponse(const Ip6::Address &aDestination,
|
||||
const DiscoveryResponseInfo &aInfo,
|
||||
uint16_t aDelay)
|
||||
{
|
||||
AddSchedule(kTypeDiscoveryResponse, aDestination, aDelay, &aInfo, sizeof(aInfo));
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
void Mle::DelayedSender::AddSchedule(MessageType aMessageType,
|
||||
const Ip6::Address &aDestination,
|
||||
uint16_t aDelay,
|
||||
const void *aInfo,
|
||||
uint16_t aInfoSize)
|
||||
{
|
||||
Schedule *schedule = Get<MessagePool>().Allocate(Message::kTypeOther);
|
||||
Header header;
|
||||
|
||||
VerifyOrExit(schedule != nullptr);
|
||||
|
||||
header.mSendTime = TimerMilli::GetNow() + aDelay;
|
||||
header.mDestination = aDestination;
|
||||
header.mMessageType = aMessageType;
|
||||
SuccessOrExit(schedule->Append(header));
|
||||
|
||||
if (aInfo != nullptr)
|
||||
{
|
||||
SuccessOrExit(schedule->AppendBytes(aInfo, aInfoSize));
|
||||
}
|
||||
|
||||
mTimer.FireAtIfEarlier(header.mSendTime);
|
||||
|
||||
mSchedules.Enqueue(*schedule);
|
||||
schedule = nullptr;
|
||||
|
||||
Log(kMessageDelay, aMessageType, aDestination);
|
||||
|
||||
exit:
|
||||
FreeMessage(schedule);
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::HandleTimer(void)
|
||||
{
|
||||
NextFireTime nextSendTime;
|
||||
MessageQueue schedulesToExecute;
|
||||
|
||||
for (Message &message : mQueue)
|
||||
for (Schedule &schedule : mSchedules)
|
||||
{
|
||||
Metadata metadata;
|
||||
Header header;
|
||||
|
||||
metadata.ReadFrom(message);
|
||||
header.ReadFrom(schedule);
|
||||
|
||||
if (nextSendTime.GetNow() < metadata.mSendTime)
|
||||
if (nextSendTime.GetNow() < header.mSendTime)
|
||||
{
|
||||
nextSendTime.UpdateIfEarlier(metadata.mSendTime);
|
||||
nextSendTime.UpdateIfEarlier(header.mSendTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
mQueue.Dequeue(message);
|
||||
Send(static_cast<TxMessage &>(message), metadata);
|
||||
mSchedules.Dequeue(schedule);
|
||||
schedulesToExecute.Enqueue(schedule);
|
||||
}
|
||||
}
|
||||
|
||||
mTimer.FireAt(nextSendTime);
|
||||
|
||||
for (Schedule &schedule : schedulesToExecute)
|
||||
{
|
||||
Execute(schedule);
|
||||
}
|
||||
|
||||
schedulesToExecute.DequeueAndFreeAll();
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::Send(TxMessage &aMessage, const Metadata &aMetadata)
|
||||
void Mle::DelayedSender::Execute(const Schedule &aSchedule)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Header header;
|
||||
|
||||
aMetadata.RemoveFrom(aMessage);
|
||||
header.ReadFrom(aSchedule);
|
||||
|
||||
if (aMessage.IsMleCommand(kCommandDataRequest))
|
||||
switch (header.mMessageType)
|
||||
{
|
||||
SuccessOrExit(error = aMessage.AppendActiveAndPendingTimestampTlvs());
|
||||
case kTypeDataRequest:
|
||||
IgnoreError(Get<Mle>().SendDataRequest(header.mDestination));
|
||||
break;
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
case kTypeParentResponse:
|
||||
{
|
||||
ParentResponseInfo info;
|
||||
|
||||
IgnoreError(aSchedule.Read(sizeof(Header), info));
|
||||
Get<MleRouter>().SendParentResponse(info);
|
||||
break;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = aMessage.SendTo(aMetadata.mDestination));
|
||||
case kTypeDataResponse:
|
||||
Get<MleRouter>().SendMulticastDataResponse();
|
||||
break;
|
||||
|
||||
Log(kMessageSend, kTypeGenericDelayed, aMetadata.mDestination);
|
||||
|
||||
if (!Get<Mle>().IsRxOnWhenIdle())
|
||||
case kTypeLinkAccept:
|
||||
{
|
||||
// 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.
|
||||
LinkAcceptInfo info;
|
||||
|
||||
Get<DataPollSender>().SendFastPolls(DataPollSender::kDefaultFastPolls);
|
||||
IgnoreError(aSchedule.Read(sizeof(Header), info));
|
||||
IgnoreError(Get<MleRouter>().SendLinkAccept(info));
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (error != kErrorNone)
|
||||
case kTypeDiscoveryResponse:
|
||||
{
|
||||
aMessage.Free();
|
||||
DiscoveryResponseInfo info;
|
||||
|
||||
IgnoreError(aSchedule.Read(sizeof(Header), info));
|
||||
IgnoreError(Get<MleRouter>().SendDiscoveryResponse(header.mDestination, info));
|
||||
break;
|
||||
}
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::RemoveDataResponseMessage(void)
|
||||
bool Mle::DelayedSender::Match(const Schedule &aSchedule, MessageType aMessageType, const Ip6::Address &aDestination)
|
||||
{
|
||||
RemoveMessage(kCommandDataResponse, kTypeDataResponse, nullptr);
|
||||
Header header;
|
||||
|
||||
header.ReadFrom(aSchedule);
|
||||
|
||||
return (header.mMessageType == aMessageType) && (header.mDestination == aDestination);
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::RemoveDataRequestMessage(const Ip6::Address &aDestination)
|
||||
bool Mle::DelayedSender::HasMatchingSchedule(MessageType aMessageType, const Ip6::Address &aDestination) const
|
||||
{
|
||||
RemoveMessage(kCommandDataRequest, kTypeDataRequest, &aDestination);
|
||||
}
|
||||
bool hasMatching = false;
|
||||
|
||||
void Mle::DelayedSender::RemoveMessage(Command aCommand, MessageType aMessageType, const Ip6::Address *aDestination)
|
||||
{
|
||||
for (Message &message : mQueue)
|
||||
for (const Schedule &schedule : mSchedules)
|
||||
{
|
||||
Metadata metadata;
|
||||
|
||||
metadata.ReadFrom(message);
|
||||
|
||||
if (message.IsMleCommand(aCommand) && ((aDestination == nullptr) || (metadata.mDestination == *aDestination)))
|
||||
if (Match(schedule, aMessageType, aDestination))
|
||||
{
|
||||
mQueue.DequeueAndFree(message);
|
||||
Log(kMessageRemoveDelayed, aMessageType, metadata.mDestination);
|
||||
hasMatching = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return hasMatching;
|
||||
}
|
||||
|
||||
void Mle::DelayedSender::RemoveMatchingSchedules(MessageType aMessageType, const Ip6::Address &aDestination)
|
||||
{
|
||||
for (Schedule &schedule : mSchedules)
|
||||
{
|
||||
if (Match(schedule, aMessageType, aDestination))
|
||||
{
|
||||
mSchedules.DequeueAndFree(schedule);
|
||||
Log(kMessageRemoveDelayed, aMessageType, aDestination);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4846,11 +4944,6 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Mle::TxMessage::SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay)
|
||||
{
|
||||
return Get<Mle>().mDelayedSender.SendMessage(*this, aDestination, aDelay);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
Error Mle::TxMessage::AppendConnectivityTlv(void)
|
||||
|
||||
+58
-14
@@ -994,7 +994,6 @@ private:
|
||||
}
|
||||
|
||||
Error SendTo(const Ip6::Address &aDestination);
|
||||
Error SendAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
|
||||
|
||||
private:
|
||||
Error AppendCompressedAddressEntry(uint8_t aContextId, const Ip6::Address &aAddress);
|
||||
@@ -1064,6 +1063,33 @@ private:
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
struct ParentResponseInfo
|
||||
{
|
||||
Mac::ExtAddress mChildExtAddress; // The child extended address.
|
||||
RxChallenge mRxChallenge; // The challenge from the Parent Request.
|
||||
};
|
||||
|
||||
struct LinkAcceptInfo
|
||||
{
|
||||
Mac::ExtAddress mExtAddress; // The neighbor/router extended address.
|
||||
TlvList mRequestedTlvList; // The requested TLVs in Link Request.
|
||||
RxChallenge mRxChallenge; // The challenge in Link Request.
|
||||
uint8_t mLinkMargin; // Link margin of the received Link Request.
|
||||
};
|
||||
|
||||
struct DiscoveryResponseInfo
|
||||
{
|
||||
Mac::PanId mPanId;
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
Mac::RadioType mRadioType;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
void HandleDelayedSenderTimer(void) { mDelayedSender.HandleTimer(); }
|
||||
|
||||
class DelayedSender : public InstanceLocator
|
||||
@@ -1071,26 +1097,46 @@ private:
|
||||
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);
|
||||
void Stop(void);
|
||||
|
||||
const MessageQueue &GetQueue(void) const { return mQueue; }
|
||||
void ScheduleDataRequest(const Ip6::Address &aDestination, uint16_t aDelay);
|
||||
#if OPENTHREAD_FTD
|
||||
void ScheduleParentResponse(const ParentResponseInfo &aInfo, uint16_t aDelay);
|
||||
void ScheduleMulticastDataResponse(uint16_t aDelay);
|
||||
void ScheduleLinkAccept(const LinkAcceptInfo &aInfo, uint16_t aDelay);
|
||||
void ScheduleDiscoveryResponse(const Ip6::Address &aDestination,
|
||||
const DiscoveryResponseInfo &aInfo,
|
||||
uint16_t aDelay);
|
||||
#endif
|
||||
void HandleTimer(void);
|
||||
const MessageQueue &GetQueue(void) const { return mSchedules; }
|
||||
|
||||
private:
|
||||
struct Metadata : public Message::FooterData<Metadata>
|
||||
typedef Message Schedule;
|
||||
|
||||
struct Header
|
||||
{
|
||||
Ip6::Address mDestination;
|
||||
void ReadFrom(const Schedule &aSchedule) { IgnoreError(aSchedule.Read(/* aOffset */ 0, *this)); }
|
||||
|
||||
TimeMilli mSendTime;
|
||||
Ip6::Address mDestination;
|
||||
MessageType mMessageType;
|
||||
};
|
||||
|
||||
void Send(TxMessage &aMessage, const Metadata &aMetadata);
|
||||
void RemoveMessage(Command aCommand, MessageType aMessageType, const Ip6::Address *aDestination);
|
||||
void AddSchedule(MessageType aMessageType,
|
||||
const Ip6::Address &aDestination,
|
||||
uint16_t aDelay,
|
||||
const void *aInfo,
|
||||
uint16_t aInfoSize);
|
||||
void Execute(const Schedule &aSchedule);
|
||||
bool HasMatchingSchedule(MessageType aMessageType, const Ip6::Address &aDestination) const;
|
||||
void RemoveMatchingSchedules(MessageType aMessageType, const Ip6::Address &aDestination);
|
||||
|
||||
static bool Match(const Schedule &aSchedule, MessageType aMessageType, const Ip6::Address &aDestination);
|
||||
|
||||
using DelayTimer = TimerMilliIn<Mle, &Mle::HandleDelayedSenderTimer>;
|
||||
|
||||
MessageQueue mQueue;
|
||||
MessageQueue mSchedules;
|
||||
DelayTimer mTimer;
|
||||
};
|
||||
|
||||
@@ -1217,7 +1263,6 @@ private:
|
||||
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
void ReestablishLinkWithNeighbor(Neighbor &aNeighbor);
|
||||
Error SendChildUpdateRequest(ChildUpdateRequestMode aMode);
|
||||
Error SendDataRequestAfterDelay(const Ip6::Address &aDestination, uint16_t aDelay);
|
||||
Error SendChildUpdateRequest(void);
|
||||
Error SendChildUpdateResponse(const TlvList &aTlvList,
|
||||
const RxChallenge &aChallenge,
|
||||
@@ -1300,10 +1345,9 @@ private:
|
||||
Error SendDataRequest(const Ip6::Address &aDestination,
|
||||
const uint8_t *aTlvs,
|
||||
uint8_t aTlvsLength,
|
||||
uint16_t aDelay,
|
||||
const LinkMetrics::Initiator::QueryInfo *aQueryInfo = nullptr);
|
||||
#else
|
||||
Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength, uint16_t aDelay);
|
||||
Error SendDataRequest(const Ip6::Address &aDestination, const uint8_t *aTlvs, uint8_t aTlvsLength);
|
||||
#endif
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
|
||||
|
||||
+136
-117
@@ -668,13 +668,12 @@ exit:
|
||||
|
||||
void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Neighbor *neighbor = nullptr;
|
||||
RxChallenge challenge;
|
||||
uint16_t version;
|
||||
LeaderData leaderData;
|
||||
uint16_t sourceAddress;
|
||||
TlvList requestedTlvList;
|
||||
Error error = kErrorNone;
|
||||
Neighbor *neighbor = nullptr;
|
||||
uint16_t version;
|
||||
LeaderData leaderData;
|
||||
uint16_t sourceAddress;
|
||||
LinkAcceptInfo info;
|
||||
|
||||
Log(kMessageReceive, kTypeLinkRequest, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
@@ -682,7 +681,7 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
|
||||
VerifyOrExit(!IsAttaching(), error = kErrorInvalidState);
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(info.mRxChallenge));
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadVersionTlv(version));
|
||||
|
||||
@@ -697,6 +696,10 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(info.mExtAddress);
|
||||
|
||||
info.mLinkMargin = Get<Mac::Mac>().ComputeLinkMargin(aRxInfo.mMessage.GetAverageRss());
|
||||
|
||||
switch (Tlv::Find<SourceAddressTlv>(aRxInfo.mMessage, sourceAddress))
|
||||
{
|
||||
case kErrorNone:
|
||||
@@ -713,10 +716,7 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
}
|
||||
else
|
||||
{
|
||||
Mac::ExtAddress extAddr;
|
||||
|
||||
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
|
||||
VerifyOrExit(neighbor->GetExtAddress() == extAddr);
|
||||
VerifyOrExit(neighbor->GetExtAddress() == info.mExtAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,7 +734,7 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(info.mRequestedTlvList))
|
||||
{
|
||||
case kErrorNone:
|
||||
case kErrorNotFound:
|
||||
@@ -760,51 +760,71 @@ void MleRouter::HandleLinkRequest(RxInfo &aRxInfo)
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
ProcessKeySequence(aRxInfo);
|
||||
|
||||
SuccessOrExit(error = SendLinkAccept(aRxInfo, neighbor, requestedTlvList, challenge));
|
||||
if (aRxInfo.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
mDelayedSender.ScheduleLinkAccept(info, 1 + Random::NonCrypto::GetUint16InRange(0, kMaxLinkAcceptDelay));
|
||||
}
|
||||
else
|
||||
{
|
||||
error = SendLinkAccept(info);
|
||||
}
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeLinkRequest, error);
|
||||
OT_UNUSED_VARIABLE(neighbor);
|
||||
}
|
||||
|
||||
Error MleRouter::SendLinkAccept(const RxInfo &aRxInfo,
|
||||
Neighbor *aNeighbor,
|
||||
const TlvList &aRequestedTlvList,
|
||||
const RxChallenge &aChallenge)
|
||||
Error MleRouter::SendLinkAccept(const LinkAcceptInfo &aInfo)
|
||||
{
|
||||
static const uint8_t kRouterTlvs[] = {Tlv::kLinkMargin};
|
||||
|
||||
Error error = kErrorNone;
|
||||
TxMessage *message;
|
||||
Command command;
|
||||
uint8_t linkMargin;
|
||||
Error error = kErrorNone;
|
||||
TxMessage *message = nullptr;
|
||||
Command command = kCommandLinkAccept;
|
||||
Router *router;
|
||||
Ip6::Address destination;
|
||||
|
||||
command = (aNeighbor == nullptr || aNeighbor->IsStateValid()) ? kCommandLinkAccept : kCommandLinkAcceptAndRequest;
|
||||
VerifyOrExit(IsAttached());
|
||||
|
||||
router = mRouterTable.FindRouter(aInfo.mExtAddress);
|
||||
|
||||
if (router != nullptr)
|
||||
{
|
||||
if (router->IsStateLinkRequest())
|
||||
{
|
||||
command = kCommandLinkAcceptAndRequest;
|
||||
router->SetLastHeard(TimerMilli::GetNow());
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(router->IsStateValid());
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit((message = NewMleMessage(command)) != nullptr, error = kErrorNoBufs);
|
||||
SuccessOrExit(error = message->AppendVersionTlv());
|
||||
SuccessOrExit(error = message->AppendSourceAddressTlv());
|
||||
SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
|
||||
SuccessOrExit(error = message->AppendResponseTlv(aInfo.mRxChallenge));
|
||||
SuccessOrExit(error = message->AppendLinkAndMleFrameCounterTlvs());
|
||||
|
||||
linkMargin = Get<Mac::Mac>().ComputeLinkMargin(aRxInfo.mMessage.GetAverageRss());
|
||||
SuccessOrExit(error = message->AppendLinkMarginTlv(linkMargin));
|
||||
SuccessOrExit(error = message->AppendLinkMarginTlv(aInfo.mLinkMargin));
|
||||
|
||||
if (aNeighbor != nullptr && IsRouterRloc16(aNeighbor->GetRloc16()))
|
||||
if (router != nullptr)
|
||||
{
|
||||
SuccessOrExit(error = message->AppendLeaderDataTlv());
|
||||
}
|
||||
|
||||
for (uint8_t tlvType : aRequestedTlvList)
|
||||
for (uint8_t tlvType : aInfo.mRequestedTlvList)
|
||||
{
|
||||
switch (tlvType)
|
||||
{
|
||||
case Tlv::kRoute:
|
||||
SuccessOrExit(error = message->AppendRouteTlv(aNeighbor));
|
||||
SuccessOrExit(error = message->AppendRouteTlv(router));
|
||||
break;
|
||||
|
||||
case Tlv::kAddress16:
|
||||
VerifyOrExit(aNeighbor != nullptr, error = kErrorDrop);
|
||||
SuccessOrExit(error = message->AppendAddress16Tlv(aNeighbor->GetRloc16()));
|
||||
VerifyOrExit(router != nullptr, error = kErrorDrop);
|
||||
SuccessOrExit(error = message->AppendAddress16Tlv(router->GetRloc16()));
|
||||
break;
|
||||
|
||||
case Tlv::kLinkMargin:
|
||||
@@ -815,38 +835,26 @@ Error MleRouter::SendLinkAccept(const RxInfo &aRxInfo,
|
||||
}
|
||||
}
|
||||
|
||||
if (aNeighbor != nullptr && !aNeighbor->IsStateValid())
|
||||
if (command == kCommandLinkAcceptAndRequest)
|
||||
{
|
||||
aNeighbor->GenerateChallenge();
|
||||
router->GenerateChallenge();
|
||||
|
||||
SuccessOrExit(error = message->AppendChallengeTlv(aNeighbor->GetChallenge()));
|
||||
SuccessOrExit(error = message->AppendChallengeTlv(router->GetChallenge()));
|
||||
SuccessOrExit(error = message->AppendTlvRequestTlv(kRouterTlvs));
|
||||
aNeighbor->SetLastHeard(TimerMilli::GetNow());
|
||||
aNeighbor->SetState(Neighbor::kStateLinkRequest);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (aNeighbor != nullptr && aNeighbor->IsTimeSyncEnabled())
|
||||
if (router != nullptr && router->IsTimeSyncEnabled())
|
||||
{
|
||||
message->SetTimeSync(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aRxInfo.mMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
SuccessOrExit(error = message->SendAfterDelay(aRxInfo.mMessageInfo.GetPeerAddr(),
|
||||
1 + Random::NonCrypto::GetUint16InRange(0, kMaxLinkAcceptDelay)));
|
||||
destination.SetToLinkLocalAddress(aInfo.mExtAddress);
|
||||
|
||||
Log(kMessageDelay, (command == kCommandLinkAccept) ? kTypeLinkAccept : kTypeLinkAcceptAndRequest,
|
||||
aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = message->SendTo(aRxInfo.mMessageInfo.GetPeerAddr()));
|
||||
SuccessOrExit(error = message->SendTo(destination));
|
||||
|
||||
Log(kMessageSend, (command == kCommandLinkAccept) ? kTypeLinkAccept : kTypeLinkAcceptAndRequest,
|
||||
aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
}
|
||||
Log(kMessageSend, (command == kCommandLinkAccept) ? kTypeLinkAccept : kTypeLinkAcceptAndRequest, destination);
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
@@ -1049,12 +1057,11 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
|
||||
if (aRequest)
|
||||
{
|
||||
RxChallenge challenge;
|
||||
TlvList requestedTlvList;
|
||||
LinkAcceptInfo info;
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(info.mRxChallenge));
|
||||
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(requestedTlvList))
|
||||
switch (aRxInfo.mMessage.ReadTlvRequestTlv(info.mRequestedTlvList))
|
||||
{
|
||||
case kErrorNone:
|
||||
case kErrorNotFound:
|
||||
@@ -1063,7 +1070,10 @@ Error MleRouter::HandleLinkAccept(RxInfo &aRxInfo, bool aRequest)
|
||||
ExitNow(error = kErrorParse);
|
||||
}
|
||||
|
||||
SuccessOrExit(error = SendLinkAccept(aRxInfo, router, requestedTlvList, challenge));
|
||||
info.mExtAddress = router->GetExtAddress();
|
||||
info.mLinkMargin = Get<Mac::Mac>().ComputeLinkMargin(aRxInfo.mMessage.GetAverageRss());
|
||||
|
||||
SuccessOrExit(error = SendLinkAccept(info));
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -1360,13 +1370,13 @@ exit:
|
||||
|
||||
void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Mac::ExtAddress extAddr;
|
||||
uint16_t version;
|
||||
uint8_t scanMask;
|
||||
RxChallenge challenge;
|
||||
Child *child;
|
||||
DeviceMode mode;
|
||||
Error error = kErrorNone;
|
||||
uint16_t version;
|
||||
uint8_t scanMask;
|
||||
Child *child;
|
||||
DeviceMode mode;
|
||||
uint16_t delay;
|
||||
ParentResponseInfo info;
|
||||
|
||||
Log(kMessageReceive, kTypeParentRequest, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
@@ -1393,7 +1403,7 @@ void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
// the network (because Leader would reject any further address solicit).
|
||||
// ==> Verified below when checking the scan mask.
|
||||
|
||||
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(extAddr);
|
||||
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(info.mChildExtAddress);
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadVersionTlv(version));
|
||||
|
||||
@@ -1416,9 +1426,9 @@ void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
break;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(challenge));
|
||||
SuccessOrExit(error = aRxInfo.mMessage.ReadChallengeTlv(info.mRxChallenge));
|
||||
|
||||
child = mChildTable.FindChild(extAddr, Child::kInStateAnyExceptInvalid);
|
||||
child = mChildTable.FindChild(info.mChildExtAddress, Child::kInStateAnyExceptInvalid);
|
||||
|
||||
if (child == nullptr)
|
||||
{
|
||||
@@ -1449,7 +1459,10 @@ void MleRouter::HandleParentRequest(RxInfo &aRxInfo)
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
ProcessKeySequence(aRxInfo);
|
||||
|
||||
SendParentResponse(*child, challenge, !ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
|
||||
delay = 1 + Random::NonCrypto::GetUint16InRange(0, !ScanMaskTlv::IsEndDeviceFlagSet(scanMask)
|
||||
? kParentResponseMaxDelayRouters
|
||||
: kParentResponseMaxDelayAll);
|
||||
mDelayedSender.ScheduleParentResponse(info, delay);
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeParentRequest, error);
|
||||
@@ -1681,12 +1694,15 @@ exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void MleRouter::SendParentResponse(Child &aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest)
|
||||
void MleRouter::SendParentResponse(const ParentResponseInfo &aInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
Error error = kErrorNone;
|
||||
TxMessage *message = nullptr;
|
||||
Child *child;
|
||||
Ip6::Address destination;
|
||||
TxMessage *message;
|
||||
uint16_t delay;
|
||||
|
||||
child = mChildTable.FindChild(aInfo.mChildExtAddress, Child::kInStateAnyExceptInvalid);
|
||||
VerifyOrExit(child != nullptr);
|
||||
|
||||
VerifyOrExit((message = NewMleMessage(kCommandParentResponse)) != nullptr, error = kErrorNoBufs);
|
||||
message->SetDirectTransmission();
|
||||
@@ -1694,33 +1710,30 @@ void MleRouter::SendParentResponse(Child &aChild, const RxChallenge &aChallenge,
|
||||
SuccessOrExit(error = message->AppendSourceAddressTlv());
|
||||
SuccessOrExit(error = message->AppendLeaderDataTlv());
|
||||
SuccessOrExit(error = message->AppendLinkAndMleFrameCounterTlvs());
|
||||
SuccessOrExit(error = message->AppendResponseTlv(aChallenge));
|
||||
SuccessOrExit(error = message->AppendResponseTlv(aInfo.mRxChallenge));
|
||||
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
|
||||
if (aChild.IsTimeSyncEnabled())
|
||||
if (child->IsTimeSyncEnabled())
|
||||
{
|
||||
SuccessOrExit(error = message->AppendTimeParameterTlv());
|
||||
}
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
if (aChild.IsThreadVersionCslCapable())
|
||||
if (child->IsThreadVersionCslCapable())
|
||||
{
|
||||
SuccessOrExit(error = message->AppendCslClockAccuracyTlv());
|
||||
}
|
||||
#endif
|
||||
aChild.GenerateChallenge();
|
||||
SuccessOrExit(error = message->AppendChallengeTlv(aChild.GetChallenge()));
|
||||
SuccessOrExit(error = message->AppendLinkMarginTlv(aChild.GetLinkInfo().GetLinkMargin()));
|
||||
child->GenerateChallenge();
|
||||
SuccessOrExit(error = message->AppendChallengeTlv(child->GetChallenge()));
|
||||
SuccessOrExit(error = message->AppendLinkMarginTlv(child->GetLinkInfo().GetLinkMargin()));
|
||||
SuccessOrExit(error = message->AppendConnectivityTlv());
|
||||
SuccessOrExit(error = message->AppendVersionTlv());
|
||||
|
||||
destination.SetToLinkLocalAddress(aChild.GetExtAddress());
|
||||
destination.SetToLinkLocalAddress(aInfo.mChildExtAddress);
|
||||
|
||||
delay = 1 + Random::NonCrypto::GetUint16InRange(0, aRoutersOnlyRequest ? kParentResponseMaxDelayRouters
|
||||
: kParentResponseMaxDelayAll);
|
||||
SuccessOrExit(error = message->SendTo(destination));
|
||||
|
||||
SuccessOrExit(error = message->SendAfterDelay(destination, delay));
|
||||
|
||||
Log(kMessageDelay, kTypeParentResponse, destination);
|
||||
Log(kMessageSend, kTypeParentResponse, destination);
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
@@ -2538,7 +2551,7 @@ void MleRouter::HandleDataRequest(RxInfo &aRxInfo)
|
||||
aRxInfo.mClass = RxInfo::kPeerMessage;
|
||||
ProcessKeySequence(aRxInfo);
|
||||
|
||||
SendDataResponse(aRxInfo.mMessageInfo.GetPeerAddr(), tlvList, /* aDelay */ 0, &aRxInfo.mMessage);
|
||||
SendDataResponse(aRxInfo.mMessageInfo.GetPeerAddr(), tlvList, &aRxInfo.mMessage);
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeDataRequest, error);
|
||||
@@ -2546,17 +2559,19 @@ exit:
|
||||
|
||||
void MleRouter::HandleNetworkDataUpdateRouter(void)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
uint16_t delay;
|
||||
TlvList tlvList;
|
||||
uint16_t delay;
|
||||
|
||||
VerifyOrExit(IsRouterOrLeader());
|
||||
|
||||
destination.SetToLinkLocalAllNodesMulticast();
|
||||
tlvList.Add(Tlv::kNetworkData);
|
||||
|
||||
delay = IsLeader() ? 0 : Random::NonCrypto::GetUint16InRange(0, kUnsolicitedDataResponseJitter);
|
||||
SendDataResponse(destination, tlvList, delay);
|
||||
if (IsLeader())
|
||||
{
|
||||
SendMulticastDataResponse();
|
||||
}
|
||||
else
|
||||
{
|
||||
delay = 1 + Random::NonCrypto::GetUint16InRange(0, kUnsolicitedDataResponseJitter);
|
||||
mDelayedSender.ScheduleMulticastDataResponse(delay);
|
||||
}
|
||||
|
||||
SynchronizeChildNetworkData();
|
||||
|
||||
@@ -2622,6 +2637,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
|
||||
MeshCoP::DiscoveryRequestTlv discoveryRequestTlv;
|
||||
MeshCoP::ExtendedPanId extPanId;
|
||||
OffsetRange offsetRange;
|
||||
DiscoveryResponseInfo responseInfo;
|
||||
|
||||
Log(kMessageReceive, kTypeDiscoveryRequest, aRxInfo.mMessageInfo.GetPeerAddr());
|
||||
|
||||
@@ -2687,28 +2703,34 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
|
||||
}
|
||||
}
|
||||
|
||||
error = SendDiscoveryResponse(aRxInfo.mMessageInfo.GetPeerAddr(), aRxInfo.mMessage);
|
||||
responseInfo.mPanId = aRxInfo.mMessage.GetPanId();
|
||||
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
// Send the MLE Discovery Response message on same radio link
|
||||
// from which the "MLE Discover Request" message was received.
|
||||
responseInfo.mRadioType = aRxInfo.mMessage.GetRadioType();
|
||||
#endif
|
||||
|
||||
mDelayedSender.ScheduleDiscoveryResponse(aRxInfo.mMessageInfo.GetPeerAddr(), responseInfo,
|
||||
1 + Random::NonCrypto::GetUint16InRange(0, kDiscoveryMaxJitter));
|
||||
|
||||
exit:
|
||||
LogProcessError(kTypeDiscoveryRequest, error);
|
||||
}
|
||||
|
||||
Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage)
|
||||
Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const DiscoveryResponseInfo &aInfo)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
TxMessage *message;
|
||||
uint16_t startOffset;
|
||||
Tlv tlv;
|
||||
MeshCoP::DiscoveryResponseTlv discoveryResponseTlv;
|
||||
uint16_t delay;
|
||||
|
||||
VerifyOrExit((message = NewMleMessage(kCommandDiscoveryResponse)) != nullptr, error = kErrorNoBufs);
|
||||
message->SetDirectTransmission();
|
||||
message->SetPanId(aDiscoverRequestMessage.GetPanId());
|
||||
message->SetPanId(aInfo.mPanId);
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
// Send the MLE Discovery Response message on same radio link
|
||||
// from which the "MLE Discover Request" message was received.
|
||||
message->SetRadioType(aDiscoverRequestMessage.GetRadioType());
|
||||
message->SetRadioType(aInfo.mRadioType);
|
||||
#endif
|
||||
|
||||
tlv.SetType(Tlv::kDiscovery);
|
||||
@@ -2762,11 +2784,9 @@ Error MleRouter::SendDiscoveryResponse(const Ip6::Address &aDestination, const M
|
||||
tlv.SetLength(static_cast<uint8_t>(message->GetLength() - startOffset));
|
||||
message->Write(startOffset - sizeof(tlv), tlv);
|
||||
|
||||
delay = Random::NonCrypto::GetUint16InRange(0, kDiscoveryMaxJitter + 1);
|
||||
SuccessOrExit(error = message->SendTo(aDestination));
|
||||
|
||||
SuccessOrExit(error = message->SendAfterDelay(aDestination, delay));
|
||||
|
||||
Log(kMessageDelay, kTypeDiscoveryResponse, aDestination);
|
||||
Log(kMessageSend, kTypeDiscoveryResponse, aDestination);
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
@@ -3037,9 +3057,18 @@ exit:
|
||||
FreeMessageOnError(message, error);
|
||||
}
|
||||
|
||||
void MleRouter::SendMulticastDataResponse(void)
|
||||
{
|
||||
Ip6::Address destination;
|
||||
TlvList tlvList;
|
||||
|
||||
destination.SetToLinkLocalAllNodesMulticast();
|
||||
tlvList.Add(Tlv::kNetworkData);
|
||||
SendDataResponse(destination, tlvList);
|
||||
}
|
||||
|
||||
void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
|
||||
const TlvList &aTlvList,
|
||||
uint16_t aDelay,
|
||||
const Message *aRequestMessage)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aRequestMessage);
|
||||
@@ -3048,6 +3077,8 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
|
||||
TxMessage *message = nullptr;
|
||||
Neighbor *neighbor;
|
||||
|
||||
VerifyOrExit(IsAttached());
|
||||
|
||||
if (mRetrieveNewNetworkData)
|
||||
{
|
||||
LogInfo("Suppressing Data Response - waiting for new network data");
|
||||
@@ -3092,20 +3123,8 @@ void MleRouter::SendDataResponse(const Ip6::Address &aDestination,
|
||||
}
|
||||
}
|
||||
|
||||
if (aDelay)
|
||||
{
|
||||
Get<MeshForwarder>().RemoveDataResponseMessages();
|
||||
|
||||
mDelayedSender.RemoveDataResponseMessage();
|
||||
|
||||
SuccessOrExit(error = message->SendAfterDelay(aDestination, aDelay));
|
||||
Log(kMessageDelay, kTypeDataResponse, aDestination);
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = message->SendTo(aDestination));
|
||||
Log(kMessageSend, kTypeDataResponse, aDestination);
|
||||
}
|
||||
SuccessOrExit(error = message->SendTo(aDestination));
|
||||
Log(kMessageSend, kTypeDataResponse, aDestination);
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
|
||||
@@ -616,22 +616,19 @@ private:
|
||||
const Ip6::MessageInfo &aMessageInfo);
|
||||
void SendAddressRelease(void);
|
||||
void SendAdvertisement(void);
|
||||
Error SendLinkAccept(const RxInfo &aRxInfo,
|
||||
Neighbor *aNeighbor,
|
||||
const TlvList &aRequestedTlvList,
|
||||
const RxChallenge &aChallenge);
|
||||
void SendParentResponse(Child &aChild, const RxChallenge &aChallenge, bool aRoutersOnlyRequest);
|
||||
Error SendLinkAccept(const LinkAcceptInfo &aInfo);
|
||||
void SendParentResponse(const ParentResponseInfo &aInfo);
|
||||
Error SendChildIdResponse(Child &aChild);
|
||||
Error SendChildUpdateRequest(Child &aChild);
|
||||
void SendChildUpdateResponse(Child *aChild,
|
||||
const Ip6::MessageInfo &aMessageInfo,
|
||||
const TlvList &aTlvList,
|
||||
const RxChallenge &aChallenge);
|
||||
void SendMulticastDataResponse(void);
|
||||
void SendDataResponse(const Ip6::Address &aDestination,
|
||||
const TlvList &aTlvList,
|
||||
uint16_t aDelay,
|
||||
const Message *aRequestMessage = nullptr);
|
||||
Error SendDiscoveryResponse(const Ip6::Address &aDestination, const Message &aDiscoverRequestMessage);
|
||||
Error SendDiscoveryResponse(const Ip6::Address &aDestination, const DiscoveryResponseInfo &aInfo);
|
||||
void SetStateRouter(uint16_t aRloc16);
|
||||
void SetStateLeader(uint16_t aRloc16, LeaderStartMode aStartMode);
|
||||
void SetStateRouterOrLeader(DeviceRole aRole, uint16_t aRloc16, LeaderStartMode aStartMode);
|
||||
|
||||
@@ -225,6 +225,8 @@ void InitTest(void)
|
||||
|
||||
void FinalizeTest(void)
|
||||
{
|
||||
AdvanceTime(30 * 1000);
|
||||
|
||||
SuccessOrQuit(otIp6SetEnabled(sInstance, false));
|
||||
SuccessOrQuit(otThreadSetEnabled(sInstance, false));
|
||||
// Make sure there is no message/buffer leak
|
||||
|
||||
Reference in New Issue
Block a user