From e3f0a7cc37fff434dc6e7b115c9bb9f318dc25ab Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 27 Aug 2024 11:13:32 -0700 Subject: [PATCH] [radio-spinel] fix tracking of current MAC frame counter (#10635) This commit fixes an issue in `RadioSpinel` related to the tracking of the MAC frame counter used during RCP restoration. Previously, `RadioSpinel` tracked the last seen counter on any secured received/transmitted frame. However, the frame counter should only be tracked for frames that use Key ID Mode 1 and where the included Key ID in the frame matches the current Key ID being used. The `SubMac` module also tracks the current MAC frame counter, and it does perform Key ID Mode and Key ID checks. This commit adds a new public API `otLinkGetFrameCounter()` to get the current frame counter. This is used by `RadioSpinel` to get the frame counter instead of having `RadioSpinel` track the frame counter itself. --- include/openthread/instance.h | 2 +- include/openthread/link.h | 10 ++++++++++ src/core/api/link_api.cpp | 5 +++++ src/lib/spinel/radio_spinel.cpp | 10 ++++------ src/lib/spinel/radio_spinel.hpp | 1 - 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index d3cdebb12..d26bdf851 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (437) +#define OPENTHREAD_API_VERSION (438) /** * @addtogroup api-instance diff --git a/include/openthread/link.h b/include/openthread/link.h index 15bc0d860..bd42cff20 100644 --- a/include/openthread/link.h +++ b/include/openthread/link.h @@ -690,6 +690,16 @@ uint8_t otLinkGetMaxFrameRetriesIndirect(otInstance *aInstance); */ void otLinkSetMaxFrameRetriesIndirect(otInstance *aInstance, uint8_t aMaxFrameRetriesIndirect); +/** + * Gets the current MAC frame counter value. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * + * @returns The current MAC frame counter value. + * + */ +uint32_t otLinkGetFrameCounter(otInstance *aInstance); + /** * Gets the address mode of MAC filter. * diff --git a/src/core/api/link_api.cpp b/src/core/api/link_api.cpp index 95ec35c42..4d8484745 100644 --- a/src/core/api/link_api.cpp +++ b/src/core/api/link_api.cpp @@ -188,6 +188,11 @@ void otLinkSetMaxFrameRetriesIndirect(otInstance *aInstance, uint8_t aMaxFrameRe #endif // OPENTHREAD_FTD +uint32_t otLinkGetFrameCounter(otInstance *aInstance) +{ + return AsCoreType(aInstance).Get().GetFrameCounter(); +} + #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE otMacFilterAddressMode otLinkFilterGetAddressMode(otInstance *aInstance) diff --git a/src/lib/spinel/radio_spinel.cpp b/src/lib/spinel/radio_spinel.cpp index 49d88cbb8..0bd60e4b2 100644 --- a/src/lib/spinel/radio_spinel.cpp +++ b/src/lib/spinel/radio_spinel.cpp @@ -38,6 +38,7 @@ #include #include +#include #include #include #include @@ -703,7 +704,6 @@ otError RadioSpinel::ParseRadioFrame(otRadioFrame &aFrame, if (flags & SPINEL_MD_FLAG_ACKED_SEC) { mMacFrameCounterSet = true; - mMacFrameCounter = aFrame.mInfo.mRxInfo.mAckFrameCounter; } #endif } @@ -926,7 +926,6 @@ otError RadioSpinel::SetMacFrameCounter(uint32_t aMacFrameCounter, bool aSetIfLa aMacFrameCounter, aSetIfLarger)); #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 mMacFrameCounterSet = true; - mMacFrameCounter = aMacFrameCounter; #endif exit: @@ -1578,7 +1577,6 @@ void RadioSpinel::HandleTransmitDone(uint32_t aCommand, #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 mMacFrameCounterSet = true; - mMacFrameCounter = frameCounter; #endif } @@ -2150,7 +2148,7 @@ void RadioSpinel::RestoreProperties(void) if (mMacFrameCounterSet) { - // There is a chance that radio/RCP has used some counters after `mMacFrameCounter` (for enh ack) and they + // There is a chance that radio/RCP has used some counters after otLinkGetFrameCounter() (for enh ack) and they // are in queue to be sent to host (not yet processed by host RadioSpinel). Here we add some guard jump // when we restore the frame counter. // Consider the worst case: the radio/RCP continuously receives the shortest data frame and replies with the @@ -2162,8 +2160,8 @@ void RadioSpinel::RestoreProperties(void) // CounterGuard: 2000ms(Timeout) / [(28bytes(Data) + 29bytes(Ack)) * 32us/byte + 192us(Ifs)] = 992 static constexpr uint16_t kFrameCounterGuard = 1000; - SuccessOrDie( - Set(SPINEL_PROP_RCP_MAC_FRAME_COUNTER, SPINEL_DATATYPE_UINT32_S, mMacFrameCounter + kFrameCounterGuard)); + SuccessOrDie(Set(SPINEL_PROP_RCP_MAC_FRAME_COUNTER, SPINEL_DATATYPE_UINT32_S, + otLinkGetFrameCounter(mInstance) + kFrameCounterGuard)); } for (int i = 0; i < mSrcMatchShortEntryCount; ++i) diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index 36acc7773..1e1590880 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -1316,7 +1316,6 @@ private: int8_t mCcaEnergyDetectThreshold; int8_t mTransmitPower; int8_t mFemLnaGain; - uint32_t mMacFrameCounter; bool mCoexEnabled : 1; bool mSrcMatchEnabled : 1;