Page MenuHomec4science

printroutingpacket.cc
No OneTemporary

File Metadata

Created
Fri, Jul 4, 18:50

printroutingpacket.cc

#include <click/config.h>
#include <clicknet/ether.h>
#include <clicknet/ip.h>
#include <click/args.hh>
#include <click/error.hh>
#include <click/straccum.hh>
#include "printroutingpacket.hh"
#include <click/timestamp.hh>
#ifdef CLICK_LINUXMODULE
#include <linux/kernel.h>
#endif
CLICK_DECLS
PrintRoutingPacket::PrintRoutingPacket()
{
}
PrintRoutingPacket::~PrintRoutingPacket()
{
}
int
PrintRoutingPacket::configure(Vector<String> &conf, ErrorHandler *errh)
{
_active = true;
_all_msgs = false;
_with_eth = true;
_test_time = "";
_nb_packets = 0;
_wait_time = 0;
_begin = false;
_test_mab_id = false;
_mab_ctrl_msgs = false;
_print_every = 1;
_count_every = 0;
_count_every_all = 0;
_ts_only = false;
_print_special = false;
if(Args(this, errh).bind(conf)
.read("LABEL", _label)
.read("ACTIVE", _active)
.read("ALL_MSGS", _all_msgs)
.read("ETH_HDR_PRESENT", _with_eth)
.read("TIMESTAMP_ONLY", _ts_only)
.read("TEST_TIME", _test_time)
.read("WAIT_TIME", _wait_time)
.read("TEST_MAB_ID", _test_mab_id)
.read("MAB_CTRL_MSGS", _mab_ctrl_msgs)
.read("PRINT_EVERY", _print_every)
.read("PRINT_SPECIAL", _print_special)
.complete() < 0)
return -1;
if (!(_test_time.compare("") == 0 || _test_time.compare("fwd") == 0 || _test_time.compare("mfl") == 0 ||
_test_time.compare("price") == 0 || _test_time.compare("queue") == 0 ||
_test_time.compare("out") == 0 || _test_time.compare("final") == 0)) {
click_chatter("WARNING: unknown TEST_TIME argument in PrintRoutingPacket.");
_test_time = "";
}
return 0;
}
void
PrintRoutingPacket::push(int port, Packet *p) {
if (_active) {
if (_test_time.compare("") == 0)
print_packet(p);
else
p = update_packet_test_time(p);
}
else {
output(port).push(p);
return;
}
if (p)
output(port).push(p);
else
click_chatter("Error in PrintRoutingPacket, packet dropped");
}
Packet *
PrintRoutingPacket::pull(int port) {
Packet *p = input(port).pull();
if(p == 0) return 0;
if (_active) {
if (_test_time.compare("") == 0)
print_packet(p);
else
p = update_packet_test_time(p);
}
return p;
}
Packet *
PrintRoutingPacket::update_packet_test_time(Packet *p) {
Timestamp now;
now.assign_now();
if (_test_time.compare("fwd") == 0) {
// Header is acne_header
acne_header *acne_hdr = (acne_header *) (p->data());
if (acne_hdr->_type == PROTO_IP_TEST) {
test_time_header *tt_hdr = (test_time_header *) (p->data() + sizeof(acne_header));
tt_hdr->_ts_fwd = now;
}
return p;
}
// Header is ethernet header + acne_header
acne_header *acne_hdr = (acne_header *) (p->data() + sizeof(click_ether));
test_time_header *tt_hdr;
if (acne_hdr->_type == PROTO_IP_TEST) {
tt_hdr = (test_time_header *) (p->data() + sizeof(click_ether) + sizeof(acne_header));
}
else
return p;
if (_test_time.compare("mfl") == 0) {
tt_hdr->_ts_mfl = now;
return p;
}
if (_test_time.compare("price") == 0) {
tt_hdr->_ts_price = now;
return p;
}
if (_test_time.compare("queue") == 0) {
tt_hdr->_ts_queue = now;
return p;
}
if (_test_time.compare("out") == 0) {
tt_hdr->_ts_out = now;
return p;
}
if (_test_time.compare("final") == 0) {
if (_time_first_packet == Timestamp())
_time_first_packet = now;
if (_begin || (now - _time_first_packet).sec() >= _wait_time) {
if (!_begin)
_time_first_packet = now;
_begin = true;
_time_last_packet = now;
_nb_packets++;
_bytes_received += p->length();
_time_cc_fwd += (tt_hdr->_ts_fwd - tt_hdr->_ts_cc);
if ((tt_hdr->_ts_fwd - tt_hdr->_ts_cc) > _max_time_cc_fwd)
_max_time_cc_fwd = (tt_hdr->_ts_fwd - tt_hdr->_ts_cc);
_time_fwd_mfl += (tt_hdr->_ts_mfl - tt_hdr->_ts_fwd);
if ((tt_hdr->_ts_mfl - tt_hdr->_ts_fwd) > _max_time_fwd_mfl)
_max_time_fwd_mfl = (tt_hdr->_ts_mfl - tt_hdr->_ts_fwd);
_time_mfl_price += (tt_hdr->_ts_price - tt_hdr->_ts_mfl);
if ((tt_hdr->_ts_price - tt_hdr->_ts_mfl) > _max_time_mfl_price)
_max_time_mfl_price = (tt_hdr->_ts_price - tt_hdr->_ts_mfl);
_time_price_queue += (tt_hdr->_ts_queue - tt_hdr->_ts_price);
if ((tt_hdr->_ts_queue - tt_hdr->_ts_price) > _max_time_price_queue)
_max_time_price_queue = (tt_hdr->_ts_queue - tt_hdr->_ts_price);
_time_queue_out += (tt_hdr->_ts_out - tt_hdr->_ts_queue);
if ((tt_hdr->_ts_out - tt_hdr->_ts_queue) > _max_time_queue_out)
_max_time_queue_out = (tt_hdr->_ts_out - tt_hdr->_ts_queue);
}
return p;
}
return p;
}
void
PrintRoutingPacket::print_packet(Packet *p) {
if (_ts_only) {
Timestamp now;
now.assign_now();
if(_label)
click_chatter("%s: %s", _label.c_str(), now.unparse().c_str());
else
click_chatter("%s", now.unparse().c_str());
return;
}
String str;
StringAccum s;
click_ether *eth_hdr;
click_ether_vlan *vlan_hdr;
if (_with_eth) {
eth_hdr = (click_ether *) (p->data());
vlan_hdr = (click_ether_vlan *) p->data();
}
if(!_with_eth || ntohs(eth_hdr->ether_type) == ETHERTYPE_ACNE) {
acne_header *hdr = (acne_header *)(p->data() + _with_eth*sizeof(click_ether));
if(hdr->_type == REGULAR_TRAFFIC || (_print_special && hdr->_type == SPECIAL_TRAFFIC) || hdr->_type == PROTO_IP_TEST || hdr->_type == DUMMY_TRAFFIC_MAB) {
_count_every++;
String last_str = "";
if(!hdr->_is_last) {
if(_count_every < _print_every)
return;
_count_every = 0;
}
else
last_str = " last";
if(!_test_mab_id || hdr->_id_rate_mab > 0) {
const click_ip *ip_hdr = (click_ip *) (p->data() + _with_eth*sizeof(click_ether) + sizeof(acne_header));
if(_label) {
s << _label;
s << ": ";
}
Timestamp now;
now.assign_now();
s << now << "(" << p->timestamp_anno() << ")";
s << ": ";
s << String(p->length());
s << " | ";
if (_with_eth){
s << "eth ";
s << " (" << String::make_numeric(static_cast<String::uintmax_t>(ntohs(eth_hdr->ether_type)), 16, true) << ") ";
s << EtherAddress(eth_hdr->ether_shost);
s << "->";
s << EtherAddress(eth_hdr->ether_dhost);
s << "; ";
}
if(hdr->_type == SPECIAL_TRAFFIC)
s << "SPECIAL_TRAF" << last_str;
else if (hdr->_type == REGULAR_TRAFFIC)
s << "REG_TRAF" << last_str;
else if (hdr->_type == PROTO_IP_TEST)
s << "IP_TEST" << last_str;
else if (hdr->_type == DUMMY_TRAFFIC_MAB)
s << "DUMMY_MAB" << last_str;
else
s << "type " << String(hdr->_type) << last_str;
s << ", seq "+String(hdr->_seq)+", from " << LastAddrBytes(hdr->_route._src).unparse() << " to " << LastAddrBytes(hdr->_route._dst).unparse();
s << " MAB id " << String(hdr->_id_rate_mab) << ", hop ";
str = String::make_garbage(1);
if (char *x = str.mutable_c_str())
sprintf(x, "%d",hdr->_hop);
s << str << ", route " << hdr->_route.unparse() << "; ";
s << "ip " << IPAddress(ip_hdr->ip_src) << "->" << IPAddress(ip_hdr->ip_dst);
click_chatter(s.c_str());
}
}
else if(_all_msgs || _mab_ctrl_msgs) {
StringAccum s;
if(_label) {
s << _label;
s << ": ";
}
Timestamp now;
now.assign_now();
s << now << "(" << p->timestamp_anno() << ")";
s << ": ";
s << String(p->length());
s << " | ";
if (_with_eth) {
s << "eth (" << String::make_numeric(static_cast<String::uintmax_t>(ntohs(eth_hdr->ether_type)), 16, true) << ") ";
s << EtherAddress(eth_hdr->ether_shost) << "->" << EtherAddress(eth_hdr->ether_dhost) << "; ";
}
hello_pkt *payload_hello = (hello_pkt *)(p->data() + _with_eth*sizeof(click_ether) + sizeof(acne_header));
mab_control *payload_mabctrl = (mab_control *)(p->data() + _with_eth*sizeof(click_ether) + sizeof(acne_header));
linkstate_header *ls_hdr = (linkstate_header *) (p->data() + _with_eth*sizeof(click_ether) + sizeof(acne_header));
flow_broadcast *flow_bdcst = (flow_broadcast *)(p->data() + _with_eth*sizeof(click_ether) + sizeof(acne_header));
mab_ack *payload_maback = (mab_ack *)(p->data() + _with_eth*sizeof(click_ether) + sizeof(acne_header));
bool pass = false;
switch (hdr->_type) {
case ROUTING_CTRL:
if(!_all_msgs)
return;
s << "RTG_CTRL, type " << ((int)ls_hdr->_type) << ", length " << String(p->length() - _with_eth*sizeof(click_ether)) << ": ";
break;
case HELLO_INT2:
if(!_all_msgs)
return;
s << "HELLO_INT2: src " << payload_hello->src_addr.unparse() << " ";
break;
case HELLO_INT1:
if(!_all_msgs)
return;
s << "HELLO_INT1: src " << payload_hello->src_addr.unparse() << " ";
break;
case MAB_CONTROL:
s << "MAB_CONTROL: id " << hdr->_id_rate_mab << ", type " << ((int)payload_mabctrl->_type);
s << ", flow " << FlowTuple(payload_mabctrl->_flow_src, payload_mabctrl->_flow_dst).unparse() ;
s << ", " << (int) payload_mabctrl->_max_nb_flows << " flows ";
if(payload_mabctrl->_first_message)
s << "(first message) ";
break;
case FLOW_BROADCAST_INT1:
if(_all_msgs)
s << "FLOW_BROADCAST_INT1: src " << flow_bdcst->_src.unparse() << ", " << ((int)flow_bdcst->_nb_flow_ids) << " flows ";
else pass = true;
break;
case FLOW_BROADCAST_INT2:
if(_all_msgs)
s << "FLOW_BROADCAST_INT2: src " << flow_bdcst->_src.unparse() << ", " << ((int)flow_bdcst->_nb_flow_ids) << " flows ";
else pass = true;
break;
case MAB_ACK:
s << "MAB_ACK: id " << hdr->_id_rate_mab << ", route " << payload_maback->_target_route.unparse() << ", " << ((int)payload_maback->_max_nb_flows) << " flows";
s << ", flow " << FlowTuple(payload_maback->_flow_src, payload_maback->_flow_dst).unparse() << ", ts " << payload_maback->_ctrl_id << " ";
break;
default:
if(!_all_msgs)
return;
s << "type ";
str = String::make_garbage(1);
if (char *x = str.mutable_c_str())
sprintf(x, "%d",hdr->_type);
s << str;
s << ": ";
break;
}
if(!pass) {
str = String::make_garbage(4);
if (char *x = str.mutable_c_str())
sprintf(x, "%02X%02X",hdr->_route._dst[0], hdr->_route._dst[1]);
//sprintf(x, "%02X%02X",hdr->_route._route[(hdr->_route._route_length-1)*NB_BYTES_HOP], hdr->_route._route[(hdr->_route._route_length-1)*NB_BYTES_HOP+1]);
s << "dst " << str;
click_chatter(s.c_str());
}
}
}
// with_eth == true here
else if (ntohs(eth_hdr->ether_type) == ETHERTYPE_IP) { // encapsulated IP
click_ip *ip_hdr = (click_ip *) (p->data() + sizeof(click_ether));
acne_header *hdr = (acne_header *)(p->data() + sizeof(click_ether) + sizeof(click_ip));
StringAccum s;
if(_label) {
s << _label;
s << ": ";
}
Timestamp now;
now.assign_now();
s << now << "(" << p->timestamp_anno() << ")";
s << ": ";
s << String(p->length());
s << " (encapsulated tos "<< String(ip_hdr->ip_tos) <<") | ";
if (_with_eth) {
s << "eth (" << String::make_numeric(static_cast<String::uintmax_t>(ntohs(eth_hdr->ether_type)), 16, true) << ") ";
s << EtherAddress(eth_hdr->ether_shost) << "->" << EtherAddress(eth_hdr->ether_dhost) << "; ";
}
mab_control *payload_mabctrl = (mab_control *)(p->data() + sizeof(click_ether) + sizeof(click_ip) + sizeof(acne_header));
mab_ack *payload_maback = (mab_ack *)(p->data() + sizeof(click_ether) + sizeof(click_ip) + sizeof(acne_header));
switch (hdr->_type) {
case MAB_CONTROL:
s << "MAB_CONTROL: id " << hdr->_id_rate_mab << ", type " << String((int) payload_mabctrl->_type);
s << ", flow " << FlowTuple(payload_mabctrl->_flow_src, payload_mabctrl->_flow_dst).unparse() << " ";
break;
case MAB_ACK:
s << "MAB_ACK: id " << hdr->_id_rate_mab << ", route " << payload_maback->_target_route.unparse() << ", " << ((int)payload_maback->_max_nb_flows) << " flows";
s << ", flow " << FlowTuple(payload_maback->_flow_src, payload_maback->_flow_dst).unparse() << ", ts " << payload_maback->_ctrl_id << " ";
break;
default:
return;
}
str = String::make_garbage(4);
if (char *x = str.mutable_c_str())
sprintf(x, "%02X%02X",hdr->_route._dst[0], hdr->_route._dst[1]);
//sprintf(x, "%02X%02X",hdr->_route._route[(hdr->_route._route_length-1)*NB_BYTES_HOP], hdr->_route._route[(hdr->_route._route_length-1)*NB_BYTES_HOP+1]);
s << "dst " << str;
click_chatter(s.c_str());
}
else if (ntohs(vlan_hdr->ether_vlan_proto) == ETHERTYPE_8021Q) { // encapuslated in VLAN packet
acne_header *hdr = (acne_header *)(p->data() + sizeof(click_ether_vlan));
StringAccum s;
if(_label) {
s << _label;
s << ": ";
}
Timestamp now;
now.assign_now();
s << now << "(" << p->timestamp_anno() << ")";
s << ": ";
s << String(p->length());
s << " (encapsulated VLAN proto "<< String::make_numeric(static_cast<String::uintmax_t>(ntohs(vlan_hdr->ether_vlan_encap_proto)), 16, true);
s << " tci " << String::make_numeric(static_cast<String::uintmax_t>(ntohs(vlan_hdr->ether_vlan_tci)), 16, true) << ") | ";
if (_with_eth) {
s << "eth (" << String::make_numeric(static_cast<String::uintmax_t>(ntohs(vlan_hdr->ether_vlan_proto)), 16, true) << ") ";
s << EtherAddress(vlan_hdr->ether_shost) << "->" << EtherAddress(vlan_hdr->ether_dhost) << "; ";
}
mab_control *payload_mabctrl = (mab_control *)(p->data() + sizeof(click_ether_vlan) + sizeof(acne_header));
mab_ack *payload_maback = (mab_ack *)(p->data() + sizeof(click_ether_vlan) + sizeof(acne_header));
nack_order *nack = (nack_order *) (p->data() + sizeof(click_ether_vlan) + sizeof(acne_header));
switch (hdr->_type) {
case MAB_CONTROL:
s << "MAB_CONTROL: id " << hdr->_id_rate_mab << ", type " << String((int) payload_mabctrl->_type);
s << ", flow " << FlowTuple(payload_mabctrl->_flow_src, payload_mabctrl->_flow_dst).unparse() << " ";
break;
case MAB_ACK:
s << "MAB_ACK: id " << hdr->_id_rate_mab << ", route " << payload_maback->_target_route.unparse() << ", " << ((int)payload_maback->_max_nb_flows) << " flows";
s << ", flow " << FlowTuple(payload_maback->_flow_src, payload_maback->_flow_dst).unparse() << ", ts " << payload_maback->_ctrl_id << " ";
break;
case SPECIAL_TRAFFIC:
if(!_print_special)
return;
s << "SPECIAL_TRAFFIC: seq " << hdr->_seq << ", route " << hdr->_route.unparse() << " ";
break;
case NACK_ORDER:
s << "NACK_ORDER: flow src " << nack->flow_src_addr.unparse() << " flow dst " << nack->flow_dst_addr.unparse() << ", last seq " << nack->last_seq;
s << ", with " << nack->nb_nacks << " nacks ";
break;
default:
break;
}
str = String::make_garbage(4);
if (char *x = str.mutable_c_str())
sprintf(x, "%02X%02X",hdr->_route._dst[0], hdr->_route._dst[1]);
//sprintf(x, "%02X%02X",hdr->_route._route[(hdr->_route._route_length-1)*NB_BYTES_HOP], hdr->_route._route[(hdr->_route._route_length-1)*NB_BYTES_HOP+1]);
s << "dst " << str;
click_chatter(s.c_str());
}
else if (_all_msgs) {
_count_every_all++;
if(_count_every_all < _print_every)
return;
_count_every_all = 0;
if(_label) {
s << _label;
s << ": ";
}
Timestamp now;
now.assign_now();
s << now << "(" << p->timestamp_anno() << ")";
s << ": ";
s << p->length();
s << " | ";
s << "eth (" << String::make_numeric(static_cast<String::uintmax_t>(ntohs(eth_hdr->ether_type)), 16, true) << ") ";
s << EtherAddress(eth_hdr->ether_shost);
s << "->";
s << EtherAddress(eth_hdr->ether_dhost);
s << "; ";
click_chatter(s.c_str());
}
}
String PrintRoutingPacket::print_info() {
StringAccum s;
if (_nb_packets > 0) {
s << "Statistics: received " << _nb_packets << " packets (" << _bytes_received <<" bytes) between "
<< _time_first_packet.unparse() << " and " << _time_last_packet.unparse() << ".";
if (_time_first_packet != _time_last_packet)
s << " Rate=" << int_divide(_bytes_received*1000, usec_timestamp(_time_last_packet - _time_first_packet)) << " kB/s.";
s << "\n";
s << "Average durations in us: CC->FWD=" << int_divide(usec_timestamp(_time_cc_fwd),_nb_packets) << ", "
<< "FWD->MFL=" << int_divide(usec_timestamp(_time_fwd_mfl),_nb_packets) << ", "
<< "MFL->PRICE=" << int_divide(usec_timestamp(_time_mfl_price),_nb_packets) << ", "
<< "PRICE->QUEUE=" << int_divide(usec_timestamp(_time_price_queue),_nb_packets) << ", "
<< "QUEUE->OUT=" << int_divide(usec_timestamp(_time_queue_out),_nb_packets) << ".\n";
s << "Max durations in us: CC->FWD=" << usec_timestamp(_max_time_cc_fwd) << ", "
<< "FWD->MFL=" << usec_timestamp(_max_time_fwd_mfl) << ", "
<< "MFL->PRICE=" << usec_timestamp(_max_time_mfl_price) << ", "
<< "PRICE->QUEUE=" << usec_timestamp(_max_time_price_queue) << ", "
<< "QUEUE->OUT=" << usec_timestamp(_max_time_queue_out) << ".\n";
}
else
s << "No packet received yet";
return s.take_string();
}
void
PrintRoutingPacket::reset() {
_nb_packets = 0;
_bytes_received = 0;
_begin = false;
_time_first_packet.clear();
_time_last_packet.clear();
_time_cc_fwd.clear();
_time_fwd_mfl.clear();
_time_mfl_price.clear();
_time_price_queue.clear();
_time_queue_out.clear();
_max_time_cc_fwd.clear();
_max_time_fwd_mfl.clear();
_max_time_mfl_price.clear();
_max_time_price_queue.clear();
_max_time_queue_out.clear();
}
static String
print_handler(Element *e, void *) {
PrintRoutingPacket *pr_rtg = (PrintRoutingPacket *)e;
return pr_rtg->print_info();
}
static int
reset_handler
(const String &, Element *e, void *, ErrorHandler *)
{
PrintRoutingPacket *c = (PrintRoutingPacket *)e;
c->reset();
return 0;
}
int
PrintRoutingPacket::active_handler(const String &s, Element *e, void *,
ErrorHandler *errh) {
PrintRoutingPacket *elmt = (PrintRoutingPacket *)e;
int active;
if(!cp_integer(s, &active))
return errh->error("Active must be 0 or 1");
if (!(active == 0 || active == 1))
return errh->error("Active must be 0 or 1");
elmt->set_active(active==1);
return 0;
}
void PrintRoutingPacket::add_handlers() {
add_read_handler("print_info", print_handler,0);
add_write_handler("reset", reset_handler, 0, Handler::BUTTON);
add_write_handler("active", active_handler, 0);
}
EXPORT_ELEMENT(PrintRoutingPacket)
CLICK_ENDDECLS

Event Timeline