[mesh-forwarder] allow limiting max num of frames in direct tx queue (#7908)

This commit adds a new feature in `MeshForwarder` to specify a max
limit for the number of frames in tx queue marked for direct
transmission. `OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE`
specifies the maximum number. If set to zero then this behavior is
disabled, i.e., no check is performed on tx queue length.

This commit also adds a new message action log "Dropping (dir queue
full)" which indicates when a message is being dropped due to the
newly added check.
This commit is contained in:
Abtin Keshavarzian
2022-07-27 13:39:51 -07:00
committed by GitHub
parent c96bf599b7
commit 1c9373bb0c
5 changed files with 127 additions and 0 deletions
+16
View File
@@ -483,6 +483,22 @@
#define OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_FRAG_TAG_ENTRY_LIST_SIZE 16
#endif
/**
* @def OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE
*
* Specifies the maximum number of frames in direct tx queue before new direct tx messages are dropped.
*
* If set to zero then the behavior is disabled, i.e., no check is performed on tx queue length.
*
*/
#ifndef OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_3)
#define OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE 100
#else
#define OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE 0
#endif
#endif
/**
* @def OPENTHREAD_CONFIG_PLATFORM_RADIO_PROPRIETARY_SUPPORT
*
+96
View File
@@ -438,6 +438,89 @@ Error MeshForwarder::RemoveAgedMessages(void)
#endif // OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
bool MeshForwarder::IsDirectTxQueueOverMaxFrameThreshold(void) const
{
uint16_t frameCount = 0;
for (const Message &message : mSendQueue)
{
if (!message.IsDirectTransmission() || (&message == mSendMessage))
{
continue;
}
switch (message.GetType())
{
case Message::kTypeIp6:
{
// If it is an IPv6 message, we estimate the number of
// fragment frames assuming typical header sizes and lowpan
// compression. Since this estimate is only used for queue
// management, we lean towards an under estimate in sense
// that we may allow few more frames in the tx queue over
// threshold in some rare cases.
//
// The constants below are derived as follows: Typical MAC
// header (15 bytes) and MAC footer (6 bytes) leave 106
// bytes for MAC payload. Next fragment header is 5 bytes
// leaving 96 for next fragment payload. Lowpan compression
// on average compresses 40 bytes IPv6 header into about 19
// bytes leaving 87 bytes for the IPv6 payload, so the first
// fragment can fit 87 + 40 = 127 bytes.
static constexpr uint16_t kFirstFragmentMaxLength = 127;
static constexpr uint16_t kNextFragmentSize = 96;
uint16_t length = message.GetLength();
frameCount++;
if (length > kFirstFragmentMaxLength)
{
frameCount += (length - kFirstFragmentMaxLength) / kNextFragmentSize;
}
break;
}
case Message::kType6lowpan:
case Message::kTypeMacEmptyData:
frameCount++;
break;
case Message::kTypeSupervision:
default:
break;
}
}
return (frameCount > OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE);
}
void MeshForwarder::ApplyDirectTxQueueLimit(Message &aMessage)
{
VerifyOrExit(aMessage.IsDirectTransmission());
VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold());
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
if (RemoveAgedMessages() == kErrorNone)
{
VerifyOrExit(IsDirectTxQueueOverMaxFrameThreshold());
}
#endif
LogMessage(kMessageFullQueueDrop, aMessage);
aMessage.ClearDirectTransmission();
RemoveMessageIfNoPendingTx(aMessage);
exit:
return;
}
#endif // (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
{
aTasklet.Get<MeshForwarder>().ScheduleTransmissionTask();
@@ -1809,6 +1892,9 @@ const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aE
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
"Marked ECN", // (6) kMessageMarkEcn
"Dropping (queue mgmt)", // (7) kMessageQueueMgmtDrop
#endif
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
"Dropping (dir queue full)", // (8) kMessageFullQueueDrop
#endif
};
@@ -1823,6 +1909,13 @@ const char *MeshForwarder::MessageActionToString(MessageAction aAction, Error aE
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
static_assert(kMessageMarkEcn == 6, "kMessageMarkEcn is incorrect");
static_assert(kMessageQueueMgmtDrop == 7, "kMessageQueueMgmtDrop is incorrect");
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
static_assert(kMessageFullQueueDrop == 8, "kMessageFullQueueDrop is incorrect");
#endif
#else
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
static_assert(kMessageFullQueueDrop == 6, "kMessageFullQueueDrop is incorrect");
#endif
#endif
if ((aAction == kMessageTransmit) && (aError != kErrorNone))
@@ -1932,6 +2025,9 @@ void MeshForwarder::LogMessage(MessageAction aAction,
case kMessageEvict:
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
case kMessageQueueMgmtDrop:
#endif
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
case kMessageFullQueueDrop:
#endif
logLevel = kLogLevelNote;
break;
+7
View File
@@ -352,6 +352,9 @@ private:
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
kMessageMarkEcn, // Indicates that ECN is marked on an outbound message by delay-aware queue management.
kMessageQueueMgmtDrop, // Indicates that an outbound message is dropped by delay-aware queue management.
#endif
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
kMessageFullQueueDrop, // Indicates message drop due to reaching max allowed frames in direct tx queue.
#endif
};
@@ -460,6 +463,10 @@ private:
#if OPENTHREAD_CONFIG_DELAY_AWARE_QUEUE_MANAGEMENT_ENABLE
Error UpdateEcnOrDrop(Message &aMessage, bool aPreparingToSend = true);
Error RemoveAgedMessages(void);
#endif
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
bool IsDirectTxQueueOverMaxFrameThreshold(void) const;
void ApplyDirectTxQueueLimit(Message &aMessage);
#endif
void SendMesh(Message &aMessage, Mac::TxFrame &aFrame);
void SendDestinationUnreachable(uint16_t aMeshSource, const Ip6::Headers &aIp6Headers);
+4
View File
@@ -134,6 +134,10 @@ Error MeshForwarder::SendMessage(Message &aMessage)
break;
}
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
ApplyDirectTxQueueLimit(aMessage);
#endif
mScheduleTransmissionTask.Post();
return error;
+4
View File
@@ -47,6 +47,10 @@ Error MeshForwarder::SendMessage(Message &aMessage)
mSendQueue.Enqueue(aMessage);
mScheduleTransmissionTask.Post();
#if (OPENTHREAD_CONFIG_MAX_FRAMES_IN_DIRECT_TX_QUEUE > 0)
ApplyDirectTxQueueLimit(aMessage);
#endif
return kErrorNone;
}