Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F120570397
acnesource.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Jul 5, 07:38
Size
8 KB
Mime Type
text/x-c
Expires
Mon, Jul 7, 07:38 (2 d)
Engine
blob
Format
Raw Data
Handle
27193213
Attached To
R6591 HyMAB
acnesource.cc
View Options
#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
Log In to Comment