From dccc5193afd64cfe1b3488a1ed2107355d5eeabc Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Fri, 13 Sep 2024 14:02:07 +0800 Subject: [PATCH] [radio] add a helper of SFD handler (#10670) This commit adds a helper of SFD handler to deal with IEs and security needs to be processed in SFD handler from ISR. --- examples/platforms/simulation/radio.c | 162 +++++-------------------- examples/platforms/utils/mac_frame.cpp | 101 +++++++++++++++ examples/platforms/utils/mac_frame.h | 48 ++++++++ 3 files changed, 177 insertions(+), 134 deletions(-) diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c index 430440bc5..cb10766ff 100644 --- a/examples/platforms/simulation/radio.c +++ b/examples/platforms/simulation/radio.c @@ -112,15 +112,13 @@ static otRadioFrame sAckFrame; static otRadioIeInfo sTransmitIeInfo; #endif -static otExtAddress sExtAddress; -static otShortAddress sShortAddress; -static otPanId sPanid; -static bool sPromiscuous = false; -static bool sTxWait = false; -static int8_t sTxPower = 0; -static int8_t sCcaEdThresh = -74; -static int8_t sLnaGain = 0; -static uint16_t sRegionCode = 0; +static otPanId sPanid; +static bool sPromiscuous = false; +static bool sTxWait = false; +static int8_t sTxPower = 0; +static int8_t sCcaEdThresh = -74; +static int8_t sLnaGain = 0; +static uint16_t sRegionCode = 0; enum { @@ -137,11 +135,6 @@ static uint8_t sAckIeData[OT_ACK_IE_MAX_SIZE]; static uint8_t sAckIeDataLength = 0; #endif -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -static uint32_t sCslSampleTime; -static uint32_t sCslPeriod; -#endif - #if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_ENABLE static bool sRadioCoexEnabled = true; #endif @@ -153,12 +146,7 @@ otRadioCaps gRadioCaps = OT_RADIO_CAPS_NONE; #endif -static uint32_t sMacFrameCounter; -static uint8_t sKeyId; -static otMacKeyMaterial sPrevKey; -static otMacKeyMaterial sCurrKey; -static otMacKeyMaterial sNextKey; -static otRadioKeyType sKeyType; +static otRadioContext sRadioContext; static int8_t GetRssi(uint16_t aChannel); @@ -382,7 +370,7 @@ void otPlatRadioSetExtendedAddress(otInstance *aInstance, const otExtAddress *aE assert(aInstance != NULL); - ReverseExtAddress(&sExtAddress, aExtAddress); + ReverseExtAddress(&sRadioContext.mExtAddress, aExtAddress); } void otPlatRadioSetShortAddress(otInstance *aInstance, otShortAddress aShortAddress) @@ -391,7 +379,7 @@ void otPlatRadioSetShortAddress(otInstance *aInstance, otShortAddress aShortAddr assert(aInstance != NULL); - sShortAddress = aShortAddress; + sRadioContext.mShortAddress = aShortAddress; } void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) @@ -433,17 +421,6 @@ void platformRadioInit(void) #endif } -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE -static uint16_t getCslPhase(void) -{ - uint32_t curTime = otPlatAlarmMicroGetNow(); - uint32_t cslPeriodInUs = sCslPeriod * OT_US_PER_TEN_SYMBOLS; - uint32_t diff = ((sCslSampleTime % cslPeriodInUs) - (curTime % cslPeriodInUs) + cslPeriodInUs) % cslPeriodInUs; - - return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS); -} -#endif - bool otPlatRadioIsEnabled(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); @@ -659,92 +636,16 @@ static void radioComputeCrc(struct RadioMessage *aMessage, uint16_t aLength) aMessage->mPsdu[crc_offset + 1] = crc >> 8; } -static otError radioProcessTransmitSecurity(otRadioFrame *aFrame) -{ - otError error = OT_ERROR_NONE; -#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 - otMacKeyMaterial *key = NULL; - uint8_t keyId; - - otEXPECT(otMacFrameIsSecurityEnabled(aFrame) && otMacFrameIsKeyIdMode1(aFrame) && - !aFrame->mInfo.mTxInfo.mIsSecurityProcessed); - - if (otMacFrameIsAck(aFrame)) - { - keyId = otMacFrameGetKeyId(aFrame); - - otEXPECT_ACTION(keyId != 0, error = OT_ERROR_FAILED); - - if (keyId == sKeyId) - { - key = &sCurrKey; - } - else if (keyId == sKeyId - 1) - { - key = &sPrevKey; - } - else if (keyId == sKeyId + 1) - { - key = &sNextKey; - } - else - { - error = OT_ERROR_SECURITY; - otEXPECT(false); - } - } - else - { - key = &sCurrKey; - keyId = sKeyId; - } - - aFrame->mInfo.mTxInfo.mAesKey = key; - - if (!aFrame->mInfo.mTxInfo.mIsHeaderUpdated) - { - otMacFrameSetKeyId(aFrame, keyId); - otMacFrameSetFrameCounter(aFrame, sMacFrameCounter++); - } -#else - otEXPECT(!aFrame->mInfo.mTxInfo.mIsSecurityProcessed); -#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 - - otMacFrameProcessTransmitAesCcm(aFrame, &sExtAddress); - -exit: - return error; -} - void radioSendMessage(otInstance *aInstance) { -#if OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) + // This block should be called in SFD ISR { - uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset; - uint64_t time = (uint64_t)((int64_t)otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset); + uint64_t sfdTxTime = otPlatTimeGet(); - *timeIe = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq; - - *(++timeIe) = (uint8_t)(time & 0xff); - for (uint8_t i = 1; i < sizeof(uint64_t); i++) - { - time = time >> 8; - *(++timeIe) = (uint8_t)(time & 0xff); - } + otEXPECT(otMacFrameProcessTxSfd(&sTransmitFrame, sfdTxTime, &sRadioContext) == OT_ERROR_NONE); } -#endif // OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT && OPENTHREAD_CONFIG_TIME_SYNC_ENABLE - -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (sCslPeriod > 0 && !sTransmitFrame.mInfo.mTxInfo.mIsHeaderUpdated) - { - otMacFrameSetCslIe(&sTransmitFrame, (uint16_t)sCslPeriod, getCslPhase()); - } -#endif sTransmitMessage.mChannel = sTransmitFrame.mChannel; - - otEXPECT(radioProcessTransmitSecurity(&sTransmitFrame) == OT_ERROR_NONE); otPlatRadioTxStarted(aInstance, &sTransmitFrame); radioComputeCrc(&sTransmitMessage, sTransmitFrame.mLength); radioTransmit(&sTransmitMessage, &sTransmitFrame); @@ -915,16 +816,7 @@ void radioSendAck(void) otEXPECT(otMacFrameGenerateEnhAck(&sReceiveFrame, sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending, sAckIeData, sAckIeDataLength, &sAckFrame) == OT_ERROR_NONE); -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (sCslPeriod > 0) - { - otMacFrameSetCslIe(&sAckFrame, (uint16_t)sCslPeriod, getCslPhase()); - } -#endif - if (otMacFrameIsSecurityEnabled(&sAckFrame)) - { - otEXPECT(radioProcessTransmitSecurity(&sAckFrame) == OT_ERROR_NONE); - } + otEXPECT(otMacFrameProcessTxSfd(&sAckFrame, otPlatTimeGet(), &sRadioContext) == OT_ERROR_NONE); } else #endif @@ -957,8 +849,9 @@ void radioProcessFrame(otInstance *aInstance) otEXPECT(sPromiscuous == false); - otEXPECT_ACTION(otMacFrameDoesAddrMatch(&sReceiveFrame, sPanid, sShortAddress, &sExtAddress), - error = OT_ERROR_ABORT); + otEXPECT_ACTION( + otMacFrameDoesAddrMatch(&sReceiveFrame, sPanid, sRadioContext.mShortAddress, &sRadioContext.mExtAddress), + error = OT_ERROR_ABORT); #if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE otEXPECT_ACTION(otMacFrameGetSrcAddr(&sReceiveFrame, &macAddress) == OT_ERROR_NONE, error = OT_ERROR_PARSE); @@ -1181,7 +1074,7 @@ static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, uint8_t aLinkMetri uint8_t offset = 0; #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (sCslPeriod > 0) + if (sRadioContext.mCslPeriod > 0) { offset += otMacFrameGenerateCslIeTemplate(sAckIeData); } @@ -1208,7 +1101,8 @@ otError otPlatRadioEnableCsl(otInstance *aInstance, OT_UNUSED_VARIABLE(aShortAddr); OT_UNUSED_VARIABLE(aExtAddr); - sCslPeriod = aCslPeriod; + assert(aCslPeriod < UINT16_MAX); + sRadioContext.mCslPeriod = (uint16_t)aCslPeriod; return OT_ERROR_NONE; } @@ -1217,7 +1111,7 @@ otError otPlatRadioResetCsl(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); - sCslPeriod = 0; + sRadioContext.mCslPeriod = 0; return OT_ERROR_NONE; } @@ -1226,7 +1120,7 @@ void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTi { OT_UNUSED_VARIABLE(aInstance); - sCslSampleTime = aCslSampleTime; + sRadioContext.mCslSampleTime = aCslSampleTime; } uint8_t otPlatRadioGetCslAccuracy(otInstance *aInstance) @@ -1250,11 +1144,11 @@ void otPlatRadioSetMacKey(otInstance *aInstance, otEXPECT(aPrevKey != NULL && aCurrKey != NULL && aNextKey != NULL); - sKeyId = aKeyId; - sKeyType = aKeyType; - memcpy(&sPrevKey, aPrevKey, sizeof(otMacKeyMaterial)); - memcpy(&sCurrKey, aCurrKey, sizeof(otMacKeyMaterial)); - memcpy(&sNextKey, aNextKey, sizeof(otMacKeyMaterial)); + sRadioContext.mKeyId = aKeyId; + sRadioContext.mKeyType = aKeyType; + memcpy(&sRadioContext.mPrevKey, aPrevKey, sizeof(otMacKeyMaterial)); + memcpy(&sRadioContext.mCurrKey, aCurrKey, sizeof(otMacKeyMaterial)); + memcpy(&sRadioContext.mNextKey, aNextKey, sizeof(otMacKeyMaterial)); exit: return; @@ -1264,7 +1158,7 @@ void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCoun { OT_UNUSED_VARIABLE(aInstance); - sMacFrameCounter = aMacFrameCounter; + sRadioContext.mMacFrameCounter = aMacFrameCounter; } otError otPlatRadioSetChannelMaxTransmitPower(otInstance *aInstance, uint8_t aChannel, int8_t aMaxPower) diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp index 98ea21736..08d21996d 100644 --- a/examples/platforms/utils/mac_frame.cpp +++ b/examples/platforms/utils/mac_frame.cpp @@ -29,6 +29,10 @@ #include "mac_frame.h" #include + +#include + +#include "common/code_utils.hpp" #include "mac/mac_frame.hpp" using namespace ot; @@ -277,3 +281,100 @@ void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, ui reinterpret_cast(aFrame)->SetEnhAckProbingIe(aData, aDataLen); } #endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE +static uint16_t ComputeCslPhase(uint32_t aRadioTime, otRadioContext *aRadioContext) +{ + return (aRadioContext->mCslSampleTime - aRadioTime) % (aRadioContext->mCslPeriod * OT_US_PER_TEN_SYMBOLS) / + OT_US_PER_TEN_SYMBOLS; +} +#endif +otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext) +{ + otError error = OT_ERROR_NONE; +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + otMacKeyMaterial *key = nullptr; + uint8_t keyId; + + VerifyOrExit(otMacFrameIsSecurityEnabled(aFrame) && otMacFrameIsKeyIdMode1(aFrame) && + !aFrame->mInfo.mTxInfo.mIsSecurityProcessed); + + if (otMacFrameIsAck(aFrame)) + { + keyId = otMacFrameGetKeyId(aFrame); + + VerifyOrExit(keyId != 0, error = OT_ERROR_FAILED); + + if (keyId == aRadioContext->mKeyId) + { + key = &aRadioContext->mCurrKey; + } + else if (keyId == aRadioContext->mKeyId - 1) + { + key = &aRadioContext->mPrevKey; + } + else if (keyId == aRadioContext->mKeyId + 1) + { + key = &aRadioContext->mNextKey; + } + else + { + ExitNow(error = OT_ERROR_SECURITY); + } + } + else if (!aFrame->mInfo.mTxInfo.mIsHeaderUpdated) + { + key = &aRadioContext->mCurrKey; + keyId = aRadioContext->mKeyId; + } + + if (key != nullptr) + { + aFrame->mInfo.mTxInfo.mAesKey = key; + + otMacFrameSetKeyId(aFrame, keyId); + otMacFrameSetFrameCounter(aFrame, aRadioContext->mMacFrameCounter++); + aFrame->mInfo.mTxInfo.mIsHeaderUpdated = true; + } +#else + VerifyOrExit(!aFrame->mInfo.mTxInfo.mIsSecurityProcessed); +#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + + otMacFrameProcessTransmitAesCcm(aFrame, &aRadioContext->mExtAddress); + +exit: + return error; +} + +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE +void otMacFrameUpdateTimeIe(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext) +{ + if (aFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) + { + uint8_t *timeIe = aFrame->mPsdu + aFrame->mInfo.mTxInfo.mIeInfo->mTimeIeOffset; + uint64_t time = aRadioTime + aFrame->mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset; + + *timeIe = aFrame->mInfo.mTxInfo.mIeInfo->mTimeSyncSeq; + + *(++timeIe) = static_cast(time & 0xff); + for (uint8_t i = 1; i < sizeof(uint64_t); i++) + { + time = time >> 8; + *(++timeIe) = static_cast(time & 0xff); + } + } +} +#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + +otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext) +{ +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + if (aRadioContext->mCslPeriod > 0) // CSL IE should be filled for every transmit attempt + { + otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext)); + } +#endif +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE + otMacFrameUpdateTimeIe(aFrame, aRadioTime, aRadioContext); +#endif + return otMacFrameProcessTransmitSecurity(aFrame, aRadioContext); +} diff --git a/examples/platforms/utils/mac_frame.h b/examples/platforms/utils/mac_frame.h index adbed43f2..6c8f74521 100644 --- a/examples/platforms/utils/mac_frame.h +++ b/examples/platforms/utils/mac_frame.h @@ -334,6 +334,54 @@ uint8_t otMacFrameGenerateEnhAckProbingIe(uint8_t *aDest, const uint8_t *aIeData */ void otMacFrameSetEnhAckProbingIe(otRadioFrame *aFrame, const uint8_t *aData, uint8_t aDataLen); +/** + * Represents the context for radio layer. + */ +typedef struct otRadioContext +{ + otExtAddress mExtAddress; ///< In little-endian byte order. + uint32_t mMacFrameCounter; + uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer. + uint16_t mCslPeriod; ///< In unit of 10 symbols. + otShortAddress mShortAddress; + otRadioKeyType mKeyType; + uint8_t mKeyId; + otMacKeyMaterial mPrevKey; + otMacKeyMaterial mCurrKey; + otMacKeyMaterial mNextKey; +} otRadioContext; + +/** + * Perform processing of SFD callback from ISR. + * + * This function may do multiple tasks as follows. + * + * - CSL IE will be populated (if present) + * - Time IE will be populated (if present) + * - Tx security will be performed (including assignment of security frame counter and key id if not assigned) + * + * @param[in,out] aFrame The target frame. MUST NOT be `NULL`. + * @param[in] aRadioTime The radio time when the SFD was at the antenna. + * @param[in,out] aRadioContext The radio context accessible in ISR. + * + * @returns the error processing the callback. The caller should abort transmission on failures. + * + */ +otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadioContext *aRadioContext); + +/** + * Process frame tx security. + * + * @param[in,out] aFrame The target frame. MUST NOT be `NULL`. + * @param[in,out] aRadioContext The radio context accessible in ISR. + * + * @retval OT_ERROR_NONE Successfully processed security. + * @retval OT_ERROR_FAILED Failed to processed security. + * @retval OT_ERROR_SECURITY Failed to processed security for missing key. + * + */ +otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext); + #ifdef __cplusplus } // extern "C" #endif