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
This commit is contained in:
Sam Leffler 2002-12-31 18:22:12 +00:00
parent ae5c97aaed
commit addea9d4d7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=108511

View file

@ -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);
}
}