📄 aodv.cpp
字号:
#include "h/aodv.h"#include "h/aodvCostants.h"#define max(a,b) (a>b ? a : b)Define_Module_Like(AODV,Routing);//****************** costructors and destructors of secondary objects ****************AODV::~AODV(){}WaitingPkt::WaitingPkt(){};WaitingPkt::~WaitingPkt(){};OldReqs::OldReqs(){};OldReqs::~OldReqs(){};PrecursorElement::PrecursorElement(){};PrecursorElement::~PrecursorElement(){};BlackListElement::BlackListElement(){};BlackListElement::~BlackListElement(){};WaitingRREP::WaitingRREP(){};WaitingRREP::~WaitingRREP(){};RouteTableElement::RouteTableElement(){};RouteTableElement::~RouteTableElement(){};PartialStat::PartialStat(double lat, double th)
{
latencySum = lat;
throughSum = th;
samples = 1;
};PartialStat::~PartialStat(){};Statistics::Statistics(){ hopsSum = 0; deliveredDataMsg = 0; sendDataMsg = 0; sentCtrlPkt =0; sentDataPkt =0; maxHop =0;}Statistics::~Statistics(){};//function used by queue.inset to set up a oredered queueint compareFunc(cObject* a, cObject *b){ RouteTableElement* l = (RouteTableElement*)a; RouteTableElement* r = (RouteTableElement*)b; return ( l->destId - r->destId);}//***********************************************************************************void AODV::initialize(){ d("AODV protocol simulator based on the IEEE-MANET Internet Draft v.10"); //initialize the local variables sequenceNumber = 0; //counter to generate unique RREQs reqId = 0; // pktHistogram.setName("paket kind histogram"); pktHistogram.setRange(0,13); hopsHistogram.setName("hops number histogram"); hopsHistogram.setRange(1,20); //give to the queue the sorting capability routeTab.setup(compareFunc); //let some vars to be editable from the TkEnv environment WATCH(sequenceNumber); WATCH(statistics.sentCtrlPkt); //schedule the first message tho initialize the send hello chain helloEvent = new cMessage("sendHello",MK_SEND_HELLO,0,P_SEND_HELLO); scheduleAt(simTime()+0.5, helloEvent);}void AODV::handleMessage(cMessage *msg){ cMessage* reply = NULL; d("HANDLE message routine"); if (msg->arrivedOn("fromApp") ) { d("messasge arrived from app"); reply = sendData(msg); broadcast(reply); delete msg; } else { //collect the message kind pktHistogram.collect( msg->kind() ); switch(msg->kind()) { case MK_SEND_HELLO: d("sendHello"); reply = generateHELLOmsg(); broadcast(reply); break; case MK_DELETE: /* * Note that the Lifetime field in the * routing table plays a dual role * -- for an active route it is the * expiry time, and for an invalid * route it is the deletion time. * If a data packet is received for an * invalid route, the Lifetime field is * updated to current time plus * DELETE_PERIOD. */ d("delete"); reply = handleDelete(msg); broadcast(reply); break; case HELLO: d("hello"); //AODV specification says that the HELLO messages //are a spcial kind of RREP msg. //For semplicity I've chosen to treat //them as a different kind of message. handleHELLO(msg); delete msg; break; case MK_FLUSH: d("flush"); //A RREQ has been timed out //so do what has to be done reply = handleFlush(msg); broadcast(reply); break; case RREQ: d("rreq "<<msg->name()); reply = handleRREQ(msg); //if the message received need a reply //then send it to the mac module that will //care about sending it around broadcast(reply); delete msg; break; case RREP: d("rrep"); reply = handleRREP(msg); broadcast(reply); delete msg; break; case RERR: d("rerr"); reply = handleRERR(msg); broadcast(reply); delete msg; break; case DATA: d("data"); reply = handleData(msg); broadcast(reply); delete msg; break; case RREP_ACK: d("ack"); handleACK(msg); delete msg; break; case MK_ESP_ACK: d("esp_ack"); reply = handleESP_ACK(msg); broadcast(reply); break; case MK_BLK_LIST: d("black list"); handleBLK_LIST(msg); delete msg; break; } }}void AODV::finish(){ //I will write on a file instead of usa recordScalar() beacuse of a bug in this //function that rewrites the file on each run FILE* fout = fopen("collectedData.dat","a"); dd("Hosts number..........."<< (int)parentModule()->par("numHost")); dd("Sent control pakets...."<<statistics.sentCtrlPkt); dd("Sent data pakets......."<<statistics.sentDataPkt); dd("Delivered data pakets.."<<statistics.deliveredDataMsg); if(statistics.deliveredDataMsg > 0) dd("Hops Avarage..........."<<statistics.hopsSum / statistics.deliveredDataMsg ); PartialStat* cell; fprintf(fout,"Hosts number:............... %d\n",(int)parentModule()->par("numHost")); fprintf(fout,"Sent control pakets......... %d\n",statistics.sentCtrlPkt); fprintf(fout,"Sent data pakets............ %d\n",statistics.sentDataPkt); fprintf(fout,"Delivered data pakets....... %d\n",statistics.deliveredDataMsg); for(int i=0; i<= statistics.maxHop; i++) { cell = (PartialStat*) statistics.hopsV[i]; if(cell) { fprintf(fout,"Per-Hop throughput misured... %d %.0f\n",i, cell->throughSum/cell->samples); dd("Per-Hop throughput misured..."<<i<<" "<<cell->throughSum / cell->samples); fprintf(fout,"Per-Hop latency misured..... %d %.6f\n",i, cell->latencySum / cell->samples); dd("Per-Hop latency misured....."<<i<<" "<<cell->latencySum / cell->samples); } } if(statistics.deliveredDataMsg > 0) fprintf(fout,"Hops Avarage................ %d\n",statistics.hopsSum / statistics.deliveredDataMsg); fclose(fout);}void AODV::broadcast(cMessage* reply){ if(reply !=NULL) { int ttl; d("send to mac:"<<reply->name()<<" "<<reply->kind()); ttl = (int) reply->par("ttl")-1; if( ttl >= 0 ) { reply->par("ttl") = ttl; reply->par("hopCount") = 1+ (int)reply->par("hopCount"); //add the source parmeter that is common to all the messages if(reply->hasPar("source")) reply->par("source") = (int)parentModule()->id(); else reply->addPar("source") = (int)parentModule()->id(); send(reply,"toMac"); // FIXME it is illegal to send a msg object and keep referencing it!!! -Andras //send Hello only when helloEvent is extracted from the FES (event queue) //or the message(like data) do not make the route //table to be refreshed if((reply->kind() != HELLO) && (reply->kind() != DATA) ) if (helloEvent->isScheduled() ) cancelEvent( helloEvent ); //only control packets make the other nodes refresh //their route if( reply->kind() != DATA) scheduleAt(simTime()+HELLO_INTERVAL,helloEvent ); if( (reply->kind() == RREQ) || (reply->kind() == RREP) || (reply->kind() == RERR) || (reply->kind() == RREP_ACK) ) statistics.sentCtrlPkt ++; } else { d("ttl espired! the msg will not be sent:"); delete reply; } }}void AODV::waitForAck(cMessage* msg){ d("waitForAck"); //schedule a trigger to simulate an ACK failure WaitingRREP* e = new WaitingRREP(); e->destId = (int) msg->par("originator"); e->nextHopId = (int) msg->par("mac"); e->trials = 1; //pointer to the rreq message e->rreqMsg = new cMessage(*msg); //trigger e->espireEvent = new cMessage("rrep ack espired",MK_ESP_ACK,0,P_ESP_ACK); //pointer to the RREP entry in that has failed to arrive e->espireEvent->addPar("element") = (WaitingRREP*) e; waitingRrep.insert( (WaitingRREP*) e); scheduleAt(simTime()+ NEXT_HOP_WAIT, e->espireEvent);}cMessage* AODV::handleESP_ACK(cMessage* msg){ bool done = false; WaitingRREP*e = NULL; d("handle MK_ESP_ACK"); //ugly but it is the only way... e = (WaitingRREP*) (cObject*) msg->par("element"); d("RREP ACK timed out (the ack message is not arrived) check out what's to be done"); e->trials++; if(e->trials > RREP_RETRIES) { d("no more trials left...put the neig. in the black list"); //flush the RREP buffer! waitingRrep.remove(e); //add the node to the black list BlackListElement* b = new BlackListElement(); b->id = e->nextHopId; b->removeEvent = new cMessage("remove from B.L.",MK_BLK_LIST,0,P_BLK_LIST); b->removeEvent->addPar("node") = (cObject*) b; blackList.insert( (BlackListElement*) b ); //scehdule the node removal from the blacklist scheduleAt(simTime()+BLACKLIST_TIMEOUT,b->removeEvent); //delete the message here because it has to be deleted only in this case delete msg; //msg is stored in e so I have to delete it here rather than before delete e; return NULL; } else { d("there are more chance left"); //retrasmit the stored rrep cMessage* rrep = new cMessage(*e->rreqMsg); //schedule the next ack time out event scheduleAt(simTime()+ NEXT_HOP_WAIT, e->espireEvent); return rrep; }}void AODV::handleBLK_LIST(cMessage* msg){ d("hanldle black list"); BlackListElement* e = (BlackListElement*)(cObject*) msg->par("node"); blackList.remove(e); delete e;}bool AODV::isInBlackList(int node){ cQueue :: Iterator iter(blackList,1); bool found = false; BlackListElement* e = NULL; d("isInBlackList"); while( ( !iter.end() ) && ( !found ) ) { e = (BlackListElement*) iter(); if(e->id == node) { found = true; } else iter++; } return found;}cMessage* AODV::sendData(cMessage* msg){ RouteTableElement *e = NULL; d("sendData"); //check for a route e = findNode(msg->par("dest") ); if( (e == NULL) || (e->active==false)) { cMessage* reply; //bufferize the request while look for a route, //returns the event that has to be scheduled to //menage the retrasmit RREQ event reply = bufferize(msg->par("dest"),msg->length()); if(reply !=NULL) { //schedule the RREQ failure scheduleAt(simTime()+ 2 * TTL_START * NODE_TRAVERSAL_TIME , reply); reply = generateRREQmsg(e,msg->par("dest"),TTL_START); //remember the rreq addNewReq(reply); //return the RREQ message that wil be sent out return reply; } else { d("RREQ not generated"); return reply; } } else { //add all the params that are needed cMessage* m = generateDATAmsg(e,msg->length()); d("want to send data to a known destination "<<msg->par("dest")); statistics.sentDataPkt ++; return m; };}cMessage* AODV::bufferize(int dest,int pktSize){ bool found = false; WaitingPkt* p = NULL; d("bufferize"); for(cQueue:: Iterator iter(pktBuffer,1); !iter.end(); iter++) { p = (WaitingPkt*) iter(); if(p->dest == dest) { //if there is a RREQ at work just add a new pkt p->pktNum++; return NULL; } } //this is a new paket : create the message that //make the RREQ msg to be timed-out and reseded p = new WaitingPkt; p->dest = dest; p->trial = 1; p->pktNum = 1; p->pktSize = pktSize; //RREQ time out trigger p->deleteEvent = new cMessage("RREQ time out",MK_FLUSH,P_FLUSH); p->deleteEvent->addPar("dest") = dest; p->deleteEvent->addPar("ttl") = TTL_START; pktBuffer.insert(p); return p->deleteEvent;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -