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
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to