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