diff --git a/src/core/diags/README.md b/src/core/diags/README.md index 9ec39c2cfed..b2fbd6f36a6 100644 --- a/src/core/diags/README.md +++ b/src/core/diags/README.md @@ -80,13 +80,14 @@ Done ### diag frame -Usage: `diag frame [-c] [-p TX_POWER] [-s] ` +Usage: `diag frame [-c] [-p TX_POWER] [-s] [-u] ` Set the frame (hex encoded) to be used by `diag send` and `diag repeat`. The frame may be overwritten by `diag send` and `diag repeat`. -- Specify `-s` to indicate that tx security is already processed so that it should be skipped in the radio layer. - Specify `-c` to enable CSMA/CA for this frame in the radio layer. - Specify `-p` to specify the tx power in dBm for this frame. +- Specify `-s` to indicate that tx security is already processed so that it should be skipped in the radio layer. +- Specify `-u` to specify the `mInfo.mTxInfo.mIsHeaderUpdated` filed for this frame. ```bash > diag frame 11223344 diff --git a/src/core/diags/factory_diags.cpp b/src/core/diags/factory_diags.cpp index ab88579f34d..6a42c7b619f 100644 --- a/src/core/diags/factory_diags.cpp +++ b/src/core/diags/factory_diags.cpp @@ -213,6 +213,7 @@ Diags::Diags(Instance &aInstance) void Diags::ResetTxPacket(void) { + mIsHeaderUpdated = false; mTxPacket->mInfo.mTxInfo.mTxDelayBaseTime = 0; mTxPacket->mInfo.mTxInfo.mTxDelay = 0; mTxPacket->mInfo.mTxInfo.mMaxCsmaBackoffs = 0; @@ -232,6 +233,7 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) uint16_t size = OT_RADIO_FRAME_MAX_SIZE; bool securityProcessed = false; bool csmaCaEnabled = false; + bool isHeaderUpdated = false; int8_t txPower = OT_RADIO_POWER_INVALID; while (aArgsLength > 1) @@ -239,6 +241,7 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) if (StringMatch(aArgs[0], "-s")) { securityProcessed = true; + isHeaderUpdated = true; } else if (StringMatch(aArgs[0], "-p")) { @@ -255,6 +258,10 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) { csmaCaEnabled = true; } + else if (StringMatch(aArgs[0], "-u")) + { + isHeaderUpdated = true; + } else { ExitNow(error = kErrorInvalidArgs); @@ -276,6 +283,7 @@ Error Diags::ProcessFrame(uint8_t aArgsLength, char *aArgs[]) mTxPacket->mInfo.mTxInfo.mTxPower = txPower; mTxPacket->mLength = size; mIsTxPacketSet = true; + mIsHeaderUpdated = isHeaderUpdated; exit: AppendErrorResult(error); @@ -514,7 +522,13 @@ void Diags::TransmitPacket(void) { mTxPacket->mChannel = mChannel; - if (!mIsTxPacketSet) + if (mIsTxPacketSet) + { + // The `mInfo.mTxInfo.mIsHeaderUpdated` field may be updated by the radio driver after the frame is sent, + // set the `mInfo.mTxInfo.mIsHeaderUpdated` field before transmitting the frame. + mTxPacket->mInfo.mTxInfo.mIsHeaderUpdated = mIsHeaderUpdated; + } + else { ResetTxPacket(); mTxPacket->mLength = mTxLen; diff --git a/src/core/diags/factory_diags.hpp b/src/core/diags/factory_diags.hpp index a3f87042c2c..6d6ac6bc302 100644 --- a/src/core/diags/factory_diags.hpp +++ b/src/core/diags/factory_diags.hpp @@ -218,9 +218,10 @@ class Diags : public InstanceLocator, private NonCopyable uint8_t mChannel; int8_t mTxPower; uint8_t mTxLen; - bool mIsTxPacketSet; - bool mRepeatActive; - bool mDiagSendOn; + bool mIsHeaderUpdated : 1; + bool mIsTxPacketSet : 1; + bool mRepeatActive : 1; + bool mDiagSendOn : 1; #endif otDiagOutputCallback mOutputCallback; diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index 36b8dfb3f88..d7606ff6aff 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -1582,10 +1582,8 @@ void RadioSpinel::HandleTransmitDone(uint32_t aCommand, error = SpinelStatusToOtError(status); } - static_cast(mTransmitFrame)->SetIsHeaderUpdated(headerUpdated); - - if ((sRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) && headerUpdated && - static_cast(mTransmitFrame)->GetSecurityEnabled()) + if ((sRadioCaps & OT_RADIO_CAPS_TRANSMIT_SEC) && (!mTransmitFrame->mInfo.mTxInfo.mIsHeaderUpdated) && + headerUpdated && static_cast(mTransmitFrame)->GetSecurityEnabled()) { uint8_t keyId; uint32_t frameCounter; @@ -1602,6 +1600,8 @@ void RadioSpinel::HandleTransmitDone(uint32_t aCommand, #endif } + static_cast(mTransmitFrame)->SetIsHeaderUpdated(headerUpdated); + exit: // A parse error indicates an RCP misbehavior, so recover the RCP immediately. mState = kStateTransmitDone;