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];

Reply via email to