diff options
author | sam <sam@FreeBSD.org> | 2002-12-20 23:54:47 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2002-12-20 23:54:47 +0000 |
commit | 78550cc698095f1b298ad5214fae5caf59b9baa1 (patch) | |
tree | 1bc9b5a23847e24ac3a3c4a53fc5079e74f0f721 /sys | |
parent | d522abfb6d47ee167a0c53c0083f506210ae0a0c (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/kern/kern_time.c | 88 | ||||
-rw-r--r-- | sys/sys/time.h | 2 |
2 files changed, 90 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); +} diff --git a/sys/sys/time.h b/sys/sys/time.h index 52b958b..b77ad39 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -302,6 +302,8 @@ void getmicrotime(struct timeval *tvp); /* Other functions */ int itimerdecr(struct itimerval *itp, int usec); int itimerfix(struct timeval *tv); +int ppsratecheck(struct timeval *, int *, int); +int ratecheck(struct timeval *, const struct timeval *); void timevaladd(struct timeval *t1, struct timeval *t2); void timevalsub(struct timeval *t1, struct timeval *t2); int tvtohz(struct timeval *tv); |