clientlog: allow very short rate limiting intervals

Support negative token shift to allow coarse rate limiting with
intervals down to -19.
This commit is contained in:
Miroslav Lichvar 2016-12-14 18:00:49 +01:00
parent 11ed197663
commit c6a38f5069
2 changed files with 23 additions and 8 deletions

View file

@ -95,7 +95,7 @@ static unsigned int max_slots;
number of tokens spent on response are determined from configured
minimum inverval between responses (in log2) and burst length. */
#define MIN_LIMIT_INTERVAL (-TS_FRAC)
#define MIN_LIMIT_INTERVAL (-15 - TS_FRAC)
#define MAX_LIMIT_INTERVAL 12
#define MIN_LIMIT_BURST 1
#define MAX_LIMIT_BURST 255
@ -105,7 +105,8 @@ static uint16_t max_cmd_tokens;
static uint16_t ntp_tokens_per_packet;
static uint16_t cmd_tokens_per_packet;
/* Reduction of token rates to avoid overflow of 16-bit counters */
/* Reduction of token rates to avoid overflow of 16-bit counters. Negative
shift is used for coarse limiting with intervals shorter than -TS_FRAC. */
static int ntp_token_shift;
static int cmd_token_shift;
@ -271,11 +272,18 @@ set_bucket_params(int interval, int burst, uint16_t *max_tokens,
interval = CLAMP(MIN_LIMIT_INTERVAL, interval, MAX_LIMIT_INTERVAL);
burst = CLAMP(MIN_LIMIT_BURST, burst, MAX_LIMIT_BURST);
/* Find smallest shift with which the maximum number fits in 16 bits */
if (interval >= -TS_FRAC) {
/* Find the smallest shift with which the maximum number fits in 16 bits */
for (*token_shift = 0; *token_shift < interval + TS_FRAC; (*token_shift)++) {
if (burst << (TS_FRAC + interval - *token_shift) < 1U << 16)
break;
}
} else {
/* Coarse rate limiting */
*token_shift = interval + TS_FRAC;
*tokens_per_packet = 1;
burst = MAX(1U << -*token_shift, burst);
}
*tokens_per_packet = 1U << (TS_FRAC + interval - *token_shift);
*max_tokens = *tokens_per_packet * burst;
@ -369,7 +377,12 @@ update_record(struct timespec *now, uint32_t *last_hit, uint32_t *hits,
if (prev_hit == INVALID_TS || (int32_t)interval < 0)
return;
if (token_shift >= 0)
new_tokens = (now_ts >> token_shift) - (prev_hit >> token_shift);
else if (now_ts - prev_hit > max_tokens)
new_tokens = max_tokens;
else
new_tokens = (now_ts - prev_hit) << -token_shift;
*tokens = MIN(*tokens + new_tokens, max_tokens);
/* Convert the interval to scaled and rounded log2 */

View file

@ -1238,7 +1238,9 @@ in any order):
*interval*:::
This option sets the minimum interval between responses. It is defined as a
power of 2 in seconds. The default value is 3 (8 seconds). The minimum value
is -4 and the maximum value is 12.
is -19 and the maximum value is 12. Note that with values below -4 the rate
limiting is coarse (responses are allowed in bursts, even if the interval
between them is shorter than the specified interval).
*burst*:::
This option sets the maximum number of responses that can be sent in a burst,
temporarily exceeding the limit specified by the *interval* option. This is