mirror of
https://github.com/espressif/openthread.git
synced 2026-08-07 19:27:46 +00:00
[mesh-forwarder] keep msgs during address resolution in mSendQueue (#7577)
This commit updates how the messages waiting for address query resolution are processed and queued. It adds a boolean flag in `Message` metadata to indicate whether or not a message is waiting for an address query resolution. Messages that require address query are marked and kept in `mSendQueue` instead of being placed in a different queue `mResolvingQueue`. When the address is resolved the messages are updated accordingly. This ensures that the order of messages in `mSendQueue` are preserved.
This commit is contained in:
@@ -264,10 +264,6 @@ void Instance::GetBufferInfo(BufferInfo &aInfo)
|
||||
|
||||
Get<MeshForwarder>().GetReassemblyQueue().GetInfo(aInfo.m6loReassemblyMessages, aInfo.m6loReassemblyBuffers);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
Get<MeshForwarder>().GetResolvingQueue().GetInfo(aInfo.mArpMessages, aInfo.mArpBuffers);
|
||||
#endif
|
||||
|
||||
Get<Ip6::Ip6>().GetSendQueue().GetInfo(aInfo.mIp6Messages, aInfo.mIp6Buffers);
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
@@ -203,15 +203,16 @@ protected:
|
||||
#endif
|
||||
ChildMask mChildMask; // ChildMask to indicate which sleepy children need to receive this.
|
||||
|
||||
uint8_t mType : 3; // The message type.
|
||||
uint8_t mSubType : 4; // The message sub type.
|
||||
bool mDirectTx : 1; // Whether a direct transmission is required.
|
||||
bool mLinkSecurity : 1; // Whether link security is enabled.
|
||||
uint8_t mPriority : 2; // The message priority level (higher value is higher priority).
|
||||
bool mInPriorityQ : 1; // Whether the message is queued in normal or priority queue.
|
||||
bool mTxSuccess : 1; // Whether the direct tx of the message was successful.
|
||||
bool mDoNotEvict : 1; // Whether this message may be evicted.
|
||||
bool mMulticastLoop : 1; // Whether this multicast message may be looped back.
|
||||
uint8_t mType : 3; // The message type.
|
||||
uint8_t mSubType : 4; // The message sub type.
|
||||
bool mDirectTx : 1; // Whether a direct transmission is required.
|
||||
bool mLinkSecurity : 1; // Whether link security is enabled.
|
||||
uint8_t mPriority : 2; // The message priority level (higher value is higher priority).
|
||||
bool mInPriorityQ : 1; // Whether the message is queued in normal or priority queue.
|
||||
bool mTxSuccess : 1; // Whether the direct tx of the message was successful.
|
||||
bool mDoNotEvict : 1; // Whether this message may be evicted.
|
||||
bool mMulticastLoop : 1; // Whether this multicast message may be looped back.
|
||||
bool mResolvingAddress : 1; // Whether the message is pending an address query resolution.
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
uint8_t mRadioType : 2; // The radio link type the message was received on, or should be sent on.
|
||||
bool mIsRadioTypeSet : 1; // Whether the radio type is set.
|
||||
@@ -1030,6 +1031,23 @@ public:
|
||||
*/
|
||||
void SetDoNotEvict(bool aDoNotEvict) { GetMetadata().mDoNotEvict = aDoNotEvict; }
|
||||
|
||||
/**
|
||||
* This method indicates whether the message is waiting for an address query resolution.
|
||||
*
|
||||
* @retval TRUE If the message is waiting for address query resolution.
|
||||
* @retval FALSE If the message is not waiting for address query resolution.
|
||||
*
|
||||
*/
|
||||
bool IsResolvingAddress(void) const { return GetMetadata().mResolvingAddress; }
|
||||
|
||||
/**
|
||||
* This method sets whether the message is waiting for an address query resolution.
|
||||
*
|
||||
* @param[in] aResolvingAddress TRUE if message is waiting for address resolution, FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
void SetResolvingAddress(bool aResolvingAddress) { GetMetadata().mResolvingAddress = aResolvingAddress; }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not link security is enabled for the message.
|
||||
*
|
||||
|
||||
@@ -267,7 +267,7 @@ Message *MeshForwarder::PrepareNextDirectTransmission(void)
|
||||
|
||||
for (curMessage = mSendQueue.GetHead(); curMessage; curMessage = nextMessage)
|
||||
{
|
||||
if (!curMessage->IsDirectTransmission())
|
||||
if (!curMessage->IsDirectTransmission() || curMessage->IsResolvingAddress())
|
||||
{
|
||||
nextMessage = curMessage->GetNext();
|
||||
continue;
|
||||
@@ -311,12 +311,9 @@ Message *MeshForwarder::PrepareNextDirectTransmission(void)
|
||||
ExitNow();
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
case kErrorAddressQuery:
|
||||
mSendQueue.Dequeue(*curMessage);
|
||||
mResolvingQueue.Enqueue(*curMessage);
|
||||
curMessage->SetResolvingAddress(true);
|
||||
continue;
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
||||
@@ -311,15 +311,6 @@ public:
|
||||
*/
|
||||
void ResetCounters(void) { memset(&mIpCounters, 0, sizeof(mIpCounters)); }
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
/**
|
||||
* This method returns a reference to the resolving queue.
|
||||
*
|
||||
* @returns A reference to the resolving queue.
|
||||
*
|
||||
*/
|
||||
const PriorityQueue &GetResolvingQueue(void) const { return mResolvingQueue; }
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
/**
|
||||
* This method handles a deferred ack.
|
||||
@@ -536,10 +527,6 @@ private:
|
||||
uint16_t & aSourcePort,
|
||||
uint16_t & aDestPort);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
otError ForwardDuaToBackboneLink(Message &aMessage, const Ip6::Address &aDst);
|
||||
#endif
|
||||
|
||||
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_NOTE)
|
||||
const char *MessageActionToString(MessageAction aAction, Error aError);
|
||||
const char *MessagePriorityToString(const Message &aMessage);
|
||||
@@ -605,7 +592,6 @@ private:
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
FragmentPriorityList mFragmentPriorityList;
|
||||
PriorityQueue mResolvingQueue;
|
||||
IndirectSender mIndirectSender;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -141,103 +141,84 @@ Error MeshForwarder::SendMessage(Message &aMessage)
|
||||
void MeshForwarder::HandleResolved(const Ip6::Address &aEid, Error aError)
|
||||
{
|
||||
Ip6::Address ip6Dst;
|
||||
bool enqueuedMessage = false;
|
||||
bool didUpdate = false;
|
||||
|
||||
for (Message &message : mResolvingQueue)
|
||||
for (Message &message : mSendQueue)
|
||||
{
|
||||
if (message.GetType() != Message::kTypeIp6)
|
||||
if (!message.IsResolvingAddress())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IgnoreError(message.Read(Ip6::Header::kDestinationFieldOffset, ip6Dst));
|
||||
|
||||
if (ip6Dst == aEid)
|
||||
if (ip6Dst != aEid)
|
||||
{
|
||||
mResolvingQueue.Dequeue(message);
|
||||
|
||||
if (aError == kErrorNone)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
// Pass back to IPv6 layer for DUA destination resolved by Backbone Query
|
||||
if (ForwardDuaToBackboneLink(message, ip6Dst) != kErrorNone)
|
||||
#endif
|
||||
{
|
||||
mSendQueue.Enqueue(message);
|
||||
enqueuedMessage = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogMessage(kMessageDrop, message, aError);
|
||||
message.Free();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aError != kErrorNone)
|
||||
{
|
||||
LogMessage(kMessageDrop, message, kErrorAddressQuery);
|
||||
mSendQueue.DequeueAndFree(message);
|
||||
continue;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
// Pass back to IPv6 layer for DUA destination resolved
|
||||
// by Backbone Query
|
||||
if (Get<BackboneRouter::Local>().IsPrimary() && Get<BackboneRouter::Leader>().IsDomainUnicast(ip6Dst) &&
|
||||
Get<AddressResolver>().LookUp(ip6Dst) == Get<Mle::MleRouter>().GetRloc16())
|
||||
{
|
||||
uint8_t hopLimit;
|
||||
|
||||
mSendQueue.Dequeue(message);
|
||||
|
||||
// Avoid decreasing Hop Limit twice
|
||||
IgnoreError(message.Read(Ip6::Header::kHopLimitFieldOffset, hopLimit));
|
||||
hopLimit++;
|
||||
message.Write(Ip6::Header::kHopLimitFieldOffset, hopLimit);
|
||||
|
||||
IgnoreError(Get<Ip6::Ip6>().HandleDatagram(message, nullptr, nullptr, /* aFromHost */ false));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
message.SetResolvingAddress(false);
|
||||
didUpdate = true;
|
||||
}
|
||||
|
||||
if (enqueuedMessage)
|
||||
if (didUpdate)
|
||||
{
|
||||
mScheduleTransmissionTask.Post();
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
|
||||
Error MeshForwarder::ForwardDuaToBackboneLink(Message &aMessage, const Ip6::Address &aDst)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
uint8_t ttl;
|
||||
|
||||
VerifyOrExit(Get<BackboneRouter::Local>().IsPrimary() && Get<BackboneRouter::Leader>().IsDomainUnicast(aDst),
|
||||
error = kErrorNoRoute);
|
||||
|
||||
VerifyOrExit(Get<AddressResolver>().LookUp(aDst) == Get<Mle::MleRouter>().GetRloc16(), error = kErrorNoRoute);
|
||||
|
||||
// Avoid decreasing TTL twice
|
||||
IgnoreError(aMessage.Read(Ip6::Header::kHopLimitFieldOffset, ttl));
|
||||
ttl++;
|
||||
aMessage.Write(Ip6::Header::kHopLimitFieldOffset, ttl);
|
||||
|
||||
IgnoreError(Get<Ip6::Ip6>().HandleDatagram(aMessage, nullptr, nullptr, /* aFromHost */ false));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
Error MeshForwarder::EvictMessage(Message::Priority aPriority)
|
||||
{
|
||||
Error error = kErrorNotFound;
|
||||
PriorityQueue *queues[] = {&mResolvingQueue, &mSendQueue};
|
||||
Message * evict = nullptr;
|
||||
Error error = kErrorNotFound;
|
||||
Message *evict = nullptr;
|
||||
|
||||
// search for a lower priority message to evict (choose lowest priority message among all queues)
|
||||
for (PriorityQueue *queue : queues)
|
||||
// Search for a lower priority message to evict
|
||||
for (uint8_t priority = 0; priority < aPriority; priority++)
|
||||
{
|
||||
for (uint8_t priority = 0; priority < aPriority; priority++)
|
||||
for (Message *message = mSendQueue.GetHeadForPriority(static_cast<Message::Priority>(priority)); message;
|
||||
message = message->GetNext())
|
||||
{
|
||||
for (Message *message = queue->GetHeadForPriority(static_cast<Message::Priority>(priority)); message;
|
||||
message = message->GetNext())
|
||||
if (message->GetPriority() != priority)
|
||||
{
|
||||
if (message->GetPriority() != priority)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (message->GetDoNotEvict())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
evict = message;
|
||||
aPriority = static_cast<Message::Priority>(priority);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (evict != nullptr)
|
||||
{
|
||||
ExitNow(error = kErrorNone);
|
||||
if (message->GetDoNotEvict())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
evict = message;
|
||||
error = kErrorNone;
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t priority = aPriority; priority < Message::kNumPriorities; priority++)
|
||||
|
||||
Reference in New Issue
Block a user