This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 6ccc2fc7c83 driver/ramlog: Implement the rate limiting function for
ramlog driver.
6ccc2fc7c83 is described below
commit 6ccc2fc7c83d34bb4ca4ef93ed86bf7ac037f90d
Author: yukangzhi <[email protected]>
AuthorDate: Tue May 27 18:07:11 2025 +0800
driver/ramlog: Implement the rate limiting function for ramlog driver.
Limit the maximum number of log entries allowed within
the specified time interval in seconds.
Signed-off-by: yukangzhi <[email protected]>
---
.../components/drivers/special/syslog.rst | 67 +++++++++++++
drivers/syslog/ramlog.c | 111 ++++++++++++++++++++-
include/nuttx/syslog/syslog.h | 11 ++
3 files changed, 187 insertions(+), 2 deletions(-)
diff --git a/Documentation/components/drivers/special/syslog.rst
b/Documentation/components/drivers/special/syslog.rst
index d53639bddfb..23a558d1a4e 100644
--- a/Documentation/components/drivers/special/syslog.rst
+++ b/Documentation/components/drivers/special/syslog.rst
@@ -539,6 +539,73 @@ Other miscellaneous settings
- ``CONFIG_RAMLOG_NPOLLWAITERS``: The maximum number of threads
that may be waiting on the poll method.
+RAMLOG Rate Limiting
+--------------------
+
+The RAMLOG SYSLOG channel supports rate limiting to prevent log flooding.
+You can set or get the rate limit using the following IOCTLs:
+
+- ``SYSLOGIOC_SETRATELIMIT``: Set the rate limit.
+- ``SYSLOGIOC_GETRATELIMIT``: Get the current rate limit.
+
+The argument is a pointer to:
+
+.. code-block:: c
+
+ struct syslog_ratelimit_s
+ {
+ unsigned int interval; /* The interval in seconds */
+ unsigned int burst; /* The max allowed log entries during interval */
+ };
+
+**Example (C code):**
+
+.. code-block:: c
+
+ struct syslog_ratelimit_s limit = { .interval = 1, .burst = 100 };
+ ioctl(fd, SYSLOGIOC_SETRATELIMIT, (unsigned long)&limit);
+
+**NSH Tool Example: setlograte**
+
+You can implement a simple NSH command to control the RAMLOG rate limit at
runtime, similar to setlogmask:
+
+.. code-block:: c
+
+ int cmd_setlograte(int argc, char **argv)
+ {
+ int fd;
+ struct syslog_ratelimit_s limit;
+
+ if (argc != 3)
+ {
+ printf("Usage: setlograte <interval_sec> <burst>\n");
+ return -1;
+ }
+
+ limit.interval = atoi(argv[1]);
+ limit.burst = atoi(argv[2]);
+
+ fd = open("/dev/ramlog", O_RDWR);
+ if (fd < 0)
+ {
+ printf("Failed to open /dev/ramlog\n");
+ return -1;
+ }
+
+ if (ioctl(fd, SYSLOGIOC_SETRATELIMIT, (unsigned long)&limit) < 0)
+ {
+ printf("Failed to set rate limit\n");
+ close(fd);
+ return -1;
+ }
+
+ printf("Set RAMLOG rate limit: interval=%u sec, burst=%u\n",
limit.interval, limit.burst);
+ close(fd);
+ return 0;
+ }
+
+This command allows you to set the maximum number of log entries (burst)
allowed in a given interval (seconds) for the RAMLOG device at runtime.
+
SYSLOG Protocol (RFC 5424)
==========================
diff --git a/drivers/syslog/ramlog.c b/drivers/syslog/ramlog.c
index d8cf0cbd1a8..86820cace37 100644
--- a/drivers/syslog/ramlog.c
+++ b/drivers/syslog/ramlog.c
@@ -65,6 +65,14 @@
* Private Types
****************************************************************************/
+struct ramlog_ratelimit_s
+{
+ unsigned int interval; /* The interval in seconds */
+ unsigned int burst; /* The max allowed note number during interval */
+ unsigned int printed; /* The number of printed note during interval */
+ unsigned long begin; /* The timestamp in seconds */
+};
+
struct ramlog_header_s
{
uint32_t rl_magic; /* The rl_magic number for ramlog buffer init
*/
@@ -98,8 +106,9 @@ struct ramlog_dev_s
FAR struct ramlog_header_s *rl_header;
- uint32_t rl_bufsize; /* Size of the Circular RAM buffer */
- struct list_node rl_list; /* The head of ramlog_user_s list */
+ uint32_t rl_bufsize; /* Size of the circular buffer */
+ struct list_node rl_list; /* The list of ramlog_user_s */
+ struct ramlog_ratelimit_s rl_ratelimit; /* The ratelimit for ramlog */
};
/****************************************************************************
@@ -173,6 +182,65 @@ static struct ramlog_dev_s g_sysdev =
* Private Functions
****************************************************************************/
+/****************************************************************************
+ * Name: ramlog_ratelimit
+ *
+ * Description:
+ * Check whether the log is limited.
+ *
+ * Input Parameters:
+ * dev - The pointer of ramlog device.
+ *
+ * Returned Value:
+ * True is returned if the log is limited.
+ *
+ ****************************************************************************/
+
+static bool ramlog_ratelimit(FAR struct ramlog_dev_s *dev)
+{
+ bool ret;
+ clock_t ticks;
+ uint32_t seconds;
+ FAR struct ramlog_ratelimit_s *limit;
+
+ limit = &dev->rl_ratelimit;
+
+ if (limit->interval == 0)
+ {
+ return false;
+ }
+
+ ticks = clock_systime_ticks();
+ seconds = ticks * CONFIG_USEC_PER_TICK / 1000000;
+
+ if (limit->begin == 0)
+ {
+ limit->begin = seconds;
+ }
+
+ /* Reset statistical information */
+
+ if ((seconds - limit->begin) >= limit->interval)
+ {
+ limit->begin = seconds;
+ limit->printed = 0;
+ }
+
+ /* Check if the note is limited */
+
+ if (limit->burst && limit->burst > limit->printed)
+ {
+ limit->printed++;
+ ret = false;
+ }
+ else
+ {
+ ret = true;
+ }
+
+ return ret;
+}
+
/****************************************************************************
* Name: ramlog_bufferused
****************************************************************************/
@@ -301,6 +369,12 @@ static ssize_t ramlog_addbuf(FAR struct ramlog_dev_s *priv,
flags = enter_critical_section();
+ if (ramlog_ratelimit(priv))
+ {
+ leave_critical_section(flags);
+ return len;
+ }
+
#ifdef CONFIG_RAMLOG_SYSLOG
if (header->rl_magic != RAMLOG_MAGIC_NUMBER && priv == &g_sysdev)
{
@@ -521,6 +595,39 @@ static int ramlog_file_ioctl(FAR struct file *filep, int
cmd,
case BIOC_FLUSH:
ramlog_bufferflush(priv);
break;
+
+ case SYSLOGIOC_SETRATELIMIT:
+ if (arg == 0)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ FAR struct syslog_ratelimit_s *limit =
+ (FAR struct syslog_ratelimit_s *)arg;
+
+ priv->rl_ratelimit.interval = limit->interval;
+ priv->rl_ratelimit.burst = limit->burst;
+ ret = 0;
+ }
+ break;
+
+ case SYSLOGIOC_GETRATELIMIT:
+ if (arg == 0)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ FAR struct syslog_ratelimit_s *limit =
+ (FAR struct syslog_ratelimit_s *)arg;
+
+ limit->interval = priv->rl_ratelimit.interval;
+ limit->burst = priv->rl_ratelimit.burst;
+ ret = 0;
+ }
+ break;
+
default:
ret = -ENOTTY;
break;
diff --git a/include/nuttx/syslog/syslog.h b/include/nuttx/syslog/syslog.h
index addf2ead100..5f096ad721a 100644
--- a/include/nuttx/syslog/syslog.h
+++ b/include/nuttx/syslog/syslog.h
@@ -88,6 +88,11 @@
#define SYSLOGIOC_SETFILTER _SYSLOGIOC(0x0002)
+/* Set/Get syslog ratelimit */
+
+#define SYSLOGIOC_SETRATELIMIT _SYSLOGIOC(0x0003)
+#define SYSLOGIOC_GETRATELIMIT _SYSLOGIOC(0x0004)
+
#define SYSLOG_CHANNEL_NAME_LEN 32
#define SYSLOG_CHANNEL_DISABLE 0x01
@@ -127,6 +132,12 @@ struct syslog_channel_ops_s
syslog_close_t sc_close; /* Channel close callback */
};
+struct syslog_ratelimit_s
+{
+ unsigned int interval; /* The interval in seconds */
+ unsigned int burst; /* The max allowed note number during interval */
+};
+
struct syslog_channel_info_s
{
char sc_name[SYSLOG_CHANNEL_NAME_LEN];