[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.
This commit is contained in:
Abtin Keshavarzian
2019-07-16 08:38:29 -07:00
committed by Jonathan Hui
parent 54e7a9b7af
commit 7c548bba23
6 changed files with 135 additions and 56 deletions
+96 -35
View File
@@ -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<MeshForwarder>().HandleFrameRequest(sendFrame));
sendFrame.SetSequence(mDataSequence++);
break;
#if OPENTHREAD_FTD
case kOperationTransmitDataIndirect:
sendFrame.SetChannel(mRadioChannel);
sendFrame.SetMaxCsmaBackoffs(kMaxCsmaBackoffsIndirect);
sendFrame.SetMaxFrameRetries(kMaxFrameRetriesIndirect);
SuccessOrExit(error = Get<IndirectSender>().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<MeshForwarder>().HandleSentFrame(aFrame, aError);
PerformNextOperation();
break;
#if OPENTHREAD_FTD
case kOperationTransmitDataIndirect:
mCounters.mTxData++;
otDumpDebgMac("TX", aFrame.GetHeader(), aFrame.GetLength());
FinishOperation();
Get<IndirectSender>().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;
+22 -4
View File
@@ -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;
+12 -4
View File
@@ -150,6 +150,16 @@ exit:
return;
}
otError IndirectSender::HandleFrameRequest(Mac::Frame &aFrame)
{
return Get<MeshForwarder>().HandleFrameRequest(aFrame);
}
void IndirectSender::HandleSentFrame(Mac::Frame &aFrame, otError aError)
{
Get<MeshForwarder>().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<MeshForwarder>().mSendMessage = child.GetIndirectMessage();
Get<MeshForwarder>().mSendMessageMaxCsmaBackoffs = Mac::kMaxCsmaBackoffsIndirect;
Get<MeshForwarder>().mSendMessageMaxFrameRetries = Mac::kMaxFrameRetriesIndirect;
Get<MeshForwarder>().mSendMessage = child.GetIndirectMessage();
if (Get<MeshForwarder>().mSendMessage == NULL)
{
@@ -234,7 +242,7 @@ otError IndirectSender::GetIndirectTransmission(void)
mIndirectStartingChild = &child;
Get<Mac::Mac>().RequestFrameTransmission();
Get<Mac::Mac>().RequestIndirectFrameTransmission();
ExitNow(error = OT_ERROR_NONE);
}
+4
View File
@@ -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
{
+1 -10
View File
@@ -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<Mac::Mac>().RequestFrameTransmission();
Get<Mac::Mac>().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
-3
View File
@@ -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;