mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 06:17:47 +00:00
[mesh-forwarder] collision avoidance delay mechanism (#7512)
This commit adds a new feature in `MeshForwarder` to add wait delay after a successful frame tx to a neighbor which is expected to forward the frame. This wait time applies before the next direct tx to any neighbor on an FTD. This mechanism is intended to help prevent self-interference when messages are sent to a destination that is at least 2-hops away. This commit adds new OT build configs to enable/disable this behavior and specify the wait interval (default is set to 8 msec).
This commit is contained in:
@@ -119,6 +119,32 @@
|
||||
#define OPENTHREAD_CONFIG_MAC_RETX_DELAY_MAX_BACKOFF_EXPONENT 5
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
*
|
||||
* Define as 1 to enable collision avoidance delay feature, which adds a delay wait time after a successful frame tx
|
||||
* to a neighbor which is expected to forward the frame. This delay is applied before the next direct frame tx (towards
|
||||
* any neighbor) on an FTD.
|
||||
*
|
||||
* The delay interval is specified by `OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL` (in milliseconds).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
#define OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL
|
||||
*
|
||||
* Specifies the collision avoidance delay interval in milliseconds. This is added after a successful frame tx to a
|
||||
* neighbor that is expected to forward the frame (when `OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE` is
|
||||
* enabled).
|
||||
*
|
||||
*/
|
||||
#ifndef OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL
|
||||
#define OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL 8
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @def OPENTHREAD_CONFIG_MAC_RETRY_SUCCESS_HISTOGRAM_ENABLE
|
||||
*
|
||||
|
||||
@@ -101,6 +101,10 @@ MeshForwarder::MeshForwarder(Instance &aInstance)
|
||||
, mEnabled(false)
|
||||
, mTxPaused(false)
|
||||
, mSendBusy(false)
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
, mDelayNextTx(false)
|
||||
, mTxDelayTimer(aInstance, HandleTxDelayTimer)
|
||||
#endif
|
||||
, mScheduleTransmissionTask(aInstance, MeshForwarder::ScheduleTransmissionTask)
|
||||
#if OPENTHREAD_FTD
|
||||
, mIndirectSender(aInstance)
|
||||
@@ -145,6 +149,11 @@ void MeshForwarder::Stop(void)
|
||||
mFragmentPriorityList.Clear();
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
mTxDelayTimer.Stop();
|
||||
mDelayNextTx = false;
|
||||
#endif
|
||||
|
||||
mEnabled = false;
|
||||
mSendMessage = nullptr;
|
||||
Get<Mac::Mac>().SetRxOnWhenIdle(false);
|
||||
@@ -237,6 +246,20 @@ void MeshForwarder::ResumeMessageTransmissions(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
void MeshForwarder::HandleTxDelayTimer(Timer &aTimer)
|
||||
{
|
||||
aTimer.Get<MeshForwarder>().HandleTxDelayTimer();
|
||||
}
|
||||
|
||||
void MeshForwarder::HandleTxDelayTimer(void)
|
||||
{
|
||||
mDelayNextTx = false;
|
||||
mScheduleTransmissionTask.Post();
|
||||
LogDebg("Tx delay timer expired");
|
||||
}
|
||||
#endif
|
||||
|
||||
void MeshForwarder::ScheduleTransmissionTask(Tasklet &aTasklet)
|
||||
{
|
||||
aTasklet.Get<MeshForwarder>().ScheduleTransmissionTask();
|
||||
@@ -246,6 +269,10 @@ void MeshForwarder::ScheduleTransmissionTask(void)
|
||||
{
|
||||
VerifyOrExit(!mSendBusy && !mTxPaused);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
VerifyOrExit(!mDelayNextTx);
|
||||
#endif
|
||||
|
||||
mSendMessage = PrepareNextDirectTransmission();
|
||||
VerifyOrExit(mSendMessage != nullptr);
|
||||
|
||||
@@ -996,6 +1023,18 @@ void MeshForwarder::HandleSentFrame(Mac::TxFrame &aFrame, Error aError)
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
if (mDelayNextTx && (aError == kErrorNone))
|
||||
{
|
||||
mTxDelayTimer.Start(kTxDelayInterval);
|
||||
LogDebg("Start tx delay timer for %u msec", kTxDelayInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDelayNextTx = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!aFrame.IsEmpty())
|
||||
{
|
||||
IgnoreError(aFrame.GetDstAddr(macDest));
|
||||
|
||||
@@ -334,6 +334,8 @@ private:
|
||||
static constexpr uint8_t kMeshHeaderFrameMtu = OT_RADIO_FRAME_MAX_SIZE; // Max MTU with a Mesh Header frame.
|
||||
static constexpr uint8_t kMeshHeaderFrameFcsSize = sizeof(uint16_t); // Frame FCS size for Mesh Header frame.
|
||||
|
||||
static constexpr uint32_t kTxDelayInterval = OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_INTERVAL; // In msec
|
||||
|
||||
enum MessageAction : uint8_t
|
||||
{
|
||||
kMessageReceive, // Indicates that the message was received.
|
||||
@@ -503,11 +505,15 @@ private:
|
||||
void PauseMessageTransmissions(void) { mTxPaused = true; }
|
||||
void ResumeMessageTransmissions(void);
|
||||
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
static void HandleTxDelayTimer(Timer &aTimer);
|
||||
void HandleTxDelayTimer(void);
|
||||
#endif
|
||||
|
||||
void LogMessage(MessageAction aAction,
|
||||
const Message & aMessage,
|
||||
Error aError = kErrorNone,
|
||||
const Mac::Address *aAddress = nullptr);
|
||||
|
||||
void LogFrame(const char *aActionText, const Mac::Frame &aFrame, Error aError);
|
||||
void LogFragmentFrameDrop(Error aError,
|
||||
uint16_t aFrameLength,
|
||||
@@ -585,6 +591,10 @@ private:
|
||||
bool mEnabled : 1;
|
||||
bool mTxPaused : 1;
|
||||
bool mSendBusy : 1;
|
||||
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
bool mDelayNextTx : 1;
|
||||
TimerMilli mTxDelayTimer;
|
||||
#endif
|
||||
|
||||
Tasklet mScheduleTransmissionTask;
|
||||
|
||||
|
||||
@@ -403,6 +403,13 @@ Error MeshForwarder::UpdateMeshRoute(Message &aMessage)
|
||||
mMeshDest = meshHeader.GetDestination();
|
||||
mMeshSource = meshHeader.GetSource();
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
if (mMacDest.GetShort() != mMeshDest)
|
||||
{
|
||||
mDelayNextTx = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
@@ -616,6 +623,9 @@ Error MeshForwarder::UpdateIp6RouteFtd(Ip6::Header &ip6Header, Message &aMessage
|
||||
// destination is not neighbor
|
||||
mMacSource.SetShort(mMeshSource);
|
||||
mAddMeshHeader = true;
|
||||
#if OPENTHREAD_CONFIG_MAC_COLLISION_AVOIDANCE_DELAY_ENABLE
|
||||
mDelayNextTx = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
Reference in New Issue
Block a user