mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 01:17:46 +00:00
[nrf52840] implement enh-ack probing (#6021)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user