From fab01a7f0fcdc5ee9bcdd62bcccd2bdba977f2c0 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Tue, 30 Sep 2025 09:24:38 +0800 Subject: [PATCH] [simulation] use the CSL receiver's peer address to include CSL IE (#11905) The description of the method `otPlatRadioEnableCsl()` requires the platform to include the CSL IE in the enhanced ACK when the received data frame's source address matches the CSL receiver's peer address. This commit implements this requirement in the simulation radio. --- examples/platforms/simulation/radio.c | 32 ++++++++++++++++++------ examples/platforms/utils/mac_frame.cpp | 34 +++++++++++++++++++++++++- examples/platforms/utils/mac_frame.h | 19 ++++++++++++-- 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/examples/platforms/simulation/radio.c b/examples/platforms/simulation/radio.c index 6c5d6edd8..3fb0d5c45 100644 --- a/examples/platforms/simulation/radio.c +++ b/examples/platforms/simulation/radio.c @@ -98,7 +98,9 @@ static void radioSendMessage(otInstance *aInstance); static void radioSendAck(void); static void radioProcessFrame(otInstance *aInstance); #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 -static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, uint8_t aLinkMetricsIeDataLen); +static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, + uint8_t aLinkMetricsIeDataLen, + const struct otRadioFrame *aReceivedFrame); #endif static otRadioState sState = OT_RADIO_STATE_DISABLED; @@ -643,6 +645,7 @@ void radioSendMessage(otInstance *aInstance) { uint64_t sfdTxTime = otPlatTimeGet(); + sRadioContext.mCslPresent = sTransmitFrame.mInfo.mTxInfo.mCslPresent; otEXPECT(otMacFrameProcessTxSfd(&sTransmitFrame, sfdTxTime, &sRadioContext) == OT_ERROR_NONE); } @@ -802,7 +805,7 @@ void radioSendAck(void) } #endif - sAckIeDataLength = generateAckIeData(dataPtr, linkMetricsDataLen); + sAckIeDataLength = generateAckIeData(dataPtr, linkMetricsDataLen, &sReceiveFrame); otEXPECT(otMacFrameGenerateEnhAck(&sReceiveFrame, sReceiveFrame.mInfo.mRxInfo.mAckedWithFramePending, sAckIeData, sAckIeDataLength, &sAckFrame) == OT_ERROR_NONE); @@ -1047,15 +1050,21 @@ uint64_t otPlatRadioGetNow(otInstance *aInstance) } #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 -static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, uint8_t aLinkMetricsIeDataLen) +static uint8_t generateAckIeData(uint8_t *aLinkMetricsIeData, + uint8_t aLinkMetricsIeDataLen, + const struct otRadioFrame *aReceivedFrame) { OT_UNUSED_VARIABLE(aLinkMetricsIeData); OT_UNUSED_VARIABLE(aLinkMetricsIeDataLen); + OT_UNUSED_VARIABLE(aReceivedFrame); uint8_t offset = 0; #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (sRadioContext.mCslPeriod > 0) + sRadioContext.mCslPresent = + (sRadioContext.mCslPeriod > 0) && otMacFrameSrcAddrMatchCslReceiverPeer(aReceivedFrame, &sRadioContext); + + if (sRadioContext.mCslPresent) { offset += otMacFrameGenerateCslIeTemplate(sAckIeData); } @@ -1079,13 +1088,20 @@ otError otPlatRadioEnableCsl(otInstance *aInstance, const otExtAddress *aExtAddr) { OT_UNUSED_VARIABLE(aInstance); - OT_UNUSED_VARIABLE(aShortAddr); - OT_UNUSED_VARIABLE(aExtAddr); + otError error = OT_ERROR_NONE; assert(aCslPeriod < UINT16_MAX); - sRadioContext.mCslPeriod = (uint16_t)aCslPeriod; + otEXPECT_ACTION((aShortAddr != OT_RADIO_BROADCAST_SHORT_ADDR) && (aShortAddr != OT_RADIO_INVALID_SHORT_ADDR), + error = OT_ERROR_FAILED); + otEXPECT_ACTION(aExtAddr != NULL, error = OT_ERROR_FAILED); - return OT_ERROR_NONE; + sRadioContext.mCslPeriod = (uint16_t)aCslPeriod; + sRadioContext.mCslShortAddress = aShortAddr; + + ReverseExtAddress(&sRadioContext.mCslExtAddress, aExtAddr); + +exit: + return error; } otError otPlatRadioResetCsl(otInstance *aInstance) diff --git a/examples/platforms/utils/mac_frame.cpp b/examples/platforms/utils/mac_frame.cpp index 333fe2f9f..88c144001 100644 --- a/examples/platforms/utils/mac_frame.cpp +++ b/examples/platforms/utils/mac_frame.cpp @@ -404,7 +404,7 @@ exit: 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 + if (aRadioContext->mCslPresent) // CSL IE should be filled for every transmit attempt { otMacFrameSetCslIe(aFrame, aRadioContext->mCslPeriod, ComputeCslPhase(aRadioTime, aRadioContext)); } @@ -415,3 +415,35 @@ otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadi aFrame->mInfo.mTxInfo.mTimestamp = aRadioTime; return otMacFrameProcessTransmitSecurity(aFrame, aRadioContext); } + +bool otMacFrameSrcAddrMatchCslReceiverPeer(const otRadioFrame *aFrame, const otRadioContext *aRadioContext) +{ + const Mac::Frame &frame = *static_cast(aFrame); + bool matches = false; + Mac::Address src; + + VerifyOrExit(frame.GetSrcAddr(src) == kErrorNone); + + switch (src.GetType()) + { + case Mac::Address::kTypeShort: + VerifyOrExit(aRadioContext->mCslShortAddress != Mac::kShortAddrBroadcast && + aRadioContext->mCslShortAddress != Mac::kShortAddrInvalid); + VerifyOrExit(src.GetShort() == aRadioContext->mCslShortAddress); + matches = true; + break; + + case Mac::Address::kTypeExtended: + VerifyOrExit(*reinterpret_cast(aRadioContext->mCslExtAddress.m8) != 0); + VerifyOrExit(src.GetExtended() == *static_cast(&aRadioContext->mCslExtAddress)); + matches = true; + break; + + case Mac::Address::kTypeNone: + matches = false; + break; + } + +exit: + return matches; +} diff --git a/examples/platforms/utils/mac_frame.h b/examples/platforms/utils/mac_frame.h index 8817db6bd..1a4eb174b 100644 --- a/examples/platforms/utils/mac_frame.h +++ b/examples/platforms/utils/mac_frame.h @@ -345,8 +345,11 @@ typedef struct otRadioContext otExtAddress mExtAddress; ///< In little-endian byte order. uint32_t mMacFrameCounter; uint32_t mPrevMacFrameCounter; - uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer. - uint16_t mCslPeriod; ///< In unit of 10 symbols. + uint32_t mCslSampleTime; ///< The sample time based on the microsecond timer. + uint16_t mCslPeriod; ///< In unit of 10 symbols. + otShortAddress mCslShortAddress; ///< The short address of the CSL receiver's peer. + otExtAddress mCslExtAddress; ///< The extended address of the CSL receiver's peer. + bool mCslPresent : 1; ///< Indicates whether the CSL header IE is present. otShortAddress mShortAddress; otShortAddress mAlternateShortAddress; otRadioKeyType mKeyType; @@ -386,6 +389,18 @@ otError otMacFrameProcessTxSfd(otRadioFrame *aFrame, uint64_t aRadioTime, otRadi */ otError otMacFrameProcessTransmitSecurity(otRadioFrame *aFrame, otRadioContext *aRadioContext); +/** + * Indicates whether the 15.4 frame's source address matches the short or extended address of the CSL receiver's peer. + * + * @param[in] aFrame The target 15.4 frame. MUST NOT be `NULL`. + * @param[in] aRadioContext The radio context accessible in ISR. + * + * @retval TRUE The source address of the frame matches the short or extended address of the CSL receiver's peer. + * @retval FALSE The source address of the frame does not match the short or extended address of the CSL receiver's + * peer. + */ +bool otMacFrameSrcAddrMatchCslReceiverPeer(const otRadioFrame *aFrame, const otRadioContext *aRadioContext); + #ifdef __cplusplus } // extern "C" #endif