[mac] enforce single initialization lifecycle for TxFrames (#13264)

This commit refactors `Mac::Links` and `Mac` frame preparation to ensure
`TxFrames` buffers are initialized (`Clear()`) exactly once per TX cycle.

Specifically, this commit:
- Replaces `Links::GetTxFrames()` with `Links::InitTxFrames()`, which
  encapsulates calling `Clear()` on `mTxFrames` prior to returning its
  reference. This prevents callers from retrieving uninitialized or dirty
  transmission buffers from a previous radio cycle.
- Updates `PrepareBeaconRequest()` and `PrepareBeacon()` to accept the
  initialized `TxFrames &` reference directly as a parameter, making the
  data flow explicit.
- Replaces non-const `GetTxFrames()` calls in `HandleTransmitDone()` with
  `GetTxFramesRequiredRadioTypes()`, enforcing const-correctness during
  TX completion handling.
This commit is contained in:
Abtin Keshavarzian
2026-06-22 15:10:22 -07:00
committed by GitHub
parent ff121bfce3
commit 6e8570e233
3 changed files with 30 additions and 17 deletions
+9 -11
View File
@@ -703,9 +703,9 @@ void Mac::FinishOperation(void)
mOperation = kOperationIdle;
}
TxFrame *Mac::PrepareBeaconRequest(void)
TxFrame *Mac::PrepareBeaconRequest(TxFrames &aTxFrames)
{
TxFrame &frame = mLinks.GetTxFrames().GetBroadcastTxFrame();
TxFrame &frame = aTxFrames.GetBroadcastTxFrame();
TxFrame::Info frameInfo;
frameInfo.mAddrs.mSource.SetNone();
@@ -723,7 +723,7 @@ TxFrame *Mac::PrepareBeaconRequest(void)
return &frame;
}
TxFrame *Mac::PrepareBeacon(void)
TxFrame *Mac::PrepareBeacon(TxFrames &aTxFrames)
{
TxFrame *frame;
TxFrame::Info frameInfo;
@@ -735,10 +735,10 @@ TxFrame *Mac::PrepareBeacon(void)
#if OPENTHREAD_CONFIG_MULTI_RADIO
OT_ASSERT(!mTxBeaconRadioLinks.IsEmpty());
frame = &mLinks.GetTxFrames().GetTxFrame(mTxBeaconRadioLinks);
frame = &aTxFrames.GetTxFrame(mTxBeaconRadioLinks);
mTxBeaconRadioLinks.Clear();
#else
frame = &mLinks.GetTxFrames().GetBroadcastTxFrame();
frame = &aTxFrames.GetBroadcastTxFrame();
#endif
frameInfo.mAddrs.mSource.SetExtended(GetExtAddress());
@@ -917,11 +917,9 @@ exit:
void Mac::BeginTransmit(void)
{
TxFrame *frame = nullptr;
TxFrames &txFrames = mLinks.GetTxFrames();
TxFrames &txFrames = mLinks.InitTxFrames();
Address dstAddr;
txFrames.Clear();
#if OPENTHREAD_CONFIG_MULTI_RADIO
mTxPendingRadioLinks.Clear();
mTxError = kErrorAbort;
@@ -933,7 +931,7 @@ void Mac::BeginTransmit(void)
{
case kOperationActiveScan:
mLinks.SetPanId(kPanIdBroadcast);
frame = PrepareBeaconRequest();
frame = PrepareBeaconRequest(txFrames);
VerifyOrExit(frame != nullptr);
frame->SetChannel(mScanChannel);
frame->SetSequence(0);
@@ -942,7 +940,7 @@ void Mac::BeginTransmit(void)
break;
case kOperationTransmitBeacon:
frame = PrepareBeacon();
frame = PrepareBeacon(txFrames);
VerifyOrExit(frame != nullptr);
frame->SetChannel(mRadioChannel);
frame->SetSequence(mBeaconSequence++);
@@ -1319,7 +1317,7 @@ void Mac::HandleTransmitDone(TxFrame &aFrame, RxFrame *aAckFrame, Error aError)
if (!aFrame.IsEmpty())
{
RadioType radio = aFrame.GetRadioType();
RadioTypes requiredRadios = mLinks.GetTxFrames().GetRequiredRadioTypes();
RadioTypes requiredRadios = mLinks.GetTxFramesRequiredRadioTypes();
Get<RadioSelector>().UpdateOnSendDone(aFrame, aError);
+2 -2
View File
@@ -832,8 +832,8 @@ private:
void StartOperation(Operation aOperation);
void FinishOperation(void);
void PerformNextOperation(void);
TxFrame *PrepareBeaconRequest(void);
TxFrame *PrepareBeacon(void);
TxFrame *PrepareBeaconRequest(TxFrames &aTxFrames);
TxFrame *PrepareBeacon(TxFrames &aTxFrames);
bool ShouldSendBeacon(void) const;
bool IsJoinable(void) const;
void BeginTransmit(void);
+19 -4
View File
@@ -517,18 +517,22 @@ public:
}
/**
* Gets the radio transmit frames.
* Initializes and retrieves the radio transmit frames `TxFrames`.
*
* @returns The transmit frames.
*/
TxFrames &GetTxFrames(void) { return mTxFrames; }
TxFrames &InitTxFrames(void)
{
mTxFrames.Clear();
return mTxFrames;
}
#if !OPENTHREAD_CONFIG_MULTI_RADIO
/**
* Sends a prepared frame.
*
* The prepared frame is from `GetTxFrames()`. This method is available only in single radio link mode.
* The prepared frame is from `InitTxFrames()`. This method is available only in single radio link mode.
*/
void Send(void)
{
@@ -545,13 +549,24 @@ public:
/**
* Sends prepared frames over a given set of radio links.
*
* The prepared frame must be from `GetTxFrames()`. This method is available only in multi radio link mode.
* The prepared frame must be from `InitTxFrames()`. This method is available only in multi radio link mode.
*
* @param[in] aFrame A reference to a prepared frame.
* @param[in] aRadioTypes A set of radio types to send on.
*/
void Send(TxFrame &aFrame, RadioTypes aRadioTypes);
/**
* Gets the required radio types (`GetRequiredRadioTypes()`) from `TxFrames`.
*
* This set specifies the radio links for which we expect the frame tx to be successful to consider the overall tx
* successful. If the set is empty, successful tx over any radio link is sufficient for overall tx to be considered
* successful. The required radio type set is expected to be a subset of selected radio types.
*
* @returns The required radio types.
*/
RadioTypes GetTxFramesRequiredRadioTypes(void) const { return mTxFrames.GetRequiredRadioTypes(); }
#endif // !OPENTHREAD_CONFIG_MULTI_RADIO
/**