From 4bba202a0ae1a662d710a93f79dcdb0e804ae17b Mon Sep 17 00:00:00 2001 From: jakob Date: Fri, 17 Mar 2000 22:24:26 +0000 Subject: [PATCH] ratecheck - function to help implement rate-limited actions (from NetBSD) ok art@ --- share/man/man9/Makefile | 4 +- share/man/man9/ratecheck.9 | 141 +++++++++++++++++++++++++++++++++++++ sys/kern/kern_time.c | 31 +++++++- sys/sys/time.h | 3 +- 4 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 share/man/man9/ratecheck.9 diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 37fb99ab43d..14c2668dd9c 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.14 1999/09/22 09:54:37 espie Exp $ +# $OpenBSD: Makefile,v 1.15 2000/03/17 22:24:27 jakob Exp $ # $NetBSD: Makefile,v 1.4 1996/01/09 03:23:01 thorpej Exp $ # Makefile for section 9 (kernel function and variable) manual pages. @@ -6,7 +6,7 @@ MAN= boot.9 copy.9 disk.9 doshutdownhooks.9 fetch.9 fork1.9 \ extent.9 hz.9 hzto.9 intro.9 inittodr.9 log.9 kthread.9 \ malloc.9 md5.9 microtime.9 panic.9 pfind.9 printf.9 \ - psignal.9 resettodr.9 \ + psignal.9 ratecheck.9 resettodr.9 \ random.9 shutdownhook_establish.9 sleep.9 spl.9 store.9 style.9 \ time.9 timeout.9 vm_allocate.9 vm_map_copy.9 vm_deallocate.9 \ vm_map_inherit.9 vm_map_protect.9 diff --git a/share/man/man9/ratecheck.9 b/share/man/man9/ratecheck.9 new file mode 100644 index 00000000000..ab9cf62d8a4 --- /dev/null +++ b/share/man/man9/ratecheck.9 @@ -0,0 +1,141 @@ +.\" $OpenBSD: ratecheck.9,v 1.1 2000/03/17 22:24:27 jakob Exp $ +.\" $NetBSD: ratecheck.9,v 1.1.2.1 2000/02/18 20:26:43 he Exp $ +.\" +.\" Copyright (c) 2000 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Christopher G. Demetriou. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd February 2, 2000 +.Dt RATECHECK 9 +.Os +.Sh NAME +.Nm ratecheck +.Nd function to help implement rate-limited actions +.Sh SYNOPSIS +.Fd #include +.Ft int +.Fn ratecheck "struct timeval *lasttime" "const struct timeval *mininterval" +.Sh DESCRIPTION +The +.Fn ratecheck +function provides a simple time interval check which can be used +when implementing time-based rate-limited actions. +If the difference between the current monotonically-increasing +system time +.Pq Va mono_time +and +.Fa lasttime +is less than the value given by the +.Fa mininterval +argument, zero is returned. Otherwise, +.Fa lasttime +is set to the current time and a non-zero value is returned. +.Pp +The motivation for implementing +.Fn ratecheck +was to provide a mechanism that could be used to add rate limiting to +diagnostic message output. If printed too often, diagnostic messages can +keep the system from doing useful work. If the repeated messages can +be caused by deliberate user action or network events, they can be +exploited to cause denial of system service. +.Pp +Note that using a very short time interval (less than a second) +for +.Fa mininterval +defeats the purpose of this function. (It doesn't +take much to flood a 9600 baud serial console with output, for instance.) +.Sh EXAMPLES +Here is a simple example of use of the +.Fn ratecheck +function: +.Bd -literal +/* + * The following variables could be global, in a device softc, etc., + * depending on the exact usage. + */ +struct timeval drv_lasterr1time; /* time of last err1 message */ +long drv_err1count; /* # of err1 errs since last msg */ +struct timeval drv_lasterr2time; /* time of last err2 message */ +long drv_err2count; /* # of err2 errs since last msg */ + +/* + * the following variable will often be global or shared by all + * instances of a driver. It should be initalized, so it can be + * patched. Allowing it to be set via an option might be nice, + * but could lead to an insane proliferation of options. + */ +struct timeval drv_errintvl = { 5, 0 }; /* 5 seconds */ + +/* error handling/reporting function */ +void +drv_errhandler(int err1, int err2) +{ + + /* + * Note that you should NOT use the same last-event + * time variable for dissimilar messages! + */ + if (err1) { + /* handle err1 condition */ + ... + + drv_err1count++; + if (ratecheck(&drv_lasterr1notice, + &drv_errinterval)) { + printf("drv: %ld err1 errors occurred", + drv_err1count); + drv_err1count = 0; + } + } + if (err2) { + /* handle err2 condition */ + ... + + drv_err2count++; + if (ratecheck(&drv_lasterr2notice, + &drv_errinterval)) { + printf("drv: %ld err2 errors occurred", + drv_err2count); + drv_err2count = 0; + } + } +} +.Sh SEE ALSO +.Xr log 9 , +.Xr printf 9 , +.Xr time 9 +.Sh HISTORY +The +.Fn ratecheck +function appeared in +.Ox 2.7 . diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 7951376f7e5..eac35bced09 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_time.c,v 1.16 2000/01/22 23:41:42 millert Exp $ */ +/* $OpenBSD: kern_time.c,v 1.17 2000/03/17 22:24:26 jakob Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* @@ -594,3 +594,32 @@ expire: itp->it_value.tv_usec = 0; /* sec is already 0 */ return (0); } + +/* + * ratecheck(): simple time-based rate-limit checking. see ratecheck(9) + * for usage and rationale. + */ +int +ratecheck(lasttime, mininterval) + struct timeval *lasttime; + const struct timeval *mininterval; +{ + struct timeval delta; + int s, rv = 0; + + s = splclock(); + timersub(&mono_time, lasttime, &delta); + + /* + * check for 0,0 is so that the message will be seen at least once, + * even if interval is huge. + */ + if (timercmp(&delta, mininterval, >=) || + (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { + *lasttime = mono_time; + rv = 1; + } + splx(s); + + return (rv); +} diff --git a/sys/sys/time.h b/sys/sys/time.h index fdc90fd6cf8..d1b218942e5 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -1,4 +1,4 @@ -/* $OpenBSD: time.h,v 1.9 1999/12/06 19:36:42 aaron Exp $ */ +/* $OpenBSD: time.h,v 1.10 2000/03/17 22:24:27 jakob Exp $ */ /* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ /* @@ -167,6 +167,7 @@ int itimerfix __P((struct timeval *tv)); int itimerdecr __P((struct itimerval *itp, int usec)); void microtime __P((struct timeval *tv)); void settime __P((struct timeval *tv)); +int ratecheck __P((struct timeval *, const struct timeval *)); #else /* !_KERNEL */ #include -- 2.20.1