diff --git a/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi b/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi index d8f78cfd40c..e6bda0940db 100644 --- a/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi +++ b/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi @@ -59,6 +59,7 @@ ; bias-pull-down; }; + group2 { psels = ; bias-pull-up; @@ -73,12 +74,14 @@ , ; bias-pull-down; + low-power-enable; }; + group2 { psels = ; bias-pull-up; + low-power-enable; }; - low-power-enable; }; uart1_default: uart1_default { diff --git a/doc/services/logging/index.rst b/doc/services/logging/index.rst index 86f5e97d8c9..be683161655 100644 --- a/doc/services/logging/index.rst +++ b/doc/services/logging/index.rst @@ -32,6 +32,7 @@ Summary of the logging features: - Support for logging floating point variables and long long arguments. - Built-in copying of transient strings used as arguments. - Support for multi-domain logging. +- Rate-limited logging macros to prevent log flooding when messages are generated frequently. Logging API is highly configurable at compile time as well as at run time. Using Kconfig options (see :ref:`logging_kconfig`) logs can be gradually removed from @@ -59,6 +60,16 @@ The warning level also exposes the following additional macro: - :c:macro:`LOG_WRN_ONCE` for warnings where only the first occurrence is of interest. +Rate-limited logging macros are also available for all severity levels to prevent log flooding: + +- ``LOG_X_RATELIMIT`` for rate-limited standard printf-like messages using default rate, e.g. :c:macro:`LOG_ERR_RATELIMIT`. +- ``LOG_X_RATELIMIT_RATE`` for rate-limited standard printf-like messages with custom rate, e.g. :c:macro:`LOG_ERR_RATELIMIT_RATE`. +- ``LOG_HEXDUMP_X_RATELIMIT`` for rate-limited data dumping using default rate, e.g. :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT`. +- ``LOG_HEXDUMP_X_RATELIMIT_RATE`` for rate-limited data dumping with custom rate, e.g. :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT_RATE`. + +The convenience macros use the default rate specified by ``CONFIG_LOG_RATELIMIT_INTERVAL_MS``, +while the explicit rate macros take a rate parameter (in milliseconds) that specifies the minimum interval between log messages. + There are two configuration categories: configurations per module and global configuration. When logging is enabled globally, it works for modules. However, modules can disable logging locally. Every module can specify its own logging @@ -341,6 +352,94 @@ If logs are processed from a thread (user or internal) then it is possible to en a feature which will wake up processing thread when certain amount of log messages are buffered (see :kconfig:option:`CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD`). +.. _logging_ratelimited: + +Rate-limited logging +******************** + +Rate-limited logging macros provide a way to prevent log flooding when messages are +generated frequently. These macros ensure that log messages are not output more +frequently than a specified interval, similar to Linux's ``printk_ratelimited`` +functionality. + +The rate-limited logging system provides two types of macros: + +**Convenience macros (using default rate):** +- :c:macro:`LOG_ERR_RATELIMIT` - Rate-limited error messages +- :c:macro:`LOG_WRN_RATELIMIT` - Rate-limited warning messages +- :c:macro:`LOG_INF_RATELIMIT` - Rate-limited info messages +- :c:macro:`LOG_DBG_RATELIMIT` - Rate-limited debug messages +- :c:macro:`LOG_HEXDUMP_ERR_RATELIMIT` - Rate-limited error hexdump +- :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT` - Rate-limited warning hexdump +- :c:macro:`LOG_HEXDUMP_INF_RATELIMIT` - Rate-limited info hexdump +- :c:macro:`LOG_HEXDUMP_DBG_RATELIMIT` - Rate-limited debug hexdump + +**Explicit rate macros (with custom rate):** +- :c:macro:`LOG_ERR_RATELIMIT_RATE` - Rate-limited error messages with custom rate +- :c:macro:`LOG_WRN_RATELIMIT_RATE` - Rate-limited warning messages with custom rate +- :c:macro:`LOG_INF_RATELIMIT_RATE` - Rate-limited info messages with custom rate +- :c:macro:`LOG_DBG_RATELIMIT_RATE` - Rate-limited debug messages with custom rate +- :c:macro:`LOG_HEXDUMP_ERR_RATELIMIT_RATE` - Rate-limited error hexdump with custom rate +- :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT_RATE` - Rate-limited warning hexdump with custom rate +- :c:macro:`LOG_HEXDUMP_INF_RATELIMIT_RATE` - Rate-limited info hexdump with custom rate +- :c:macro:`LOG_HEXDUMP_DBG_RATELIMIT_RATE` - Rate-limited debug hexdump with custom rate + +The convenience macros use the default rate specified by :kconfig:option:`CONFIG_LOG_RATELIMIT_INTERVAL_MS` +(5000ms by default). The explicit rate macros take a rate parameter (in milliseconds) that specifies +the minimum interval between log messages. The rate limiting is per-macro-call-site, meaning +that each unique call to a rate-limited macro has its own independent rate limit. + +Example usage: + +.. code-block:: c + + #include + #include + + LOG_MODULE_REGISTER(my_module, CONFIG_LOG_DEFAULT_LEVEL); + + void process_data(void) + { + /* Convenience macros using default rate (CONFIG_LOG_RATELIMIT_INTERVAL_MS) */ + LOG_WRN_RATELIMIT("Data processing warning: %d", error_code); + LOG_ERR_RATELIMIT("Critical error occurred: %s", error_msg); + LOG_INF_RATELIMIT("Processing status: %d items", item_count); + LOG_HEXDUMP_WRN_RATELIMIT(data_buffer, data_len, "Data buffer:"); + + /* Explicit rate macros with custom intervals */ + LOG_WRN_RATELIMIT_RATE(1000, "Fast rate warning: %d", error_code); + LOG_ERR_RATELIMIT_RATE(30000, "Slow rate error: %s", error_msg); + LOG_INF_RATELIMIT_RATE(2000, "Custom rate status: %d items", item_count); + LOG_HEXDUMP_ERR_RATELIMIT_RATE(5000, data_buffer, data_len, "Error data:"); + } + +Rate-limited logging is particularly useful for: + +- Error conditions that might occur frequently but don't need to flood the logs +- Status updates in tight loops or high-frequency callbacks +- Debug information that could overwhelm the logging system +- Network or I/O operations that might fail repeatedly + +Configuration +============== + +Rate-limited logging can be configured using the following Kconfig options: + +- :kconfig:option:`CONFIG_LOG_RATELIMIT` - Master switch to enable/disable rate-limited logging +- :kconfig:option:`CONFIG_LOG_RATELIMIT_INTERVAL_MS` - Default interval for convenience macros (5000ms) + +When :kconfig:option:`CONFIG_LOG_RATELIMIT` is disabled, the behavior of rate-limited macros is controlled +by the :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK` choice: + +- :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK_LOG` - All rate-limited macros behave as regular logging macros +- :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK_DROP` - All rate-limited macros expand to no-ops (default) + +This allows you to control whether rate-limited log macros should always print or be completely +suppressed when rate limiting is not available. + +The rate limiting is implemented using static variables and :c:func:`k_uptime_get_32` +to track the last log time for each call site. + .. _logging_panic: Logging panic diff --git a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi index 414900f581b..af3e7827dcb 100644 --- a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi +++ b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi @@ -748,11 +748,12 @@ config NRF_WIFI_RPU_RECOVERY_PS_ACTIVE_TIMEOUT_MS config NRF_WIFI_RPU_MIN_TIME_TO_ENTER_SLEEP_MS int "Minimum idle time to enter sleep in milliseconds" - range 100 5000 - default 1000 + range 100 40000 + default 5000 help Minimum time the host should de-assert WAKEUP_NOW and let RPU enter - sleep mode, assuming there is no activity. + sleep mode, assuming there is no activity. Please note that higher values + of this value may increase the power consumption. config NRF_WIFI_RPU_RECOVERY_DEBUG bool "RPU recovery debug logs" diff --git a/dts/bindings/wifi/nordic,wlan.yaml b/dts/bindings/wifi/nordic,wlan.yaml new file mode 100644 index 00000000000..9c704bc9586 --- /dev/null +++ b/dts/bindings/wifi/nordic,wlan.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic Wi-Fi network interface. + + This binding defines a Wi-Fi network interface for Nordic nRF70 series + Wi-Fi chips. The interface is used to identify and name Wi-Fi network + interfaces like wlan0. + +compatible: "nordic,wlan" diff --git a/include/zephyr/logging/log.h b/include/zephyr/logging/log.h index 2358b332ef4..84601af4393 100644 --- a/include/zephyr/logging/log.h +++ b/include/zephyr/logging/log.h @@ -10,6 +10,7 @@ #include #include #include +#include #if CONFIG_USERSPACE && CONFIG_LOG_ALWAYS_RUNTIME #include @@ -96,6 +97,340 @@ extern "C" { } \ } while (0) +#if defined(CONFIG_LOG_RATELIMIT) || defined(__DOXYGEN__) +/** + * @brief Core rate-limited logging macro + * + * @details Internal macro that provides rate-limited logging functionality. + * Uses atomic operations to ensure thread safety in multi-threaded environments. + * Only one thread can successfully log a message within the specified rate limit period. + * + * @param _level Log level (LOG_LEVEL_ERR, LOG_LEVEL_WRN, etc.) + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _skipped_msg Message to show when messages are skipped. + * @param _log_func Logging function to call (Z_LOG or Z_LOG_HEXDUMP) + * @param ... Arguments to pass to the logging function. + */ +#define _LOG_RATELIMIT_CORE(_level, _rate_ms, _skipped_msg, _log_func, ...) \ + do { \ + static atomic_t __last_log_time ; \ + static atomic_t __skipped_count ; \ + uint32_t __now = k_uptime_get_32(); \ + uint32_t __last = atomic_get(&__last_log_time); \ + uint32_t __diff = __now - __last; \ + if (unlikely(__diff >= (_rate_ms))) { \ + if (atomic_cas(&__last_log_time, __last, __now)) { \ + uint32_t __skipped = atomic_clear(&__skipped_count); \ + if (__skipped > 0) { \ + Z_LOG(_level, _skipped_msg, __skipped); \ + } \ + _log_func(_level, __VA_ARGS__); \ + } else { \ + atomic_inc(&__skipped_count); \ + } \ + } else { \ + atomic_inc(&__skipped_count); \ + } \ + } while (0) + +/** + * @brief Rate-limited logging macros + * + * @details These macros provide rate-limited logging functionality to prevent + * log flooding when messages are generated frequently. Each macro ensures that + * log messages are not output more frequently than a specified interval. + * Rate limiting is per-macro-call-site, meaning each unique call has its own + * independent rate limit. + * + * The macros use atomic operations to ensure thread safety in multi-threaded + * environments. Only one thread can successfully log a message within the + * specified rate limit period. + * + * @see CONFIG_LOG_RATELIMIT_INTERVAL_MS + */ + +/** + * @brief Writes a WARNING level message to the log with rate limiting. + * + * @details It's meant for situations that warrant investigation but could clutter + * the logs if output too frequently. The message will be logged at most once + * per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_WRN_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_WRN, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes a WARNING level message to the log with rate limiting. + * + * @details It's meant for situations that warrant investigation but could clutter + * the logs if output too frequently. The message will be logged at most once + * per default interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_WRN_RATELIMIT(...) \ + LOG_WRN_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes an ERROR level message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_ERR_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_ERR, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes an ERROR level message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per default interval (see + * CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_ERR_RATELIMIT(...) \ + LOG_ERR_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes an INFO level message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_INF_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_INF, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes an INFO level message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_INF_RATELIMIT(...) \ + LOG_INF_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes a DEBUG level message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_DBG_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_DBG, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes a DEBUG level message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_DBG_RATELIMIT(...) \ + LOG_DBG_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes an ERROR level hexdump message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_ERR, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes an ERROR level hexdump message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per default interval (see + * CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_ERR_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_ERR_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +/** + * @brief Writes a WARNING level hexdump message to the log with rate limiting. + * + * @details It's meant to register messages related to unusual situations that + * are not necessarily errors, but with rate limiting to prevent log flooding. + * The message will be logged at most once per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_WRN, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes a WARNING level hexdump message to the log with rate limiting. + * + * @details It's meant to register messages related to unusual situations that + * are not necessarily errors, but with rate limiting to prevent log flooding. + * The message will be logged at most once per default interval (see + * CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_WRN_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_WRN_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +/** + * @brief Writes an INFO level hexdump message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_INF, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes an INFO level hexdump message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_INF_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_INF_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +/** + * @brief Writes a DEBUG level hexdump message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_DBG, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes a DEBUG level hexdump message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_DBG_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_DBG_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +#else /* CONFIG_LOG_RATELIMIT */ + +/* Rate-limited logging macros when CONFIG_LOG_RATELIMIT is disabled */ +#if defined(CONFIG_LOG_RATELIMIT_FALLBACK_DROP) +/* Fallback: Drop all prints (no output) */ +#define LOG_WRN_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_WRN_RATELIMIT(...) (void)0 +#define LOG_ERR_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_ERR_RATELIMIT(...) (void)0 +#define LOG_INF_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_INF_RATELIMIT(...) (void)0 +#define LOG_DBG_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_DBG_RATELIMIT(...) (void)0 +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_ERR_RATELIMIT(_data, _length, _str) (void)0 +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_WRN_RATELIMIT(_data, _length, _str) (void)0 +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_INF_RATELIMIT(_data, _length, _str) (void)0 +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_DBG_RATELIMIT(_data, _length, _str) (void)0 +#else /* Catch all, not just CONFIG_LOG_RATELIMIT_FALLBACK_LOG */ +/* Fallback: Log all prints (ignore rate limiting) */ +#define LOG_WRN_RATELIMIT_RATE(_rate_ms, ...) LOG_WRN(__VA_ARGS__) +#define LOG_WRN_RATELIMIT(...) LOG_WRN(__VA_ARGS__) +#define LOG_ERR_RATELIMIT_RATE(_rate_ms, ...) LOG_ERR(__VA_ARGS__) +#define LOG_ERR_RATELIMIT(...) LOG_ERR(__VA_ARGS__) +#define LOG_INF_RATELIMIT_RATE(_rate_ms, ...) LOG_INF(__VA_ARGS__) +#define LOG_INF_RATELIMIT(...) LOG_INF(__VA_ARGS__) +#define LOG_DBG_RATELIMIT_RATE(_rate_ms, ...) LOG_DBG(__VA_ARGS__) +#define LOG_DBG_RATELIMIT(...) LOG_DBG(__VA_ARGS__) +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_ERR(_data, _length, _str) +#define LOG_HEXDUMP_ERR_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_ERR(_data, _length, _str) +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_WRN(_data, _length, _str) +#define LOG_HEXDUMP_WRN_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_WRN(_data, _length, _str) +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_INF(_data, _length, _str) +#define LOG_HEXDUMP_INF_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_INF(_data, _length, _str) +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_DBG(_data, _length, _str) +#define LOG_HEXDUMP_DBG_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_DBG(_data, _length, _str) +#endif + +#endif /* CONFIG_LOG_RATELIMIT */ + /** * @brief Unconditionally print raw log message. * @@ -499,6 +834,46 @@ extern struct k_mem_partition k_log_partition; #define LOG_HEXDUMP_WRN(...) (void) 0 #define LOG_HEXDUMP_DBG(...) (void) 0 #define LOG_HEXDUMP_INF(...) (void) 0 + +#undef LOG_ERR_RATELIMIT +#undef LOG_WRN_RATELIMIT +#undef LOG_INF_RATELIMIT +#undef LOG_DBG_RATELIMIT + +#undef LOG_ERR_RATELIMIT_RATE +#undef LOG_WRN_RATELIMIT_RATE +#undef LOG_INF_RATELIMIT_RATE +#undef LOG_DBG_RATELIMIT_RATE + +#undef LOG_HEXDUMP_ERR_RATELIMIT +#undef LOG_HEXDUMP_WRN_RATELIMIT +#undef LOG_HEXDUMP_INF_RATELIMIT +#undef LOG_HEXDUMP_DBG_RATELIMIT + +#undef LOG_HEXDUMP_ERR_RATELIMIT_RATE +#undef LOG_HEXDUMP_WRN_RATELIMIT_RATE +#undef LOG_HEXDUMP_INF_RATELIMIT_RATE +#undef LOG_HEXDUMP_DBG_RATELIMIT_RATE + +#define LOG_ERR_RATELIMIT(...) (void) 0 +#define LOG_WRN_RATELIMIT(...) (void) 0 +#define LOG_INF_RATELIMIT(...) (void) 0 +#define LOG_DBG_RATELIMIT(...) (void) 0 + +#define LOG_HEXDUMP_ERR_RATELIMIT(...) (void) 0 +#define LOG_HEXDUMP_WRN_RATELIMIT(...) (void) 0 +#define LOG_HEXDUMP_INF_RATELIMIT(...) (void) 0 +#define LOG_HEXDUMP_DBG_RATELIMIT(...) (void) 0 + +#define LOG_ERR_RATELIMIT_RATE(...) (void) 0 +#define LOG_WRN_RATELIMIT_RATE(...) (void) 0 +#define LOG_INF_RATELIMIT_RATE(...) (void) 0 +#define LOG_DBG_RATELIMIT_RATE(...) (void) 0 + +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(...) (void) 0 +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(...) (void) 0 +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(...) (void) 0 +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(...) (void) 0 #endif /** diff --git a/include/zephyr/net/net_core.h b/include/zephyr/net/net_core.h index e4b18418b3a..505683eb139 100644 --- a/include/zephyr/net/net_core.h +++ b/include/zephyr/net/net_core.h @@ -61,8 +61,14 @@ extern "C" { #define NET_WARN(fmt, ...) LOG_WRN(fmt, ##__VA_ARGS__) #define NET_INFO(fmt, ...) LOG_INF(fmt, ##__VA_ARGS__) -#define NET_HEXDUMP_DBG(_data, _length, _str) LOG_HEXDUMP_DBG(_data, _length, _str) -#define NET_HEXDUMP_ERR(_data, _length, _str) LOG_HEXDUMP_ERR(_data, _length, _str) +/* Rate-limited network logging macros */ +#define NET_ERR_RATELIMIT(fmt, ...) LOG_ERR_RATELIMIT(fmt, ##__VA_ARGS__) +#define NET_WARN_RATELIMIT(fmt, ...) LOG_WRN_RATELIMIT(fmt, ##__VA_ARGS__) +#define NET_INFO_RATELIMIT(fmt, ...) LOG_INF_RATELIMIT(fmt, ##__VA_ARGS__) +#define NET_DBG_RATELIMIT(fmt, ...) LOG_DBG_RATELIMIT(fmt, ##__VA_ARGS__) + +#define NET_HEXDUMP_DBG(_data, _length, _str) LOG_HEXDUMP_DBG(_data, _length, _str) +#define NET_HEXDUMP_ERR(_data, _length, _str) LOG_HEXDUMP_ERR(_data, _length, _str) #define NET_HEXDUMP_WARN(_data, _length, _str) LOG_HEXDUMP_WRN(_data, _length, _str) #define NET_HEXDUMP_INFO(_data, _length, _str) LOG_HEXDUMP_INF(_data, _length, _str) diff --git a/modules/hostap/src/supp_api.h b/modules/hostap/src/supp_api.h index bae1c3ab4df..9d2b90b50fe 100644 --- a/modules/hostap/src/supp_api.h +++ b/modules/hostap/src/supp_api.h @@ -313,7 +313,6 @@ int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_param */ int supplicant_set_bss_max_idle_period(const struct device *dev, unsigned short bss_max_idle_period); - #ifdef CONFIG_AP int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth); diff --git a/modules/nrf_wifi/os/shim.c b/modules/nrf_wifi/os/shim.c index df460d5ab53..79137e46e13 100644 --- a/modules/nrf_wifi/os/shim.c +++ b/modules/nrf_wifi/os/shim.c @@ -34,7 +34,14 @@ LOG_MODULE_REGISTER(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL); -#if !defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) +/* Memory pool management - unified pool-based API */ +#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) +/* Use global system heap */ +extern struct sys_heap _system_heap; +static struct k_heap * const wifi_ctrl_pool = &_system_heap; +static struct k_heap * const wifi_data_pool = &_system_heap; +#else +/* Use dedicated heaps */ #if defined(CONFIG_NOCACHE_MEMORY) K_HEAP_DEFINE_NOCACHE(wifi_drv_ctrl_mem_pool, CONFIG_NRF_WIFI_CTRL_HEAP_SIZE); K_HEAP_DEFINE_NOCACHE(wifi_drv_data_mem_pool, CONFIG_NRF_WIFI_DATA_HEAP_SIZE); @@ -42,6 +49,8 @@ K_HEAP_DEFINE_NOCACHE(wifi_drv_data_mem_pool, CONFIG_NRF_WIFI_DATA_HEAP_SIZE); K_HEAP_DEFINE(wifi_drv_ctrl_mem_pool, CONFIG_NRF_WIFI_CTRL_HEAP_SIZE); K_HEAP_DEFINE(wifi_drv_data_mem_pool, CONFIG_NRF_WIFI_DATA_HEAP_SIZE); #endif /* CONFIG_NOCACHE_MEMORY */ +static struct k_heap * const wifi_ctrl_pool = &wifi_drv_ctrl_mem_pool; +static struct k_heap * const wifi_data_pool = &wifi_drv_data_mem_pool; #endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ #define WORD_SIZE 4 @@ -52,22 +61,14 @@ static void *zep_shim_mem_alloc(size_t size) { size_t size_aligned = ROUND_UP(size, 4); -#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) - return k_malloc(size_aligned); -#else /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ - return k_heap_aligned_alloc(&wifi_drv_ctrl_mem_pool, WORD_SIZE, size_aligned, K_FOREVER); -#endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ + return k_heap_aligned_alloc(wifi_ctrl_pool, WORD_SIZE, size_aligned, K_FOREVER); } static void *zep_shim_data_mem_alloc(size_t size) { size_t size_aligned = ROUND_UP(size, 4); -#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) - return k_malloc(size_aligned); -#else /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ - return k_heap_aligned_alloc(&wifi_drv_data_mem_pool, WORD_SIZE, size_aligned, K_FOREVER); -#endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ + return k_heap_aligned_alloc(wifi_data_pool, WORD_SIZE, size_aligned, K_FOREVER); } static void *zep_shim_mem_zalloc(size_t size) @@ -111,22 +112,14 @@ static void *zep_shim_data_mem_zalloc(size_t size) static void zep_shim_mem_free(void *buf) { if (buf) { -#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) - k_free(buf); -#else /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ - k_heap_free(&wifi_drv_ctrl_mem_pool, buf); -#endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ + k_heap_free(wifi_ctrl_pool, buf); } } static void zep_shim_data_mem_free(void *buf) { if (buf) { -#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) - k_free(buf); -#else /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ - k_heap_free(&wifi_drv_data_mem_pool, buf); -#endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ + k_heap_free(wifi_data_pool, buf); } } @@ -206,10 +199,11 @@ static void *zep_shim_spinlock_alloc(void) { struct k_mutex *lock = NULL; - lock = zep_shim_mem_zalloc(sizeof(*lock)); - + lock = k_heap_aligned_alloc(wifi_ctrl_pool, WORD_SIZE, sizeof(*lock), K_FOREVER); if (!lock) { LOG_ERR("%s: Unable to allocate memory for spinlock", __func__); + } else { + memset(lock, 0, sizeof(*lock)); } return lock; @@ -217,11 +211,9 @@ static void *zep_shim_spinlock_alloc(void) static void zep_shim_spinlock_free(void *lock) { -#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) - k_free(lock); -#else /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ - k_heap_free(&wifi_drv_ctrl_mem_pool, lock); -#endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ + if (lock) { + k_heap_free(wifi_ctrl_pool, lock); + } } static void zep_shim_spinlock_init(void *lock) diff --git a/subsys/logging/Kconfig b/subsys/logging/Kconfig index f7a7b32b804..00a91f43c14 100644 --- a/subsys/logging/Kconfig +++ b/subsys/logging/Kconfig @@ -49,6 +49,56 @@ endif rsource "Kconfig.misc" +config LOG_RATELIMIT + bool "Rate-limited logging macros" + default y + help + When enabled, provides rate-limited logging macros that prevent + log flooding when messages are generated frequently. Rate limiting + is per-macro-call-site, meaning each unique call has its own + independent rate limit. + +if LOG_RATELIMIT + +config LOG_RATELIMIT_INTERVAL_MS + int "Default rate limit interval (milliseconds)" + default 5000 + range 100 60000 + help + Default interval between rate-limited log messages. + This is used by the convenience macros LOG_*_RATELIMIT + when no explicit rate is provided. Can be overridden per call + using LOG_*_RATELIMIT_RATE macros. +endif # LOG_RATELIMIT + +if !LOG_RATELIMIT +choice LOG_RATELIMIT_FALLBACK + prompt "Fallback behavior for rate-limited logging macros" + default LOG_RATELIMIT_FALLBACK_DROP + help + Select fallback behavior for rate-limited logging macros when + LOG_RATELIMIT is disabled. + + - "Log all prints": All log prints are output, i.e., rate limiting is ignored. + - "Drop all prints": All log prints using rate-limited macros are dropped. + + This option allows you to control whether rate-limited log macros + should always print or be completely suppressed when rate limiting + is not available. + +config LOG_RATELIMIT_FALLBACK_LOG + bool "Log all prints (ignore rate limiting)" + help + All log prints using rate-limited macros are output as normal logs. + +config LOG_RATELIMIT_FALLBACK_DROP + bool "Drop all prints" + help + All log prints using rate-limited macros are dropped (no output). + +endchoice +endif # !LOG_RATELIMIT + endif # LOG config LOG_OUTPUT diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index b541787a0d9..8c5e7b81548 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -262,8 +262,8 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt) status = net_if_l2(iface)->send(iface, pkt); net_if_tx_unlock(iface); if (status < 0) { - NET_WARN("iface %d pkt %p send failure status %d", - net_if_get_by_iface(iface), pkt, status); + NET_WARN_RATELIMIT("iface %d pkt %p send failure status %d", + net_if_get_by_iface(iface), pkt, status); } if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS) || diff --git a/subsys/net/l2/wifi/Kconfig b/subsys/net/l2/wifi/Kconfig index f129c3bf72d..7728678cc97 100644 --- a/subsys/net/l2/wifi/Kconfig +++ b/subsys/net/l2/wifi/Kconfig @@ -155,11 +155,10 @@ endif # WIFI_SHELL_RUNTIME_CERTIFICATES endif # WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE - config WIFI_MGMT_BSS_MAX_IDLE_TIME int "BSS max idle timeout in seconds" range 0 64000 - default 300 + default 30 help As per 802.11-2020: 11.21.13 BSS max idle period management If dot11WirelessManagementImplemented is true, dot11BSSMaxIdlePeriod is diff --git a/tests/subsys/logging/log_ratelimited/CMakeLists.txt b/tests/subsys/logging/log_ratelimited/CMakeLists.txt new file mode 100644 index 00000000000..29df5637b03 --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(log_ratelimited_test) + +FILE(GLOB app_sources *.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/logging/log_ratelimited/prj.conf b/tests/subsys/logging/log_ratelimited/prj.conf new file mode 100644 index 00000000000..e3621aa1a7e --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/prj.conf @@ -0,0 +1,18 @@ +CONFIG_MAIN_THREAD_PRIORITY=5 +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_TEST_LOGGING_DEFAULTS=n +CONFIG_LOG=y +CONFIG_LOG_OUTPUT=y +CONFIG_LOG_PRINTK=n +CONFIG_LOG_BACKEND_UART=y +CONFIG_LOG_BUFFER_SIZE=768 +CONFIG_KERNEL_LOG_LEVEL_OFF=y +CONFIG_SOC_LOG_LEVEL_OFF=y +CONFIG_ARCH_LOG_LEVEL_OFF=y +CONFIG_LOG_FUNC_NAME_PREFIX_DBG=n +CONFIG_LOG_PROCESS_THREAD=n +CONFIG_ASSERT=y +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_LOG_DEFAULT_LEVEL=4 +CONFIG_LOG_RATELIMIT=y diff --git a/tests/subsys/logging/log_ratelimited/test_log_ratelimited.c b/tests/subsys/logging/log_ratelimited/test_log_ratelimited.c new file mode 100644 index 00000000000..ea22fe57964 --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/test_log_ratelimited.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_REGISTER(test_log_ratelimited, CONFIG_LOG_DEFAULT_LEVEL); + +#ifndef CONFIG_LOG_RATELIMIT_FALLBACK_DROP +/* Test data for hexdump */ +static uint8_t test_data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; +#endif /* CONFIG_LOG_RATELIMIT_FALLBACK_DROP */ + +/** + * @brief Test compilation of all rate-limited macros. + * This test primarily checks for compilation errors and does not assert log + * counts, as log levels might filter some messages depending on Kconfig. + */ +ZTEST(log_ratelimited, test_compilation) +{ + /* This test only checks if the macros compile without errors. */ + /* Call each macro once to ensure compilation. */ + LOG_ERR_RATELIMIT("Compilation test: Error message"); + LOG_WRN_RATELIMIT("Compilation test: Warning message"); + LOG_INF_RATELIMIT("Compilation test: Info message"); + LOG_DBG_RATELIMIT("Compilation test: Debug message"); + + LOG_ERR_RATELIMIT_RATE(100, "Compilation test: Error message with rate"); + LOG_WRN_RATELIMIT_RATE(100, "Compilation test: Warning message with rate"); + LOG_INF_RATELIMIT_RATE(100, "Compilation test: Info message with rate"); + LOG_DBG_RATELIMIT_RATE(100, "Compilation test: Debug message with rate"); + + LOG_HEXDUMP_ERR_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Error hexdump"); + LOG_HEXDUMP_WRN_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Warning hexdump"); + LOG_HEXDUMP_INF_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Info hexdump"); + LOG_HEXDUMP_DBG_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Debug hexdump"); + + LOG_HEXDUMP_ERR_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Error hexdump with rate"); + LOG_HEXDUMP_WRN_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Warning hexdump with rate"); + LOG_HEXDUMP_INF_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Info hexdump with rate"); + LOG_HEXDUMP_DBG_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Debug hexdump with rate"); + + zassert_true(true, "All rate-limited macros compile successfully"); +} + + +/* Define the test suite and specify the setup function to be called before each + * test case. + */ +ZTEST_SUITE(log_ratelimited, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/logging/log_ratelimited/testcase.yaml b/tests/subsys/logging/log_ratelimited/testcase.yaml new file mode 100644 index 00000000000..5fa2d18a562 --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/testcase.yaml @@ -0,0 +1,23 @@ +common: + integration_platforms: + - native_sim + tags: + - logging + platform_allow: + - native_sim + +tests: + logging.log_ratelimited: + build_only: true + extra_configs: + - CONFIG_LOG_RATELIMIT_INTERVAL_MS=1000 + logging.log_ratelimited.fallback_drop: + build_only: true + extra_configs: + - CONFIG_LOG_RATELIMIT=n + - CONFIG_LOG_RATELIMIT_FALLBACK_DROP=y + logging.log_ratelimited.fallback_log: + build_only: true + extra_configs: + - CONFIG_LOG_RATELIMIT=n + - CONFIG_LOG_RATELIMIT_FALLBACK_LOG=y diff --git a/west.yml b/west.yml index 31740627efb..157ee35fc4d 100644 --- a/west.yml +++ b/west.yml @@ -328,7 +328,7 @@ manifest: revision: 968d55ff22579080466bf2f482596dd6e35361c6 path: modules/bsim_hw_models/nrf_hw_models - name: nrf_wifi - revision: 660071c36afa4c725c9b4922e4de466174bdf0e1 + revision: 787eea1a3c8dd13c86214e204a919e6f9bcebf91 path: modules/lib/nrf_wifi - name: open-amp revision: f7f4d083c7909a39d86e217376c69b416ec4faf3