[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:
Abtin Keshavarzian
2022-04-12 09:22:23 -07:00
committed by GitHub
parent cbd1d50995
commit a2106646bc
5 changed files with 81 additions and 103 deletions
-4
View File
@@ -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
+27 -9
View File
@@ -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.
*
+2 -5
View File
@@ -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:
-14
View File
@@ -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
+52 -71
View File
@@ -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++)