[spinel] add missing Link Metrics Subject functionality (#7118)

This commit adds the missing Link Metrics configuration of Enh-ACK
probing in RCP.
This commit is contained in:
konradderda
2021-10-29 14:26:03 -07:00
committed by GitHub
parent 319068637c
commit 09dd21abca
10 changed files with 161 additions and 38 deletions
+26
View File
@@ -675,6 +675,32 @@ public:
*/
otError GetRadioRegion(uint16_t *aRegionCode);
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
/**
* Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator.
*
* After Enhanced-ACK Based Probing is configured by a specific Probing Initiator, the Enhanced-ACK sent to that
* node should include Vendor-Specific IE containing Link Metrics data. This method informs the radio to start/stop
* to collect Link Metrics data and include Vendor-Specific IE that containing the data in Enhanced-ACK sent to that
* Probing Initiator.
*
* @param[in] aLinkMetrics This parameter specifies what metrics to query. Per spec 4.11.3.4.4.6, at most 2
* metrics can be specified. The probing would be disabled if @p aLinkMetrics is
* bitwise 0.
* @param[in] aShortAddress The short address of the Probing Initiator.
* @param[in] aExtAddress The extended source address of the Probing Initiator. @p aExtAddress MUST NOT be
* nullptr.
*
* @retval OT_ERROR_NONE Successfully configured the Enhanced-ACK Based Probing.
* @retval OT_ERROR_INVALID_ARGS @p aExtAddress is nullptr.
* @retval OT_ERROR_NOT_FOUND The Initiator indicated by @p aShortAddress is not found when trying to clear.
* @retval OT_ERROR_NO_BUFS No more Initiator can be supported.
*/
otError ConfigureEnhAckProbing(otLinkMetrics aLinkMetrics,
const otShortAddress aShortAddress,
const otExtAddress & aExtAddress);
#endif
/**
* This method checks whether the spinel interface is radio-only.
*
+36
View File
@@ -2406,5 +2406,41 @@ exit:
return error;
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
template <typename InterfaceType, typename ProcessContextType>
otError RadioSpinel<InterfaceType, ProcessContextType>::ConfigureEnhAckProbing(otLinkMetrics aLinkMetrics,
const otShortAddress aShortAddress,
const otExtAddress & aExtAddress)
{
otError error = OT_ERROR_NONE;
uint8_t flags = 0;
if (aLinkMetrics.mPduCount)
{
flags |= SPINEL_THREAD_LINK_METRIC_PDU_COUNT;
}
if (aLinkMetrics.mLqi)
{
flags |= SPINEL_THREAD_LINK_METRIC_LQI;
}
if (aLinkMetrics.mLinkMargin)
{
flags |= SPINEL_THREAD_LINK_METRIC_LINK_MARGIN;
}
if (aLinkMetrics.mRssi)
{
flags |= SPINEL_THREAD_LINK_METRIC_RSSI;
}
error = Set(SPINEL_PROP_RCP_ENH_ACK_PROBING, SPINEL_DATATYPE_UINT16_S, SPINEL_DATATYPE_EUI64_S,
SPINEL_DATATYPE_UINT8_S, aShortAddress, aExtAddress.m8, flags);
return error;
}
#endif
} // namespace Spinel
} // namespace ot
+1
View File
@@ -1400,6 +1400,7 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key)
{SPINEL_PROP_CHILD_SUPERVISION_INTERVAL, "CHILD_SUPERVISION_INTERVAL"},
{SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT, "CHILD_SUPERVISION_CHECK_TIMEOUT"},
{SPINEL_PROP_RCP_VERSION, "RCP_VERSION"},
{SPINEL_PROP_RCP_ENH_ACK_PROBING, "ENH_ACK_PROBING"},
{SPINEL_PROP_PARENT_RESPONSE_INFO, "PARENT_RESPONSE_INFO"},
{SPINEL_PROP_SLAAC_ENABLED, "SLAAC_ENABLED"},
{SPINEL_PROP_SUPPORTED_RADIO_LINKS, "SUPPORTED_RADIO_LINKS"},
+23 -1
View File
@@ -377,7 +377,7 @@
* Please see section "Spinel definition compatibility guideline" for more details.
*
*/
#define SPINEL_RCP_API_VERSION 4
#define SPINEL_RCP_API_VERSION 5
/**
* @def SPINEL_MIN_HOST_SUPPORTED_RCP_API_VERSION
@@ -752,6 +752,7 @@ enum
// @ref SPINEL_PROP_THREAD_LINK_METRICS_QUERY_RESULT
// @ref SPINEL_PROP_THREAD_LINK_METRICS_MGMT_ENH_ACK
// @ref SPINEL_PROP_THREAD_LINK_METRICS_MGMT_FORWARD
// @ref SPINEL_PROP_RCP_ENH_ACK_PROBING
enum
{
SPINEL_THREAD_LINK_METRIC_PDU_COUNT = (1 << 0),
@@ -4709,6 +4710,27 @@ enum
*/
SPINEL_PROP_RCP_TIMESTAMP = SPINEL_PROP_RCP_EXT__BEGIN + 2,
/// Configure Enhanced ACK probing
/** Format: `SEC` (Write-only).
*
* `S`: Short address
* `E`: Extended address
* `C`: List of requested metric ids encoded as bit fields in single byte
*
* +---------------+----+
* | Metric | Id |
* +---------------+----+
* | Received PDUs | 0 |
* | LQI | 1 |
* | Link margin | 2 |
* | RSSI | 3 |
* +---------------+----+
*
* Enable/disable or update Enhanced-ACK Based Probing in radio for a specific Initiator.
*
*/
SPINEL_PROP_RCP_ENH_ACK_PROBING = SPINEL_PROP_RCP_EXT__BEGIN + 3,
SPINEL_PROP_RCP_EXT__END = 0x900,
SPINEL_PROP_NEST__BEGIN = 0x3BC0,
+34
View File
@@ -2541,6 +2541,40 @@ exit:
}
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
otError NcpBase::DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount)
{
otError error = OT_ERROR_NONE;
uint8_t metrics = 0;
SuccessOrExit(error = mDecoder.ReadUint8(metrics));
if (metrics & SPINEL_THREAD_LINK_METRIC_PDU_COUNT)
{
VerifyOrExit(aAllowPduCount, error = OT_ERROR_INVALID_ARGS);
aMetrics->mPduCount = true;
}
if (metrics & SPINEL_THREAD_LINK_METRIC_LQI)
{
aMetrics->mLqi = true;
}
if (metrics & SPINEL_THREAD_LINK_METRIC_LINK_MARGIN)
{
aMetrics->mLinkMargin = true;
}
if (metrics & SPINEL_THREAD_LINK_METRIC_RSSI)
{
aMetrics->mRssi = true;
}
exit:
return error;
}
#endif
} // namespace Ncp
} // namespace ot
+4 -2
View File
@@ -389,8 +389,6 @@ protected:
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
otError DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount);
otError EncodeLinkMetricsValues(const otLinkMetricsValues *aMetricsValues);
#endif
@@ -404,6 +402,10 @@ protected:
#endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
#endif // OPENTHREAD_MTD || OPENTHREAD_FTD
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE || OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
otError DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount);
#endif
otError CommandHandler_NOOP(uint8_t aHeader);
otError CommandHandler_RESET(uint8_t aHeader);
// Combined command handler for `VALUE_GET`, `VALUE_SET`, `VALUE_INSERT` and `VALUE_REMOVE`.
+3
View File
@@ -479,7 +479,10 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey)
#if OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_MAC_KEY),
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_MAC_FRAME_COUNTER),
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_RCP_ENH_ACK_PROBING),
#endif
#endif // OPENTHREAD_RADIO || OPENTHREAD_CONFIG_LINK_RAW_ENABLE
#if OPENTHREAD_MTD || OPENTHREAD_FTD
OT_NCP_SET_HANDLER_ENTRY(SPINEL_PROP_UNSOL_UPDATE_FILTER),
#if OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE
+3 -35
View File
@@ -215,38 +215,6 @@ exit:
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
otError NcpBase::DecodeLinkMetrics(otLinkMetrics *aMetrics, bool aAllowPduCount)
{
otError error = OT_ERROR_NONE;
uint8_t metrics = 0;
SuccessOrExit(error = mDecoder.ReadUint8(metrics));
if (metrics & SPINEL_THREAD_LINK_METRIC_PDU_COUNT)
{
VerifyOrExit(aAllowPduCount, error = OT_ERROR_INVALID_ARGS);
aMetrics->mPduCount = true;
}
if (metrics & SPINEL_THREAD_LINK_METRIC_LQI)
{
aMetrics->mLqi = true;
}
if (metrics & SPINEL_THREAD_LINK_METRIC_LINK_MARGIN)
{
aMetrics->mLinkMargin = true;
}
if (metrics & SPINEL_THREAD_LINK_METRIC_RSSI)
{
aMetrics->mRssi = true;
}
exit:
return error;
}
otError NcpBase::EncodeLinkMetricsValues(const otLinkMetricsValues *aMetricsValues)
{
otError error = OT_ERROR_NONE;
@@ -3155,7 +3123,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_LINK_METRICS_Q
SuccessOrExit(error = mDecoder.ReadIp6Address(address));
SuccessOrExit(error = mDecoder.ReadUint8(seriesId));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, true));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ true));
error =
otLinkMetricsQuery(mInstance, &address, seriesId, &linkMetrics, &NcpBase::HandleLinkMetricsReport_Jump, this);
@@ -3190,7 +3158,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_LINK_METRICS_M
SuccessOrExit(error = mDecoder.ReadIp6Address(address));
SuccessOrExit(error = mDecoder.ReadUint8(controlFlags));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, false));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ false));
error = otLinkMetricsConfigEnhAckProbing(mInstance, &address, static_cast<otLinkMetricsEnhAckFlags>(controlFlags),
controlFlags ? &linkMetrics : nullptr,
@@ -3214,7 +3182,7 @@ template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_LINK_METRICS_M
SuccessOrExit(error = mDecoder.ReadUint8(seriesId));
SuccessOrExit(error = mDecoder.ReadUint8(types));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, true));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ true));
if (types & SPINEL_THREAD_FRAME_TYPE_MLE_LINK_PROBE)
{
+19
View File
@@ -512,6 +512,25 @@ exit:
return error;
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_RCP_ENH_ACK_PROBING>(void)
{
otError error = OT_ERROR_NONE;
uint16_t shortAddress;
const otExtAddress *extAddress;
otLinkMetrics linkMetrics = {};
SuccessOrExit(error = mDecoder.ReadUint16(shortAddress));
SuccessOrExit(error = mDecoder.ReadEui64(extAddress));
SuccessOrExit(error = DecodeLinkMetrics(&linkMetrics, /* aAllowPduCount */ true));
error = otPlatRadioConfigureEnhAckProbing(mInstance, linkMetrics, shortAddress, extAddress);
exit:
return error;
}
#endif
} // namespace Ncp
} // namespace ot
+12
View File
@@ -619,6 +619,18 @@ otError otPlatRadioGetRegion(otInstance *aInstance, uint16_t *aRegionCode)
return sRadioSpinel.GetRadioRegion(aRegionCode);
}
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
otError otPlatRadioConfigureEnhAckProbing(otInstance * aInstance,
otLinkMetrics aLinkMetrics,
const otShortAddress aShortAddress,
const otExtAddress * aExtAddress)
{
OT_UNUSED_VARIABLE(aInstance);
return sRadioSpinel.ConfigureEnhAckProbing(aLinkMetrics, aShortAddress, *aExtAddress);
}
#endif
otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t aStart, uint32_t aDuration)
{
OT_UNUSED_VARIABLE(aInstance);