void *unique_ptr, int unique_int);
int rad_copy_string(char *dst, const char *src);
int rad_copy_variable(char *dst, const char *from);
+int rad_pps(int *past, int *present, time_t *then,
+ struct timeval *now);
/* client.c */
RADCLIENT_LIST *clients_init(void);
&max_pps, "0");
if (rcode < 0) return -1;
- if ((max_pps < 10) || (max_pps > 1000000)) {
+ if (max_pps && ((max_pps < 10) || (max_pps > 1000000))) {
cf_log_err(cf_sectiontoitem(cs),
"Invalid value for \"max_pps\"");
return -1;
if (sock->max_rate) {
int pps;
- /*
- * Track packets in the previous second.
- */
- if (sock->rate_time != now.tv_sec) {
- sock->rate_time = now.tv_sec;
- sock->rate_pps_old = sock->rate_pps_now;
- sock->rate_pps_now = 0;
- }
-
- /*
- * Bootstrap PPS by looking at a percentage of
- * the previous PPS. This lets us take a moving
- * count, without doing a moving average. If
- * we're a fraction "f" (0..1) into the current
- * second, we can get a good guess for PPS by
- * doing:
- *
- * PPS = pps_now + pps_old * (1 - f)
- *
- * It's an instantaneous measurement, rather than
- * a moving average. This will hopefully let it
- * respond better to sudden spikes.
- *
- * Doing the calculations by thousands allows us
- * to not overflow 2^32, AND to not underflow
- * when we divide by USEC.
- */
- pps = USEC - now.tv_usec;
- pps /= 1000; /* now 0..9999 */
- pps *= sock->rate_pps_old; /* capped at 1000000 */
-
- pps += sock->rate_pps_now * 1000;
- pps /= 1000;
+ pps = rad_pps(&sock->rate_pps_old, &sock->rate_pps_now,
+ &sock->rate_time, &now);
if (pps > sock->max_rate) {
DEBUG("Dropping request due to rate limiting");
return -1;
}
+#ifndef USEC
+#define USEC 1000000
+#endif
+
+int rad_pps(int *past, int *present, time_t *then, struct timeval *now)
+{
+ int pps;
+
+ if (*then != now->tv_sec) {
+ *then = now->tv_sec;
+ *past = *present;
+ *present = 0;
+ }
+
+ /*
+ * Bootstrap PPS by looking at a percentage of
+ * the previous PPS. This lets us take a moving
+ * count, without doing a moving average. If
+ * we're a fraction "f" (0..1) into the current
+ * second, we can get a good guess for PPS by
+ * doing:
+ *
+ * PPS = pps_now + pps_old * (1 - f)
+ *
+ * It's an instantaneous measurement, rather than
+ * a moving average. This will hopefully let it
+ * respond better to sudden spikes.
+ *
+ * Doing the calculations by thousands allows us
+ * to not overflow 2^32, AND to not underflow
+ * when we divide by USEC.
+ */
+ pps = USEC - now->tv_usec; /* useconds left in previous second */
+ pps /= 1000; /* scale to milliseconds */
+ pps *= *past; /* multiply by past count to get fraction */
+ pps /= 1000; /* scale to usec again */
+ pps += *present; /* add in current count */
+
+ return pps;
+}