From 27cac08e8a4a1aa7f87592a94a9bc0d47f73478a Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Thu, 22 Aug 2019 03:25:27 +0800 Subject: [PATCH] [radio] add coex metrics (#4108) - Add platform get coex metrics API - Add spinel property for coex metrics --- .travis/check-posix-app-pty | 2 + .../posix/openthread-core-posix-config.h | 10 ++++ examples/platforms/posix/radio.c | 35 ++++++++++++ include/openthread/platform/radio.h | 39 ++++++++++++- src/cli/cli.cpp | 41 +++++++++++++ src/cli/cli.hpp | 3 + src/core/config/platform.h | 10 ++++ src/ncp/ncp_base.cpp | 46 +++++++++++++++ src/ncp/ncp_base_dispatcher.cpp | 5 ++ src/ncp/spinel.c | 4 ++ src/ncp/spinel.h | 37 ++++++++++++ .../platform/openthread-core-posix-config.h | 9 +++ src/posix/platform/radio_spinel.cpp | 57 +++++++++++++++++++ src/posix/platform/radio_spinel.hpp | 13 +++++ 14 files changed, 310 insertions(+), 1 deletion(-) diff --git a/.travis/check-posix-app-pty b/.travis/check-posix-app-pty index 258bc7425..5535948dd 100755 --- a/.travis/check-posix-app-pty +++ b/.travis/check-posix-app-pty @@ -96,6 +96,8 @@ send "extaddr\r\n" expect "Done" send "ipaddr\r\n" expect "Done" +send "coex\r\n" +expect "Done" wait EOF diff --git a/examples/platforms/posix/openthread-core-posix-config.h b/examples/platforms/posix/openthread-core-posix-config.h index 4273d4e98..7d3184813 100644 --- a/examples/platforms/posix/openthread-core-posix-config.h +++ b/examples/platforms/posix/openthread-core-posix-config.h @@ -126,4 +126,14 @@ * */ #define CLI_COAP_SECURE_USE_COAP_DEFAULT_HANDLER 1 + +/** + * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + * + * Define to 1 if you want to enable radio coexistence metrics implemented in platform. + * + */ +#ifndef OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE 1 +#endif #endif // OPENTHREAD_CORE_POSIX_CONFIG_H_ diff --git a/examples/platforms/posix/radio.c b/examples/platforms/posix/radio.c index 904b0fe46..42e157f78 100644 --- a/examples/platforms/posix/radio.c +++ b/examples/platforms/posix/radio.c @@ -1083,3 +1083,38 @@ int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) return POSIX_RECEIVE_SENSITIVITY; } + +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics) +{ + otError error = OT_ERROR_NONE; + + assert(aInstance != NULL); + otEXPECT_ACTION(aCoexMetrics != NULL, error = OT_ERROR_INVALID_ARGS); + + memset(aCoexMetrics, 0, sizeof(otRadioCoexMetrics)); + + aCoexMetrics->mStopped = false; + aCoexMetrics->mNumGrantGlitch = 1; + aCoexMetrics->mNumTxRequest = 2; + aCoexMetrics->mNumTxGrantImmediate = 3; + aCoexMetrics->mNumTxGrantWait = 4; + aCoexMetrics->mNumTxGrantWaitActivated = 5; + aCoexMetrics->mNumTxGrantWaitTimeout = 6; + aCoexMetrics->mNumTxGrantDeactivatedDuringRequest = 7; + aCoexMetrics->mNumTxDelayedGrant = 8; + aCoexMetrics->mAvgTxRequestToGrantTime = 9; + aCoexMetrics->mNumRxRequest = 10; + aCoexMetrics->mNumRxGrantImmediate = 11; + aCoexMetrics->mNumRxGrantWait = 12; + aCoexMetrics->mNumRxGrantWaitActivated = 13; + aCoexMetrics->mNumRxGrantWaitTimeout = 14; + aCoexMetrics->mNumRxGrantDeactivatedDuringRequest = 15; + aCoexMetrics->mNumRxDelayedGrant = 16; + aCoexMetrics->mAvgRxRequestToGrantTime = 17; + aCoexMetrics->mNumRxGrantNone = 18; + +exit: + return error; +} +#endif diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 62bbc0f34..0829a62fa 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -245,6 +245,32 @@ typedef enum otRadioState * signal TransmitDone */ +/** + * This structure represents radio coexistence metrics. + */ +typedef struct otRadioCoexMetrics +{ + uint32_t mNumGrantGlitch; ///< Number of grant glitches. + uint32_t mNumTxRequest; ///< Number of tx requests. + uint32_t mNumTxGrantImmediate; ///< Number of tx requests while grant was active. + uint32_t mNumTxGrantWait; ///< Number of tx requests while grant was inactive. + uint32_t mNumTxGrantWaitActivated; ///< Number of tx requests while grant was inactive that were ultimately granted. + uint32_t mNumTxGrantWaitTimeout; ///< Number of tx requests while grant was inactive that timed out. + uint32_t mNumTxGrantDeactivatedDuringRequest; ///< Number of tx that were in progress when grant was deactivated. + uint32_t mNumTxDelayedGrant; ///< Number of tx requests that were not granted within 50us. + uint32_t mAvgTxRequestToGrantTime; ///< Average time in usec from tx request to grant. + uint32_t mNumRxRequest; ///< Number of rx requests. + uint32_t mNumRxGrantImmediate; ///< Number of rx requests while grant was active. + uint32_t mNumRxGrantWait; ///< Number of rx requests while grant was inactive. + uint32_t mNumRxGrantWaitActivated; ///< Number of rx requests while grant was inactive that were ultimately granted. + uint32_t mNumRxGrantWaitTimeout; ///< Number of rx requests while grant was inactive that timed out. + uint32_t mNumRxGrantDeactivatedDuringRequest; ///< Number of rx that were in progress when grant was deactivated. + uint32_t mNumRxDelayedGrant; ///< Number of rx requests that were not granted within 50us. + uint32_t mAvgRxRequestToGrantTime; ///< Average time in usec from rx request to grant. + uint32_t mNumRxGrantNone; ///< Number of rx requests that completed without receiving grant. + bool mStopped; ///< Stats collection stopped due to saturation. +} otRadioCoexMetrics; + /** * @} * @@ -706,13 +732,24 @@ uint32_t otPlatRadioGetSupportedChannelMask(otInstance *aInstance); /** * Get the radio preferred channel mask that the device prefers to form on. * - * @param[in] aInstance The OpenThread instance strucyyture. + * @param[in] aInstance The OpenThread instance structure. * * @returns The radio preferred channel mask. * */ uint32_t otPlatRadioGetPreferredChannelMask(otInstance *aInstance); +/** + * Get the radio coexistence metrics. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[out] aCoexMetrics A pointer to the coexistence metrics structure. + * + * @retval OT_ERROR_NONE Successfully retrieved the coex metrics. + * @retval OT_ERROR_INVALID_ARGS @p aCoexMetrics was NULL. + */ +otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics); + /** * @} * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 7fc1beeb9..4705d41a5 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -106,6 +106,9 @@ const struct Command Interpreter::sCommands[] = { #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE {"coaps", &Interpreter::ProcessCoapSecure}, #endif +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + {"coex", &Interpreter::ProcessCoexMetrics}, +#endif #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD {"commissioner", &Interpreter::ProcessCommissioner}, #endif @@ -781,6 +784,44 @@ void Interpreter::ProcessCoapSecure(int argc, char *argv[]) #endif // OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +void Interpreter::ProcessCoexMetrics(int argc, char *argv[]) +{ + OT_UNUSED_VARIABLE(argc); + OT_UNUSED_VARIABLE(argv); + + otRadioCoexMetrics metrics; + otError error = otPlatRadioGetCoexMetrics(mInstance, &metrics); + + SuccessOrExit(error); + + mServer->OutputFormat("Stopped: %s\r\n", metrics.mStopped ? "true" : "false"); + mServer->OutputFormat("Grant Glitch: %u\r\n", metrics.mNumGrantGlitch); + mServer->OutputFormat("Transmit metrics\r\n"); + mServer->OutputFormat(" Request: %u\r\n", metrics.mNumTxRequest); + mServer->OutputFormat(" Grant Immediate: %u\r\n", metrics.mNumTxGrantImmediate); + mServer->OutputFormat(" Grant Wait: %u\r\n", metrics.mNumTxGrantWait); + mServer->OutputFormat(" Grant Wait Activated: %u\r\n", metrics.mNumTxGrantWaitActivated); + mServer->OutputFormat(" Grant Wait Timeout: %u\r\n", metrics.mNumTxGrantWaitTimeout); + mServer->OutputFormat(" Grant Deactivated During Request: %u\r\n", metrics.mNumTxGrantDeactivatedDuringRequest); + mServer->OutputFormat(" Delayed Grant: %u\r\n", metrics.mNumTxDelayedGrant); + mServer->OutputFormat(" Average Request To Grant Time: %u\r\n", metrics.mAvgTxRequestToGrantTime); + mServer->OutputFormat("Receive metrics\r\n"); + mServer->OutputFormat(" Request: %u\r\n", metrics.mNumRxRequest); + mServer->OutputFormat(" Grant Immediate: %u\r\n", metrics.mNumRxGrantImmediate); + mServer->OutputFormat(" Grant Wait: %u\r\n", metrics.mNumRxGrantWait); + mServer->OutputFormat(" Grant Wait Activated: %u\r\n", metrics.mNumRxGrantWaitActivated); + mServer->OutputFormat(" Grant Wait Timeout: %u\r\n", metrics.mNumRxGrantWaitTimeout); + mServer->OutputFormat(" Grant Deactivated During Request: %u\r\n", metrics.mNumRxGrantDeactivatedDuringRequest); + mServer->OutputFormat(" Delayed Grant: %u\r\n", metrics.mNumRxDelayedGrant); + mServer->OutputFormat(" Average Request To Grant Time: %u\r\n", metrics.mAvgRxRequestToGrantTime); + mServer->OutputFormat(" Grant None: %u\r\n", metrics.mNumRxGrantNone); + +exit: + AppendResult(error); +} +#endif // OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + #if OPENTHREAD_FTD void Interpreter::ProcessContextIdReuseDelay(int argc, char *argv[]) { diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 6ccecda03..e8318816a 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -208,6 +208,9 @@ private: #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE void ProcessCoapSecure(int argc, char *argv[]); #endif // OPENTHREAD_CONFIG_COAP_API_ENABLE +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + void ProcessCoexMetrics(int argc, char *argv[]); +#endif #if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD void ProcessCommissioner(int argc, char *argv[]); #endif diff --git a/src/core/config/platform.h b/src/core/config/platform.h index 7507ac082..b45b166e7 100644 --- a/src/core/config/platform.h +++ b/src/core/config/platform.h @@ -97,4 +97,14 @@ #define OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + * + * Define to 1 if you want to enable radio coexistence metrics implemented in platform. + * + */ +#ifndef OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE 0 +#endif + #endif // CONFIG_PLATFORM_H_ diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 84acfdfdb..42bdd7d6e 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -2200,6 +2200,52 @@ template <> otError NcpBase::HandlePropertyGet(v return EncodeChannelMask(otPlatRadioGetPreferredChannelMask(mInstance)); } +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +template <> otError NcpBase::HandlePropertyGet(void) +{ + otRadioCoexMetrics coexMetrics; + otError error = otPlatRadioGetCoexMetrics(mInstance, &coexMetrics); + + if (error != OT_ERROR_NONE) + { + error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_INVALID_COMMAND_FOR_PROP); + ExitNow(); + } + + // Encode Tx Request related metrics + SuccessOrExit(error = mEncoder.OpenStruct()); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxRequest)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantImmediate)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantWait)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantWaitActivated)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantWaitTimeout)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxGrantDeactivatedDuringRequest)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumTxDelayedGrant)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mAvgTxRequestToGrantTime)); + SuccessOrExit(error = mEncoder.CloseStruct()); + + // Encode Rx Request related metrics + SuccessOrExit(error = mEncoder.OpenStruct()); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxRequest)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantImmediate)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantWait)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantWaitActivated)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantWaitTimeout)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantDeactivatedDuringRequest)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxDelayedGrant)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mAvgRxRequestToGrantTime)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumRxGrantNone)); + SuccessOrExit(error = mEncoder.CloseStruct()); + + // Encode common metrics + SuccessOrExit(error = mEncoder.WriteBool(coexMetrics.mStopped)); + SuccessOrExit(error = mEncoder.WriteUint32(coexMetrics.mNumGrantGlitch)); + +exit: + return error; +} +#endif + } // namespace Ncp } // namespace ot diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index cf17708d7..7eb7041b4 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -140,6 +140,11 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) case SPINEL_PROP_PHY_CHAN_PREFERRED: handler = &NcpBase::HandlePropertyGet; break; +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + case SPINEL_PROP_RADIO_COEX_METRICS: + handler = &NcpBase::HandlePropertyGet; + break; +#endif // -------------------------------------------------------------------------- // MTD (or FTD) Properties (Get Handler) diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index 15ad51efa..1b0184dae 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -1407,6 +1407,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "CHANNEL_MONITOR_CHANNEL_OCCUPANCY"; break; + case SPINEL_PROP_RADIO_COEX_METRICS: + ret = "RADIO_COEX_METRICS"; + break; + case SPINEL_PROP_MAC_SCAN_STATE: ret = "MAC_SCAN_STATE"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 198ed24c0..3deb0a6ae 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -1627,6 +1627,43 @@ typedef enum */ SPINEL_PROP_RADIO_CAPS = SPINEL_PROP_PHY_EXT__BEGIN + 11, + /// All coex metrics related counters. + /** Format: t(LLLLLLLL)t(LLLLLLLLL)bL (Read-only) + * + * The contents include two structures and two common variables, first structure corresponds to + * all transmit related coex counters, second structure provides the receive related counters. + * + * The transmit structure includes: + * 'L': NumTxRequest (The number of tx requests). + * 'L': NumTxGrantImmediate (The number of tx requests while grant was active). + * 'L': NumTxGrantWait (The number of tx requests while grant was inactive). + * 'L': NumTxGrantWaitActivated (The number of tx requests while grant was inactive that were + * ultimately granted). + * 'L': NumTxGrantWaitTimeout (The number of tx requests while grant was inactive that timed out). + * 'L': NumTxGrantDeactivatedDuringRequest (The number of tx requests that were in progress when grant was + * deactivated). + * 'L': NumTxDelayedGrant (The number of tx requests that were not granted within 50us). + * 'L': AvgTxRequestToGrantTime (The average time in usec from tx request to grant). + * + * The receive structure includes: + * 'L': NumRxRequest (The number of rx requests). + * 'L': NumRxGrantImmediate (The number of rx requests while grant was active). + * 'L': NumRxGrantWait (The number of rx requests while grant was inactive). + * 'L': NumRxGrantWaitActivated (The number of rx requests while grant was inactive that were + * ultimately granted). + * 'L': NumRxGrantWaitTimeout (The number of rx requests while grant was inactive that timed out). + * 'L': NumRxGrantDeactivatedDuringRequest (The number of rx requests that were in progress when grant was + * deactivated). + * 'L': NumRxDelayedGrant (The number of rx requests that were not granted within 50us). + * 'L': AvgRxRequestToGrantTime (The average time in usec from rx request to grant). + * 'L': NumRxGrantNone (The number of rx requests that completed without receiving grant). + * + * Two common variables: + * 'b': Stopped (Stats collection stopped due to saturation). + * 'L': NumGrantGlitch (The number of of grant glitches). + */ + SPINEL_PROP_RADIO_COEX_METRICS = SPINEL_PROP_PHY_EXT__BEGIN + 12, + SPINEL_PROP_PHY_EXT__END = 0x1300, SPINEL_PROP_MAC__BEGIN = 0x30, diff --git a/src/posix/platform/openthread-core-posix-config.h b/src/posix/platform/openthread-core-posix-config.h index 4d6ae7622..908809a36 100644 --- a/src/posix/platform/openthread-core-posix-config.h +++ b/src/posix/platform/openthread-core-posix-config.h @@ -62,4 +62,13 @@ */ #define OPENTHREAD_CONFIG_NCP_UART_ENABLE 1 +/** + * @def OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + * + * Define to 1 if you want to enable radio coexistence metrics implemented in platform. + * + */ +#ifndef OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +#define OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE 1 +#endif #endif // OPENTHREAD_CORE_POSIX_CONFIG_H_ diff --git a/src/posix/platform/radio_spinel.cpp b/src/posix/platform/radio_spinel.cpp index 55c02768e..e024ebfea 100644 --- a/src/posix/platform/radio_spinel.cpp +++ b/src/posix/platform/radio_spinel.cpp @@ -892,6 +892,47 @@ int8_t RadioSpinel::GetRssi(void) return rssi; } +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +otError RadioSpinel::GetCoexMetrics(otRadioCoexMetrics &aCoexMetrics) +{ + otError error; + + error = Get(SPINEL_PROP_RADIO_COEX_METRICS, + SPINEL_DATATYPE_STRUCT_S( // Tx Coex Metrics Structure + SPINEL_DATATYPE_UINT32_S // NumTxRequest + SPINEL_DATATYPE_UINT32_S // NumTxGrantImmediate + SPINEL_DATATYPE_UINT32_S // NumTxGrantWait + SPINEL_DATATYPE_UINT32_S // NumTxGrantWaitActivated + SPINEL_DATATYPE_UINT32_S // NumTxGrantWaitTimeout + SPINEL_DATATYPE_UINT32_S // NumTxGrantDeactivatedDuringRequest + SPINEL_DATATYPE_UINT32_S // NumTxDelayedGrant + SPINEL_DATATYPE_UINT32_S // AvgTxRequestToGrantTime + ) SPINEL_DATATYPE_STRUCT_S( // Rx Coex Metrics Structure + SPINEL_DATATYPE_UINT32_S // NumRxRequest + SPINEL_DATATYPE_UINT32_S // NumRxGrantImmediate + SPINEL_DATATYPE_UINT32_S // NumRxGrantWait + SPINEL_DATATYPE_UINT32_S // NumRxGrantWaitActivated + SPINEL_DATATYPE_UINT32_S // NumRxGrantWaitTimeout + SPINEL_DATATYPE_UINT32_S // NumRxGrantDeactivatedDuringRequest + SPINEL_DATATYPE_UINT32_S // NumRxDelayedGrant + SPINEL_DATATYPE_UINT32_S // AvgRxRequestToGrantTime + SPINEL_DATATYPE_UINT32_S // NumRxGrantNone + ) SPINEL_DATATYPE_BOOL_S // Stopped + SPINEL_DATATYPE_UINT32_S, // NumGrantGlitch + &aCoexMetrics.mNumTxRequest, &aCoexMetrics.mNumTxGrantImmediate, &aCoexMetrics.mNumTxGrantWait, + &aCoexMetrics.mNumTxGrantWaitActivated, &aCoexMetrics.mNumTxGrantWaitTimeout, + &aCoexMetrics.mNumTxGrantDeactivatedDuringRequest, &aCoexMetrics.mNumTxDelayedGrant, + &aCoexMetrics.mAvgTxRequestToGrantTime, &aCoexMetrics.mNumRxRequest, &aCoexMetrics.mNumRxGrantImmediate, + &aCoexMetrics.mNumRxGrantWait, &aCoexMetrics.mNumRxGrantWaitActivated, + &aCoexMetrics.mNumRxGrantWaitTimeout, &aCoexMetrics.mNumRxGrantDeactivatedDuringRequest, + &aCoexMetrics.mNumRxDelayedGrant, &aCoexMetrics.mAvgRxRequestToGrantTime, &aCoexMetrics.mNumRxGrantNone, + &aCoexMetrics.mStopped, &aCoexMetrics.mNumGrantGlitch); + + LogIfFail("Get Coex Metrics failed", error); + return error; +} +#endif + otError RadioSpinel::SetTransmitPower(int8_t aPower) { otError error = Set(SPINEL_PROP_PHY_TX_POWER, SPINEL_DATATYPE_INT8_S, aPower); @@ -1629,6 +1670,22 @@ int8_t otPlatRadioGetReceiveSensitivity(otInstance *aInstance) return sRadioSpinel.GetReceiveSensitivity(); } +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE +otError otPlatRadioGetCoexMetrics(otInstance *aInstance, otRadioCoexMetrics *aCoexMetrics) +{ + OT_UNUSED_VARIABLE(aInstance); + + otError error = OT_ERROR_NONE; + + VerifyOrExit(aCoexMetrics != NULL, error = OT_ERROR_INVALID_ARGS); + + error = sRadioSpinel.GetCoexMetrics(*aCoexMetrics); + +exit: + return error; +} +#endif + #if OPENTHREAD_POSIX_VIRTUAL_TIME void ot::PosixApp::RadioSpinel::Process(const Event &aEvent) { diff --git a/src/posix/platform/radio_spinel.hpp b/src/posix/platform/radio_spinel.hpp index c5d5f9ee7..1a2917b0e 100644 --- a/src/posix/platform/radio_spinel.hpp +++ b/src/posix/platform/radio_spinel.hpp @@ -197,6 +197,19 @@ public: */ int8_t GetReceiveSensitivity(void) const { return mRxSensitivity; } +#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE + /** + * This method retrieves the radio coexistence metrics. + * + * @param[out] aCoexMetrics A reference to the coexistence metrics structure. + * + * @retval OT_ERROR_NONE Successfully retrieved the coex metrics. + * @retval OT_ERROR_INVALID_ARGS @p aCoexMetrics was NULL. + * + */ + otError GetCoexMetrics(otRadioCoexMetrics &aCoexMetrics); +#endif + /** * This method returns a reference to the transmit buffer. *