mirror of
https://github.com/espressif/openthread.git
synced 2026-08-23 02:39:52 +00:00
[spinel] add an API to get the radio spinel metrics (#7859)
When the RCP is not stable, it causes the Thread stack to crash. To better know the stability of the RCP, this commit adds an API to return the radio spinel metrics.
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
#include <openthread/platform/radio.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -218,6 +218,7 @@ RadioSpinel<InterfaceType, ProcessContextType>::RadioSpinel(void)
|
||||
, mRadioTimeOffset(0)
|
||||
{
|
||||
mVersion[0] = '\0';
|
||||
memset(&mRadioSpinelMetrics, 0, sizeof(mRadioSpinelMetrics));
|
||||
}
|
||||
|
||||
template <typename InterfaceType, typename ProcessContextType>
|
||||
@@ -482,6 +483,8 @@ exit:
|
||||
mRxFrameBuffer.DiscardFrame();
|
||||
otLogWarnPlat("Error handling hdlc frame: %s", otThreadErrorToString(error));
|
||||
}
|
||||
|
||||
UpdateParseErrorCount(error);
|
||||
}
|
||||
|
||||
template <typename InterfaceType, typename ProcessContextType>
|
||||
@@ -535,6 +538,7 @@ exit:
|
||||
aFrameBuffer.DiscardFrame();
|
||||
}
|
||||
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Error processing notification", error);
|
||||
}
|
||||
|
||||
@@ -556,6 +560,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::HandleNotification(const ui
|
||||
HandleValueIs(key, data, static_cast<uint16_t>(len));
|
||||
|
||||
exit:
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Error processing saved notification", error);
|
||||
}
|
||||
|
||||
@@ -597,6 +602,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::HandleResponse(const uint8_
|
||||
}
|
||||
|
||||
exit:
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Error processing response", error);
|
||||
}
|
||||
|
||||
@@ -829,6 +835,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::HandleWaitingResponse(uint3
|
||||
}
|
||||
|
||||
exit:
|
||||
UpdateParseErrorCount(mError);
|
||||
LogIfFail("Error processing result", mError);
|
||||
}
|
||||
|
||||
@@ -936,6 +943,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::HandleValueIs(spinel_prop_k
|
||||
}
|
||||
|
||||
exit:
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Failed to handle ValueIs", error);
|
||||
}
|
||||
|
||||
@@ -1007,6 +1015,7 @@ otError RadioSpinel<InterfaceType, ProcessContextType>::ParseRadioFrame(otRadioF
|
||||
}
|
||||
|
||||
exit:
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Handle radio frame failed", error);
|
||||
return error;
|
||||
}
|
||||
@@ -1924,6 +1933,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::HandleTransmitDone(uint32_t
|
||||
exit:
|
||||
mState = kStateTransmitDone;
|
||||
mTxError = error;
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Handle transmit done failed", error);
|
||||
}
|
||||
|
||||
@@ -2117,6 +2127,7 @@ uint32_t RadioSpinel<InterfaceType, ProcessContextType>::GetRadioChannelMask(boo
|
||||
channelMask &= mMaxPowerTable.GetSupportedChannelMask();
|
||||
|
||||
exit:
|
||||
UpdateParseErrorCount(error);
|
||||
LogIfFail("Get radio channel mask failed", error);
|
||||
return channelMask;
|
||||
}
|
||||
@@ -2211,6 +2222,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::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<InterfaceType, ProcessContextType>::HandleRcpUnexpectedReset(sp
|
||||
template <typename InterfaceType, typename ProcessContextType>
|
||||
void RadioSpinel<InterfaceType, ProcessContextType>::HandleRcpTimeout(void)
|
||||
{
|
||||
mRadioSpinelMetrics.mRcpTimeoutCount++;
|
||||
|
||||
#if OPENTHREAD_SPINEL_CONFIG_RCP_RESTORATION_MAX_COUNT > 0
|
||||
mRcpFailed = true;
|
||||
#else
|
||||
@@ -2245,6 +2259,7 @@ void RadioSpinel<InterfaceType, ProcessContextType>::RecoverFromRcpFailure(void)
|
||||
|
||||
otLogWarnPlat("RCP failure detected");
|
||||
|
||||
++mRadioSpinelMetrics.mRcpRestorationCount;
|
||||
++mRcpFailureCount;
|
||||
if (mRcpFailureCount > kMaxFailureCount)
|
||||
{
|
||||
|
||||
@@ -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_
|
||||
@@ -45,6 +45,8 @@
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/platform/misc.h>
|
||||
|
||||
#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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user