[mac] simplify the tx processing (#2411)

This commit is contained in:
Abtin Keshavarzian
2017-12-14 05:51:29 +00:00
committed by Jonathan Hui
parent 5b25a57db7
commit 7b706a9aa6
2 changed files with 82 additions and 115 deletions
+69 -102
View File
@@ -937,7 +937,7 @@ exit:
if (error != OT_ERROR_NONE)
{
TransmitDoneTask(mTxFrame, NULL, OT_ERROR_ABORT);
HandleTransmitDone(mTxFrame, NULL, OT_ERROR_ABORT);
}
}
@@ -947,12 +947,12 @@ extern "C" void otPlatRadioTxStarted(otInstance *aInstance, otRadioFrame *aFrame
otLogFuncEntry();
VerifyOrExit(instance->IsInitialized());
instance->GetThreadNetif().GetMac().TransmitStartedTask(aFrame);
instance->GetThreadNetif().GetMac().HandleTransmitStarted(aFrame);
exit:
otLogFuncExit();
}
void Mac::TransmitStartedTask(otRadioFrame *aFrame)
void Mac::HandleTransmitStarted(otRadioFrame *aFrame)
{
Frame *frame = static_cast<Frame *>(aFrame);
@@ -980,111 +980,60 @@ extern "C" void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame, o
else
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
{
instance->GetThreadNetif().GetMac().TransmitDoneTask(aFrame, aAckFrame, aError);
instance->GetThreadNetif().GetMac().HandleTransmitDone(aFrame, aAckFrame, aError);
}
exit:
otLogFuncExit();
}
void Mac::TransmitDoneTask(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
void Mac::HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError)
{
Frame *txFrame = static_cast<Frame *>(aFrame);
Address addr;
Frame &sendFrame = *static_cast<Frame *>(aFrame);
bool framePending = false;
Address dstAddr;
// Stop the ack timer.
mMacTimer.Stop();
txFrame->GetDstAddr(addr);
if (aError == OT_ERROR_NONE && txFrame->GetAckRequest() && aAckFrame != NULL)
{
Frame *ackFrame = static_cast<Frame *>(aAckFrame);
Neighbor *neighbor;
framePending = ackFrame->GetFramePending();
neighbor = GetNetif().GetMle().GetNeighbor(addr);
if (neighbor != NULL)
{
neighbor->GetLinkInfo().AddRss(GetNoiseFloor(), ackFrame->GetRssi());
}
}
if (aError == OT_ERROR_ABORT)
switch (aError)
{
case OT_ERROR_ABORT:
mCounters.mTxErrAbort++;
// fall through
case OT_ERROR_NONE:
case OT_ERROR_NO_ACK:
case OT_ERROR_CHANNEL_ACCESS_FAILURE:
break;
default:
assert(false);
ExitNow();
}
// Determine whether a CSMA retry is required.
if (aError == OT_ERROR_CHANNEL_ACCESS_FAILURE)
{
mCounters.mTxErrCca++;
}
if (!RadioSupportsCsmaBackoff() &&
aError == OT_ERROR_CHANNEL_ACCESS_FAILURE &&
mCsmaAttempts < kMaxCSMABackoffs)
{
mCsmaAttempts++;
StartCsmaBackoff();
ExitNow();
if (!RadioSupportsCsmaBackoff() && mCsmaAttempts < kMaxCSMABackoffs)
{
mCsmaAttempts++;
StartCsmaBackoff();
ExitNow();
}
}
mCsmaAttempts = 0;
switch (mOperation)
{
case kOperationTransmitData:
if (framePending && txFrame->IsDataRequestCommand())
{
mReceiveTimer.Start(kDataPollTimeout);
StartOperation(kOperationWaitingForData);
}
// fall through
case kOperationActiveScan:
case kOperationTransmitBeacon:
SentFrame(aError);
break;
default:
#if OPENTHREAD_ENABLE_RAW_LINK_API
if (GetInstance().GetLinkRaw().IsEnabled())
{
GetInstance().GetLinkRaw().InvokeTransmitDone(mTxFrame, NULL, OT_ERROR_NO_ACK);
}
else
#endif
{
assert(false);
}
break;
}
exit:
return;
}
void Mac::SentFrame(otError aError)
{
Frame &sendFrame(*mTxFrame);
Sender *sender;
Address addr;
// Determine whether to re-transmit the frame.
mTransmitAttempts++;
switch (aError)
{
case OT_ERROR_NONE:
break;
case OT_ERROR_CHANNEL_ACCESS_FAILURE:
case OT_ERROR_ABORT:
case OT_ERROR_NO_ACK:
if (aError != OT_ERROR_NONE)
{
char stringBuffer[Frame::kInfoStringSize];
@@ -1093,25 +1042,36 @@ void Mac::SentFrame(otError aError)
sendFrame.ToInfoString(stringBuffer, sizeof(stringBuffer)));
otDumpDebgMac(GetInstance(), "TX ERR", sendFrame.GetHeader(), 16);
if (!RadioSupportsRetries() &&
mTransmitAttempts < sendFrame.GetMaxTxAttempts())
if (!RadioSupportsRetries() && mTransmitAttempts < sendFrame.GetMaxTxAttempts())
{
StartCsmaBackoff();
mCounters.mTxRetry++;
StartCsmaBackoff();
ExitNow();
}
OT_UNUSED_VARIABLE(stringBuffer);
break;
}
default:
assert(false);
break;
}
mTransmitAttempts = 0;
mCsmaAttempts = 0;
// Process the ack frame for "frame pending".
sendFrame.GetDstAddr(dstAddr);
if (aError == OT_ERROR_NONE && sendFrame.GetAckRequest() && aAckFrame != NULL)
{
Frame &ackFrame = *static_cast<Frame *>(aAckFrame);
Neighbor *neighbor = GetNetif().GetMle().GetNeighbor(dstAddr);
framePending = ackFrame.GetFramePending();
if (neighbor != NULL)
{
neighbor->GetLinkInfo().AddRss(GetNoiseFloor(), ackFrame.GetRssi());
}
}
// Update MAC counters.
mCounters.mTxTotal++;
@@ -1120,16 +1080,12 @@ void Mac::SentFrame(otError aError)
mCounters.mTxErrBusyChannel++;
}
mTxFrame->GetDstAddr(addr);
if (addr.mShortAddress == kShortAddrBroadcast)
if (dstAddr.mShortAddress == kShortAddrBroadcast)
{
// Broadcast frame
mCounters.mTxBroadcast++;
}
else
{
// Unicast Frame
mCounters.mTxUnicast++;
}
@@ -1147,6 +1103,8 @@ void Mac::SentFrame(otError aError)
mCounters.mTxNoAckRequested++;
}
// Determine next action based on current operation.
switch (mOperation)
{
case kOperationActiveScan:
@@ -1160,8 +1118,17 @@ void Mac::SentFrame(otError aError)
break;
case kOperationTransmitData:
if (mReceiveTimer.IsRunning())
{
Sender *sender;
if (sendFrame.IsDataRequestCommand())
{
if (framePending)
{
mReceiveTimer.Start(kDataPollTimeout);
StartOperation(kOperationWaitingForData);
}
mCounters.mTxDataPoll++;
}
else
@@ -1186,9 +1153,9 @@ void Mac::SentFrame(otError aError)
otDumpDebgMac(GetInstance(), "TX", sendFrame.GetHeader(), sendFrame.GetLength());
sender->HandleSentFrame(sendFrame, aError);
FinishOperation();
break;
}
default:
assert(false);
@@ -1319,7 +1286,7 @@ void Mac::HandleMacTimer(void)
case kOperationTransmitData:
otLogDebgMac(GetInstance(), "Ack timer fired");
SentFrame(OT_ERROR_NO_ACK);
HandleTransmitDone(mTxFrame, NULL, OT_ERROR_NO_ACK);
break;
default:
@@ -1527,14 +1494,14 @@ extern "C" void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFra
else
#endif // OPENTHREAD_ENABLE_RAW_LINK_API
{
instance->GetThreadNetif().GetMac().ReceiveDoneTask(static_cast<Frame *>(aFrame), aError);
instance->GetThreadNetif().GetMac().HandleReceivedFrame(static_cast<Frame *>(aFrame), aError);
}
exit:
otLogFuncExit();
}
void Mac::ReceiveDoneTask(Frame *aFrame, otError aError)
void Mac::HandleReceivedFrame(Frame *aFrame, otError aError)
{
Address srcaddr;
Address dstaddr;
+13 -13
View File
@@ -164,7 +164,8 @@ class Sender: public OwnerLocator
public:
/**
* This function pointer is called when the MAC is about to transmit the frame.
* This function pointer is called when the MAC is about to transmit the frame asking MAC sender client to provide
* the frame.
*
* @param[in] aSender A reference to the MAC sender client object.
* @param[in] aFrame A reference to the MAC frame buffer.
@@ -466,34 +467,34 @@ public:
#endif // OPENTHREAD_ENABLE_MAC_FILTER
/**
* This method is called to handle receive events.
* This method is called to handle a received frame.
*
* @param[in] aFrame A pointer to the received frame, or NULL if the receive operation aborted.
* @param[in] aError OT_ERROR_NONE when successfully received a frame, OT_ERROR_ABORT when reception
* was aborted and a frame was not received.
* @param[in] aFrame A pointer to the received frame, or NULL if the receive operation was aborted.
* @param[in] aError OT_ERROR_NONE when successfully received a frame,
* OT_ERROR_ABORT when reception was aborted and a frame was not received.
*
*/
void ReceiveDoneTask(Frame *aFrame, otError aError);
void HandleReceivedFrame(Frame *aFrame, otError aError);
/**
* This method is called to handle transmission start events.
*
* @param[in] aFrame A pointer to the frame that is transmitted.
*/
void TransmitStartedTask(otRadioFrame *aFrame);
void HandleTransmitStarted(otRadioFrame *aFrame);
/**
* This method is called to handle transmit events.
*
* @param[in] aFrame A pointer to the frame that was transmitted.
* @param[in] aAckFrame A pointer to the ACK frame, NULL if no ACK was received.
* @param[in] aError OT_ERROR_NONE when the frame was transmitted, OT_ERROR_NO_ACK when the frame was
* transmitted but no ACK was received, OT_ERROR_CHANNEL_ACCESS_FAILURE when the
* transmission could not take place due to activity on the channel, OT_ERROR_ABORT when
* transmission was aborted for other reasons.
* @param[in] aError OT_ERROR_NONE when the frame was transmitted,
* OT_ERROR_NO_ACK when the frame was transmitted but no ACK was received,
* OT_ERROR_CHANNEL_ACCESS_FAILURE when the tx failed due to activity on the channel,
* OT_ERROR_ABORT when transmission was aborted for other reasons.
*
*/
void TransmitDoneTask(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
void HandleTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError);
/**
* This method returns if an active scan is in progress.
@@ -627,7 +628,6 @@ private:
void UpdateIdleMode(void);
void StartOperation(Operation aOperation);
void FinishOperation(void);
void SentFrame(otError aError);
void SendBeaconRequest(Frame &aFrame);
void SendBeacon(Frame &aFrame);
void StartBackoff(void);