Skip to content

Commit

Permalink
TokenBucket: use 64bit if supported
Browse files Browse the repository at this point in the history
Allows all elements such as ratedsource, ratedsplitter, ratedunqueue,
and bandwidthratedunqueue to use > 4G rate.

tokenbucket64 could have lass copy pasting, but I don't have time.
  • Loading branch information
tbarbette committed May 7, 2020
1 parent b482e34 commit 6989217
Show file tree
Hide file tree
Showing 8 changed files with 1,130 additions and 40 deletions.
6 changes: 3 additions & 3 deletions elements/standard/ratedsource.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ RatedSource::configure(Vector<String> &conf, ErrorHandler *errh)
String data =
"Random bullshit in a packet, at least 64 bytes long. Well, now it is.";
unsigned rate = 10;
unsigned bandwidth = 0;
ucounter_t bandwidth = 0;
int limit = -1;
int datasize = -1;
bool active = true, stop = false;
Expand All @@ -62,11 +62,11 @@ RatedSource::configure(Vector<String> &conf, ErrorHandler *errh)
.read_p("RATE", rate)
.read_p("LIMIT", limit)
.read_p("ACTIVE", active)
.read("HEADROOM", _headroom)
.read("HEADROOM", _headroom)
.read("LENGTH", datasize)
.read("DATASIZE", datasize) // deprecated
.read("STOP", stop)
.read("BANDWIDTH", BandwidthArg(), bandwidth)
.read("BANDWIDTH", bandwidth_arg_t(), bandwidth)
.read("END_CALL", HandlerCallArg(HandlerCall::writable), end_h)
.complete() < 0)
return -1;
Expand Down
33 changes: 24 additions & 9 deletions elements/standard/ratedsource.hh
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
#ifndef CLICK_RATEDSOURCE_HH
#define CLICK_RATEDSOURCE_HH
#include <click/batchelement.hh>
#include <click/tokenbucket.hh>
#if HAVE_INT64_TYPES
# include <click/tokenbucket64.hh>
#else
# include <click/tokenbucket.hh>
#endif
#include <click/task.hh>
#include <click/notifier.hh>
CLICK_DECLS
class HandlerCall;


#if HAVE_INT64_TYPES
class Bandwidth64Arg;
#else
class BandwidthArg;
#endif

/*
=c
Expand Down Expand Up @@ -120,15 +131,19 @@ class RatedSource : public BatchElement, public ActiveNotifier {
static const unsigned NO_LIMIT = 0xFFFFFFFFU;
static const unsigned DEF_BATCH_SIZE = 32;

#if HAVE_INT64_TYPES
typedef uint64_t ucounter_t;
typedef int64_t counter_t;
#else
typedef uint32_t ucounter_t;
typedef int32_t counter_t;
#endif
#if HAVE_INT64_TYPES
typedef uint64_t ucounter_t;
typedef int64_t counter_t;
typedef TokenBucket64 token_bucket_t;
typedef Bandwidth64Arg bandwidth_arg_t;
#else
typedef uint32_t ucounter_t;
typedef int32_t counter_t;
typedef TokenBucket token_bucket_t;
typedef BandwidthArg bandwidth_arg_t;
#endif

TokenBucket _tb;
token_bucket_t _tb;
ucounter_t _count;
ucounter_t _limit;
#if HAVE_BATCH
Expand Down
6 changes: 5 additions & 1 deletion elements/standard/ratedsplitter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#define CLICK_RATEDSPLITTER_HH
#include <click/element.hh>
#include <click/batchelement.hh>
#include <click/tokenbucket.hh>
#include <click/tokenbucket64.hh>
CLICK_DECLS

/*
Expand Down Expand Up @@ -84,7 +84,11 @@ class RatedSplitter : public BatchElement { public:

protected:

#if HAVE_INT64_TYPES
TokenBucket64 _tb;
#else
TokenBucket _tb;
#endif

static String read_handler(Element *, void *) CLICK_COLD;

Expand Down
21 changes: 13 additions & 8 deletions elements/standard/ratedunqueue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,17 @@ RatedUnqueue::configure(Vector<String> &conf, ErrorHandler *errh)
}

int
RatedUnqueue::configure_helper(TokenBucket *tb, bool is_bandwidth, Element *elt, Vector<String> &conf, ErrorHandler *errh)
RatedUnqueue::configure_helper(token_bucket_t *tb, bool is_bandwidth, Element *elt, Vector<String> &conf, ErrorHandler *errh)
{
unsigned r;
ucounter_t r;
unsigned dur_msec = 20;
unsigned tokens;
ucounter_t tokens;
bool dur_specified, tokens_specified;
const char *burst_size = is_bandwidth ? "BURST_BYTES" : "BURST_SIZE";

Args args(conf, elt, errh);
if (is_bandwidth)
args.read_mp("RATE", BandwidthArg(), r);
args.read_mp("RATE", bandwidth_arg_t(), r);
else
args.read_mp("RATE", r);
if (args.read("BURST_DURATION", SecondsArg(3), dur_msec).read_status(dur_specified)
Expand All @@ -65,17 +65,22 @@ RatedUnqueue::configure_helper(TokenBucket *tb, bool is_bandwidth, Element *elt,
return -1;

if (dur_specified && tokens_specified)
return errh->error("cannot specify both BURST_DURATION and BURST_SIZE");
return errh->error("cannot specify both BURST_DURATION and BURST_SIZE");
else if (!tokens_specified) {
#if !HAVE_INT64_TYPES
bigint::limb_type res[2];
bigint::multiply(res[1], res[0], r, dur_msec);
bigint::divide(res, res, 2, 1000);
tokens = res[1] ? UINT_MAX : res[0];
#else
ucounter_t l = r * (ucounter_t)dur_msec;
tokens = l / 1000;
#endif
}

if (is_bandwidth) {
unsigned new_tokens = tokens + tb_bandwidth_thresh;
tokens = (tokens < new_tokens ? new_tokens : UINT_MAX);
ucounter_t new_tokens = tokens + tb_bandwidth_thresh;
tokens = (tokens < new_tokens ? new_tokens : UINT64_MAX);
}

tb->assign(r, tokens ? tokens : 1);
Expand All @@ -98,7 +103,7 @@ RatedUnqueue::run_task(Task *)
_runs++;

if (!_active)
return false;
return false;

_tb.refill();
if (_tb.contains(1)) {
Expand Down
41 changes: 32 additions & 9 deletions elements/standard/ratedunqueue.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@
#ifndef CLICK_RATEDUNQUEUE_HH
#define CLICK_RATEDUNQUEUE_HH
#include <click/batchelement.hh>
#include <click/tokenbucket.hh>
#if HAVE_INT64_TYPES
# include <click/tokenbucket64.hh>
#else
# include <click/tokenbucket.hh>
#endif
#include <click/task.hh>
#include <click/timer.hh>
#include <click/notifier.hh>
CLICK_DECLS

#if HAVE_INT64_TYPES
class Bandwidth64Arg;
#else
class BandwidthArg;
#endif

/*
* =c
* RatedUnqueue(RATE, I[<KEYWORDS>])
Expand Down Expand Up @@ -51,8 +61,20 @@ class RatedUnqueue : public BatchElement { public:
const char *processing() const { return PULL_TO_PUSH; }
bool is_bandwidth() const { return class_name()[0] == 'B'; }

#if HAVE_INT64_TYPES
typedef uint64_t ucounter_t;
typedef int64_t counter_t;
typedef TokenBucket64 token_bucket_t;
typedef Bandwidth64Arg bandwidth_arg_t;
#else
typedef uint32_t ucounter_t;
typedef int32_t counter_t;
typedef TokenBucket token_bucket_t;
typedef BandwidthArg bandwidth_arg_t;
#endif

int configure(Vector<String> &, ErrorHandler *) CLICK_COLD;
static int configure_helper(TokenBucket *tb, bool is_bandwidth, Element *elt, Vector<String> &conf, ErrorHandler *errh);
static int configure_helper(token_bucket_t *tb, bool is_bandwidth, Element *elt, Vector<String> &conf, ErrorHandler *errh);
enum { tb_bandwidth_thresh = 131072 };

bool can_live_reconfigure() const { return true; }
Expand All @@ -63,16 +85,17 @@ class RatedUnqueue : public BatchElement { public:

protected:

TokenBucket _tb;
token_bucket_t _tb;
Task _task;
Timer _timer;
NotifierSignal _signal;
uint32_t _runs;
uint32_t _packets;
uint32_t _pushes;
uint32_t _failed_pulls;
uint32_t _empty_runs;
uint32_t _burst;
ucounter_t _runs;
ucounter_t _packets;
ucounter_t _pushes;
ucounter_t _failed_pulls;
ucounter_t _empty_runs;

unsigned _burst;

enum { h_calls, h_rate };

Expand Down
11 changes: 11 additions & 0 deletions include/click/args.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,17 @@ class BandwidthArg : public NumArg { public:
int status;
};

/** @class Bandwidth64Arg
@brief Parser class for 64bit bandwidth specifications.
Handles suffixes such as "Gbps", "k", etc. */
class Bandwidth64Arg : public NumArg { public:
bool parse(const String &str, uint64_t &result, const ArgContext & = blank_args);
static String unparse(uint64_t x);
int status;
};



/** @class BitvectorArg **/
class BitvectorArg { public:
Expand Down
Loading

0 comments on commit 6989217

Please sign in to comment.