mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 10:27:49 +00:00
[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:
committed by
Jonathan Hui
parent
54e7a9b7af
commit
7c548bba23
+96
-35
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user