Page MenuHomec4science

acnesource.cc
No OneTemporary

File Metadata

Created
Sat, Jul 5, 07:38

acnesource.cc

#include <click/config.h>
#include "acnesource.hh"
#define DEBUG_CHATTER(arg, ...) do { if (_debug) { click_chatter(arg, ## __VA_ARGS__);} } while (0)
#define VERB_DEBUG_CHATTER(arg, ...) do { if (_verb_debug) { click_chatter(arg, ## __VA_ARGS__);} } while (0)
CLICK_DECLS
AcneSource::AcneSource() : _task(this), _timer(&_task)
{
}
AcneSource::~AcneSource()
{
}
int
AcneSource::configure(Vector<String> &conf, ErrorHandler *errh) {
_length = 1420;
_min_sending_rate = 0; // in B/s
_rate = 0; // in B/s
_active = true;
_debug = false;
_packet_per_burst = 1;
_max_sending_rate = 10500000; // because of CPU, cannot send more anyway
if(Args(this, errh).bind(conf)
.read("LENGTH", _length)
.read("RATE", _rate)
.read("ACTIVE", _active)
.read("DEBUG", _debug)
.read("SEND_MIN", _min_sending_rate)
.read("MAX_SENDING_RATE", _max_sending_rate)
.read("BURST", _packet_per_burst)
.complete() < 0)
return -1;
_rate = mymax(_rate, _min_sending_rate);
uint32_t nb_pack_per_sec = int_divide(_rate,_length);
if(nb_pack_per_sec > 0)
_ms_freq = int_divide(1000,nb_pack_per_sec);
else
_ms_freq = 0;
int burst = nb_pack_per_sec < 20 ? 2 : int_divide(nb_pack_per_sec,10);
if (burst < 2 * _length)
burst = 2 * _length;
_tb.assign(nb_pack_per_sec, burst*_packet_per_burst);
_packet = Packet::make(100, (void *) ("This is an Acne packet. "), _length, 10);
if(_packet == 0)
return errh->error("[AcneSource] Error when creating the packet");
return 0;
}
int
AcneSource::initialize(ErrorHandler *errh)
{
_count = 0;
ScheduleInfo::initialize_task(this, &_task, errh);
_tb.set(1);
_timer.initialize(this);
return 0;
}
bool
AcneSource::run_task(Task *t) {
assert(t == &_task);
if (!_active)
return false;
if(_debug) {
_now.assign_now();
if(_last_task != Timestamp())
_time_between_tasks.push_back(_now-_last_task);
_last_task = _now;
if((_now-_last_print).sec() >= 5)
print_debug(_rate);
}
_tb.refill();
for(int i=0;i<_packet_per_burst;i++) {
if (_tb.remove_if(1)) {
Packet *p = _packet->clone();
p->set_timestamp_anno(Timestamp::now());
_bytes_sent+=p->length();
output(0).push(p);
_count++;
}
else if(i==0) {
_timer_schedule++;
_timer.schedule_after(Timestamp::make_jiffies(_tb.time_until_contains(1)));
return false;
}
else
break;
}
_task.fast_reschedule();
return true;
}
void
AcneSource::set_rate(uint32_t rate) {
_task.unschedule();
uint32_t old_rate = _rate;
_rate = mymax(rate, _min_sending_rate);
_rate = mymin(_rate, _max_sending_rate);
uint32_t nb_pack_per_sec = int_divide(_rate,_length);
if(nb_pack_per_sec > 0)
_ms_freq = int_divide(1000,nb_pack_per_sec);
else
_ms_freq = 0;
//_tb.clear();
//_tb.assign(nb_pack_per_sec, 2000);
_tb.assign_adjust(nb_pack_per_sec, nb_pack_per_sec < 20 ? 2*_packet_per_burst : int_divide(nb_pack_per_sec*_packet_per_burst,10));
if(_active) {
if(_rate > 0)
_task.reschedule();
if(_debug)
print_debug(old_rate);
}
}
bool
AcneSource::set_length(uint32_t length) {
WritablePacket *packet = Packet::make(100, (void *) ("This is an Acne packet. "), length, 10);
if(packet == 0)
return false;
_length=length;
_packet = packet;
set_rate(_rate);
return true;
}
void
AcneSource::print_debug(uint32_t old_rate) {
_now.assign_now();
DEBUG_CHATTER("[AcneSource %s] Entering print_debug...", _now.unparse().c_str());
uint32_t diff_msec = (_now - _last_set).msecval();
uint64_t sent_rate = 0;
if(diff_msec > 0)
sent_rate = int_divide(_bytes_sent*1000,diff_msec);
if(_time_between_tasks.size() > 0) {
Timestamp max_ts;
Timestamp total;
for(int i=0;i<_time_between_tasks.size();i++) {
if(_time_between_tasks[i] > max_ts)
max_ts = _time_between_tasks[i];
total+=_time_between_tasks[i];
}
click_chatter("[AcneSource:%d %s] Now sending at rate %d, have sent at %d for %d (%d bytes, %s ms)."
"Average time between tasks %d ms (%d calls, %d timer, %d packets), max %d ms", _task.home_thread_id(),
_now.unparse().c_str(), _rate, (int) sent_rate, (int) old_rate, (int) _bytes_sent, String(diff_msec).c_str(),
int_divide(total.msecval(),_time_between_tasks.size()), _time_between_tasks.size(), _timer_schedule,
(int) _count, max_ts.msecval());
}
Vector<Task *> scheduled_tasks_vec;
_task.thread()->scheduled_tasks(router(), scheduled_tasks_vec);
for(int i=0;i<scheduled_tasks_vec.size();i++)
click_chatter("Task from element %s, scheduled %d", scheduled_tasks_vec[i]->element()->name().c_str(), scheduled_tasks_vec[i]->scheduled());
reinitialize_counters();
_last_print = _now;
}
int
AcneSource::reset_handler(const String &, Element *e, void *, ErrorHandler *) {
AcneSource *elmt = (AcneSource *)e;
elmt->reset_count();
return 0;
}
int
AcneSource::length_handler(const String &s, Element *e, void *, ErrorHandler *errh) {
AcneSource *elmt = (AcneSource *)e;
uint32_t arg;
if(!cp_integer(s, &arg))
return errh->error("Length must be an integer");
if(!elmt->set_length(arg))
return errh->error("Error when creating the packet");;
return 0;
}
int
AcneSource::active_handler(const String &s, Element *e, void *, ErrorHandler *errh) {
AcneSource *elmt = (AcneSource *)e;
int arg;
if(!cp_integer(s, &arg))
return errh->error("Active must be 0 or 1");
if (!(arg == 0 || arg == 1))
return errh->error("Active must be 0 or 1");
elmt->set_active(arg==1);
return 0;
}
int
AcneSource::set_rate_handler(const String &s, Element *e, void *a, ErrorHandler *errh) {
AcneSource *elmt = (AcneSource *)e;
uint32_t arg;
if(!cp_integer(s, &arg))
return errh->error("Rate must be an integer (rate in B/s)");
if(((intptr_t) a) == 0)
elmt->set_rate(arg);
else if(((intptr_t) a) == 1)
elmt->set_max_rate(arg);
else if(((intptr_t) a) == 2)
elmt->set_min_rate(arg);
return 0;
}
int
AcneSource::set_ppb_handler(const String &s, Element *e, void *, ErrorHandler *errh) {
AcneSource *elmt = (AcneSource *)e;
uint32_t arg;
if(!cp_integer(s, &arg))
return errh->error("NUmber of packets per burst must be an integer (rate in B/s)");
elmt->set_ppb(arg);
return 0;
}
void
AcneSource::set_active(bool b) {
if(b && !_task.scheduled()) {
_tb.set(1);
_task.reschedule();
}
if(_active && !b) {
if(_debug)
print_debug(_rate);
DEBUG_CHATTER("[AcneSource] Now inactive");
}
else if(b && !_active) {
if(_debug)
reinitialize_counters();
DEBUG_CHATTER("[AcneSource] Now active");
}
_active = b;
}
void
AcneSource::set_debug(bool b) {
if(!_debug && b)
reinitialize_counters();
_debug = b;
}
void
AcneSource::reinitialize_counters() {
_time_between_tasks.clear();
_timer_schedule = 0;
_count = 0;
_bytes_sent = 0;
_last_set.assign_now();
}
int
AcneSource::debug_handler(const String &s, Element *e, void *,
ErrorHandler *errh) {
AcneSource *elmt = (AcneSource *)e;
int debug;
if(!cp_integer(s, &debug))
return errh->error("Debug must be 0 or 1");
if (!(debug == 0 || debug == 1))
return errh->error("Debug must be 0 or 1");
elmt->set_debug(debug==1);
return 0;
}
static String
count_handler(Element *e, void *) {
AcneSource *elmt = (AcneSource *)e;
return String(elmt->get_count());
}
static String
rate_handler(Element *e, void *) {
AcneSource *elmt = (AcneSource *)e;
return String(elmt->get_rate());
}
static String
active_read_handler(Element *e, void *) {
AcneSource *elmt = (AcneSource *)e;
return String(elmt->get_active());
}
void AcneSource::add_handlers() {
add_read_handler("count", count_handler,0);
add_read_handler("rate", rate_handler,0);
add_read_handler("active", active_read_handler,0);
add_write_handler("reset", reset_handler, 0);
add_write_handler("length", length_handler, 0);
add_write_handler("active", active_handler, 0);
add_write_handler("debug", debug_handler, 0);
add_write_handler("set_rate", set_rate_handler, 0);
add_write_handler("set_max_rate", set_rate_handler, 1);
add_write_handler("set_min_rate", set_rate_handler, 2);
add_write_handler("set_packet_per_burst", set_ppb_handler, 0);
}
EXPORT_ELEMENT(AcneSource)
CLICK_ENDDECLS

Event Timeline