#include <nsProtoManetKernel.h>
#include <nsProtoManetKernel_packet.h>
int hdr_ProtolibMK::offset_;
static class ProtolibMKHeaderClass : public PacketHeaderClass {
public:
ProtolibMKHeaderClass() : PacketHeaderClass("PacketHeader/ProtolibMK", sizeof(hdr_ProtolibMK)) { bind_offset(&hdr_ProtolibMK::offset_);
}
} class_rtProtoProtolibMK_hdr;
static class ProtolibMKclass : public TclClass {
public:
ProtolibMKclass() : TclClass("Agent/ProtolibMK") {}
TclObject* create(int argc, const char*const* argv) {
assert(argc == 5);
return (new ProtolibMK((nsaddr_t) Address::instance().str2addr(argv[4])));
}
} class_rtProtoProtolibMK;
int
ProtolibMK::command(int argc, const char*const* argv) {
if(argc == 2) {
Tcl& tcl = Tcl::instance();
if(strncasecmp(argv[1], "id", 2) == 0) {
tcl.resultf("%d", index);
return TCL_OK;
}
if(strncasecmp(argv[1], "start", 2) == 0) {
return TCL_OK;
}
}
else if(argc == 3) {
if(strcmp(argv[1], "port-dmux") == 0) {
dmux_ = (PortClassifier *)TclObject::lookup(argv[2]);
if (dmux_ == 0) {
fprintf(stderr,"protolibManetKernel::command: %s lookup of %s failed\n",argv[1],argv[2]);
return TCL_ERROR;
}
return TCL_OK;
}
else if(strcmp(argv[1], "attach-manet") == 0) {
manetpointer = (Agent*)TclObject::lookup(argv[2]);
return TCL_OK;
}
else if(strcmp(argv[1], "log-target" ) == 0 || strcmp(argv[1], "tracetarget") == 0) {
logtarget = (Trace*) TclObject::lookup(argv[2]);
if(logtarget == 0)
return TCL_ERROR;
return TCL_OK;
}
else if(strcmp(argv[1], "if-queue") == 0) {
ifqueue = (PriQueue*) TclObject::lookup(argv[2]);
if(ifqueue == 0)
return TCL_ERROR;
return TCL_OK;
}
else if(strcmp(argv[1], "target") == 0) {
Tcl& tcl = Tcl::instance();
tcl.evalf("%s set node_", this->name());
tcl.evalf("%s set ifq_(0)",tcl.result());
ifqueue = (PriQueue*) TclObject::lookup(tcl.result());
return Agent::command(argc, argv);
}
}
return Agent::command(argc, argv);
}
ProtolibMK::ProtolibMK(nsaddr_t id) : Agent(PT_PROTOLIBMK) {
srand(10);
index = id;
logtarget = 0;
numberofforwards = 0;
numberofrecv = 0;
idnumber = 0;
}
void
ProtolibMK::recv(Packet *p, Handler*) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
assert(initialized());
if(ch->ptype() == PT_PROTOLIBMK) {
ih->ttl_ -= 1;
manetpointer->recv(p,NULL);
return;
}
if((ih->saddr() == index) && (ch->num_forwards() == 0)) {
if(ih->ttl_ == 0)
ih->ttl_ = 255; ch->uid_ = idnumber++; if(ih->dport()==698){
ch->ptype() = PT_PROTOLIBMK;
ih->daddr() = IP_BROADCAST;
}
if(ih->daddr()== (int)IP_BROADCAST){ }
} else if(ih->saddr() == index) {
Packet::free(p);
return;
} else {
if(--ih->ttl_ == 0) {
drop(p, DROP_RTR_TTL);
return;
}
}
if(ih->daddr()== (int)IP_BROADCAST){
if(ih->dport()!=-1){
if(ih->dport()!=698){ NsObject* node = ProtolibMKFind(p); if (node) { Packet *copy_p=p->copy(); if(!copy_p) {
fprintf(stderr,"ProtoManetKernel::recv error copying packet returning without recving packet\n");
return;
}
dmux_->recv(copy_p,NULL);
}
manetpointer->recv(p,this);
} else { forward(p,(nsaddr_t)ih->daddr()); }
} else {
drop(p, DROP_RTR_NO_ROUTE);
}
} else {
manetpointer->recv(p,NULL); }
return;
}
NsObject* ProtolibMK::ProtolibMKFind(Packet* p){
NsObject* returnnode = NULL;
int cl = ((Classifier*)dmux_)->classify(p);
if ((returnnode = dmux_->slot(cl)) == 0) {
}
return returnnode;
}
void ProtolibMK::rt_failed(Packet *p) {
drop(p,DROP_RTR_NO_ROUTE); }
void ProtolibMK::forward(Packet *p, nsaddr_t nexthop) {
struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
if (ih->ttl_ == 0){
drop(p, DROP_RTR_TTL);
return;
}
if (nexthop == here_.addr_) {
ch->next_hop_ = nexthop;
ch->addr_type() = NS_AF_INET;
ch->direction() = hdr_cmn::UP;
} else {
ch->prev_hop_ = here_.addr_;
ch->next_hop_ = nexthop;
ch->addr_type() = NS_AF_INET;
ch->direction() = hdr_cmn::DOWN;
}
Scheduler::instance().schedule(target_, p, 0.);
}
bool ProtolibMK::bcastforward(Packet *p) { struct hdr_cmn *ch = HDR_CMN(p);
struct hdr_ip *ih = HDR_IP(p);
double jitter;
if (ih->ttl_ == 0){
drop(p, DROP_RTR_TTL);
return false;
}
ch->prev_hop_ = here_.addr_;
ch->next_hop_ = IP_BROADCAST;
ch->addr_type() = NS_AF_INET;
ch->direction() = hdr_cmn::DOWN;
jitter = 0.00 * (double)rand() / (double)RAND_MAX;
Scheduler::instance().schedule(target_, p, jitter);
return true;
}