[radio] add coex metrics (#4108)

- Add platform get coex metrics API
- Add spinel property for coex metrics
This commit is contained in:
Zhanglong Xia
2019-08-21 12:25:27 -07:00
committed by Jonathan Hui
parent bbd289e278
commit 27cac08e8a
14 changed files with 310 additions and 1 deletions
+2
View File
@@ -96,6 +96,8 @@ send "extaddr\r\n"
expect "Done"
send "ipaddr\r\n"
expect "Done"
send "coex\r\n"
expect "Done"
wait
EOF
@@ -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_
+35
View File
@@ -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
+38 -1
View File
@@ -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);
/**
* @}
*
+41
View File
@@ -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[])
{
+3
View File
@@ -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
+10
View File
@@ -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_
+46
View File
@@ -2200,6 +2200,52 @@ template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>(v
return EncodeChannelMask(otPlatRadioGetPreferredChannelMask(mInstance));
}
#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_RADIO_COEX_METRICS>(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
+5
View File
@@ -140,6 +140,11 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey)
case SPINEL_PROP_PHY_CHAN_PREFERRED:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_PHY_CHAN_PREFERRED>;
break;
#if OPENTHREAD_CONFIG_PLATFORM_RADIO_COEX_METRICS_ENABLE
case SPINEL_PROP_RADIO_COEX_METRICS:
handler = &NcpBase::HandlePropertyGet<SPINEL_PROP_RADIO_COEX_METRICS>;
break;
#endif
// --------------------------------------------------------------------------
// MTD (or FTD) Properties (Get Handler)
+4
View File
@@ -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;
+37
View File
@@ -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,
@@ -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_
+57
View File
@@ -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)
{
+13
View File
@@ -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.
*