From 112d1bb0087115cf4b1bf6a2a62414faba5bcc83 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 29 Oct 2019 15:34:03 -0700 Subject: [PATCH] [ncp] add support for clearing all/subset of counters (#4286) This commit adds support in NCP/spinel for clearing counters. It also adds new `PROP_CNTR_ALL_IP_COUNTERS` property to get all IPv6 counters. All (MAC, MLE, IPv6, and NCP) counters can be cleared by writing (`PROP_VALUE_SET` with any value) to `SPINEL_PROP_CNTR_RESET` property. A specific subset of counters (MAC, MLE, IP) can be cleared by writing (any value) to the corresponding spinel property (`ROP_CNTR_ALL_MAC_COUNTERS`, `PROP_CNTR_MLE_COUNTERS`, or `PROP_CNTR_ALL_IP_COUNTERS`). --- src/ncp/ncp_base.cpp | 17 ++++++++ src/ncp/ncp_base.hpp | 2 + src/ncp/ncp_base_dispatcher.cpp | 12 ++++++ src/ncp/ncp_base_mtd.cpp | 72 +++++++++++++++++++++++---------- src/ncp/spinel.c | 4 ++ src/ncp/spinel.h | 39 +++++++++++++++--- 6 files changed, 119 insertions(+), 27 deletions(-) diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index 69f1064ce..7c155b833 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -296,6 +296,23 @@ NcpBase *NcpBase::GetNcpInstance(void) return sNcpInstance; } +void NcpBase::ResetCounters(void) +{ + mFramingErrorCounter = 0; + mRxSpinelFrameCounter = 0; + mRxSpinelOutOfOrderTidCounter = 0; + mTxSpinelFrameCounter = 0; + +#if OPENTHREAD_MTD || OPENTHREAD_FTD + mInboundSecureIpFrameCounter = 0; + mInboundInsecureIpFrameCounter = 0; + mOutboundSecureIpFrameCounter = 0; + mOutboundInsecureIpFrameCounter = 0; + mDroppedOutboundIpFrameCounter = 0; + mDroppedInboundIpFrameCounter = 0; +#endif +} + // ---------------------------------------------------------------------------- // MARK: Serial Traffic Glue // ---------------------------------------------------------------------------- diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index d0439bdf4..b2fe3a829 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -421,6 +421,8 @@ protected: otError HandlePropertySet_SPINEL_PROP_STREAM_RAW(uint8_t aHeader); #endif + void ResetCounters(void); + #if OPENTHREAD_CONFIG_LEGACY_ENABLE void StartLegacy(void); void StopLegacy(void); diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index 1ec487914..53395f4b5 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -513,6 +513,9 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) case SPINEL_PROP_CNTR_IP_RX_FAILURE: handler = &NcpBase::HandlePropertyGet; break; + case SPINEL_PROP_CNTR_ALL_IP_COUNTERS: + handler = &NcpBase::HandlePropertyGet; + break; #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE case SPINEL_PROP_THREAD_NETWORK_TIME: handler = &NcpBase::HandlePropertyGet; @@ -891,6 +894,15 @@ NcpBase::PropertyHandler NcpBase::FindSetPropertyHandler(spinel_prop_key_t aKey) case SPINEL_PROP_CNTR_RESET: handler = &NcpBase::HandlePropertySet; break; + case SPINEL_PROP_CNTR_ALL_MAC_COUNTERS: + handler = &NcpBase::HandlePropertySet; + break; + case SPINEL_PROP_CNTR_MLE_COUNTERS: + handler = &NcpBase::HandlePropertySet; + break; + case SPINEL_PROP_CNTR_ALL_IP_COUNTERS: + handler = &NcpBase::HandlePropertySet; + break; #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE case SPINEL_PROP_CHILD_SUPERVISION_CHECK_TIMEOUT: handler = &NcpBase::HandlePropertySet; diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 1d3cd4518..5c5b52dbc 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -2448,11 +2448,7 @@ template <> otError NcpBase::HandlePropertyGet otError NcpBase::HandlePropertySet(void) +{ + otLinkResetCounters(mInstance); + + return OT_ERROR_NONE; +} + template <> otError NcpBase::HandlePropertyGet(void) { otError error = OT_ERROR_NONE; const otMleCounters *counters = otThreadGetMleCounters(mInstance); - if (counters == NULL) - { - error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_INVALID_COMMAND_FOR_PROP); - ExitNow(); - } + assert(counters != NULL); SuccessOrExit(error = mEncoder.WriteUint16(counters->mDisabledRole)); SuccessOrExit(error = mEncoder.WriteUint16(counters->mDetachedRole)); @@ -2523,6 +2522,43 @@ exit: return error; } +template <> otError NcpBase::HandlePropertySet(void) +{ + otThreadResetMleCounters(mInstance); + + return OT_ERROR_NONE; +} + +template <> otError NcpBase::HandlePropertyGet(void) +{ + otError error = OT_ERROR_NONE; + const otIpCounters *counters = otThreadGetIp6Counters(mInstance); + + assert(counters != NULL); + + // Encode Tx related counters + SuccessOrExit(error = mEncoder.OpenStruct()); + SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxSuccess)); + SuccessOrExit(error = mEncoder.WriteUint32(counters->mTxFailure)); + SuccessOrExit(error = mEncoder.CloseStruct()); + + // Encode Rx related counters + SuccessOrExit(error = mEncoder.OpenStruct()); + SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxSuccess)); + SuccessOrExit(error = mEncoder.WriteUint32(counters->mRxFailure)); + SuccessOrExit(error = mEncoder.CloseStruct()); + +exit: + return error; +} + +template <> otError NcpBase::HandlePropertySet(void) +{ + otThreadResetIp6Counters(mInstance); + + return OT_ERROR_NONE; +} + #if OPENTHREAD_CONFIG_MAC_FILTER_ENABLE template <> otError NcpBase::HandlePropertyGet(void) @@ -2885,18 +2921,12 @@ exit: template <> otError NcpBase::HandlePropertySet(void) { - uint8_t value = 0; - otError error = OT_ERROR_NONE; + otLinkResetCounters(mInstance); + otThreadResetIp6Counters(mInstance); + otThreadResetMleCounters(mInstance); + ResetCounters(); - SuccessOrExit(error = mDecoder.ReadUint8(value)); - - VerifyOrExit(value == 1, error = OT_ERROR_INVALID_ARGS); - - // TODO: Implement counter reset! - error = OT_ERROR_NOT_IMPLEMENTED; - -exit: - return error; + return OT_ERROR_NONE; } template <> otError NcpBase::HandlePropertyInsert(void) diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index e4c0c8e97..82e5954e6 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -2171,6 +2171,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "CNTR_MLE_COUNTERS"; break; + case SPINEL_PROP_CNTR_ALL_IP_COUNTERS: + ret = "CNTR_ALL_IP_COUNTERS"; + break; + case SPINEL_PROP_NEST_STREAM_MFG: ret = "NEST_STREAM_MFG"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 43fdf8c93..6e99451e7 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -3531,10 +3531,12 @@ typedef enum SPINEL_PROP_CNTR__BEGIN = 0x500, - /// Counter reset behavior - /** Format: `C` - * Writing a '1' to this property will reset - * all of the counters to zero. */ + /// Counter reset + /** Format: Empty (Write only). + * + * Writing to this property (with any value) will reset all MAC, MLE, IP, and NCP counters to zero. + * + */ SPINEL_PROP_CNTR_RESET = SPINEL_PROP_CNTR__BEGIN + 0, /// The total number of transmissions. @@ -3739,7 +3741,7 @@ typedef enum SPINEL_PROP_MSG_BUFFER_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 400, /// All MAC related counters. - /** Format: t(A(L))t(A(L)) (Read-only) + /** Format: t(A(L))t(A(L)) * * The contents include two structs, first one corresponds to * all transmit related MAC counters, second one provides the @@ -3782,11 +3784,14 @@ typedef enum * 'L': RxErrSec (The number of received packets with security error). * 'L': RxErrFcs (The number of received packets with FCS error). * 'L': RxErrOther (The number of received packets with other error). + * + * Writing to this property with any value would reset all MAC counters to zero. + * */ SPINEL_PROP_CNTR_ALL_MAC_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 401, /// Thread MLE counters. - /** Format: `SSSSSSSSS` (Read-only) + /** Format: `SSSSSSSSS` * * 'S': DisabledRole (The number of times device entered OT_DEVICE_ROLE_DISABLED role). * 'S': DetachedRole (The number of times device entered OT_DEVICE_ROLE_DETACHED role). @@ -3798,9 +3803,31 @@ typedef enum * 'S': BetterPartitionAttachAttempts (The number of attempts to attach to a better partition). * 'S': ParentChanges (The number of times device changed its parents). * + * Writing to this property with any value would reset all MLE counters to zero. + * */ SPINEL_PROP_CNTR_MLE_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 402, + /// Thread IPv6 counters. + /** Format: `t(LL)t(LL)` + * + * The contents include two structs, first one corresponds to + * all transmit related MAC counters, second one provides the + * receive related counters. + * + * The transmit structure includes: + * 'L': TxSuccess (The number of IPv6 packets successfully transmitted). + * 'L': TxFailure (The number of IPv6 packets failed to transmit). + * + * The receive structure includes: + * 'L': RxSuccess (The number of IPv6 packets successfully received). + * 'L': RxFailure (The number of IPv6 packets failed to receive). + * + * Writing to this property with any value would reset all IPv6 counters to zero. + * + */ + SPINEL_PROP_CNTR_ALL_IP_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 403, + SPINEL_PROP_CNTR__END = 0x800, SPINEL_PROP_NEST__BEGIN = 0x3BC0,