1 /*- 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 30 */ 31 #include <sys/kernel.h> 32 #include <sys/time.h> 33 34 /* 35 * ratecheck(): simple time-based rate-limit checking. 36 */ 37 int 38 ratecheck(struct timeval *lasttime, const struct timeval *mininterval) 39 { 40 struct timeval tv, delta; 41 int rv = 0; 42 43 getmicrouptime(&tv); /* NB: 10ms precision */ 44 delta = tv; 45 timevalsub(&delta, lasttime); 46 47 /* 48 * check for 0,0 is so that the message will be seen at least once, 49 * even if interval is huge. 50 */ 51 if (timevalcmp(&delta, mininterval, >=) || 52 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 53 *lasttime = tv; 54 rv = 1; 55 } 56 57 return (rv); 58 } 59 60 /* 61 * ppsratecheck(): packets (or events) per second limitation. 62 * 63 * Return 0 if the limit is to be enforced (e.g. the caller 64 * should drop a packet because of the rate limitation). 65 * 66 * maxpps of 0 always causes zero to be returned. maxpps of -1 67 * always causes 1 to be returned; this effectively defeats rate 68 * limiting. 69 * 70 * Note that we maintain the struct timeval for compatibility 71 * with other bsd systems. We reuse the storage and just monitor 72 * clock ticks for minimal overhead. 73 */ 74 int 75 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 76 { 77 int now; 78 79 /* 80 * Reset the last time and counter if this is the first call 81 * or more than a second has passed since the last update of 82 * lasttime. 83 */ 84 now = ticks; 85 if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { 86 lasttime->tv_sec = now; 87 *curpps = 1; 88 return (maxpps != 0); 89 } else { 90 (*curpps)++; /* NB: ignore potential overflow */ 91 return (maxpps < 0 || *curpps <= maxpps); 92 } 93 } 94 95 static void 96 timevalfix(struct timeval *t1) 97 { 98 99 if (t1->tv_usec < 0) { 100 t1->tv_sec--; 101 t1->tv_usec += 1000000; 102 } 103 if (t1->tv_usec >= 1000000) { 104 t1->tv_sec++; 105 t1->tv_usec -= 1000000; 106 } 107 } 108 109 /* 110 * Add and subtract routines for timevals. 111 * N.B.: subtract routine doesn't deal with 112 * results which are before the beginning, 113 * it just gets very confused in this case. 114 * Caveat emptor. 115 */ 116 void 117 timevaladd(struct timeval *t1, const struct timeval *t2) 118 { 119 120 t1->tv_sec += t2->tv_sec; 121 t1->tv_usec += t2->tv_usec; 122 timevalfix(t1); 123 } 124 125 void 126 timevalsub(struct timeval *t1, const struct timeval *t2) 127 { 128 129 t1->tv_sec -= t2->tv_sec; 130 t1->tv_usec -= t2->tv_usec; 131 timevalfix(t1); 132 } 133