mirror of
https://github.com/espressif/openthread.git
synced 2026-07-30 15:47:46 +00:00
[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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
#include "mac_frame.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#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<Mac::Frame *>(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<uint8_t>(time & 0xff);
|
||||
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
|
||||
{
|
||||
time = time >> 8;
|
||||
*(++timeIe) = static_cast<uint8_t>(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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user