diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 53df17706..4f2dd3b45 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (583) +#define OPENTHREAD_API_VERSION (584) /** * @addtogroup api-instance diff --git a/include/openthread/platform/logging.h b/include/openthread/platform/logging.h index 6b587b725..5e69e4d0a 100644 --- a/include/openthread/platform/logging.h +++ b/include/openthread/platform/logging.h @@ -35,6 +35,7 @@ #ifndef OPENTHREAD_PLATFORM_LOGGING_H_ #define OPENTHREAD_PLATFORM_LOGGING_H_ +#include #include #ifdef __cplusplus @@ -140,6 +141,9 @@ typedef enum otLogRegion /** * Outputs logs. * + * This platform API is used to output logs when the configuration `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE` + * is disabled. When the configuration is enabled, `otPlatLogOutput()` is used instead. + * * Note that the support for log region is removed. The OT core will always emit all logs with `OT_LOG_REGION_CORE` * as @p aLogRegion. * @@ -151,6 +155,23 @@ typedef enum otLogRegion void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(3, 4); +/** + * Outputs a log line. + * + * This platform API is an alternative to `otPlatLog()` and is used when the configuration + * `OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE` is enabled. + * + * Unlike `otPlatLog()`, this API also provides a pointer to the OpenThread instance (`otInstance*`) from which the + * log is generated. This is particularly helpful in a multi-instance setup to distinguish logs from different + * instances. Additionally, it provides the log line as a fully formatted null-terminated string instead of + * a format string and variable arguments. + * + * @param[in] aInstance A pointer to the OpenThread instance. + * @param[in] aLogLevel The log level. + * @param[in] aLogLine A pointer to the null-terminated string containing the log line. + */ +void otPlatLogOutput(otInstance *aInstance, otLogLevel aLogLevel, const char *aLogLine); + /** * Handles OpenThread log level changes. * diff --git a/src/core/common/locator.hpp b/src/core/common/locator.hpp index efa18b3b3..1ae65f7a9 100644 --- a/src/core/common/locator.hpp +++ b/src/core/common/locator.hpp @@ -48,6 +48,13 @@ class Instance; extern uint64_t gInstanceRaw[]; #endif +#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE +extern Instance *gActiveInstance; +inline Instance *UpdateActiveInstance(Instance *aInstance) { return gActiveInstance = aInstance; } +#else +inline Instance *UpdateActiveInstance(Instance *aInstance) { return aInstance; } +#endif + /** * @addtogroup core-locator * @@ -117,7 +124,7 @@ public: * @returns A reference to the parent otInstance. */ #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE - Instance &GetInstance(void) const { return *mInstance; } + Instance &GetInstance(void) const { return *UpdateActiveInstance(mInstance); } #else Instance &GetInstance(void) const { return GetSingleInstance(); } #endif diff --git a/src/core/common/log.cpp b/src/core/common/log.cpp index 203a02b2b..2018fcf72 100644 --- a/src/core/common/log.cpp +++ b/src/core/common/log.cpp @@ -166,7 +166,23 @@ void Logger::Log(const char *aModuleName, LogLevel aLogLevel, Error aError, cons } logString.Append("%s", OPENTHREAD_CONFIG_LOG_SUFFIX); + +#if OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE + { + Instance *instance; + +#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE + instance = Instance::GetActiveInstance(); + VerifyOrExit(instance != nullptr); +#else + instance = &Instance::Get(); +#endif + + otPlatLogOutput(instance, aLogLevel, logString.AsCString()); + } +#else otPlatLog(aLogLevel, OT_LOG_REGION_CORE, "%s", logString.AsCString()); +#endif ExitNow(); diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index 3a729a6f4..06ef455b2 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -476,7 +476,7 @@ public: * @returns A reference to the `Instance`. */ #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE - Instance &GetInstance(void) const { return *GetMetadata().mInstance; } + Instance &GetInstance(void) const { return *UpdateActiveInstance(GetMetadata().mInstance); } #else Instance &GetInstance(void) const { return GetSingleInstance(); } #endif diff --git a/src/core/config/logging.h b/src/core/config/logging.h index 4c278ee15..d5a73d244 100644 --- a/src/core/config/logging.h +++ b/src/core/config/logging.h @@ -77,6 +77,20 @@ /** Log output is handled by a platform defined function */ #define OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED 3 +/** + * @def OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE + * + * Define to 1 to enable the instance-aware platform logging API. + * + * When this configuration is enabled, OpenThread logging will track the OpenThread instance (`otInstance`) from which + * a log is generated. The core will use the `otPlatLogOutput()` platform API instead of `otPlatLog()`. The new + * platform API provides the `otInstance` pointer along with the log as a fully formatted string, which is particularly + * useful in multi-instance setups to distinguish logs from different OpenThread instances. + */ +#ifndef OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE +#define OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE 0 +#endif + /** * @def OPENTHREAD_CONFIG_LOG_LEVEL * diff --git a/src/core/instance/instance.cpp b/src/core/instance/instance.cpp index 2c076ed27..263f62ba3 100644 --- a/src/core/instance/instance.cpp +++ b/src/core/instance/instance.cpp @@ -51,6 +51,11 @@ OT_DEFINE_ALIGNED_VAR(gInstanceRaw, sizeof(Instance), uint64_t); #endif +#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE +// The currently active instance +Instance *gActiveInstance = nullptr; +#endif + #if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_MULTIPLE_STATIC_INSTANCE_ENABLE #define INSTANCE_SIZE_ALIGNED OT_ALIGNED_VAR_SIZE(sizeof(ot::Instance), uint64_t) @@ -411,6 +416,10 @@ exit: return instance; } +#if OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE +Instance *Instance::GetActiveInstance(void) { return gActiveInstance; } +#endif + #endif // OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE void Instance::Reset(void) { otPlatReset(this); } diff --git a/src/core/instance/instance.hpp b/src/core/instance/instance.hpp index fc5a42aec..b21b1078b 100644 --- a/src/core/instance/instance.hpp +++ b/src/core/instance/instance.hpp @@ -429,6 +429,17 @@ public: */ template inline Type &Get(void); +#if OPENTHREAD_CONFIG_MULTIPLE_INSTANCE_ENABLE && OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE + /** + * Gets the currently active OpenThread instance. + * + * It is used to determine the active instance primarily for logging purposes. + * + * @returns A pointer to the active OpenThread instance, or `nullptr` if not known. + */ + static Instance *GetActiveInstance(void); +#endif + #if OPENTHREAD_PLATFORM_NEXUS /** * Constructor to initialize an `Instance` diff --git a/src/core/net/tcp6.cpp b/src/core/net/tcp6.cpp index 3a72826c8..d572c49d6 100644 --- a/src/core/net/tcp6.cpp +++ b/src/core/net/tcp6.cpp @@ -109,7 +109,10 @@ exit: return error; } -Instance &Tcp::Endpoint::GetInstance(void) const { return AsNonConst(AsCoreType(GetTcb().instance)); } +Instance &Tcp::Endpoint::GetInstance(void) const +{ + return *UpdateActiveInstance(&AsNonConst(AsCoreType(GetTcb().instance))); +} const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const { @@ -547,7 +550,10 @@ exit: return error; } -Instance &Tcp::Listener::GetInstance(void) const { return AsNonConst(AsCoreType(GetTcbListen().instance)); } +Instance &Tcp::Listener::GetInstance(void) const +{ + return *UpdateActiveInstance(&AsNonConst(AsCoreType(GetTcbListen().instance))); +} Error Tcp::Listener::Listen(const SockAddr &aSockName) { diff --git a/tests/nexus/openthread-core-nexus-config.h b/tests/nexus/openthread-core-nexus-config.h index 16ada005c..ee5d1f5fb 100644 --- a/tests/nexus/openthread-core-nexus-config.h +++ b/tests/nexus/openthread-core-nexus-config.h @@ -83,7 +83,6 @@ #define OPENTHREAD_CONFIG_JAM_DETECTION_ENABLE 1 #define OPENTHREAD_CONFIG_JOINER_ENABLE 1 #define OPENTHREAD_CONFIG_LOG_LEVEL OT_LOG_LEVEL_INFO - #define OPENTHREAD_CONFIG_LOG_LEVEL_DYNAMIC_ENABLE 1 #define OPENTHREAD_CONFIG_LOG_LEVEL_INIT OT_LOG_LEVEL_CRIT #define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_PLATFORM_DEFINED @@ -91,6 +90,7 @@ #define OPENTHREAD_CONFIG_LOG_PREPEND_LEVEL 1 #define OPENTHREAD_CONFIG_LOG_PREPEND_UPTIME 0 #define OPENTHREAD_CONFIG_LOG_SUFFIX "" +#define OPENTHREAD_CONFIG_LOG_INSTANCE_AWARE_API_ENABLE 1 #define OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE 1 #define OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE 1 #define OPENTHREAD_CONFIG_MAC_FILTER_ENABLE 1 diff --git a/tests/nexus/platform/nexus_misc.cpp b/tests/nexus/platform/nexus_misc.cpp index e9e17b75f..646551534 100644 --- a/tests/nexus/platform/nexus_misc.cpp +++ b/tests/nexus/platform/nexus_misc.cpp @@ -39,8 +39,7 @@ namespace ot { namespace Nexus { -static void LogVarArgs(Node *aActiveNode, const char *aFormat, va_list aArgs) - OT_TOOL_PRINTF_STYLE_FORMAT_ARG_CHECK(2, 0); +static void LogTime(void); extern "C" { @@ -57,16 +56,18 @@ void otTaskletsSignalPending(otInstance *aInstance) //--------------------------------------------------------------------------------------------------------------------- // otPlatLog -void otPlatLog(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFormat, ...) +void otPlatLogOutput(otInstance *aInstance, otLogLevel aLogLevel, const char *aLogLine) { OT_UNUSED_VARIABLE(aLogLevel); - OT_UNUSED_VARIABLE(aLogRegion); - va_list args; + VerifyOrExit(aInstance != nullptr); - va_start(args, aFormat); - LogVarArgs(Core::Get().GetActiveNode(), aFormat, args); - va_end(args); + LogTime(); + printf("%03u %s\n", AsNode(aInstance).GetId(), aLogLine); + fflush(stdout); + +exit: + return; } //--------------------------------------------------------------------------------------------------------------------- @@ -136,29 +137,25 @@ void otPlatWakeHost(void) {} //--------------------------------------------------------------------------------------------------------------------- // Log related function +static void LogTime(void) +{ + uint32_t now = Core::Get().GetNow().GetValue(); + + printf("%02u:%02u:%02u.%03u ", now / 3600000, (now / 60000) % 60, (now / 1000) % 60, now % 1000); +} + void Log(const char *aFormat, ...) { va_list args; va_start(args, aFormat); - LogVarArgs(nullptr, aFormat, args); - va_end(args); -} -static void LogVarArgs(Node *aActiveNode, const char *aFormat, va_list aArgs) -{ - uint32_t now = Core::Get().GetNow().GetValue(); - - printf("%02u:%02u:%02u.%03u ", now / 3600000, (now / 60000) % 60, (now / 1000) % 60, now % 1000); - - if (aActiveNode != nullptr) - { - printf("%03u ", aActiveNode->GetInstance().GetId()); - } - - vprintf(aFormat, aArgs); + LogTime(); + vprintf(aFormat, args); printf("\n"); fflush(stdout); + + va_end(args); } } // namespace Nexus