summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2002-12-20 23:54:47 +0000
committersam <sam@FreeBSD.org>2002-12-20 23:54:47 +0000
commit78550cc698095f1b298ad5214fae5caf59b9baa1 (patch)
tree1bc9b5a23847e24ac3a3c4a53fc5079e74f0f721 /sys/kern/kern_time.c
parentd522abfb6d47ee167a0c53c0083f506210ae0a0c (diff)
downloadFreeBSD-src-78550cc698095f1b298ad5214fae5caf59b9baa1.zip
FreeBSD-src-78550cc698095f1b298ad5214fae5caf59b9baa1.tar.gz
add generic rate limiting support from netbsd; ratelimit is purely time based,
ppsratecheck is for controlling packets/second Obtained from: netbsd
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r--sys/kern/kern_time.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 27b1fdd..169d5e0 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -663,3 +663,91 @@ timevalfix(struct timeval *t1)
t1->tv_usec -= 1000000;
}
}
+
+#ifndef timersub
+#define timersub(tvp, uvp, vvp) \
+ do { \
+ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
+/*
+ * ratecheck(): simple time-based rate-limit checking. see ratecheck(9)
+ * for usage and rationale.
+ */
+int
+ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
+{
+ struct timeval tv, delta;
+ int rv = 0;
+
+ getmicrouptime(&tv);
+ timersub(&tv, lasttime, &delta);
+
+ /*
+ * check for 0,0 is so that the message will be seen at least once,
+ * even if interval is huge.
+ */
+ if (timevalcmp(&delta, mininterval, >=) ||
+ (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
+ *lasttime = tv;
+ rv = 1;
+ }
+
+ return (rv);
+}
+
+/*
+ * ppsratecheck(): packets (or events) per second limitation.
+ */
+int
+ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
+{
+ struct timeval tv, delta;
+ int rv;
+
+ getmicrouptime(&tv);
+ timersub(&tv, lasttime, &delta);
+
+ /*
+ * check for 0,0 is so that the message will be seen at least once.
+ * if more than one second have passed since the last update of
+ * lasttime, reset the counter.
+ *
+ * we do increment *curpps even in *curpps < maxpps case, as some may
+ * try to use *curpps for stat purposes as well.
+ */
+ if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) ||
+ delta.tv_sec >= 1) {
+ *lasttime = tv;
+ *curpps = 0;
+ rv = 1;
+ } else if (maxpps < 0)
+ rv = 1;
+ else if (*curpps < maxpps)
+ rv = 1;
+ else
+ rv = 0;
+
+#if 1 /*DIAGNOSTIC?*/
+ /* be careful about wrap-around */
+ if (*curpps + 1 > *curpps)
+ *curpps = *curpps + 1;
+#else
+ /*
+ * assume that there's not too many calls to this function.
+ * not sure if the assumption holds, as it depends on *caller's*
+ * behavior, not the behavior of this function.
+ * IMHO it is wrong to make assumption on the caller's behavior,
+ * so the above #if is #if 1, not #ifdef DIAGNOSTIC.
+ */
+ *curpps = *curpps + 1;
+#endif
+
+ return (rv);
+}
OpenPOWER on IntegriCloud