Looks good, only minor nit picks.
> +struct token_bucket {
> + /* Configuration settings. */
> + unsigned int rate; /* Tokens added per millisecond. */
> + unsigned int burst; /* Max cumulative tokens credit. */
> +
> + /* Current status. */
> + unsigned int tokens; /* Current number of tokens. */
> + long long int last_fill; /* Last time tokens added. */
> +};
I think this would read better as "Last time tokens were added."
> +void token_bucket_set(struct token_bucket *,
> + unsigned int rate, unsigned int burst);
Indentation is off by a space here.
Thanks,
Ethan
> +bool token_bucket_withdraw(struct token_bucket *, unsigned int n);
> +void token_bucket_wait(struct token_bucket *, unsigned int n);
> +
> +#endif /* token-bucket.h */
> diff --git a/lib/vlog.c b/lib/vlog.c
> index a7d9e48..4b4465a 100644
> --- a/lib/vlog.c
> +++ b/lib/vlog.c
> @@ -762,28 +762,15 @@ vlog_should_drop(const struct vlog_module *module, enum
> vlog_level level,
> return true;
> }
>
> - if (rl->tokens < VLOG_MSG_TOKENS) {
> + if (!token_bucket_withdraw(&rl->token_bucket, VLOG_MSG_TOKENS)) {
> time_t now = time_now();
> - if (rl->last_fill > now) {
> - /* Last filled in the future? Time must have gone backward, or
> - * 'rl' has not been used before. */
> - rl->tokens = rl->burst;
> - } else if (rl->last_fill < now) {
> - unsigned int add = sat_mul(rl->rate, now - rl->last_fill);
> - unsigned int tokens = sat_add(rl->tokens, add);
> - rl->tokens = MIN(tokens, rl->burst);
> - rl->last_fill = now;
> - }
> - if (rl->tokens < VLOG_MSG_TOKENS) {
> - if (!rl->n_dropped) {
> - rl->first_dropped = now;
> - }
> - rl->last_dropped = now;
> - rl->n_dropped++;
> - return true;
> + if (!rl->n_dropped) {
> + rl->first_dropped = now;
> }
> + rl->last_dropped = now;
> + rl->n_dropped++;
> + return true;
> }
> - rl->tokens -= VLOG_MSG_TOKENS;
>
> if (rl->n_dropped) {
> time_t now = time_now();
> diff --git a/lib/vlog.h b/lib/vlog.h
> index 2dce3c6..e15e441 100644
> --- a/lib/vlog.h
> +++ b/lib/vlog.h
> @@ -1,5 +1,5 @@
> /*
> - * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
> + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
> *
> * Licensed under the Apache License, Version 2.0 (the "License");
> * you may not use this file except in compliance with the License.
> @@ -22,6 +22,8 @@
> #include <stdbool.h>
> #include <time.h>
> #include "compiler.h"
> +#include "sat-math.h"
> +#include "token-bucket.h"
> #include "util.h"
>
> #ifdef __cplusplus
> @@ -87,35 +89,24 @@ struct vlog_module *vlog_module_from_name(const char
> *name);
>
> /* Rate-limiter for log messages. */
> struct vlog_rate_limit {
> - /* Configuration settings. */
> - unsigned int rate; /* Tokens per second. */
> - unsigned int burst; /* Max cumulative tokens credit. */
> -
> - /* Current status. */
> - unsigned int tokens; /* Current number of tokens. */
> - time_t last_fill; /* Last time tokens added. */
> + struct token_bucket token_bucket;
> time_t first_dropped; /* Time first message was dropped. */
> time_t last_dropped; /* Time of most recent message drop. */
> unsigned int n_dropped; /* Number of messages dropped. */
> };
>
> -/* Number of tokens to emit a message. We add 'rate' tokens per second,
> which
> - * is 60 times the unit used for 'rate', thus 60 tokens are required to emit
> - * one message. */
> -#define VLOG_MSG_TOKENS 60
> +/* Number of tokens to emit a message. We add 'rate' tokens per millisecond,
> + * thus 60,000 tokens are required to emit one message per minute. */
> +#define VLOG_MSG_TOKENS (60 * 1000)
>
> /* Initializer for a struct vlog_rate_limit, to set up a maximum rate of RATE
> * messages per minute and a maximum burst size of BURST messages. */
> -#define VLOG_RATE_LIMIT_INIT(RATE, BURST) \
> - { \
> - RATE, /* rate */ \
> - (MIN(BURST, UINT_MAX / VLOG_MSG_TOKENS) \
> - * VLOG_MSG_TOKENS), /* burst */ \
> - 0, /* tokens */ \
> - 0, /* last_fill */ \
> - 0, /* first_dropped */ \
> - 0, /* last_dropped */ \
> - 0, /* n_dropped */ \
> +#define VLOG_RATE_LIMIT_INIT(RATE, BURST) \
> + { \
> + TOKEN_BUCKET_INIT(RATE, SAT_MUL(BURST, VLOG_MSG_TOKENS)), \
> + 0, /* first_dropped */ \
> + 0, /* last_dropped */ \
> + 0, /* n_dropped */ \
> }
>
> /* Configuring how each module logs messages. */
> diff --git a/ofproto/pinsched.c b/ofproto/pinsched.c
> index 4a939b8..57e8e23 100644
> --- a/ofproto/pinsched.c
> +++ b/ofproto/pinsched.c
> @@ -28,7 +28,9 @@
> #include "poll-loop.h"
> #include "random.h"
> #include "rconn.h"
> +#include "sat-math.h"
> #include "timeval.h"
> +#include "token-bucket.h"
> #include "vconn.h"
>
> struct pinqueue {
> @@ -39,24 +41,13 @@ struct pinqueue {
> };
>
> struct pinsched {
> - /* Client-supplied parameters. */
> - int rate_limit; /* Packets added to bucket per second. */
> - int burst_limit; /* Maximum token bucket size, in packets. */
> + struct token_bucket token_bucket;
>
> /* One queue per physical port. */
> struct hmap queues; /* Contains "struct pinqueue"s. */
> int n_queued; /* Sum over queues[*].n. */
> struct pinqueue *next_txq; /* Next pinqueue check in round-robin. */
>
> - /* Token bucket.
> - *
> - * It costs 1000 tokens to send a single packet_in message. A single
> token
> - * per message would be more straightforward, but this choice lets us
> avoid
> - * round-off error in refill_bucket()'s calculation of how many tokens to
> - * add to the bucket, since no division step is needed. */
> - long long int last_fill; /* Time at which we last added tokens. */
> - int tokens; /* Current number of tokens. */
> -
> /* Transmission queue. */
> int n_txq; /* No. of packets waiting in rconn for tx. */
>
> @@ -86,6 +77,20 @@ dequeue_packet(struct pinsched *ps, struct pinqueue *q)
> return packet;
> }
>
> +static void
> +adjust_limits(int *rate_limit, int *burst_limit)
> +{
> + if (*rate_limit <= 0) {
> + *rate_limit = 1000;
> + }
> + if (*burst_limit <= 0) {
> + *burst_limit = *rate_limit / 4;
> + }
> + if (*burst_limit < 1) {
> + *burst_limit = 1;
> + }
> +}
> +
> /* Destroys 'q' and removes it from 'ps''s set of queues.
> * (The caller must ensure that 'q' is empty.) */
> static void
> @@ -169,30 +174,13 @@ get_tx_packet(struct pinsched *ps)
> return packet;
> }
>
> -/* Add tokens to the bucket based on elapsed time. */
> -static void
> -refill_bucket(struct pinsched *ps)
> -{
> - long long int now = time_msec();
> - long long int tokens = (now - ps->last_fill) * ps->rate_limit +
> ps->tokens;
> - if (tokens >= 1000) {
> - ps->last_fill = now;
> - ps->tokens = MIN(tokens, ps->burst_limit * 1000);
> - }
> -}
> -
> /* Attempts to remove enough tokens from 'ps' to transmit a packet. Returns
> * true if successful, false otherwise. (In the latter case no tokens are
> * removed.) */
> static bool
> get_token(struct pinsched *ps)
> {
> - if (ps->tokens >= 1000) {
> - ps->tokens -= 1000;
> - return true;
> - } else {
> - return false;
> - }
> + return token_bucket_withdraw(&ps->token_bucket, 1000);
> }
>
> void
> @@ -216,7 +204,7 @@ pinsched_send(struct pinsched *ps, uint16_t port_no,
> * otherwise wasted space. */
> ofpbuf_trim(packet);
>
> - if (ps->n_queued >= ps->burst_limit) {
> + if (ps->n_queued * 1000 >= ps->token_bucket.burst) {
> drop_packet(ps);
> }
> q = pinqueue_get(ps, port_no);
> @@ -235,7 +223,6 @@ pinsched_run(struct pinsched *ps, pinsched_tx_cb *cb,
> void *aux)
>
> /* Drain some packets out of the bucket if possible, but limit the
> * number of iterations to allow other code to get work done too. */
> - refill_bucket(ps);
> for (i = 0; ps->n_queued && get_token(ps) && i < 50; i++) {
> cb(get_tx_packet(ps), aux);
> }
> @@ -246,14 +233,7 @@ void
> pinsched_wait(struct pinsched *ps)
> {
> if (ps && ps->n_queued) {
> - if (ps->tokens >= 1000) {
> - /* We can transmit more packets as soon as we're called again. */
> - poll_immediate_wake();
> - } else {
> - /* We have to wait for the bucket to re-fill. We could calculate
> - * the exact amount of time here for increased smoothness. */
> - poll_timer_wait(TIME_UPDATE_INTERVAL / 2);
> - }
> + token_bucket_wait(&ps->token_bucket, 1000);
> }
> }
>
> @@ -264,16 +244,18 @@ pinsched_create(int rate_limit, int burst_limit)
> struct pinsched *ps;
>
> ps = xzalloc(sizeof *ps);
> +
> + adjust_limits(&rate_limit, &burst_limit);
> + token_bucket_init(&ps->token_bucket,
> + rate_limit, sat_mul(burst_limit, 1000));
> +
> hmap_init(&ps->queues);
> ps->n_queued = 0;
> ps->next_txq = NULL;
> - ps->last_fill = time_msec();
> - ps->tokens = rate_limit * 1000;
> ps->n_txq = 0;
> ps->n_normal = 0;
> ps->n_limited = 0;
> ps->n_queue_dropped = 0;
> - pinsched_set_limits(ps, rate_limit, burst_limit);
>
> return ps;
> }
> @@ -298,24 +280,16 @@ void
> pinsched_get_limits(const struct pinsched *ps,
> int *rate_limit, int *burst_limit)
> {
> - *rate_limit = ps->rate_limit;
> - *burst_limit = ps->burst_limit;
> + *rate_limit = ps->token_bucket.rate;
> + *burst_limit = ps->token_bucket.burst / 1000;
> }
>
> void
> pinsched_set_limits(struct pinsched *ps, int rate_limit, int burst_limit)
> {
> - if (rate_limit <= 0) {
> - rate_limit = 1000;
> - }
> - if (burst_limit <= 0) {
> - burst_limit = rate_limit / 4;
> - }
> - burst_limit = MAX(burst_limit, 1);
> - burst_limit = MIN(burst_limit, INT_MAX / 1000);
> -
> - ps->rate_limit = rate_limit;
> - ps->burst_limit = burst_limit;
> + adjust_limits(&rate_limit, &burst_limit);
> + token_bucket_set(&ps->token_bucket,
> + rate_limit, sat_mul(burst_limit, 1000));
> while (ps->n_queued > burst_limit) {
> drop_packet(ps);
> }
> --
> 1.7.2.5
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev