From addea9d4d74e7e8fae161b7375e627b62161ead2 Mon Sep 17 00:00:00 2001 From: Sam Leffler Date: Tue, 31 Dec 2002 18:22:12 +0000 Subject: [PATCH] o reduce the overhead of calling ppsratecheck by using ticks instead of calling getmicrouptime (but maintain the struct timeval-based calling convention for compatibility) o eliminate the use of timersub in ratecheck Note that flood ping tests indicate ppsratecheck is inaccurate (but on the conservative side) with this revised implementation. If more accuracy is needed we'll have to introduce an alternate interface or increase the overhead. Reviewed by: silby, dillon, bde --- sys/kern/kern_time.c | 79 ++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 55 deletions(-) diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 169d5e0fd74a..2d53d3fb892d 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -664,21 +664,8 @@ timevalfix(struct timeval *t1) } } -#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. + * ratecheck(): simple time-based rate-limit checking. */ int ratecheck(struct timeval *lasttime, const struct timeval *mininterval) @@ -686,8 +673,9 @@ ratecheck(struct timeval *lasttime, const struct timeval *mininterval) struct timeval tv, delta; int rv = 0; - getmicrouptime(&tv); - timersub(&tv, lasttime, &delta); + getmicrouptime(&tv); /* NB: 10ms precision */ + delta = tv; + timevalsub(&delta, lasttime); /* * check for 0,0 is so that the message will be seen at least once, @@ -704,50 +692,31 @@ ratecheck(struct timeval *lasttime, const struct timeval *mininterval) /* * ppsratecheck(): packets (or events) per second limitation. + * + * Return 0 if the limit is to be enforced (e.g. the caller + * should drop a packet because of the rate limitation). + * + * Note that we maintain the struct timeval for compatibility + * with other bsd systems. We reuse the storage and just monitor + * clock ticks for minimal overhead. */ int ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) { - struct timeval tv, delta; - int rv; - - getmicrouptime(&tv); - timersub(&tv, lasttime, &delta); + int now; /* - * 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. + * Reset the last time and counter if this is the first call + * or more than a second has passed since the last update of + * lasttime. */ - 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); + now = ticks; + if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { + lasttime->tv_sec = now; + *curpps = 1; + return (1); + } else { + (*curpps)++; /* NB: ignore potential overflow */ + return (maxpps < 0 || *curpps < maxpps); + } }