Skip to content

Commit

Permalink
[thread] refine RetrieveTelemetryData to populate metrics with best…
Browse files Browse the repository at this point in the history
… effort (#2076)

Best effort means, for a given telemetry, if its retrieval has error,
it is left unpopulated and the process continues to retrieve the
remaining telemetries instead of the immediately return. The error
code OT_ERRROR_FAILED will be returned if there is one or more
error(s) happened in the process.

This change helps to retrieve telemetries with best effort when
needed.
  • Loading branch information
morningboata authored Nov 3, 2023
1 parent 7df21bd commit 45c857c
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 59 deletions.
5 changes: 4 additions & 1 deletion src/dbus/server/dbus_thread_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1412,7 +1412,10 @@ otError DBusThreadObject::GetTelemetryDataHandler(DBusMessageIter &aIter)
threadnetwork::TelemetryData telemetryData;
auto threadHelper = mNcp->GetThreadHelper();

VerifyOrExit(threadHelper->RetrieveTelemetryData(mPublisher, telemetryData) == OT_ERROR_NONE);
if (threadHelper->RetrieveTelemetryData(mPublisher, telemetryData) != OT_ERROR_NONE)
{
otbrLogWarning("Some metrics were not populated in RetrieveTelemetryData");
}

{
const std::string telemetryDataBytes = telemetryData.SerializeAsString();
Expand Down
158 changes: 102 additions & 56 deletions src/utils/thread_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -917,8 +917,14 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
{
int8_t radioTxPower;

SuccessOrExit(error = otPlatRadioGetTransmitPower(mInstance, &radioTxPower));
wpanStats->set_radio_tx_power(radioTxPower);
if (otPlatRadioGetTransmitPower(mInstance, &radioTxPower) == OT_ERROR_NONE)
{
wpanStats->set_radio_tx_power(radioTxPower);
}
else
{
error = OT_ERROR_FAILED;
}
}

{
Expand Down Expand Up @@ -972,10 +978,18 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn

wpanTopoFull->set_rloc16(rloc16);

otRouterInfo info;
{
otRouterInfo info;

VerifyOrExit(otThreadGetRouterInfo(mInstance, rloc16, &info) == OT_ERROR_NONE, error = OT_ERROR_INVALID_STATE);
wpanTopoFull->set_router_id(info.mRouterId);
if (otThreadGetRouterInfo(mInstance, rloc16, &info) == OT_ERROR_NONE)
{
wpanTopoFull->set_router_id(info.mRouterId);
}
else
{
error = OT_ERROR_FAILED;
}
}

otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
otNeighborInfo neighborInfo;
Expand All @@ -997,13 +1011,21 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
}
wpanTopoFull->set_child_table_size(childTable.size());

struct otLeaderData leaderData;
{
struct otLeaderData leaderData;

SuccessOrExit(error = otThreadGetLeaderData(mInstance, &leaderData));
wpanTopoFull->set_leader_router_id(leaderData.mLeaderRouterId);
wpanTopoFull->set_leader_weight(leaderData.mWeighting);
wpanTopoFull->set_network_data_version(leaderData.mDataVersion);
wpanTopoFull->set_stable_network_data_version(leaderData.mStableDataVersion);
if (otThreadGetLeaderData(mInstance, &leaderData) == OT_ERROR_NONE)
{
wpanTopoFull->set_leader_router_id(leaderData.mLeaderRouterId);
wpanTopoFull->set_leader_weight(leaderData.mWeighting);
wpanTopoFull->set_network_data_version(leaderData.mDataVersion);
wpanTopoFull->set_stable_network_data_version(leaderData.mStableDataVersion);
}
else
{
error = OT_ERROR_FAILED;
}
}

uint8_t weight = otThreadGetLocalLeaderWeight(mInstance);

Expand All @@ -1019,19 +1041,31 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
uint8_t len = sizeof(data);
std::vector<uint8_t> networkData;

SuccessOrExit(error = otNetDataGet(mInstance, /*stable=*/false, data, &len));
networkData = std::vector<uint8_t>(&data[0], &data[len]);
wpanTopoFull->set_network_data(std::string(networkData.begin(), networkData.end()));
if (otNetDataGet(mInstance, /*stable=*/false, data, &len) == OT_ERROR_NONE)
{
networkData = std::vector<uint8_t>(&data[0], &data[len]);
wpanTopoFull->set_network_data(std::string(networkData.begin(), networkData.end()));
}
else
{
error = OT_ERROR_FAILED;
}
}

{
uint8_t data[kNetworkDataMaxSize];
uint8_t len = sizeof(data);
std::vector<uint8_t> networkData;

SuccessOrExit(error = otNetDataGet(mInstance, /*stable=*/true, data, &len));
networkData = std::vector<uint8_t>(&data[0], &data[len]);
wpanTopoFull->set_stable_network_data(std::string(networkData.begin(), networkData.end()));
if (otNetDataGet(mInstance, /*stable=*/true, data, &len) == OT_ERROR_NONE)
{
networkData = std::vector<uint8_t>(&data[0], &data[len]);
wpanTopoFull->set_stable_network_data(std::string(networkData.begin(), networkData.end()));
}
else
{
error = OT_ERROR_FAILED;
}
}

int8_t rssi = otPlatRadioGetRssi(mInstance);
Expand Down Expand Up @@ -1331,31 +1365,38 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn

// Start of WpanRcp section.
{
auto wpanRcp = telemetryData.mutable_wpan_rcp();
auto rcpStabilityStatistics = wpanRcp->mutable_rcp_stability_statistics();
otRadioSpinelMetrics otRadioSpinelMetrics = *otSysGetRadioSpinelMetrics();
auto wpanRcp = telemetryData.mutable_wpan_rcp();
const otRadioSpinelMetrics *otRadioSpinelMetrics = otSysGetRadioSpinelMetrics();
auto rcpStabilityStatistics = wpanRcp->mutable_rcp_stability_statistics();

rcpStabilityStatistics->set_rcp_timeout_count(otRadioSpinelMetrics.mRcpTimeoutCount);
rcpStabilityStatistics->set_rcp_reset_count(otRadioSpinelMetrics.mRcpUnexpectedResetCount);
rcpStabilityStatistics->set_rcp_restoration_count(otRadioSpinelMetrics.mRcpRestorationCount);
rcpStabilityStatistics->set_spinel_parse_error_count(otRadioSpinelMetrics.mSpinelParseErrorCount);
if (otRadioSpinelMetrics != nullptr)
{
rcpStabilityStatistics->set_rcp_timeout_count(otRadioSpinelMetrics->mRcpTimeoutCount);
rcpStabilityStatistics->set_rcp_reset_count(otRadioSpinelMetrics->mRcpUnexpectedResetCount);
rcpStabilityStatistics->set_rcp_restoration_count(otRadioSpinelMetrics->mRcpRestorationCount);
rcpStabilityStatistics->set_spinel_parse_error_count(otRadioSpinelMetrics->mSpinelParseErrorCount);
}

// TODO: provide rcp_firmware_update_count info.
rcpStabilityStatistics->set_thread_stack_uptime(otInstanceGetUptime(mInstance));

auto rcpInterfaceStatistics = wpanRcp->mutable_rcp_interface_statistics();
otRcpInterfaceMetrics otRcpInterfaceMetrics = *otSysGetRcpInterfaceMetrics();

rcpInterfaceStatistics->set_rcp_interface_type(otRcpInterfaceMetrics.mRcpInterfaceType);
rcpInterfaceStatistics->set_transferred_frames_count(otRcpInterfaceMetrics.mTransferredFrameCount);
rcpInterfaceStatistics->set_transferred_valid_frames_count(
otRcpInterfaceMetrics.mTransferredValidFrameCount);
rcpInterfaceStatistics->set_transferred_garbage_frames_count(
otRcpInterfaceMetrics.mTransferredGarbageFrameCount);
rcpInterfaceStatistics->set_rx_frames_count(otRcpInterfaceMetrics.mRxFrameCount);
rcpInterfaceStatistics->set_rx_bytes_count(otRcpInterfaceMetrics.mRxFrameByteCount);
rcpInterfaceStatistics->set_tx_frames_count(otRcpInterfaceMetrics.mTxFrameCount);
rcpInterfaceStatistics->set_tx_bytes_count(otRcpInterfaceMetrics.mTxFrameByteCount);
const otRcpInterfaceMetrics *otRcpInterfaceMetrics = otSysGetRcpInterfaceMetrics();

if (otRcpInterfaceMetrics != nullptr)
{
auto rcpInterfaceStatistics = wpanRcp->mutable_rcp_interface_statistics();

rcpInterfaceStatistics->set_rcp_interface_type(otRcpInterfaceMetrics->mRcpInterfaceType);
rcpInterfaceStatistics->set_transferred_frames_count(otRcpInterfaceMetrics->mTransferredFrameCount);
rcpInterfaceStatistics->set_transferred_valid_frames_count(
otRcpInterfaceMetrics->mTransferredValidFrameCount);
rcpInterfaceStatistics->set_transferred_garbage_frames_count(
otRcpInterfaceMetrics->mTransferredGarbageFrameCount);
rcpInterfaceStatistics->set_rx_frames_count(otRcpInterfaceMetrics->mRxFrameCount);
rcpInterfaceStatistics->set_rx_bytes_count(otRcpInterfaceMetrics->mRxFrameByteCount);
rcpInterfaceStatistics->set_tx_frames_count(otRcpInterfaceMetrics->mTxFrameCount);
rcpInterfaceStatistics->set_tx_bytes_count(otRcpInterfaceMetrics->mTxFrameByteCount);
}
}
// End of WpanRcp section.

Expand All @@ -1364,24 +1405,30 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
auto coexMetrics = telemetryData.mutable_coex_metrics();
otRadioCoexMetrics otRadioCoexMetrics;

SuccessOrExit(error = otPlatRadioGetCoexMetrics(mInstance, &otRadioCoexMetrics));
coexMetrics->set_count_tx_request(otRadioCoexMetrics.mNumTxRequest);
coexMetrics->set_count_tx_grant_immediate(otRadioCoexMetrics.mNumTxGrantImmediate);
coexMetrics->set_count_tx_grant_wait(otRadioCoexMetrics.mNumTxGrantWait);
coexMetrics->set_count_tx_grant_wait_activated(otRadioCoexMetrics.mNumTxGrantWaitActivated);
coexMetrics->set_count_tx_grant_wait_timeout(otRadioCoexMetrics.mNumTxGrantWaitTimeout);
coexMetrics->set_count_tx_grant_deactivated_during_request(
otRadioCoexMetrics.mNumTxGrantDeactivatedDuringRequest);
coexMetrics->set_tx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgTxRequestToGrantTime);
coexMetrics->set_count_rx_request(otRadioCoexMetrics.mNumRxRequest);
coexMetrics->set_count_rx_grant_immediate(otRadioCoexMetrics.mNumRxGrantImmediate);
coexMetrics->set_count_rx_grant_wait(otRadioCoexMetrics.mNumRxGrantWait);
coexMetrics->set_count_rx_grant_wait_activated(otRadioCoexMetrics.mNumRxGrantWaitActivated);
coexMetrics->set_count_rx_grant_wait_timeout(otRadioCoexMetrics.mNumRxGrantWaitTimeout);
coexMetrics->set_count_rx_grant_deactivated_during_request(
otRadioCoexMetrics.mNumRxGrantDeactivatedDuringRequest);
coexMetrics->set_count_rx_grant_none(otRadioCoexMetrics.mNumRxGrantNone);
coexMetrics->set_rx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgRxRequestToGrantTime);
if (otPlatRadioGetCoexMetrics(mInstance, &otRadioCoexMetrics) == OT_ERROR_NONE)
{
coexMetrics->set_count_tx_request(otRadioCoexMetrics.mNumTxRequest);
coexMetrics->set_count_tx_grant_immediate(otRadioCoexMetrics.mNumTxGrantImmediate);
coexMetrics->set_count_tx_grant_wait(otRadioCoexMetrics.mNumTxGrantWait);
coexMetrics->set_count_tx_grant_wait_activated(otRadioCoexMetrics.mNumTxGrantWaitActivated);
coexMetrics->set_count_tx_grant_wait_timeout(otRadioCoexMetrics.mNumTxGrantWaitTimeout);
coexMetrics->set_count_tx_grant_deactivated_during_request(
otRadioCoexMetrics.mNumTxGrantDeactivatedDuringRequest);
coexMetrics->set_tx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgTxRequestToGrantTime);
coexMetrics->set_count_rx_request(otRadioCoexMetrics.mNumRxRequest);
coexMetrics->set_count_rx_grant_immediate(otRadioCoexMetrics.mNumRxGrantImmediate);
coexMetrics->set_count_rx_grant_wait(otRadioCoexMetrics.mNumRxGrantWait);
coexMetrics->set_count_rx_grant_wait_activated(otRadioCoexMetrics.mNumRxGrantWaitActivated);
coexMetrics->set_count_rx_grant_wait_timeout(otRadioCoexMetrics.mNumRxGrantWaitTimeout);
coexMetrics->set_count_rx_grant_deactivated_during_request(
otRadioCoexMetrics.mNumRxGrantDeactivatedDuringRequest);
coexMetrics->set_count_rx_grant_none(otRadioCoexMetrics.mNumRxGrantNone);
coexMetrics->set_rx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgRxRequestToGrantTime);
}
else
{
error = OT_ERROR_FAILED;
}
}
// End of CoexMetrics section.
}
Expand All @@ -1408,7 +1455,6 @@ otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadn
}
#endif // OTBR_ENABLE_LINK_METRICS_TELEMETRY

exit:
return error;
}
#endif // OTBR_ENABLE_TELEMETRY_DATA_API
Expand Down
8 changes: 6 additions & 2 deletions src/utils/thread_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,12 +258,16 @@ class ThreadHelper

#if OTBR_ENABLE_TELEMETRY_DATA_API
/**
* This method populates the telemetry data and returns the error code if error happens.
* This method populates the telemetry data with best effort. The best effort means, for a given
* telemetry, if its retrieval has error, it is left unpopulated and the process continues to
* retrieve the remaining telemetries instead of the immediately return. The error code
* OT_ERRROR_FAILED will be returned if there is one or more error(s) happened in the process.
*
* @param[in] aPublisher The Mdns::Publisher to provide MDNS telemetry if it is not `nullptr`.
* @param[in] telemetryData The telemetry data to be populated.
*
* @returns The error code if error happens during the population of the telemetry data.
* @retval OTBR_ERROR_NONE There is no error happened in the process.
* @retval OT_ERRROR_FAILED There is one or more error(s) happened in the process.
*/
otError RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadnetwork::TelemetryData &telemetryData);
#endif // OTBR_ENABLE_TELEMETRY_DATA_API
Expand Down

0 comments on commit 45c857c

Please sign in to comment.