mirror of
https://github.com/espressif/openthread.git
synced 2026-08-13 14:17:47 +00:00
[indirect-sender] skip over HandleSentFrameToChild() for an empty frame (#6293)
This commit updates `IndirectSender` to check exit quickly from the `HandleSentFrameToChild()` callback if the sent frame is an empty frame. `PrepareFrameForChild()` prepares an empty frame when there is no indirect message in the send queue for the child. This can happen in the (not common) situation where the radio platform does not support the "source address match" feature and always include "frame pending" flag in acks to data poll frames. The change in this commit address a potential issue in this situation and ensures that the "send done" is not incorrectly processed for any newly added indirect message after preparing the empty frame (which would cause the message to be assumed sent and removed without actual tx).
This commit is contained in:
@@ -338,6 +338,7 @@ Error IndirectSender::PrepareFrameForChild(Mac::TxFrame &aFrame, FrameContext &a
|
||||
if (message == nullptr)
|
||||
{
|
||||
PrepareEmptyFrame(aFrame, aChild, /* aAckRequest */ true);
|
||||
aContext.mMessageNextOffset = 0;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
@@ -422,10 +423,28 @@ void IndirectSender::HandleSentFrameToChild(const Mac::TxFrame &aFrame,
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
|
||||
if (aError == kErrorNone)
|
||||
{
|
||||
Get<Utils::ChildSupervisor>().UpdateOnSend(aChild);
|
||||
}
|
||||
|
||||
// A zero `nextOffset` indicates that the sent frame is an empty
|
||||
// frame generated by `PrepareFrameForChild()` when there was no
|
||||
// indirect message in the send queue for the child. This can happen
|
||||
// in the (not common) case where the radio platform does not
|
||||
// support the "source address match" feature and always includes
|
||||
// "frame pending" flag in acks to data poll frames. In such a case,
|
||||
// `IndirectSender` prepares and sends an empty frame to the child
|
||||
// after it sends a data poll. Here in `HandleSentFrameToChild()` we
|
||||
// exit quickly if we detect the "send done" is for the empty frame
|
||||
// to ensure we do not update any newly added indirect message after
|
||||
// preparing the empty frame.
|
||||
|
||||
VerifyOrExit(nextOffset != 0);
|
||||
|
||||
switch (aError)
|
||||
{
|
||||
case kErrorNone:
|
||||
Get<Utils::ChildSupervisor>().UpdateOnSend(aChild);
|
||||
break;
|
||||
|
||||
case kErrorNoAck:
|
||||
|
||||
Reference in New Issue
Block a user