[csl-tx-scheduler] simplify HandleSentFrame() implementation (#13390)

This commit simplifies `CslTxScheduler::HandleSentFrame()` by inlining
the helper method directly into the main callback. Since `mCslTxNeighbor`
is already a member variable, passing it as a reference parameter to a
helper method was unnecessary.

Additionally, clearing of `mCslTxMessage` and `mCslTxNeighbor` is moved
to the `exit:` block after calling `HandleSentFrameToCslNeighbor()`.
Keeping `mCslTxMessage` non-null while `HandleSentFrameToCslNeighbor()`
runs ensures that nested calls to `CslTxScheduler::Update()` do not
trigger a premature `RescheduleCslTx()` while the TX done callback is in
progress. All state cleanup and rescheduling now occur cleanly at `exit:`.
This commit is contained in:
Abtin Keshavarzian
2026-07-23 21:48:43 -07:00
committed by GitHub
parent ba36204b7b
commit 211267dbfb
2 changed files with 32 additions and 32 deletions
+32 -30
View File
@@ -62,15 +62,29 @@ void CslTxScheduler::Update(void)
if (mCslTxMessage == nullptr) if (mCslTxMessage == nullptr)
{ {
RescheduleCslTx(); RescheduleCslTx();
ExitNow();
} }
else if ((mCslTxNeighbor != nullptr) && (mCslTxNeighbor->GetIndirectMessage() != mCslTxMessage))
// A non-null `mCslTxMessage` indicates we are in the middle of MAC
// CSL TX, i.e., a frame was prepared for `Mac` and we are waiting
// for the TX done callback which will call `RescheduleCslTx()`.
//
// While in this state, if the indirect message being sent for the
// currently chosen neighbor is modified or removed, we clear
// `mCslTxNeighbor` to avoid processing it in the TX done
// callback.
VerifyOrExit(mCslTxNeighbor != nullptr);
if (mCslTxNeighbor->GetIndirectMessage() != mCslTxMessage)
{ {
// `Mac` has already started the CSL tx, so wait for tx done callback
// to call `RescheduleCslTx`
mCslTxNeighbor->ResetCslTxAttempts(); mCslTxNeighbor->ResetCslTxAttempts();
mCslTxNeighbor = nullptr; mCslTxNeighbor = nullptr;
mFrameContext.mMessageNextOffset = 0; mFrameContext.mMessageNextOffset = 0;
} }
exit:
return;
} }
void CslTxScheduler::Clear(void) void CslTxScheduler::Clear(void)
@@ -296,41 +310,27 @@ Mac::TxFrame *CslTxScheduler::HandleFrameRequest(Mac::TxFrames &) { return nullp
void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError) void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError)
{ {
CslNeighbor *neighbor = mCslTxNeighbor; VerifyOrExit(mCslTxNeighbor != nullptr);
mCslTxMessage = nullptr;
VerifyOrExit(neighbor != nullptr);
mCslTxNeighbor = nullptr;
HandleSentFrame(aFrame, aError, *neighbor);
exit:
RescheduleCslTx();
}
void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, CslNeighbor &aCslNeighbor)
{
switch (aError) switch (aError)
{ {
case kErrorNone: case kErrorNone:
aCslNeighbor.ResetCslTxAttempts(); mCslTxNeighbor->ResetCslTxAttempts();
aCslNeighbor.ResetIndirectTxAttempts(); mCslTxNeighbor->ResetIndirectTxAttempts();
break; break;
case kErrorNoAck: case kErrorNoAck:
OT_ASSERT(!aFrame.GetSecurityEnabled() || aFrame.IsHeaderUpdated()); OT_ASSERT(!aFrame.GetSecurityEnabled() || aFrame.IsHeaderUpdated());
aCslNeighbor.IncrementCslTxAttempts(); mCslTxNeighbor->IncrementCslTxAttempts();
LogInfo("CSL tx to %04x failed, attempt %d/%d", aCslNeighbor.GetRloc16(), aCslNeighbor.GetCslTxAttempts(), LogInfo("CSL tx to %04x failed, attempt %d/%d", mCslTxNeighbor->GetRloc16(), mCslTxNeighbor->GetCslTxAttempts(),
kMaxCslTriggeredTxAttempts); kMaxCslTriggeredTxAttempts);
if (aCslNeighbor.GetCslTxAttempts() >= kMaxCslTriggeredTxAttempts) if (mCslTxNeighbor->GetCslTxAttempts() >= kMaxCslTriggeredTxAttempts)
{ {
// CSL transmission attempts reach max, consider child out of sync // CSL transmission attempts reach max, consider child out of sync
aCslNeighbor.SetCslSynchronized(false); mCslTxNeighbor->SetCslSynchronized(false);
aCslNeighbor.ResetCslTxAttempts(); mCslTxNeighbor->ResetCslTxAttempts();
} }
OT_FALL_THROUGH; OT_FALL_THROUGH;
@@ -344,7 +344,7 @@ void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, C
if (!aFrame.IsEmpty()) if (!aFrame.IsEmpty())
{ {
aCslNeighbor.SetIndirectDataSequenceNumber(aFrame.GetSequence()); mCslTxNeighbor->SetIndirectDataSequenceNumber(aFrame.GetSequence());
if (aFrame.GetSecurityEnabled() && aFrame.IsHeaderUpdated()) if (aFrame.GetSecurityEnabled() && aFrame.IsHeaderUpdated())
{ {
@@ -352,10 +352,10 @@ void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, C
uint8_t keyIndex; uint8_t keyIndex;
IgnoreError(aFrame.GetFrameCounter(frameCounter)); IgnoreError(aFrame.GetFrameCounter(frameCounter));
aCslNeighbor.SetIndirectFrameCounter(frameCounter); mCslTxNeighbor->SetIndirectFrameCounter(frameCounter);
IgnoreError(aFrame.GetKeyIndex(keyIndex)); IgnoreError(aFrame.GetKeyIndex(keyIndex));
aCslNeighbor.SetIndirectKeyIndex(keyIndex); mCslTxNeighbor->SetIndirectKeyIndex(keyIndex);
} }
} }
@@ -366,10 +366,12 @@ void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, C
OT_UNREACHABLE_CODE(break); OT_UNREACHABLE_CODE(break);
} }
Get<IndirectSender>().HandleSentFrameToCslNeighbor(aFrame, mFrameContext, aError, aCslNeighbor); Get<IndirectSender>().HandleSentFrameToCslNeighbor(aFrame, mFrameContext, aError, *mCslTxNeighbor);
exit: exit:
return; mCslTxMessage = nullptr;
mCslTxNeighbor = nullptr;
RescheduleCslTx();
} }
} // namespace ot } // namespace ot
-2
View File
@@ -251,8 +251,6 @@ private:
// Callback from `Radio` // Callback from `Radio`
void HandleRadioBusLatencyChanged(void); void HandleRadioBusLatencyChanged(void);
void HandleSentFrame(const Mac::TxFrame &aFrame, Error aError, CslNeighbor &aaCslNeighbor);
using CslTxTimer = TimerMilliIn<CslTxScheduler, &CslTxScheduler::HandleTimer>; using CslTxTimer = TimerMilliIn<CslTxScheduler, &CslTxScheduler::HandleTimer>;
uint32_t mCslFrameRequestAheadUs; uint32_t mCslFrameRequestAheadUs;