Subject: ppsratecheck(9)
To: None <tech-kern@netbsd.org>
From: None <itojun@iijlab.net>
List: tech-kern
Date: 07/06/2000 22:35:53
kjc (of ALTQ) suggested me that:
- ratelimit(9) makes sense only for large intervals, due to limited
timer resolution in BSDs (hz)
- using ratelimit(9), with small interval, for icmp6/icmp does not
make sense
- if we implement something for icmp6/icmp/tcp-rst limitation,
it should better be packet-per-sec limitation
so, here's ppsratecheck(9). it basically try to limit some
event (like icmp6 error transmission) to happen less than X
occurrences-per-second.
you may have different idea about function names or argument types,
i'm not good at naming things:-)
itojun
Index: kern/kern_time.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_time.c,v
retrieving revision 1.48
diff -c -r1.48 kern_time.c
*** kern_time.c 2000/06/27 17:41:31 1.48
--- kern_time.c 2000/07/06 13:31:17
***************
*** 663,665 ****
--- 663,703 ----
return (rv);
}
+
+ /*
+ * ppsratecheck(): packets (or events) per second limitation.
+ */
+ int
+ ppsratecheck(lasttime, curpps, maxpps)
+ struct timeval *lasttime;
+ int *curpps;
+ int maxpps; /* maximum pps allowed */
+ {
+ struct timeval delta;
+ int s, rv;
+
+ s = splclock();
+ timersub(&mono_time, 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, start over.
+ */
+ if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) ||
+ delta.tv_sec > 0) {
+ *lasttime = mono_time;
+ *curpps = 0;
+ rv = 1;
+ } else if (*curpps < maxpps)
+ rv = 1;
+ else
+ rv = 0;
+ /* be careful about wrap-around */
+ if (*curpps + 1 > *curpps)
+ *curpps = *curpps + 1;
+
+ splx(s);
+
+ return (rv);
+ }
Index: sys/time.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/time.h,v
retrieving revision 1.29
diff -c -r1.29 time.h
*** time.h 2000/02/03 23:04:45 1.29
--- time.h 2000/07/06 13:31:17
***************
*** 164,169 ****
--- 164,170 ----
void microtime __P((struct timeval *tv));
int settime __P((struct timeval *));
int ratecheck __P((struct timeval *, const struct timeval *));
+ int ppsratecheck __P((struct timeval *, int *, int));
#else /* !_KERNEL */
#ifndef _STANDALONE
Index: netinet6/icmp6.c
===================================================================
RCS file: /cvsroot/syssrc/sys/netinet6/icmp6.c,v
retrieving revision 1.35
diff -c -r1.35 icmp6.c
*** icmp6.c 2000/07/06 12:36:18 1.35
--- icmp6.c 2000/07/06 13:31:18
***************
*** 115,120 ****
--- 115,121 ----
static struct timeval icmp6errratelim_last;
extern int icmp6errppslim;
static int icmp6errpps_count = 0;
+ static struct timeval icmp6errppslim_last;
extern int icmp6_nodeinfo;
static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
extern int pmtu_expire;
***************
*** 1962,1969 ****
--- 1963,1972 ----
mld6_fasttimeo();
+ #if 0
/* reset ICMPv6 pps limit */
icmp6errpps_count = 0;
+ #endif
}
static const char *
***************
*** 2566,2576 ****
--- 2569,2587 ----
ret = 0; /*okay to send*/
/* PPS limit */
+ #if 0
icmp6errpps_count++;
if (icmp6errppslim && icmp6errpps_count > icmp6errppslim / 5) {
/* The packet is subject to pps limit */
ret++;
}
+ #else
+ if (!ppsratecheck(&icmp6errppslim_last, &icmp6errpps_count,
+ icmp6errppslim)) {
+ /* The packet is subject to rate limit */
+ ret++;
+ }
+ #endif
if (!ratecheck(&icmp6errratelim_last, &icmp6errratelim)) {
/* The packet is subject to rate limit */