From 7c548bba23394909b787af91e36087964c3f3e0b Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 19 Jun 2019 18:28:35 -0700 Subject: [PATCH] [mac] add new operation for indirect data frame transmission (#3952) This commit adds a new operation for indirect data frame transmission in `Mac` class (only available on FTD build). The indirect tx request is handled before a direct tx request. This commit also changes how the number of retries and CMSA attempts (for a frame) are determined `Mac` class itself now sets these according to request type. --- src/core/mac/mac.cpp | 131 ++++++++++++++++++++-------- src/core/mac/mac.hpp | 26 +++++- src/core/thread/indirect_sender.cpp | 16 +++- src/core/thread/indirect_sender.hpp | 4 + src/core/thread/mesh_forwarder.cpp | 11 +-- src/core/thread/mesh_forwarder.hpp | 3 - 6 files changed, 135 insertions(+), 56 deletions(-) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 5afa1e8f6..4937b8301 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -72,7 +72,10 @@ Mac::Mac(Instance &aInstance) , mPendingActiveScan(false) , mPendingEnergyScan(false) , mPendingTransmitBeacon(false) - , mPendingTransmitData(false) + , mPendingTransmitDataDirect(false) +#if OPENTHREAD_FTD + , mPendingTransmitDataIndirect(false) +#endif , mPendingTransmitPoll(false) , mPendingTransmitOobFrame(false) , mPendingWaitingForData(false) @@ -180,7 +183,10 @@ bool Mac::IsInTransmitState(void) const switch (mOperation) { - case kOperationTransmitData: + case kOperationTransmitDataDirect: +#if OPENTHREAD_FTD + case kOperationTransmitDataIndirect: +#endif case kOperationTransmitBeacon: case kOperationTransmitPoll: case kOperationTransmitOutOfBandFrame: @@ -478,19 +484,35 @@ exit: return; } -otError Mac::RequestFrameTransmission(void) +otError Mac::RequestDirectFrameTransmission(void) { otError error = OT_ERROR_NONE; VerifyOrExit(mEnabled, error = OT_ERROR_INVALID_STATE); - VerifyOrExit(!mPendingTransmitData && (mOperation != kOperationTransmitData), error = OT_ERROR_ALREADY); + VerifyOrExit(!mPendingTransmitDataDirect && (mOperation != kOperationTransmitDataDirect), error = OT_ERROR_ALREADY); - StartOperation(kOperationTransmitData); + StartOperation(kOperationTransmitDataDirect); exit: return error; } +#if OPENTHREAD_FTD +otError Mac::RequestIndirectFrameTransmission(void) +{ + otError error = OT_ERROR_NONE; + + VerifyOrExit(mEnabled, error = OT_ERROR_INVALID_STATE); + VerifyOrExit(!mPendingTransmitDataIndirect && (mOperation != kOperationTransmitDataIndirect), + error = OT_ERROR_ALREADY); + + StartOperation(kOperationTransmitDataIndirect); + +exit: + return error; +} +#endif + otError Mac::RequestOutOfBandFrameTransmission(otRadioFrame *aOobFrame) { otError error = OT_ERROR_NONE; @@ -516,10 +538,10 @@ otError Mac::RequestDataPollTransmission(void) VerifyOrExit(!mPendingTransmitPoll && (mOperation != kOperationTransmitPoll), error = OT_ERROR_ALREADY); // We ensure data frame and data poll tx requests are handled in the - // order they are requested. So if we have a pending data frame tx - // request, it should be sent before the poll frame. + // order they are requested. So if we have a pending direct data frame + // tx request, it should be sent before the poll frame. - mShouldTxPollBeforeData = !mPendingTransmitData; + mShouldTxPollBeforeData = !mPendingTransmitDataDirect; StartOperation(kOperationTransmitPoll); @@ -597,10 +619,16 @@ void Mac::StartOperation(Operation aOperation) mPendingTransmitBeacon = true; break; - case kOperationTransmitData: - mPendingTransmitData = true; + case kOperationTransmitDataDirect: + mPendingTransmitDataDirect = true; break; +#if OPENTHREAD_FTD + case kOperationTransmitDataIndirect: + mPendingTransmitDataIndirect = true; + break; +#endif + case kOperationTransmitPoll: mPendingTransmitPoll = true; break; @@ -631,13 +659,16 @@ void Mac::PerformNextOperation(void) if (!mEnabled) { - mPendingWaitingForData = false; - mPendingTransmitOobFrame = false; - mPendingActiveScan = false; - mPendingEnergyScan = false; - mPendingTransmitBeacon = false; - mPendingTransmitData = false; - mPendingTransmitPoll = false; + mPendingWaitingForData = false; + mPendingTransmitOobFrame = false; + mPendingActiveScan = false; + mPendingEnergyScan = false; + mPendingTransmitBeacon = false; + mPendingTransmitDataDirect = false; +#if OPENTHREAD_FTD + mPendingTransmitDataIndirect = false; +#endif + mPendingTransmitPoll = false; mTimer.Stop(); #if OPENTHREAD_CONFIG_STAY_AWAKE_BETWEEN_FRAGMENTS mDelayingSleep = false; @@ -674,15 +705,22 @@ void Mac::PerformNextOperation(void) mPendingTransmitBeacon = false; mOperation = kOperationTransmitBeacon; } - else if (mPendingTransmitPoll && (!mPendingTransmitData || mShouldTxPollBeforeData)) +#if OPENTHREAD_FTD + else if (mPendingTransmitDataIndirect) + { + mPendingTransmitDataIndirect = false; + mOperation = kOperationTransmitDataIndirect; + } +#endif + else if (mPendingTransmitPoll && (!mPendingTransmitDataDirect || mShouldTxPollBeforeData)) { mPendingTransmitPoll = false; mOperation = kOperationTransmitPoll; } - else if (mPendingTransmitData) + else if (mPendingTransmitDataDirect) { - mPendingTransmitData = false; - mOperation = kOperationTransmitData; + mPendingTransmitDataDirect = false; + mOperation = kOperationTransmitDataDirect; } if (mOperation != kOperationIdle) @@ -705,7 +743,10 @@ void Mac::PerformNextOperation(void) break; case kOperationTransmitBeacon: - case kOperationTransmitData: + case kOperationTransmitDataDirect: +#if OPENTHREAD_FTD + case kOperationTransmitDataIndirect: +#endif case kOperationTransmitPoll: case kOperationTransmitOutOfBandFrame: BeginTransmit(); @@ -1013,18 +1054,28 @@ void Mac::BeginTransmit(void) sendFrame.SetMaxFrameRetries(kMaxFrameRetriesDirect); break; - case kOperationTransmitData: + case kOperationTransmitDataDirect: sendFrame.SetChannel(mRadioChannel); - + sendFrame.SetMaxCsmaBackoffs(kMaxCsmaBackoffsDirect); + sendFrame.SetMaxFrameRetries(kMaxFrameRetriesDirect); SuccessOrExit(error = Get().HandleFrameRequest(sendFrame)); + sendFrame.SetSequence(mDataSequence++); + break; + +#if OPENTHREAD_FTD + case kOperationTransmitDataIndirect: + sendFrame.SetChannel(mRadioChannel); + sendFrame.SetMaxCsmaBackoffs(kMaxCsmaBackoffsIndirect); + sendFrame.SetMaxFrameRetries(kMaxFrameRetriesIndirect); + SuccessOrExit(error = Get().HandleFrameRequest(sendFrame)); // If the frame is marked as a retransmission, then data sequence number is already set. if (!sendFrame.IsARetransmission()) { - sendFrame.SetSequence(mDataSequence); + sendFrame.SetSequence(mDataSequence++); } - break; +#endif case kOperationTransmitOutOfBandFrame: sendFrame.CopyFrom(*mOobFrame); @@ -1264,20 +1315,24 @@ void Mac::HandleTransmitDone(Frame &aFrame, Frame *aAckFrame, otError aError) PerformNextOperation(); break; - case kOperationTransmitData: + case kOperationTransmitDataDirect: mCounters.mTxData++; - - if (!aFrame.IsARetransmission()) - { - mDataSequence++; - } - otDumpDebgMac("TX", aFrame.GetHeader(), aFrame.GetLength()); FinishOperation(); Get().HandleSentFrame(aFrame, aError); PerformNextOperation(); break; +#if OPENTHREAD_FTD + case kOperationTransmitDataIndirect: + mCounters.mTxData++; + otDumpDebgMac("TX", aFrame.GetHeader(), aFrame.GetLength()); + FinishOperation(); + Get().HandleSentFrame(aFrame, aError); + PerformNextOperation(); + break; +#endif + case kOperationTransmitOutOfBandFrame: FinishOperation(); PerformNextOperation(); @@ -1861,10 +1916,16 @@ const char *Mac::OperationToString(Operation aOperation) retval = "TransmitBeacon"; break; - case kOperationTransmitData: - retval = "TransmitData"; + case kOperationTransmitDataDirect: + retval = "TransmitDataDirect"; break; +#if OPENTHREAD_FTD + case kOperationTransmitDataIndirect: + retval = "TransmitDataIndirect"; + break; +#endif + case kOperationTransmitPoll: retval = "TransmitPoll"; break; diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index f6ae7aee8..157b0ec50 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -208,14 +208,26 @@ public: void SetRxOnWhenIdle(bool aRxOnWhenIdle); /** - * This method requests a new MAC frame transmission. + * This method requests a direct data frame transmission. * * @retval OT_ERROR_NONE Frame transmission request is scheduled successfully. * @retval OT_ERROR_ALREADY MAC is busy sending earlier transmission request. * @retval OT_ERROR_INVALID_STATE The MAC layer is not enabled. * */ - otError RequestFrameTransmission(void); + otError RequestDirectFrameTransmission(void); + +#if OPENTHREAD_FTD + /** + * This method requests an indirect data frame transmission. + * + * @retval OT_ERROR_NONE Frame transmission request is scheduled successfully. + * @retval OT_ERROR_ALREADY MAC is busy sending earlier transmission request. + * @retval OT_ERROR_INVALID_STATE The MAC layer is not enabled. + * + */ + otError RequestIndirectFrameTransmission(void); +#endif /** * This method requests an Out of Band frame for MAC Transmission. @@ -600,7 +612,10 @@ private: kOperationActiveScan, kOperationEnergyScan, kOperationTransmitBeacon, - kOperationTransmitData, + kOperationTransmitDataDirect, +#if OPENTHREAD_FTD + kOperationTransmitDataIndirect, +#endif kOperationTransmitPoll, kOperationWaitingForData, kOperationTransmitOutOfBandFrame, @@ -662,7 +677,10 @@ private: bool mPendingActiveScan : 1; bool mPendingEnergyScan : 1; bool mPendingTransmitBeacon : 1; - bool mPendingTransmitData : 1; + bool mPendingTransmitDataDirect : 1; +#if OPENTHREAD_FTD + bool mPendingTransmitDataIndirect : 1; +#endif bool mPendingTransmitPoll : 1; bool mPendingTransmitOobFrame : 1; bool mPendingWaitingForData : 1; diff --git a/src/core/thread/indirect_sender.cpp b/src/core/thread/indirect_sender.cpp index 92c2c7684..a8ae327e1 100644 --- a/src/core/thread/indirect_sender.cpp +++ b/src/core/thread/indirect_sender.cpp @@ -150,6 +150,16 @@ exit: return; } +otError IndirectSender::HandleFrameRequest(Mac::Frame &aFrame) +{ + return Get().HandleFrameRequest(aFrame); +} + +void IndirectSender::HandleSentFrame(Mac::Frame &aFrame, otError aError) +{ + Get().HandleSentFrame(aFrame, aError); +} + void IndirectSender::HandleDataPoll(const Mac::Frame & aFrame, const Mac::Address & aMacSource, const otThreadLinkInfo &aLinkInfo) @@ -200,9 +210,7 @@ otError IndirectSender::GetIndirectTransmission(void) continue; } - Get().mSendMessage = child.GetIndirectMessage(); - Get().mSendMessageMaxCsmaBackoffs = Mac::kMaxCsmaBackoffsIndirect; - Get().mSendMessageMaxFrameRetries = Mac::kMaxFrameRetriesIndirect; + Get().mSendMessage = child.GetIndirectMessage(); if (Get().mSendMessage == NULL) { @@ -234,7 +242,7 @@ otError IndirectSender::GetIndirectTransmission(void) mIndirectStartingChild = &child; - Get().RequestFrameTransmission(); + Get().RequestIndirectFrameTransmission(); ExitNow(error = OT_ERROR_NONE); } diff --git a/src/core/thread/indirect_sender.hpp b/src/core/thread/indirect_sender.hpp index de6835aa9..676b39f17 100644 --- a/src/core/thread/indirect_sender.hpp +++ b/src/core/thread/indirect_sender.hpp @@ -194,6 +194,10 @@ public: otError GetIndirectTransmission(void); void HandleSentFrameToChild(const Mac::Frame &aFrame, otError aError, const Mac::Address &aMacDest); + // Callbacks from MAC layer + void HandleSentFrame(Mac::Frame &aFrame, otError aError); + otError HandleFrameRequest(Mac::Frame &aFrame); + private: enum { diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index f6cbea649..ceed0db3f 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -62,8 +62,6 @@ MeshForwarder::MeshForwarder(Instance &aInstance) , mMessageNextOffset(0) , mSendMessage(NULL) , mSendMessageIsARetransmission(false) - , mSendMessageMaxCsmaBackoffs(Mac::kMaxCsmaBackoffsDirect) - , mSendMessageMaxFrameRetries(Mac::kMaxFrameRetriesDirect) , mMeshSource() , mMeshDest() , mAddMeshHeader(false) @@ -80,7 +78,6 @@ MeshForwarder::MeshForwarder(Instance &aInstance) , mSendMessageFrameCounter(0) , mSendMessageKeyId(0) , mSendMessageDataSequenceNumber(0) - , mIndirectStartingChild(NULL) #endif , mDataPollSender(aInstance) { @@ -192,9 +189,7 @@ void MeshForwarder::ScheduleTransmissionTask(void) mSendMessage->SetTxSuccess(true); } - mSendMessageMaxCsmaBackoffs = Mac::kMaxCsmaBackoffsDirect; - mSendMessageMaxFrameRetries = Mac::kMaxFrameRetriesDirect; - Get().RequestFrameTransmission(); + Get().RequestDirectFrameTransmission(); ExitNow(); } @@ -503,8 +498,6 @@ otError MeshForwarder::HandleFrameRequest(Mac::Frame &aFrame) { SendEmptyFrame(aFrame, false); aFrame.SetIsARetransmission(false); - aFrame.SetMaxCsmaBackoffs(Mac::kMaxCsmaBackoffsDirect); - aFrame.SetMaxFrameRetries(Mac::kMaxFrameRetriesDirect); ExitNow(); } @@ -574,8 +567,6 @@ otError MeshForwarder::HandleFrameRequest(Mac::Frame &aFrame) assert(error == OT_ERROR_NONE); aFrame.SetIsARetransmission(mSendMessageIsARetransmission); - aFrame.SetMaxCsmaBackoffs(mSendMessageMaxCsmaBackoffs); - aFrame.SetMaxFrameRetries(mSendMessageMaxFrameRetries); #if OPENTHREAD_FTD diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 3e82f297a..b325e4c35 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -503,8 +503,6 @@ private: Message *mSendMessage; bool mSendMessageIsARetransmission; - uint8_t mSendMessageMaxCsmaBackoffs; - uint8_t mSendMessageMaxFrameRetries; Mac::Address mMacSource; Mac::Address mMacDest; @@ -532,7 +530,6 @@ private: uint32_t mSendMessageFrameCounter; uint8_t mSendMessageKeyId; uint8_t mSendMessageDataSequenceNumber; - Child * mIndirectStartingChild; #endif DataPollSender mDataPollSender;