[nrf52840] implement enh-ack probing (#6021)

This commit is contained in:
Li Cao
2021-01-07 12:01:06 -08:00
committed by GitHub
parent 1c70361c0e
commit b2f7bda6b4
10 changed files with 185 additions and 44 deletions
+75 -23
View File
@@ -45,6 +45,7 @@
#include "common/code_utils.hpp"
#include "utils/code_utils.h"
#include "utils/link_metrics.h"
#include "utils/mac_frame.h"
#include <platform-config.h>
@@ -195,6 +196,16 @@ static void convertShortAddress(uint8_t *aTo, uint16_t aFrom)
aTo[1] = (uint8_t)(aFrom >> 8);
}
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
static void convertExtAddress(uint8_t *aTo, const otExtAddress *aFrom)
{
for (uint8_t i = 0; i < sizeof(otExtAddress); i++)
{
aTo[i] = aFrom->m8[sizeof(otExtAddress) - i - 1];
}
}
#endif
static inline bool isPendingEventSet(RadioPendingEvents aEvent)
{
return sPendingEvents & (1UL << aEvent);
@@ -1063,8 +1074,23 @@ static uint16_t getCslPhase()
}
#endif
void nrf_802154_tx_ack_started(uint8_t *p_data)
void nrf_802154_tx_ack_started(uint8_t *p_data, int8_t power, uint8_t lqi)
{
otRadioFrame ackFrame;
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
uint8_t linkMetricsDataLen = 0;
uint8_t linkMetricsData[OT_ENH_PROBING_IE_DATA_MAX_SIZE];
otMacAddress macAddress;
#else
OT_UNUSED_VARIABLE(power);
OT_UNUSED_VARIABLE(lqi);
#endif
OT_UNUSED_VARIABLE(ackFrame);
ackFrame.mPsdu = (uint8_t *)(p_data + 1);
ackFrame.mLength = p_data[0];
// Check if the frame pending bit is set in ACK frame.
sAckedWithFramePending = p_data[FRAME_PENDING_OFFSET] & FRAME_PENDING_BIT;
@@ -1073,13 +1099,18 @@ void nrf_802154_tx_ack_started(uint8_t *p_data)
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
{
otRadioFrame ackFrame;
ackFrame.mPsdu = (uint8_t *)(p_data + 1);
ackFrame.mLength = p_data[0];
otMacFrameSetCslIe(&ackFrame, sCslPeriod, getCslPhase());
}
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
otMacFrameGetDstAddr(&ackFrame, &macAddress);
if ((linkMetricsDataLen = otLinkMetricsEnhAckGenData(&macAddress, lqi, power, linkMetricsData)) > 0)
{
otMacFrameSetEnhAckProbingIe(&ackFrame, linkMetricsData, linkMetricsDataLen);
}
#endif
txAckProcessSecurity(p_data);
#endif
}
@@ -1265,51 +1296,66 @@ void otPlatRadioSetMacFrameCounter(otInstance *aInstance, uint32_t aMacFrameCoun
}
#endif // OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
static void updateIeData(otInstance *aInstance, const uint8_t *aShortAddr, const uint8_t *aExtAddr)
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
static void updateIeData(otInstance *aInstance, otShortAddress aShortAddr, const otExtAddress *aExtAddr)
{
OT_UNUSED_VARIABLE(aInstance);
int8_t offset = 0;
uint8_t ackIeData[OT_ACK_IE_MAX_SIZE];
uint8_t extAddr[OT_EXT_ADDRESS_SIZE];
uint8_t shortAddr[SHORT_ADDRESS_SIZE];
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
uint8_t enhAckProbingDataLen = 0;
otMacAddress macAddress;
macAddress.mType = OT_MAC_ADDRESS_TYPE_SHORT;
macAddress.mAddress.mShortAddress = aShortAddr;
#endif
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
if (sCslPeriod > 0)
{
memcpy(ackIeData, sCslIeHeader, OT_IE_HEADER_SIZE);
offset += OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE; // reserve space for CSL IE
}
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
if ((enhAckProbingDataLen = otLinkMetricsEnhAckGetDataLen(&macAddress)) > 0)
{
offset += otMacFrameGenerateEnhAckProbingIe(ackIeData + offset, NULL, enhAckProbingDataLen);
}
#endif
convertShortAddress(shortAddr, aShortAddr);
convertExtAddress(extAddr, aExtAddr);
if (offset > 0)
{
nrf_802154_ack_data_set(aShortAddr, false, ackIeData, offset, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_set(aExtAddr, true, ackIeData, offset, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_set(shortAddr, false, ackIeData, offset, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_set(extAddr, true, ackIeData, offset, NRF_802154_ACK_DATA_IE);
}
else
{
nrf_802154_ack_data_clear(aShortAddr, false, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_clear(aExtAddr, true, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_clear(shortAddr, false, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_clear(extAddr, true, NRF_802154_ACK_DATA_IE);
}
}
#endif // OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE
otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, const otExtAddress *aExtAddr)
{
otError error = OT_ERROR_NONE;
uint8_t parentExtAddr[OT_EXT_ADDRESS_SIZE];
uint8_t parentShortAddress[SHORT_ADDRESS_SIZE];
const uint8_t *shortAddress;
otShortAddress shortAddress;
sCslPeriod = aCslPeriod;
for (uint32_t i = 0; i < sizeof(parentExtAddr); i++)
{
parentExtAddr[i] = aExtAddr->m8[sizeof(parentExtAddr) - i - 1];
}
shortAddress = nrf_802154_pib_short_address_get()[1]
<< 8; // Don't need the other byte because this is parent's short address
shortAddress &= 0xfc00;
shortAddress = nrf_802154_pib_short_address_get();
memcpy(parentShortAddress, shortAddress, SHORT_ADDRESS_SIZE);
parentShortAddress[0] &= 0xfc;
updateIeData(aInstance, parentShortAddress, parentExtAddr);
updateIeData(aInstance, shortAddress, aExtAddr);
return error;
}
@@ -1333,7 +1379,13 @@ otError otPlatRadioConfigureEnhAckProbing(otInstance * aInstance,
OT_UNUSED_VARIABLE(aShortAddress);
OT_UNUSED_VARIABLE(aExtAddress);
return OT_ERROR_NOT_IMPLEMENTED;
otError error = OT_ERROR_NONE;
SuccessOrExit(error = otLinkMetricsConfigureEnhAckProbing(aShortAddress, aExtAddress, aLinkMetrics));
updateIeData(aInstance, aShortAddress, aExtAddress);
exit:
return error;
}
#endif
+20 -3
View File
@@ -29,19 +29,32 @@
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
lib_LIBRARIES = libopenthread-platform-utils.a
noinst_LTLIBRARIES = libutils-link-metrics.la
libopenthread_platform_utils_a_CPPFLAGS = \
COMMON_FLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/examples/platforms \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/third_party/jlink/SEGGER_RTT_V640/RTT \
$(NULL)
libutils_link_metrics_la_CPPFLAGS = \
$(COMMON_FLAGS) \
-fno-threadsafe-statics \
$(NULL)
libutils_link_metrics_la_SOURCES = \
link_metrics.cpp \
link_metrics.h \
$(NULL)
libopenthread_platform_utils_a_CPPFLAGS = \
$(COMMON_FLAGS) \
$(NULL)
libopenthread_platform_utils_a_SOURCES = \
code_utils.h \
debug_uart.c \
link_metrics.cpp \
link_metrics.h \
logging_rtt.c \
logging_rtt.h \
mac_frame.cpp \
@@ -53,4 +66,8 @@ libopenthread_platform_utils_a_SOURCES = \
soft_source_match_table.h \
$(NULL)
libopenthread_platform_utils_a_LIBADD = \
libutils-link-metrics.la \
$(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+24
View File
@@ -113,6 +113,18 @@ public:
return bytes;
}
/**
* This method gets the length of Link Metrics Data.
*
* @returns The number of bytes for the data.
*
*/
uint8_t GetEnhAckDataLen() const
{
return static_cast<uint8_t>(mLinkMetrics.mLqi) + static_cast<uint8_t>(mLinkMetrics.mLinkMargin) +
static_cast<uint8_t>(mLinkMetrics.mRssi);
}
/**
* This method gets the metrics configured for the Enhanced-ACK Based Probing.
*
@@ -236,4 +248,16 @@ uint8_t otLinkMetricsEnhAckGenData(const otMacAddress *aMacAddress, uint8_t aLqi
exit:
return bytes;
}
uint8_t otLinkMetricsEnhAckGetDataLen(const otMacAddress *aMacAddress)
{
uint8_t len = 0;
LinkMetricsDataInfo *dataInfo = GetLinkMetricsInfoByMacAddress(aMacAddress);
VerifyOrExit(dataInfo != nullptr);
len = dataInfo->GetEnhAckDataLen();
exit:
return len;
}
#endif // OPENTHREAD_CONFIG_MLE_LINK_METRICS_ENABLE
+10
View File
@@ -97,6 +97,16 @@ otError otLinkMetricsConfigureEnhAckProbing(otShortAddress aShortAddress,
*/
uint8_t otLinkMetricsEnhAckGenData(const otMacAddress *aMacAddress, uint8_t aLqi, int8_t aRssi, uint8_t *aData);
/**
* This method returns the data length of Enhanced-ACK Based Probing for a specific Initiator.
*
* @param[in] aMacAddress The Mac address of the Initiator.
*
* @returns The size of data. `0` if it's not configured for the Initiator.
*
*/
uint8_t otLinkMetricsEnhAckGetDataLen(const otMacAddress *aMacAddress);
#ifdef __cplusplus
} // extern "C"
#endif
+33 -14
View File
@@ -91,6 +91,26 @@ bool otMacFrameIsAckRequested(const otRadioFrame *aFrame)
return static_cast<const Mac::Frame *>(aFrame)->GetAckRequest();
}
static void GetOtMacAddress(const Mac::Address &aInAddress, otMacAddress *aOutAddress)
{
switch (aInAddress.GetType())
{
case Mac::Address::kTypeNone:
aOutAddress->mType = OT_MAC_ADDRESS_TYPE_NONE;
break;
case Mac::Address::kTypeShort:
aOutAddress->mType = OT_MAC_ADDRESS_TYPE_SHORT;
aOutAddress->mAddress.mShortAddress = aInAddress.GetShort();
break;
case Mac::Address::kTypeExtended:
aOutAddress->mType = OT_MAC_ADDRESS_TYPE_EXTENDED;
aOutAddress->mAddress.mExtAddress = aInAddress.GetExtended();
break;
}
}
otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
{
otError error;
@@ -99,22 +119,21 @@ otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddre
error = static_cast<const Mac::Frame *>(aFrame)->GetSrcAddr(address);
SuccessOrExit(error);
switch (address.GetType())
{
case Mac::Address::kTypeNone:
aMacAddress->mType = OT_MAC_ADDRESS_TYPE_NONE;
break;
GetOtMacAddress(address, aMacAddress);
case Mac::Address::kTypeShort:
aMacAddress->mType = OT_MAC_ADDRESS_TYPE_SHORT;
aMacAddress->mAddress.mShortAddress = address.GetShort();
break;
exit:
return error;
}
case Mac::Address::kTypeExtended:
aMacAddress->mType = OT_MAC_ADDRESS_TYPE_EXTENDED;
aMacAddress->mAddress.mExtAddress = address.GetExtended();
break;
}
otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress)
{
otError error;
Mac::Address address;
error = static_cast<const Mac::Frame *>(aFrame)->GetDstAddr(address);
SuccessOrExit(error);
GetOtMacAddress(address, aMacAddress);
exit:
return error;
+12
View File
@@ -153,6 +153,18 @@ bool otMacFrameDoesAddrMatch(const otRadioFrame *aFrame,
*/
otError otMacFrameGetSrcAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
/**
* Get destination MAC address.
*
* @param[in] aFrame A pointer to the frame.
* @param[out] aMacAddress A pointer to MAC address.
*
* @retval OT_ERROR_NONE Successfully got the destination MAC address.
* @retval OT_ERROR_PARSE Failed to parse the destination MAC address.
*
*/
otError otMacFrameGetDstAddr(const otRadioFrame *aFrame, otMacAddress *aMacAddress);
/**
* Get the sequence of @p aFrame.
*
+1 -1
View File
@@ -498,7 +498,7 @@ void LinkMetrics::HandleLinkMetricsReport(const Message & aMessage,
case kLinkMetricsReportSub:
VerifyOrExit(!hasStatus,
error = OT_ERROR_DROP); // There shouldn't be any Report-Sub TLV when there's a Status TLV
VerifyOrExit(tlv.GetLength() == sizeof(typeIdFlags), error = OT_ERROR_PARSE);
VerifyOrExit(tlv.GetLength() > sizeof(typeIdFlags), error = OT_ERROR_PARSE);
SuccessOrExit(aMessage.Read(pos, typeIdFlags));
if (typeIdFlags.IsExtendedFlagSet())
{
+3 -1
View File
@@ -697,9 +697,11 @@ void nrf_802154_ack_timeout_set(uint32_t time)
#endif // NRF_802154_ACK_TIMEOUT_ENABLED
__WEAK void nrf_802154_tx_ack_started(uint8_t * p_data)
__WEAK void nrf_802154_tx_ack_started(uint8_t * p_data, int8_t power, uint8_t lqi)
{
(void)p_data;
(void)power;
(void)lqi;
}
#if NRF_802154_USE_RAW_API
+3 -1
View File
@@ -536,8 +536,10 @@ bool nrf_802154_continuous_carrier(void);
* @note This function must be very short to prevent dropping frames by the driver.
*
* @param[in] p_data Pointer to a buffer with PHR and PSDU of the ACK frame.
* @param[in] power RSSI of the received frame.
* @param[in] lqi LQI of the received frame.
*/
extern void nrf_802154_tx_ack_started(uint8_t * p_data);
extern void nrf_802154_tx_ack_started(uint8_t * p_data, int8_t power, uint8_t lqi);
#if NRF_802154_USE_RAW_API
@@ -169,6 +169,7 @@ static uint8_t * mp_ack; ///< Pointer to Ack frame buffer.
static const uint8_t * mp_tx_data; ///< Pointer to the data to transmit.
static uint32_t m_ed_time_left; ///< Remaining time of the current energy detection procedure [us].
static uint8_t m_ed_result; ///< Result of the current energy detection procedure.
static uint8_t m_last_lqi; ///< LQI value of last Rx frame.
static volatile radio_state_t m_state; ///< State of the radio driver.
@@ -1976,7 +1977,7 @@ static void irq_address_state_tx_frame(void)
static void irq_address_state_tx_ack(void)
{
nrf_802154_tx_ack_started(mp_ack);
nrf_802154_tx_ack_started(mp_ack, rssi_last_measurement_get(), m_last_lqi);
}
static void irq_address_state_rx_ack(void)
@@ -2144,6 +2145,8 @@ static void irq_crcok_state_rx(void)
nrf_802154_pib_auto_ack_get())
{
mp_ack = nrf_802154_ack_generator_create(mp_current_rx_buffer->data);
m_last_lqi = lqi_get(mp_current_rx_buffer->data);
if (NULL != mp_ack)
{
send_ack = true;