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 <yukangzhi@xiaomi.com>
This commit is contained in:
yukangzhi
2025-05-27 18:07:11 +08:00
committed by Xiang Xiao
parent 6538477fa5
commit 6ccc2fc7c8
3 changed files with 187 additions and 2 deletions
@@ -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)
==========================
+109 -2
View File
@@ -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;
+11
View File
@@ -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];