/* * bandwidthmeter.{cc,hh} -- element sends packets out one of several outputs * depending on recent rate (bytes/s) * Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */ #include #include "bandwidthmeter.hh" #include #include CLICK_DECLS BandwidthMeter::BandwidthMeter() : _meters(0), _nmeters(0) { } BandwidthMeter::~BandwidthMeter() { delete[] _meters; } int BandwidthMeter::configure(Vector &conf, ErrorHandler *errh) { delete[] _meters; _meters = 0; _nmeters = 0; if (conf.size() == 0) return errh->error("too few arguments to BandwidthMeter(bandwidth, ...)"); Vector vals(conf.size(), 0); for (int i = 0; i < conf.size(); i++) if (!cp_bandwidth(conf[i], &vals[i])) return errh->error("argument %d should be bandwidth (rate)", i+1); else if (i > 0 && vals[i] <= vals[i-1]) return errh->error("rate %d must be > rate %d", i+1, i); else if (cp_errno == CPE_NOUNITS) errh->warning("no units for bandwidth argument %d, assuming Bps", i+1); unsigned max_value = 0xFFFFFFFF >> _rate.scale; for (int i = 0; i < conf.size(); i++) { if (vals[i] > max_value) return errh->error("rate %d too large (max %u)", i+1, max_value); vals[i] = (vals[i]<<_rate.scale) / _rate.freq(); } if (vals.size() == 1) { _meter1 = vals[0]; _nmeters = 1; } else { _meters = new unsigned[vals.size()]; memcpy(_meters, &vals[0], vals.size() * sizeof(int)); _nmeters = vals.size(); } if (_nmeters + 1 != noutputs()) return errh->error("need %d arguments, one less than the number of output ports", noutputs() - 1); return 0; } int BandwidthMeter::initialize(ErrorHandler *) { _rate.initialize(); return 0; } void BandwidthMeter::push(int, Packet *p) { _rate.update(p->length()); unsigned r = _rate.average(); if (_nmeters < 2) { int n = (r >= _meter1); output(n).push(p); } else { unsigned *meters = _meters; int nmeters = _nmeters; for (int i = 0; i < nmeters; i++) if (r < meters[i]) { output(i).push(p); return; } output(nmeters).push(p); } } String BandwidthMeter::meters_read_handler(Element *f, void *) { BandwidthMeter *m = (BandwidthMeter *)f; if (m->_nmeters == 1) return cp_unparse_real2(m->_meter1*m->rate_freq(), m->rate_scale()); else { String s; for (int i = 0; i < m->_nmeters; i++) s = s + cp_unparse_real2(m->_meters[i]*m->rate_freq(), m->rate_scale()); return s; } } static String read_rate_handler(Element *f, void *) { BandwidthMeter *c = (BandwidthMeter *)f; return cp_unparse_real2(c->rate()*c->rate_freq(), c->rate_scale()); } void BandwidthMeter::add_handlers() { add_read_handler("rate", read_rate_handler, 0); add_read_handler("meters", BandwidthMeter::meters_read_handler, 0); } CLICK_ENDDECLS EXPORT_ELEMENT(BandwidthMeter)