diff --git a/src/lib/spinel/radio_spinel.hpp b/src/lib/spinel/radio_spinel.hpp index bfa1a18b3..b0d3b463f 100644 --- a/src/lib/spinel/radio_spinel.hpp +++ b/src/lib/spinel/radio_spinel.hpp @@ -37,6 +37,7 @@ #include #include "openthread-spinel-config.h" +#include "radio_spinel_metrics.h" #include "spinel.h" #include "spinel_interface.hpp" #include "core/radio/max_power_table.hpp" @@ -877,6 +878,14 @@ public: */ otError SendReset(uint8_t aResetType); + /** + * This method returns the radio Spinel metrics. + * + * @returns The radio Spinel metrics. + * + */ + const otRadioSpinelMetrics *GetRadioSpinelMetrics(void) const { return &mRadioSpinelMetrics; } + private: enum { @@ -982,6 +991,10 @@ private: #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 void RestoreProperties(void); #endif + void UpdateParseErrorCount(otError aError) + { + mRadioSpinelMetrics.mSpinelParseErrorCount += (aError == OT_ERROR_PARSE) ? 1 : 0; + } otInstance *mInstance; @@ -1066,6 +1079,8 @@ private: int64_t mRadioTimeOffset; ///< Time difference with estimated RCP time minus host time. MaxPowerTable mMaxPowerTable; + + otRadioSpinelMetrics mRadioSpinelMetrics; }; } // namespace Spinel diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp index 0073817ae..c9eda5c48 100644 --- a/src/lib/spinel/radio_spinel_impl.hpp +++ b/src/lib/spinel/radio_spinel_impl.hpp @@ -218,6 +218,7 @@ RadioSpinel::RadioSpinel(void) , mRadioTimeOffset(0) { mVersion[0] = '\0'; + memset(&mRadioSpinelMetrics, 0, sizeof(mRadioSpinelMetrics)); } template @@ -482,6 +483,8 @@ exit: mRxFrameBuffer.DiscardFrame(); otLogWarnPlat("Error handling hdlc frame: %s", otThreadErrorToString(error)); } + + UpdateParseErrorCount(error); } template @@ -535,6 +538,7 @@ exit: aFrameBuffer.DiscardFrame(); } + UpdateParseErrorCount(error); LogIfFail("Error processing notification", error); } @@ -556,6 +560,7 @@ void RadioSpinel::HandleNotification(const ui HandleValueIs(key, data, static_cast(len)); exit: + UpdateParseErrorCount(error); LogIfFail("Error processing saved notification", error); } @@ -597,6 +602,7 @@ void RadioSpinel::HandleResponse(const uint8_ } exit: + UpdateParseErrorCount(error); LogIfFail("Error processing response", error); } @@ -829,6 +835,7 @@ void RadioSpinel::HandleWaitingResponse(uint3 } exit: + UpdateParseErrorCount(mError); LogIfFail("Error processing result", mError); } @@ -936,6 +943,7 @@ void RadioSpinel::HandleValueIs(spinel_prop_k } exit: + UpdateParseErrorCount(error); LogIfFail("Failed to handle ValueIs", error); } @@ -1007,6 +1015,7 @@ otError RadioSpinel::ParseRadioFrame(otRadioF } exit: + UpdateParseErrorCount(error); LogIfFail("Handle radio frame failed", error); return error; } @@ -1924,6 +1933,7 @@ void RadioSpinel::HandleTransmitDone(uint32_t exit: mState = kStateTransmitDone; mTxError = error; + UpdateParseErrorCount(error); LogIfFail("Handle transmit done failed", error); } @@ -2117,6 +2127,7 @@ uint32_t RadioSpinel::GetRadioChannelMask(boo channelMask &= mMaxPowerTable.GetSupportedChannelMask(); exit: + UpdateParseErrorCount(error); LogIfFail("Get radio channel mask failed", error); return channelMask; } @@ -2211,6 +2222,7 @@ void RadioSpinel::HandleRcpUnexpectedReset(sp { OT_UNUSED_VARIABLE(aStatus); + mRadioSpinelMetrics.mRcpUnexpectedResetCount++; otLogCritPlat("Unexpected RCP reset: %s", spinel_status_to_cstr(aStatus)); #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 @@ -2223,6 +2235,8 @@ void RadioSpinel::HandleRcpUnexpectedReset(sp template void RadioSpinel::HandleRcpTimeout(void) { + mRadioSpinelMetrics.mRcpTimeoutCount++; + #if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0 mRcpFailed = true; #else @@ -2245,6 +2259,7 @@ void RadioSpinel::RecoverFromRcpFailure(void) otLogWarnPlat("RCP failure detected"); + ++mRadioSpinelMetrics.mRcpRestorationCount; ++mRcpFailureCount; if (mRcpFailureCount > kMaxFailureCount) { diff --git a/src/lib/spinel/radio_spinel_metrics.h b/src/lib/spinel/radio_spinel_metrics.h new file mode 100644 index 000000000..438e14c8a --- /dev/null +++ b/src/lib/spinel/radio_spinel_metrics.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * @brief + * This file includes the definitions of the radio spinel metrics. + */ + +#ifndef RADIO_SPINEL_METRICS_H_ +#define RADIO_SPINEL_METRICS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This structure represents the radio spinel metrics. + * + */ +typedef struct otRadioSpinelMetrics +{ + uint32_t mRcpTimeoutCount; ///< The number of RCP timeouts. + uint32_t mRcpUnexpectedResetCount; ///< The number of RCP unexcepted resets. + uint32_t mRcpRestorationCount; ///< The number of RCP restorations. + uint32_t mSpinelParseErrorCount; ///< The number of spinel frame parse errors. +} otRadioSpinelMetrics; + +#ifdef __cplusplus +} // end of extern "C" +#endif + +#endif // RADIO_SPINEL_METRICS_H_ diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h index e8210703b..c8add468a 100644 --- a/src/posix/platform/include/openthread/openthread-system.h +++ b/src/posix/platform/include/openthread/openthread-system.h @@ -45,6 +45,8 @@ #include #include +#include "lib/spinel/radio_spinel_metrics.h" + #ifdef __cplusplus extern "C" { #endif @@ -184,6 +186,14 @@ unsigned int otSysGetThreadNetifIndex(void); */ const char *otSysGetInfraNetifName(void); +/** + * This method returns the radio spinel metrics. + * + * @returns The radio spinel metrics. + * + */ +const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void); + #ifdef __cplusplus } // end of extern "C" #endif diff --git a/src/posix/platform/radio.cpp b/src/posix/platform/radio.cpp index 2e2ecdf8d..da213df42 100644 --- a/src/posix/platform/radio.cpp +++ b/src/posix/platform/radio.cpp @@ -660,3 +660,8 @@ otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, uint32_t a OT_UNUSED_VARIABLE(aDuration); return OT_ERROR_NOT_IMPLEMENTED; } + +const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void) +{ + return sRadioSpinel.GetRadioSpinelMetrics(); +}