[radio] new API to update frame counter only if new value is larger (#8607)

This commit adds a new radio platform API which updates the MAC Frame
Counter only if the new value is larger than current value being used
by radio platform, i.e., `otPlatRadioSetMacFrameCounterIfLarger()`.
OT stack provides a default weak implementation of this API which
calls the existing `otPlatRadioSetMacFrameCouter()`.

This API is used when radio provides `OT_RADIO_CAPS_TRANSMIT_SEC`
capability and thereby is responsible for assigning the frame counter
to tx frames. It helps address an edge-case where OT stack may not
yet know of the latest frame counter values used by radio platform
(e.g., due to enhanced acks processed by radio platform directly or
due to delay between RCP and host) and then setting the value from OT
stack may cause the counter value on radio to move back (OT stack
will set the counter after appending it in `LinkFrameCounterTlv` on
all radios when multi-radio links feature is enabled).

This commit also updates spinel and RCP and `radio_spinel`
implementations to support the new API. This is added in a fully
compatible way, i.e., a new host firmware works with older RCP, and
similarly an old host can work with new RCP firmware.
This commit is contained in:
Abtin Keshavarzian
2023-01-19 09:12:07 -08:00
committed by GitHub
parent a1953a7a34
commit dbe1f7019c
18 changed files with 134 additions and 26 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (276)
#define OPENTHREAD_API_VERSION (277)
/**
* @addtogroup api-instance
+15
View File
@@ -356,6 +356,9 @@ otError otLinkRawSetMacKey(otInstance *aInstance,
/**
* Sets the current MAC frame counter value.
*
* This function always sets the MAC counter to the new given value @p aMacFrameCounter independent of the current
* value.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMacFrameCounter The MAC frame counter value.
*
@@ -365,6 +368,18 @@ otError otLinkRawSetMacKey(otInstance *aInstance,
*/
otError otLinkRawSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter);
/**
* Sets the current MAC frame counter value only if the new value is larger than the current one.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMacFrameCounter The MAC frame counter value.
*
* @retval OT_ERROR_NONE If successful.
* @retval OT_ERROR_INVALID_STATE If the raw link-layer isn't enabled.
*
*/
otError otLinkRawSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter);
/**
* Get current platform time (64bits width) of the radio chip.
*
+11
View File
@@ -620,6 +620,17 @@ void otPlatRadioSetMacKey(otInstance *aInstance,
*/
void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter);
/**
* This method sets the current MAC frame counter value only if the new given value is larger than the current value.
*
* This function is used when radio provides `OT_RADIO_CAPS_TRANSMIT_SEC` capability.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aMacFrameCounter The MAC frame counter value.
*
*/
void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter);
/**
* Get the current estimated time (in microseconds) of the radio chip.
*
+6 -1
View File
@@ -223,7 +223,12 @@ otError otLinkRawSetMacKey(otInstance *aInstance,
otError otLinkRawSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter)
{
return AsCoreType(aInstance).Get<Mac::LinkRaw>().SetMacFrameCounter(aMacFrameCounter);
return AsCoreType(aInstance).Get<Mac::LinkRaw>().SetMacFrameCounter(aMacFrameCounter, /* aSetIfLarger */ false);
}
otError otLinkRawSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter)
{
return AsCoreType(aInstance).Get<Mac::LinkRaw>().SetMacFrameCounter(aMacFrameCounter, /* aSetIfLarger */ true);
}
uint64_t otLinkRawGetRadioTime(otInstance *aInstance)
+2 -2
View File
@@ -258,12 +258,12 @@ exit:
return error;
}
Error LinkRaw::SetMacFrameCounter(uint32_t aMacFrameCounter)
Error LinkRaw::SetMacFrameCounter(uint32_t aFrameCounter, bool aSetIfLarger)
{
Error error = kErrorNone;
VerifyOrExit(IsEnabled(), error = kErrorInvalidState);
mSubMac.SetFrameCounter(aMacFrameCounter);
mSubMac.SetFrameCounter(aFrameCounter, aSetIfLarger);
exit:
return error;
+4 -2
View File
@@ -271,13 +271,15 @@ public:
/**
* This method sets the current MAC frame counter value.
*
* @param[in] aMacFrameCounter The MAC frame counter value.
* @param[in] aFrameCounter The MAC frame counter value.
* @param[in] aSetIfLarger If `true`, set only if the new value @p aFrameCounter is larger than current value.
* If `false`, set the new value independent of the current value.
*
* @retval kErrorNone If successful.
* @retval kErrorInvalidState If the raw link-layer isn't enabled.
*
*/
Error SetMacFrameCounter(uint32_t aMacFrameCounter);
Error SetMacFrameCounter(uint32_t aFrameCounter, bool aSetIfLarger);
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
/**
+13 -3
View File
@@ -966,13 +966,23 @@ exit:
return;
}
void SubMac::SetFrameCounter(uint32_t aFrameCounter)
void SubMac::SetFrameCounter(uint32_t aFrameCounter, bool aSetIfLarger)
{
mFrameCounter = aFrameCounter;
if (!aSetIfLarger || (aFrameCounter > mFrameCounter))
{
mFrameCounter = aFrameCounter;
}
VerifyOrExit(!ShouldHandleTransmitSecurity());
Get<Radio>().SetMacFrameCounter(aFrameCounter);
if (aSetIfLarger)
{
Get<Radio>().SetMacFrameCounterIfLarger(aFrameCounter);
}
else
{
Get<Radio>().SetMacFrameCounter(aFrameCounter);
}
exit:
return;
+3 -1
View File
@@ -489,9 +489,11 @@ public:
* This method sets the current MAC Frame Counter value.
*
* @param[in] aFrameCounter The MAC Frame Counter value.
* @param[in] aSetIfLarger If `true`, set only if the new value @p aFrameCounter is larger than the current value.
* If `false`, set the new value independent of the current value.
*
*/
void SetFrameCounter(uint32_t aFrameCounter);
void SetFrameCounter(uint32_t aFrameCounter, bool aSetIfLarger);
#if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE
/**
+12
View File
@@ -301,6 +301,18 @@ public:
otPlatRadioSetMacFrameCounter(GetInstancePtr(), aMacFrameCounter);
}
/**
* This method sets the current MAC Frame Counter value only if the new given value is larger than the current
* value.
*
* @param[in] aMacFrameCounter The MAC Frame Counter value.
*
*/
void SetMacFrameCounterIfLarger(uint32_t aMacFrameCounter)
{
otPlatRadioSetMacFrameCounterIfLarger(GetInstancePtr(), aMacFrameCounter);
}
/**
* This method gets the radio's transmit power in dBm.
*
+22
View File
@@ -212,6 +212,28 @@ OT_TOOL_WEAK void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t
OT_UNUSED_VARIABLE(aMacFrameCounter);
}
OT_TOOL_WEAK void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter)
{
// Radio platforms that support `OT_RADIO_CAPS_TRANSMIT_SEC` should
// provide this radio platform function.
//
// This function helps address an edge-case where OT stack may not
// yet know the latest frame counter values used by radio platform
// (e.g., due to enhanced acks processed by radio platform directly
// or due to delay between RCP and host) and then setting the value
// from OT stack may cause the counter value on radio to move back
// (OT stack will set the counter after appending it in
// `LinkFrameCounterTlv` on all radios when multi-radio links
// feature is enabled).
//
// The weak implementation here is intended as a solution to ensure
// temporary compatibility with radio platforms that may not yet
// implement it. If this weak implementation is used, the edge-case
// above may still happen.
otPlatRadioSetMacFrameCounter(aInstance, aMacFrameCounter);
}
OT_TOOL_WEAK uint64_t otPlatTimeGet(void) { return UINT64_MAX; }
OT_TOOL_WEAK uint64_t otPlatRadioGetNow(otInstance *aInstance)
+6 -4
View File
@@ -381,7 +381,7 @@ void KeyManager::SetCurrentKeySequence(uint32_t aKeySequence)
mKeySequence = aKeySequence;
UpdateKeyMaterial();
SetAllMacFrameCounters(0);
SetAllMacFrameCounters(0, /* aSetIfLarger */ false);
mMleFrameCounter = 0;
Get<Notifier>().Signal(kEventThreadKeySeqCounterChanged);
@@ -412,12 +412,14 @@ const Mac::KeyMaterial &KeyManager::GetTemporaryTrelMacKey(uint32_t aKeySequence
}
#endif
void KeyManager::SetAllMacFrameCounters(uint32_t aMacFrameCounter)
void KeyManager::SetAllMacFrameCounters(uint32_t aFrameCounter, bool aSetIfLarger)
{
mMacFrameCounters.SetAll(aMacFrameCounter);
mMacFrameCounters.SetAll(aFrameCounter);
#if OPENTHREAD_CONFIG_RADIO_LINK_IEEE_802_15_4_ENABLE
Get<Mac::SubMac>().SetFrameCounter(aMacFrameCounter);
Get<Mac::SubMac>().SetFrameCounter(aFrameCounter, aSetIfLarger);
#else
OT_UNUSED_VARIABLE(aSetIfLarger);
#endif
}
+5 -3
View File
@@ -401,10 +401,12 @@ public:
/**
* This method sets the current MAC Frame Counter value for all radio links.
*
* @param[in] aMacFrameCounter The MAC Frame Counter value.
*
* @param[in] aFrameCounter The MAC Frame Counter value.
* @param[in] aSetIfLarger If `true`, set only if the new value @p aFrameCounter is larger than current value.
* If `false`, set the new value independent of the current value.
*/
void SetAllMacFrameCounters(uint32_t aMacFrameCounter);
void SetAllMacFrameCounters(uint32_t aFrameCounter, bool aSetIfLarger);
/**
* This method sets the MAC Frame Counter value which is stored in non-volatile memory.
+2 -2
View File
@@ -365,7 +365,7 @@ void Mle::Restore(void)
Get<KeyManager>().SetCurrentKeySequence(networkInfo.GetKeySequence());
Get<KeyManager>().SetMleFrameCounter(networkInfo.GetMleFrameCounter());
Get<KeyManager>().SetAllMacFrameCounters(networkInfo.GetMacFrameCounter());
Get<KeyManager>().SetAllMacFrameCounters(networkInfo.GetMacFrameCounter(), /* aSetIfLarger */ false);
#if OPENTHREAD_MTD
mDeviceMode.Set(networkInfo.GetDeviceMode() & ~DeviceMode::kModeFullThreadDevice);
@@ -4511,7 +4511,7 @@ Error Mle::TxMessage::AppendLinkFrameCounterTlv(void)
counter = Get<KeyManager>().GetMaximumMacFrameCounter();
#if OPENTHREAD_CONFIG_MULTI_RADIO
Get<KeyManager>().SetAllMacFrameCounters(counter);
Get<KeyManager>().SetAllMacFrameCounters(counter, /* aSetIfLarger */ true);
#endif
return Tlv::Append<LinkFrameCounterTlv>(*this, counter);
+4 -2
View File
@@ -648,10 +648,12 @@ public:
/**
* This method sets the current MAC Frame Counter value.
*
* @param[in] aMacFrameCounter The MAC Frame Counter value.
* @param[in] aMacFrameCounter The MAC Frame Counter value.
* @param[in] aSetIfLarger If `true`, set only if the new value is larger than the current value.
* If `false`, set the new value independent of the current value.
*
*/
otError SetMacFrameCounter(uint32_t aMacFrameCounter);
otError SetMacFrameCounter(uint32_t aMacFrameCounter, bool aSetIfLarger);
/**
* This method sets the radio region code.
+3 -2
View File
@@ -1222,11 +1222,12 @@ exit:
}
template <typename InterfaceType, typename ProcessContextType>
otError RadioSpinel<InterfaceType, ProcessContextType>::SetMacFrameCounter(uint32_t aMacFrameCounter)
otError RadioSpinel<InterfaceType, ProcessContextType>::SetMacFrameCounter(uint32_t aMacFrameCounter, bool aSetIfLarger)
{
otError error;
SuccessOrExit(error = Set(SPINEL_PROP_RCP_MAC_FRAME_COUNTER, SPINEL_DATATYPE_UINT32_S, aMacFrameCounter));
SuccessOrExit(error = Set(SPINEL_PROP_RCP_MAC_FRAME_COUNTER, SPINEL_DATATYPE_UINT32_S SPINEL_DATATYPE_BOOL_S,
aMacFrameCounter, aSetIfLarger));
exit:
return error;
+4 -1
View File
@@ -4772,9 +4772,12 @@ enum
SPINEL_PROP_RCP_MAC_KEY = SPINEL_PROP_RCP_EXT__BEGIN + 0,
/// MAC Frame Counter
/** Format: `L`.
/** Format: `L` for read and `Lb` or `L` for write
*
* `L`: MAC frame counter
* 'b': Optional boolean used only during write. If not provided, `false` is assumed.
* If `true` counter is set only if the new value is larger than current value.
* If `false` the new value is set as frame counter independent of the current value.
*
* The Spinel property is used to set MAC frame counter to RCP.
*
+14 -1
View File
@@ -508,10 +508,23 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RCP_MAC_FRAME_COUNTER
{
otError error = OT_ERROR_NONE;
uint32_t frameCounter;
bool setIfLarger = false;
SuccessOrExit(error = mDecoder.ReadUint32(frameCounter));
error = otLinkRawSetMacFrameCounter(mInstance, frameCounter);
if (!mDecoder.IsAllReadInStruct())
{
SuccessOrExit(error = mDecoder.ReadBool(setIfLarger));
}
if (setIfLarger)
{
error = otLinkRawSetMacFrameCounterIfLarger(mInstance, frameCounter);
}
else
{
error = otLinkRawSetMacFrameCounter(mInstance, frameCounter);
}
exit:
return error;
+7 -1
View File
@@ -666,7 +666,13 @@ void otPlatRadioSetMacKey(otInstance *aInstance,
void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCounter)
{
SuccessOrDie(sRadioSpinel.SetMacFrameCounter(aMacFrameCounter));
SuccessOrDie(sRadioSpinel.SetMacFrameCounter(aMacFrameCounter, /* aSetIfLarger */ false));
OT_UNUSED_VARIABLE(aInstance);
}
void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacFrameCounter)
{
SuccessOrDie(sRadioSpinel.SetMacFrameCounter(aMacFrameCounter, /* aSetIfLarger */ true));
OT_UNUSED_VARIABLE(aInstance);
}