Page MenuHomec4science

dstmab.cc
No OneTemporary

File Metadata

Created
Mon, Jul 7, 07:37

dstmab.cc

#include <click/config.h>
#include "util.hh"
#include "dstmab.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
DstMab::DstMab() : _timer(this), _ack_timer(this)
{
}
DstMab::~DstMab()
{
}
int DstMab::configure(Vector<String> &conf, ErrorHandler *errh){
String rtl_name;
_debug = false;
_verb_debug = false;
_timeout_bool = true;
_ack_waiting_time_msec = 500; //msec
if(Args(this, errh).bind(conf)
.read_m("IP_ADDR", _ip_address)
.read_m("ROUTING_LINKS", rtl_name)
.read("WIFI_ADDR", _addr_wifi)
.read("PLC_ADDR", _addr_plc)
.read("DEBUG", _debug)
.read("VERB_DEBUG", _verb_debug)
.read("TIMEOUT", _timeout_bool) // if clear things after 10 sec inactive
.read("ACK_WAITING_TIME_MSEC", _ack_waiting_time_msec)
.complete() < 0)
return -1;
_routing_links = (RoutingLinks*)router()->find(rtl_name, "", errh);
if(_routing_links == 0) {
return errh->error("No RoutingLinks element %s.", rtl_name.c_str());
}
if(_routing_links->cast("RoutingLinks") == 0)
return errh->error("%s is not a RoutingLinks.", rtl_name.c_str());
EtherAddress empty_addr = EtherAddress();
if(_addr_wifi == empty_addr && _addr_plc == empty_addr){
click_chatter("[DstMab]: !!! ERROR: Have 0 interface, should have at least 1 !!!\n");
return 1;
}
//Store last bytes of both addresses for quick dst checks!
if(_addr_wifi != empty_addr){
_lb_wifi = LastAddrBytes(_addr_wifi);
_lb_wifi.set_hash();
}
if(_addr_plc != empty_addr){
_lb_plc = LastAddrBytes(_addr_plc);
_lb_plc.set_hash();
}
_timer.initialize(this);
_ack_timer.initialize(this);
return 0;
}
int
DstMab::initialize(ErrorHandler *errh) {
_timer.schedule_after_sec(5); // timer to clear things
return 0;
}
void
DstMab::push(int, Packet *p_in) {
_last_active.assign_now();
if(!_timer.scheduled())
_timer.schedule_after_sec(10);
acne_header *acne_hdr = (acne_header *) p_in->data();
/*
LastAddrBytes lb_hop;
for(uint8_t i=0; i<NB_BYTES_HOP; i++){
lb_hop._lastbytes[i] = acne_hdr->_route._route[(acne_hdr->_hop-1)*NB_BYTES_HOP+i];
}
if(lb_hop != _lb_wifi && lb_hop != _lb_plc) {
DEBUG_CHATTER("[DstMab %s] Got a packet that is not for me (route %s, hop %d)", _last_active.unparse().c_str(),
acne_hdr->_route.unparse().c_str(), (int) (acne_hdr->_hop-1));
p_in->kill();
return;
}
*/
if(acne_hdr->_type == REGULAR_TRAFFIC || acne_hdr->_type == DUMMY_TRAFFIC_MAB || acne_hdr->_type == PROTO_IP_TEST ||
acne_hdr->_type == MAB_CONTROL || acne_hdr->_type == SPECIAL_TRAFFIC || acne_hdr->_type == NACK_RETRANSMISSION) {
VERB_DEBUG_CHATTER("[DstMab %s] Received packet of type %d for route %s", _last_active.unparse().c_str(), acne_hdr->_type, acne_hdr->_route.unparse().c_str());
unsigned char *dst = acne_hdr->_route._dst;
if(acne_hdr->_type == MAB_CONTROL) {
mab_control *mab_ctrl = (mab_control *) (p_in->data() + sizeof(acne_header));
if(mab_ctrl->_type != TRIGGER_CLEAR) {
if(acne_hdr->_id_rate_mab!=0 && acne_hdr->_id_rate_mab!=_current_id)
_current_id = acne_hdr->_id_rate_mab;
// save begin/end timestamps
_now.assign_now();
if(mab_ctrl->_type == MAB_CTRL_BEGIN) { // begin, set _ts to _route_to_diff_ts
DEBUG_CHATTER("[DstMab %s] Received BEGIN control packets for id %d, route %s (timestamp %s)...",
_now.unparse().c_str(), acne_hdr->_id_rate_mab, acne_hdr->_route.unparse().c_str(), mab_ctrl->_ts.unparse().c_str());
_exploring = true;
_exploit_traffic_during_explore = 0;
if(acne_hdr->_id_rate_mab > 0) {
if (_control_message_received[acne_hdr->_id_rate_mab].get(acne_hdr->_route) > 0) {
p_in->kill();
return;
}
}
_control_message_received[acne_hdr->_id_rate_mab][acne_hdr->_route] = 1;
_route_to_diff_ts[acne_hdr->_route].set(acne_hdr->_id_rate_mab, mab_ctrl->_ts);
_route_to_rate[acne_hdr->_route][acne_hdr->_id_rate_mab] = 0;
}
else if (mab_ctrl->_type == MAB_CTRL_END) { // end, set diff between begin and end to _route_to_diff_ts
DEBUG_CHATTER("[DstMab %s] Received END control packets for id %d, route %s (timestamp %s)...",
_now.unparse().c_str(), acne_hdr->_id_rate_mab, acne_hdr->_route.unparse().c_str(), mab_ctrl->_ts.unparse().c_str());
_exploring = false;
if(_exploit_traffic_during_explore > 0)
DEBUG_CHATTER("[DstMab %s] WARNING: have received %u B of exploit traffic during explore of id %u", _now.unparse().c_str(),
_exploit_traffic_during_explore, acne_hdr->_id_rate_mab);
if(acne_hdr->_id_rate_mab > 0) {
if (_control_message_received[acne_hdr->_id_rate_mab].get(acne_hdr->_route) > 1) {
p_in->kill();
return;
}
}
_control_message_received[acne_hdr->_id_rate_mab][acne_hdr->_route] = 2;
if(_route_to_diff_ts[acne_hdr->_route].get(acne_hdr->_id_rate_mab) > Timestamp()) {
Timestamp diff_ts = (mab_ctrl->_ts - _route_to_diff_ts[acne_hdr->_route][acne_hdr->_id_rate_mab]);
_route_to_diff_ts[acne_hdr->_route].set(acne_hdr->_id_rate_mab, diff_ts);
_is_diff_ts_ok[acne_hdr->_route].set(acne_hdr->_id_rate_mab, 1);
}
else
click_chatter("[DstMab] WARNING: diff timestamp has not been set for route %s, id %d", acne_hdr->_route.unparse().c_str(), acne_hdr->_id_rate_mab);
}
else {
DEBUG_CHATTER("[DstMab %s] Received control packets of type %d for id %d, route %s (timestamp %s), received %d...",
_now.unparse().c_str(), mab_ctrl->_type, acne_hdr->_id_rate_mab, acne_hdr->_route.unparse().c_str(),
mab_ctrl->_ts.unparse().c_str(), _route_to_rate[acne_hdr->_route][acne_hdr->_id_rate_mab]);
if(acne_hdr->_id_rate_mab == 0)
_route_to_rate[acne_hdr->_route][acne_hdr->_id_rate_mab] = 0;
}
}
}
else if(_exploring && acne_hdr->_type == REGULAR_TRAFFIC && acne_hdr->_id_rate_mab == 0) {
_exploit_traffic_during_explore+=p_in->length();
}
LastAddrBytes lb_dst = LastAddrBytes(dst);
if(lb_dst == _lb_wifi || lb_dst == _lb_plc) {
if(acne_hdr->_type == MAB_CONTROL) {
mab_control *mab_ctrl = (mab_control *) (p_in->data() + sizeof(acne_header));
if(mab_ctrl->_type == TRIGGER_CLEAR) {
p_in->kill();
return;
}
else if(mab_ctrl->_type == FLOW_INFORMATION) {
// send ack with id 0 (only flow information is interesting)
send_ack(AckInfo(acne_hdr->_route, 0, mab_ctrl->_max_nb_flows, mab_ctrl->_flow_hash, mab_ctrl->_flow_src, mab_ctrl->_flow_dst, mab_ctrl->_ts));
}
if(acne_hdr->_id_rate_mab == 0) {
// empty slot, nothing to do
p_in->kill();
return;
}
if (mab_ctrl->_type == MAB_CTRL_END) {
// send ack
if(_is_diff_ts_ok[acne_hdr->_route].get(acne_hdr->_id_rate_mab)) {
DEBUG_CHATTER("[DstMab %s] Schedule ack for id %d for route %s to be sent in %d ms", _now.unparse().c_str(),
acne_hdr->_id_rate_mab, acne_hdr->_route.unparse().c_str(), _ack_waiting_time_msec);
// schedule ack to be sent after some time
_scheduled_acks.push_back(AckInfo(acne_hdr->_route, acne_hdr->_id_rate_mab, mab_ctrl->_max_nb_flows, mab_ctrl->_flow_hash, mab_ctrl->_flow_src, mab_ctrl->_flow_dst, mab_ctrl->_ts));
if(!_ack_timer.scheduled())
_ack_timer.schedule_after_msec(_ack_waiting_time_msec);
}
else
click_chatter("[DstMab %s] WARNING: Diff timestamp has not been computed correctly for id %d on route %s", _now.unparse().c_str(),
acne_hdr->_id_rate_mab, acne_hdr->_route.unparse().c_str());
}
for(int i=0;i<mab_ctrl->_nb_missing_acks;i++) {
// send missing acks
DEBUG_CHATTER("[DstMab %s] Send missing ack for id %d for route %s", _now.unparse().c_str(),
mab_ctrl->_missing_acks[i], acne_hdr->_route.unparse().c_str());
send_ack(AckInfo(acne_hdr->_route, mab_ctrl->_missing_acks[i], mab_ctrl->_max_nb_flows, mab_ctrl->_flow_hash, mab_ctrl->_flow_src, mab_ctrl->_flow_dst, mab_ctrl->_ts));
}
// send control messages to Order
if(mab_ctrl->_type == MAB_CTRL_BEGIN || mab_ctrl->_type == MAB_CTRL_END) {
output(1).push(p_in);
return;
}
else {
p_in->kill();
return;
}
}
else {
_route_to_rate[acne_hdr->_route][acne_hdr->_id_rate_mab]+=p_in->length();
if(acne_hdr->_id_rate_mab == 0) {
if(acne_hdr->_type == DUMMY_TRAFFIC_MAB)
p_in->kill();
else
output(1).push(p_in);
return;
}
// is for me: add to count
if (_control_message_received[acne_hdr->_id_rate_mab].get(acne_hdr->_route) > 1) {
_traffic_after[acne_hdr->_route][acne_hdr->_id_rate_mab]+=p_in->length();
}
}
if(acne_hdr->_type == DUMMY_TRAFFIC_MAB)
p_in->kill();
else
output(1).push(p_in);
}
else {
if(acne_hdr->_type == REGULAR_TRAFFIC || acne_hdr->_type == DUMMY_TRAFFIC_MAB) {
_route_to_rate[acne_hdr->_route][acne_hdr->_id_rate_mab]+=p_in->length();
output(0).push(p_in);
}
else if(acne_hdr->_type == SPECIAL_TRAFFIC || acne_hdr->_type == NACK_RETRANSMISSION || acne_hdr->_type == MAB_CONTROL)
output(3).push(p_in);
else
output(0).push(p_in);
}
}
else if(acne_hdr->_type == MAB_ACK) {
VERB_DEBUG_CHATTER("[DstMab %s] Transmitting ack on route %s", _last_active.unparse().c_str(), acne_hdr->_route.unparse().c_str());
output(3).push(p_in);
}
else if(acne_hdr->_type == NACK_ORDER) {
VERB_DEBUG_CHATTER("[DstMab %s] Transmitting nack on route %s", _last_active.unparse().c_str(), acne_hdr->_route.unparse().c_str());
output(3).push(p_in);
}
else {
click_chatter("[DstMab] WARNING: got unknown message, killing it");
p_in->kill();
}
}
void DstMab::clear() {
_route_to_rate.clear();
_traffic_after.clear();
_route_to_diff_ts.clear();
_is_diff_ts_ok.clear();
_control_message_received.clear();
}
void DstMab::run_timer(Timer *timer){
VERB_DEBUG_CHATTER("[DstMab %s] Run timer %p", Timestamp::now().unparse().c_str(), timer);
if(timer == &_timer) {
_now.assign_now();
if((_now-_last_active).sec() >= 3600) {
DEBUG_CHATTER("[DstMab] 1 hour inactive, clearing");
clear();
}
else {
_timer.schedule_after_sec(10);
for(HashTable<FormatedRoute, HashTable<uint16_t, Timestamp> >::iterator it = _route_to_diff_ts.begin();it!=_route_to_diff_ts.end();it++) {
for(HashTable<uint16_t, Timestamp>::iterator it2 = _route_to_diff_ts[it.key()].begin();it2!=_route_to_diff_ts[it.key()].end();it2++) {
if(_current_id > 255 && it2.key() < (_current_id - 255)) {
_route_to_diff_ts[it.key()].erase(it2.key());
_is_diff_ts_ok[it.key()].erase(it2.key());
_control_message_received.erase(it2.key());
_route_to_rate[it.key()].erase(it2.key());
_traffic_after[it.key()].erase(it2.key());
}
}
}
}
}
else if(timer == &_ack_timer) {
_now.assign_now();
Vector<AckInfo> new_ack_vector;
for(int i=0;i<_scheduled_acks.size();i++) {
if ((_now-_scheduled_acks[i].created).msecval() >= _ack_waiting_time_msec) {
// send_ack
send_ack(_scheduled_acks[i]);
}
else {
if(!_ack_timer.scheduled())
_ack_timer.schedule_after_msec(_ack_waiting_time_msec - (_now-_scheduled_acks[i].created).msecval());
new_ack_vector.push_back(_scheduled_acks[i]);
}
}
_scheduled_acks.clear();
_scheduled_acks = new_ack_vector;
}
}
void
DstMab::send_ack(AckInfo info) {
// send ack on this route
WritablePacket *p = Packet::make(100, 0, sizeof(acne_header)+sizeof(mab_ack), 0);
memset(p->data(), 0, p->length());
acne_header *acne_hdr = (acne_header *) p->data();
mab_ack *ack = (mab_ack *) (p->data()+sizeof(acne_header));
Route route = _routing_links->get_route_from_froute(info.froute);
Route reversed_route = route.reverse_route();
uint8_t last_index = (uint8_t) (reversed_route.links.size() - 1);
acne_hdr->_type = MAB_ACK;
acne_hdr->_route = FormatedRoute(reversed_route);
acne_hdr->_hop = 0;
acne_hdr->_seq = 0;
acne_hdr->_id_rate_mab = info.id;
ack->_target_route = info.froute;
ack->_ctrl_id = info.ts;
Timestamp now;
now.assign_now();
int diff = 0;
uint32_t traffic_after = 0;
if(info.id > 0) {
diff = _route_to_diff_ts[info.froute][info.id].msecval();
traffic_after = _traffic_after[info.froute][info.id];
if(diff > 0)
ack->_route_rate = 1000*((_route_to_rate[info.froute][info.id]+traffic_after)/diff);
else {
ack->_route_rate = 0;
click_chatter("[DstMab] Interval for route %s, id %d is 0!", info.froute.unparse().c_str(), info.id);
}
}
ack->_dst = _ip_address;
ack->_flow_src = info.flow_src;
ack->_flow_dst = info.flow_dst;
ack->_max_nb_flows = info.max_nb_flows;
ack->_flow_hash = info.flow_hash;
p->set_timestamp_anno(now);
if(_debug) {
click_chatter("[DstMab %s] Sending ack on route %s, flow %s, id %d, ts %s, final rate %u, %u flows, hash %u. Received %u in %d ms, %u after END", now.unparse().c_str(),
acne_hdr->_route.unparse().c_str(), FlowTuple(info.flow_src,info.flow_dst).unparse().c_str(), acne_hdr->_id_rate_mab,
info.ts.unparse().c_str(), ack->_route_rate, info.max_nb_flows, info.flow_hash, _route_to_rate[info.froute][info.id], diff, traffic_after);
}
if(info.id==0)
_route_to_rate[info.froute][info.id]=0;
#ifdef CLICK_USERLEVEL
memset(ack->_gammas, 0, HDR_ROUTE_SIZE*sizeof(float));
#else
memset(ack->_gammas, 0, HDR_ROUTE_SIZE*sizeof(uint32_t));
#endif
ack->_current_index_in_route = last_index;
output(2).push(p);
}
int
DstMab::bool_handler(const String &s, Element *e, void *a,
ErrorHandler *errh) {
DstMab *elmt = (DstMab *)e;
int arg;
if(!cp_integer(s, &arg))
return errh->error("Debug must be 0 or 1");
if (!(arg == 0 || arg == 1))
return errh->error("Debug must be 0 or 1");
if(((intptr_t) a) == 0) {
elmt->set_debug(arg==1);
}
else if(((intptr_t) a) == 1) {
if(arg==1)
elmt->clear();
}
return 0;
}
void DstMab::add_handlers() {
add_write_handler("debug", bool_handler, 0);
add_write_handler("reset", bool_handler, 1);
}
EXPORT_ELEMENT(DstMab)
CLICK_ENDDECLS

Event Timeline