mirror of
https://github.com/espressif/openthread.git
synced 2026-09-13 12:40:05 +00:00
[mac] set tx frame as empty when tx aborted during frame preparation (#4265)
The TxDone callbacks can be invoked with `OT_ERROR_ABORT` from two different paths: Either when OpenThread itself cannot prepare the tx frame (e.g., message was removed while waiting for MAC to handle a tx request and ask next layers to prepare the frame) or when the radio platform itself need to abort the tx. This commit changes the code such that in the first case, the frame length is set to zero to mark it as empty. The empty frame helps differentiate between the two cases and ensures that a previously tx frame is not incorrectly used from the TxDone callbacks. The TxDone callback handlers (in `MeshForwarder`, `DataPollHanlder`, `IndirectSender` and `DataPollHandler` are updated to check for frame not being empty when processing the frame.
This commit is contained in:
committed by
Jonathan Hui
parent
aaafa1a480
commit
ed8c9f18df
@@ -250,7 +250,7 @@ void DataPollHandler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (aChild.GetIndirectTxAttempts() < kMaxPollTriggeredTxAttempts)
|
||||
if ((aChild.GetIndirectTxAttempts() < kMaxPollTriggeredTxAttempts) && !aFrame.IsEmpty())
|
||||
{
|
||||
// We save the frame counter, key id, and data sequence number of
|
||||
// current frame so we use the same values for the retransmission
|
||||
|
||||
@@ -199,8 +199,11 @@ void DataPollSender::HandlePollSent(Mac::TxFrame &aFrame, otError aError)
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
aFrame.GetDstAddr(macDest);
|
||||
Get<MeshForwarder>().UpdateNeighborOnSentFrame(aFrame, aError, macDest);
|
||||
if (!aFrame.IsEmpty())
|
||||
{
|
||||
aFrame.GetDstAddr(macDest);
|
||||
Get<MeshForwarder>().UpdateNeighborOnSentFrame(aFrame, aError, macDest);
|
||||
}
|
||||
|
||||
if (Get<Mle::MleRouter>().GetParentCandidate()->GetState() == Neighbor::kStateInvalid)
|
||||
{
|
||||
|
||||
+26
-14
@@ -1114,6 +1114,13 @@ exit:
|
||||
|
||||
if (error != OT_ERROR_NONE)
|
||||
{
|
||||
// If the sendFrame could not be prepared and the tx is being
|
||||
// aborted, we set the frame length to zero to mark it as empty.
|
||||
// The empty frame helps differentiate between an aborted tx due
|
||||
// to OpenThread itself not being able to prepare the frame, versus
|
||||
// the radio platform aborting the tx operation.
|
||||
|
||||
sendFrame.SetLength(0);
|
||||
HandleTransmitDone(sendFrame, NULL, OT_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
@@ -1149,6 +1156,8 @@ void Mac::RecordFrameTransmitStatus(const TxFrame &aFrame,
|
||||
Address dstAddr;
|
||||
Neighbor *neighbor;
|
||||
|
||||
VerifyOrExit(!aFrame.IsEmpty());
|
||||
|
||||
aFrame.GetDstAddr(dstAddr);
|
||||
neighbor = Get<Mle::MleRouter>().GetNeighbor(dstAddr);
|
||||
|
||||
@@ -1251,23 +1260,26 @@ exit:
|
||||
|
||||
void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError)
|
||||
{
|
||||
Address dstAddr;
|
||||
|
||||
// Determine whether to re-transmit a broadcast frame.
|
||||
|
||||
aFrame.GetDstAddr(dstAddr);
|
||||
|
||||
if (dstAddr.IsBroadcast())
|
||||
if (!aFrame.IsEmpty())
|
||||
{
|
||||
mBroadcastTransmitCount++;
|
||||
Address dstAddr;
|
||||
|
||||
if (mBroadcastTransmitCount < kTxNumBcast)
|
||||
// Determine whether to re-transmit a broadcast frame.
|
||||
|
||||
aFrame.GetDstAddr(dstAddr);
|
||||
|
||||
if (dstAddr.IsBroadcast())
|
||||
{
|
||||
mSubMac.Send();
|
||||
ExitNow();
|
||||
}
|
||||
mBroadcastTransmitCount++;
|
||||
|
||||
mBroadcastTransmitCount = 0;
|
||||
if (mBroadcastTransmitCount < kTxNumBcast)
|
||||
{
|
||||
mSubMac.Send();
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mBroadcastTransmitCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine next action based on current operation.
|
||||
@@ -1286,7 +1298,7 @@ void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, otError aError
|
||||
break;
|
||||
|
||||
case kOperationTransmitPoll:
|
||||
assert(aFrame.GetAckRequest());
|
||||
assert(aFrame.IsEmpty() || aFrame.GetAckRequest());
|
||||
|
||||
if ((aError == OT_ERROR_NONE) && (aAckFrame != NULL))
|
||||
{
|
||||
|
||||
@@ -851,6 +851,15 @@ public:
|
||||
*/
|
||||
typedef String<kInfoStringSize> InfoString;
|
||||
|
||||
/**
|
||||
* This method indicates whether the frame is empty (no payload).
|
||||
*
|
||||
* @retval TRUE The frame is empty (no PSDU payload).
|
||||
* @retval FALSE The frame is not empty.
|
||||
*
|
||||
*/
|
||||
bool IsEmpty(void) const { return (mLength == 0); }
|
||||
|
||||
/**
|
||||
* This method initializes the MAC header.
|
||||
*
|
||||
|
||||
@@ -515,8 +515,11 @@ void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
|
||||
}
|
||||
#endif
|
||||
|
||||
aFrame.GetDstAddr(macDest);
|
||||
Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageTransmit, *message, &macDest, txError);
|
||||
if (!aFrame.IsEmpty())
|
||||
{
|
||||
aFrame.GetDstAddr(macDest);
|
||||
Get<MeshForwarder>().LogMessage(MeshForwarder::kMessageTransmit, *message, &macDest, txError);
|
||||
}
|
||||
|
||||
if (message->GetType() == Message::kTypeIp6)
|
||||
{
|
||||
|
||||
@@ -897,8 +897,11 @@ void MeshForwarder::HandleSentFrame(Mac::TxFrame &aFrame, otError aError)
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
aFrame.GetDstAddr(macDest);
|
||||
neighbor = UpdateNeighborOnSentFrame(aFrame, aError, macDest);
|
||||
if (!aFrame.IsEmpty())
|
||||
{
|
||||
aFrame.GetDstAddr(macDest);
|
||||
neighbor = UpdateNeighborOnSentFrame(aFrame, aError, macDest);
|
||||
}
|
||||
|
||||
VerifyOrExit(mSendMessage != NULL);
|
||||
assert(mSendMessage->GetDirectTransmission());
|
||||
|
||||
Reference in New Issue
Block a user