From 27802bc0df22480e1a76ddb82fa336b006dddd53 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 27 Feb 2023 23:14:55 -0800 Subject: [PATCH] [message-pool] track max used buffers (#8796) This commit updates `MessagePool` to track number of in use buffers along with max used so far since OT stack initialization or since last time counter was reset. This info is then provided in `otBufferInfo` and in CLI command `bufferinfo`. A new OT API `otMessageResetBufferInfo()` is added to reset this counter. --- include/openthread/instance.h | 2 +- include/openthread/message.h | 22 ++++++++++++++-- src/cli/README.md | 11 ++++++++ src/cli/cli.cpp | 48 ++++++++++++++++++++++++++--------- src/core/api/message_api.cpp | 2 ++ src/core/common/instance.cpp | 7 +++-- src/core/common/instance.hpp | 9 +++++++ src/core/common/message.cpp | 15 +++++------ src/core/common/message.hpp | 20 ++++++++++++++- 9 files changed, 110 insertions(+), 26 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 302665967..5f536034d 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (290) +#define OPENTHREAD_API_VERSION (291) /** * @addtogroup api-instance diff --git a/include/openthread/message.h b/include/openthread/message.h index d94c176e4..0826ddb31 100644 --- a/include/openthread/message.h +++ b/include/openthread/message.h @@ -287,8 +287,16 @@ typedef struct otMessageQueueInfo */ typedef struct otBufferInfo { - uint16_t mTotalBuffers; ///< The total number of buffers in the messages pool (0xffff if unknown). - uint16_t mFreeBuffers; ///< The number of free buffers (0xffff if unknown). + uint16_t mTotalBuffers; ///< The total number of buffers in the messages pool (0xffff if unknown). + uint16_t mFreeBuffers; ///< The number of free buffers (0xffff if unknown). + + /** + * The maximum number of used buffers at the same time since OT stack initialization or last call to + * `otMessageResetBufferInfo()`. + * + */ + uint16_t mMaxUsedBuffers; + otMessageQueueInfo m6loSendQueue; ///< Info about 6LoWPAN send queue. otMessageQueueInfo m6loReassemblyQueue; ///< Info about 6LoWPAN reassembly queue. otMessageQueueInfo mIp6Queue; ///< Info about IPv6 send queue. @@ -369,6 +377,16 @@ otMessage *otMessageQueueGetNext(otMessageQueue *aQueue, const otMessage *aMessa */ void otMessageGetBufferInfo(otInstance *aInstance, otBufferInfo *aBufferInfo); +/** + * Reset the Message Buffer information counter tracking the maximum number buffers in use at the same time. + * + * This resets `mMaxUsedBuffers` in `otBufferInfo`. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * + */ +void otMessageResetBufferInfo(otInstance *aInstance); + /** * @} * diff --git a/src/cli/README.md b/src/cli/README.md index 94f08e4a8..9c8a9e0b8 100644 --- a/src/cli/README.md +++ b/src/cli/README.md @@ -359,6 +359,7 @@ Show the current message buffer information. - The `total` shows total number of message buffers in pool. - The `free` shows the number of free message buffers. +- The `max-used` shows the maximum number of used buffers at the same time since OT stack initialization or last `bufferinfo reset`. - This is then followed by info about different queues used by OpenThread stack, each line representing info about a queue. - The first number shows number messages in the queue. - The second number shows number of buffers used by all messages in the queue. @@ -368,6 +369,7 @@ Show the current message buffer information. > bufferinfo total: 40 free: 40 +max-used: 5 6lo send: 0 0 0 6lo reas: 0 0 0 ip6: 0 0 0 @@ -379,6 +381,15 @@ application coap: 0 0 0 Done ``` +### bufferinfo reset + +Reset the message buffer counter tracking maximum number buffers in use at the same time. + +```bash +> bufferinfo reset +Done +``` + ### ccathreshold Get the CCA threshold in dBm measured at antenna connector per IEEE 802.15.4 - 2015 section 10.1.4. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 0b8752bef..6c237a520 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -1352,6 +1352,7 @@ exit: * bufferinfo * total: 40 * free: 40 + * max-used: 5 * 6lo send: 0 0 0 * 6lo reas: 0 0 0 * ip6: 0 0 0 @@ -1366,6 +1367,8 @@ exit: * Gets the current message buffer information. * * `total` displays the total number of message buffers in pool. * * `free` displays the number of free message buffers. + * * `max-used` displays max number of used buffers at the same time since OT stack + * initialization or last `bufferinfo reset`. * @par * Next, the CLI displays info about different queues used by the OpenThread stack, * for example `6lo send`. Each line after the queue represents info about a queue: @@ -1376,8 +1379,6 @@ exit: */ template <> otError Interpreter::Process(Arg aArgs[]) { - OT_UNUSED_VARIABLE(aArgs); - struct BufferInfoName { const otMessageQueueInfo otBufferInfo::*mQueuePtr; @@ -1395,20 +1396,43 @@ template <> otError Interpreter::Process(Arg aArgs[]) {&otBufferInfo::mApplicationCoapQueue, "application coap"}, }; - otBufferInfo bufferInfo; + otError error = OT_ERROR_NONE; - otMessageGetBufferInfo(GetInstancePtr(), &bufferInfo); - - OutputLine("total: %u", bufferInfo.mTotalBuffers); - OutputLine("free: %u", bufferInfo.mFreeBuffers); - - for (const BufferInfoName &info : kBufferInfoNames) + if (aArgs[0].IsEmpty()) { - OutputLine("%s: %u %u %lu", info.mName, (bufferInfo.*info.mQueuePtr).mNumMessages, - (bufferInfo.*info.mQueuePtr).mNumBuffers, ToUlong((bufferInfo.*info.mQueuePtr).mTotalBytes)); + otBufferInfo bufferInfo; + + otMessageGetBufferInfo(GetInstancePtr(), &bufferInfo); + + OutputLine("total: %u", bufferInfo.mTotalBuffers); + OutputLine("free: %u", bufferInfo.mFreeBuffers); + OutputLine("max-used: %u", bufferInfo.mMaxUsedBuffers); + + for (const BufferInfoName &info : kBufferInfoNames) + { + OutputLine("%s: %u %u %lu", info.mName, (bufferInfo.*info.mQueuePtr).mNumMessages, + (bufferInfo.*info.mQueuePtr).mNumBuffers, ToUlong((bufferInfo.*info.mQueuePtr).mTotalBytes)); + } + } + /** + * @cli bufferinfo reset + * @code + * bufferinfo reset + * Done + * @enccode + * @par api_copy + * #otMessageResetBufferInfo + */ + else if (aArgs[0] == "reset") + { + otMessageResetBufferInfo(GetInstancePtr()); + } + else + { + error = OT_ERROR_INVALID_ARGS; } - return OT_ERROR_NONE; + return error; } /** diff --git a/src/core/api/message_api.cpp b/src/core/api/message_api.cpp index 52405586c..eafc1d2c7 100644 --- a/src/core/api/message_api.cpp +++ b/src/core/api/message_api.cpp @@ -131,4 +131,6 @@ void otMessageGetBufferInfo(otInstance *aInstance, otBufferInfo *aBufferInfo) { AsCoreType(aInstance).GetBufferInfo(AsCoreType(aBufferInfo)); } + +void otMessageResetBufferInfo(otInstance *aInstance) { AsCoreType(aInstance).ResetBufferInfo(); } #endif // OPENTHREAD_MTD || OPENTHREAD_FTD diff --git a/src/core/common/instance.cpp b/src/core/common/instance.cpp index e97ea08bd..9b3c886fb 100644 --- a/src/core/common/instance.cpp +++ b/src/core/common/instance.cpp @@ -386,8 +386,9 @@ void Instance::GetBufferInfo(BufferInfo &aInfo) { aInfo.Clear(); - aInfo.mTotalBuffers = Get().GetTotalBufferCount(); - aInfo.mFreeBuffers = Get().GetFreeBufferCount(); + aInfo.mTotalBuffers = Get().GetTotalBufferCount(); + aInfo.mFreeBuffers = Get().GetFreeBufferCount(); + aInfo.mMaxUsedBuffers = Get().GetMaxUsedBufferCount(); Get().GetSendQueue().GetInfo(aInfo.m6loSendQueue); Get().GetReassemblyQueue().GetInfo(aInfo.m6loReassemblyQueue); @@ -413,6 +414,8 @@ void Instance::GetBufferInfo(BufferInfo &aInfo) #endif } +void Instance::ResetBufferInfo(void) { Get().ResetMaxUsedBufferCount(); } + #endif // OPENTHREAD_MTD || OPENTHREAD_FTD #if OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE diff --git a/src/core/common/instance.hpp b/src/core/common/instance.hpp index 6789f454e..6c6ca1d44 100644 --- a/src/core/common/instance.hpp +++ b/src/core/common/instance.hpp @@ -345,6 +345,15 @@ public: */ void GetBufferInfo(BufferInfo &aInfo); + /** + * This method resets the Message Buffer information counter tracking maximum number buffers in use at the same + * time. + * + * This method resets `mMaxUsedBuffers` in `BufferInfo`. + * + */ + void ResetBufferInfo(void); + #endif // OPENTHREAD_MTD || OPENTHREAD_FTD /** diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp index 92b27e994..1cdd339e0 100644 --- a/src/core/common/message.cpp +++ b/src/core/common/message.cpp @@ -64,9 +64,8 @@ RegisterLogModule("Message"); MessagePool::MessagePool(Instance &aInstance) : InstanceLocator(aInstance) -#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE - , mNumFreeBuffers(kNumBuffers) -#endif + , mNumAllocated(0) + , mMaxAllocated(0) { #if OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT otPlatMessagePoolInit(&GetInstance(), kNumBuffers, sizeof(Buffer)); @@ -123,9 +122,8 @@ Buffer *MessagePool::NewBuffer(Message::Priority aPriority) SuccessOrExit(ReclaimBuffers(aPriority)); } -#if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE - mNumFreeBuffers--; -#endif + mNumAllocated++; + mMaxAllocated = Max(mMaxAllocated, mNumAllocated); buffer->SetNextBuffer(nullptr); @@ -149,8 +147,9 @@ void MessagePool::FreeBuffers(Buffer *aBuffer) otPlatMessagePoolFree(&GetInstance(), aBuffer); #else mBufferPool.Free(*aBuffer); - mNumFreeBuffers++; #endif + mNumAllocated--; + aBuffer = next; } } @@ -170,7 +169,7 @@ uint16_t MessagePool::GetFreeBufferCount(void) const #elif OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT rval = otPlatMessagePoolNumFreeBuffers(&GetInstance()); #else - rval = mNumFreeBuffers; + rval = kNumBuffers - mNumAllocated; #endif return rval; diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index fd70251e9..757d8a851 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -1734,15 +1734,33 @@ public: */ uint16_t GetTotalBufferCount(void) const; + /** + * This method returns the maximum number of buffers in use at the same time since OT stack initialization or + * since last call to `ResetMaxUsedBufferCount()`. + * + * @returns The maximum number of buffers in use at the same time so far (buffer allocation watermark). + * + */ + uint16_t GetMaxUsedBufferCount(void) const { return mMaxAllocated; } + + /** + * This method resets the tracked maximum number of buffers in use. + * + * @sa GetMaxUsedBufferCount + * + */ + void ResetMaxUsedBufferCount(void) { mMaxAllocated = mNumAllocated; } + private: Buffer *NewBuffer(Message::Priority aPriority); void FreeBuffers(Buffer *aBuffer); Error ReclaimBuffers(Message::Priority aPriority); #if !OPENTHREAD_CONFIG_PLATFORM_MESSAGE_MANAGEMENT && !OPENTHREAD_CONFIG_MESSAGE_USE_HEAP_ENABLE - uint16_t mNumFreeBuffers; Pool mBufferPool; #endif + uint16_t mNumAllocated; + uint16_t mMaxAllocated; }; inline Instance &Message::GetInstance(void) const { return GetMessagePool()->GetInstance(); }