Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F120801746
mfleakybucket-standalone.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
Mon, Jul 7, 04:51
Size
11 KB
Mime Type
text/x-c
Expires
Wed, Jul 9, 04:51 (2 d)
Engine
blob
Format
Raw Data
Handle
27242824
Attached To
R1252 EMPoWER
mfleakybucket-standalone.cc
View Options
#include "mfleakybucket-standalone.hh"
CLICK_DECLS
MFLeakyBucketSA::MFLeakyBucketSA(): _timer(this), _active_timer(this) {}
MFLeakyBucketSA::~MFLeakyBucketSA() {}
int
MFLeakyBucketSA::configure(Vector<String> &conf, ErrorHandler * errh) {
click_chatter("[MFLeakyBucketSA] entering configure...");
_debug = false;
_verb_debug = false;
_default_flow_info.sent = 0;
_default_flow_info.rate = 1000000; //1 MBps
_bool_limit_rate = true;
_period_print = 0; // period in second for printing info
_max_count_packets = 1; //number of packets to send before rechecking rate is OK
_count_print = 0;
_print_warning_cc = false;
if (Args(conf, this, errh)
.read("DEBUG", _debug)
.read("VERB_DEBUG", _verb_debug)
.read("RATE", _default_flow_info.rate)
.read("LIMIT_RATE", _bool_limit_rate)
.read("PERIOD_PRINT_INFO", _period_print)
.read("PRINT_INFO", _print_info)
.complete() < 0)
return -1;
/*if (cp_va_kparse(conf, this, errh,
"DEBUG"
"RATE", 0, cpUnsigned, &_default_rate,
"PERIOD", 0, cpUnsigned, &_period_msec,
cpIgnoreRest,
cpEnd) < 0)
return -1;*/
_default_flow_info._tb.assign(_default_flow_info.rate, _default_flow_info.rate/10);
click_chatter("[MFLeakyBucketSA]. Default rate: %u B/s.", _default_flow_info.rate);
return 0;
}
int
MFLeakyBucketSA::initialize(ErrorHandler *errh){
_timer.initialize(this); // Initialize timer object (mandatory).
_active_timer.initialize(this);
if(_period_print > 0 || _debug)
_timer.schedule_now(); // Set the timer to fire as soon as the router runs.
return 0;
}
void
MFLeakyBucketSA::set_cc_elmt(Cc *cc) {
_cc_elmt=cc;
click_chatter("[MFLB] Cc element %p set", _cc_elmt);
}
void
MFLeakyBucketSA::run_timer(Timer *timer) {
if (timer == &_active_timer) {
reset();
}
else if (timer == &_timer) {
if(_print_info || _debug) {
_now.assign_now();
if(_count_print > 0) {
uint32_t rate = 0;
if((_now-_last_print).msecval() > 0)
rate = int_divide(1000*_count_print, (_now-_last_print).msecval());
if (rate > 0) {
uint32_t total_rate = 0;
for(HashTable<FormatedRoute, FlowInfoLB>::iterator it=_route2info.begin(); it; ++it){
FlowInfoLB *info = _route2info.get_pointer(it.key());
total_rate += info->rate;
}
_now.assign_now();
click_chatter("[MFLeakyBucketSA (%s) %s] Rate sent since last print %d B/s "
"(received %lld B, killed %lld, current rate %d B/s for %d flows, may have changed meanwhile)", name().c_str(),
_now.unparse().c_str(), rate, (long long) _received_bytes, (long long) _killed_bytes, total_rate, _route2info.size());
}
}
_last_print = _now;
_count_print = 0;
_received_bytes = 0;
_killed_bytes = 0;
_print_error.clear();
if(_period_print > 0)
_timer.reschedule_after_sec(_period_print);
}
// for(HashTable<FormatedRoute, FlowInfoLB>::iterator it=_route2info.begin(); it; ++it){
// FlowInfoLB *info = _route2info.get_pointer(it.key());
// info->sent = 0;
// if(_debug && _print_info > 0 && _time >= _print_info) {
// _time = 0;
// click_chatter("[MFLeakyBucketSA] For flow %s, rate is %d",
// it.key().unparse().c_str() ,info->rate);
// }
// }
}
}
void
MFLeakyBucketSA::push(const int port, Packet *p){
//assert(port == 0);
//Get IPFlowID of this packet
/*IPFlowID mfh_id = IPFlowID();
const uint8_t *route = p->data() + 15; //We assume the route is one byte after the beginning of our layer 2.5 header
uint32_t fake_ip1 = (route[0] << 24) + (route[1] << 16) + (route[2] << 8) + route[3]; //byte 0-3
uint32_t fake_ip2 = (route[4] << 24) + (route[5] << 16) + (route[6] << 8) + route[7]; //byte 4-7
uint16_t fake_port1 = (route[8] << 8) + route[9]; //byte 8-9
uint16_t fake_port2 = (route[10] << 8) + route[11]; //byte 10-11
mfh_id.assign(fake_ip1, fake_port1, fake_ip2, fake_port2);*/
empower_header *hdr = (empower_header *)(p->data() + sizeof(click_ether)); //we have a MAC header here
const click_ip* ip4_header = (click_ip *) (p->data() + sizeof(click_ether) + sizeof(empower_header));
if(ip4_header==0) {
click_chatter("[MFLB] WARNING: no IP header, killing packet");
p->kill();
return;
}
const IPAddress ip_dst(ip4_header->ip_dst.s_addr);
p->set_ip_header(ip4_header, sizeof(click_ip));
_now.assign_now();
if(!is_in_hash_table(_seqNumTable,ip_dst))
_seqNumTable.set(ip_dst,0);
if(_count >= _max_count_packets || _info == 0) {
_count = 0;
FlowInfoLB *info = _route2info.get_pointer(hdr->_route);
if(info == 0){
uint32_t new_rate = _cc_elmt->get_rate(hdr->_route)*128; // Cc rate in kb/s, MFLB in B/s
if(new_rate==0) new_rate = _default_flow_info.rate;
if(_debug) click_chatter("[MFLB-SA] unknown route, setting Cc rate %u.", new_rate);
_route2info.set(hdr->_route, _default_flow_info);
info = _route2info.get_pointer(hdr->_route);
info->_tb.set(1500);
info->reinitialize(_now);
info->rate = new_rate;
info->_tb.assign_adjust(new_rate,new_rate/10);
}
_info = info;
_active_timer.schedule_after_sec(30);
}
_count++;
//if(_debug) click_chatter("[MFLB-SA] before check. sent : %d, period_multiplier : %d, info-> rate : %d", info->sent, _period_multiplier, info->rate);
_info->_tb.refill();
uint32_t len = p->length();
_received_bytes+=len;
if(_info->_tb.remove_if(len) || !_bool_limit_rate || hdr->_type == TRAFFIC_FORCED) {
_info->sent += len;
_count_print += len;
uint16_t seq = 0;
if(!_cc_elmt && !_print_warning_cc) {
click_chatter("[MFLB] WARNING: no Cc element, all sequence numbers will be 0");
_print_warning_cc = true;
}
else {
if(hdr->_type == TRAFFIC_FORCED) { // if forced packet, seq is 0
seq = 0;
if(_verb_debug) click_chatter("[MFLB %s] Forwarding forced packet to %s",Timestamp::now().unparse().c_str(),
ip_dst.unparse().c_str());
}
else {
seq = _cc_elmt->getCurrentSeqNum(ip_dst);
if(_verb_debug) click_chatter("[MFLB %s] Forwarding packet %u to %s (size of TB is %d)",Timestamp::now().unparse().c_str(),
hdr->_seq, ip_dst.unparse().c_str(), _info->_tb.size());
}
}
hdr->_seq = seq;
output(0).push(p);
} else {
_killed_bytes+=p->length();
p->kill();
}
//if(_debug) click_chatter("[MFLB-SA] after check. sent : %d, period_multiplier : %d, info-> rate : %d", info->sent, _period_multiplier, info->rate);
}
int
MFLeakyBucketSA::set_rate(FormatedRoute route, uint32_t rate){
FlowInfoLB *info = _route2info.get_pointer(route);
if(info != 0){
if(_verb_debug) click_chatter("[MFLB-SA] Setting new rate for route %s to %d B/s", route.unparse().c_str(), rate);
_now.assign_now();
info->reinitialize(_now);
info->rate = rate;
info->_tb.assign_adjust(rate,rate/10);
return 1;
} else {
if(_verb_debug || (_debug && !is_in_hash_table(_print_error,route)))
click_chatter("[MFLeakyBucketSA %s %s] I was just asked to set rate for a flow I don't know (route %s)",
name().c_str(), Timestamp::now().unparse().c_str(), route.unparse().c_str());
_print_error.set(route,true);
return 0;
}
}
bool
MFLeakyBucketSA::remove_route(FormatedRoute froute) {
FlowInfoLB *info = _route2info.get_pointer(froute);
if(info==0)
return false;
else {
if(_debug) click_chatter("[MFLB-SA] Removing route %s.", froute.unparse().c_str());
_route2info.erase(froute);
return true;
}
}
uint32_t
MFLeakyBucketSA::get_rate(FormatedRoute route){
FlowInfoLB *info = _route2info.get_pointer(route);
if(info != 0) return info->rate;
if(_debug) click_chatter("[MFLeakyBucketSA] I was just asked for the rate of a flow I don't know");
return 0;
}
void
MFLeakyBucketSA::reset() {
if(_debug) click_chatter("[MFLB-SA] Resetting element...");
_route2info.clear();
_info = 0;
_print_error.clear();
}
String MFLeakyBucketSA::print_info() {
StringAccum s;
for(HashTable<FormatedRoute, FlowInfoLB>::iterator it=_route2info.begin(); it; ++it){
FlowInfoLB *info = _route2info.get_pointer(it.key());
s << "[MFLeakyBucketSA] For flow " << it.key().unparse() << ", rate is " << info->rate << "\n";
}
return s.take_string();
}
static String
print_handler(Element *e, void *param) {
MFLeakyBucketSA *nei = (MFLeakyBucketSA *)e;
return nei->print_info();
}
int
MFLeakyBucketSA::debug_handler(const String &s, Element *e, void *,
ErrorHandler *errh) {
MFLeakyBucketSA *elmt = (MFLeakyBucketSA *)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;
}
int
MFLeakyBucketSA::limit_rate_handler(const String &s, Element *e, void *,
ErrorHandler *errh) {
MFLeakyBucketSA *elmt = (MFLeakyBucketSA *)e;
int arg;
if(!cp_integer(s, &arg))
return errh->error("Limit_rate must be 0 or 1");
if (!(arg == 0 || arg == 1))
return errh->error("Limit_rate must be 0 or 1");
elmt->set_limit_rate(arg==1);
return 0;
}
int
MFLeakyBucketSA::period_print_handler(const String &s, Element *e, void *,
ErrorHandler *errh) {
MFLeakyBucketSA *elmt = (MFLeakyBucketSA *)e;
int arg;
if(!cp_integer(s, &arg))
return errh->error("period_print must be an integer (period in seconds)");
elmt->set_period_print(arg);
return 0;
}
int
MFLeakyBucketSA::set_max_count_packets_handler(const String &s, Element *e, void *,
ErrorHandler *errh) {
MFLeakyBucketSA *elmt = (MFLeakyBucketSA *)e;
int arg;
if(!cp_integer(s, &arg))
return errh->error("Max_count_packets must be an integer");
elmt->set_max_count_packets(arg);
return 0;
}
void MFLeakyBucketSA::add_handlers() {
add_read_handler("print_info", print_handler,0);
add_write_handler("debug", debug_handler, 0);
add_write_handler("period_print", period_print_handler, 0);
add_write_handler("limit_rate", limit_rate_handler, 0);
add_write_handler("set_max_count_packets", set_max_count_packets_handler, 0);
}
CLICK_ENDDECLS
EXPORT_ELEMENT(MFLeakyBucketSA)
Event Timeline
Log In to Comment