📄 aodv.cc
字号:
#include "h/aodv.h"#include "h/aodvCostants.h"#define max(a,b) (a>b ? a : b)Define_Module_Like(AODV,Routing);//****************** constructors 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",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("message arrived from app"); reply = sendData(msg); broadcast(reply); delete msg; } else { //collect the message kind pktHistogram.collect( msg->kind() ); switch(msg->kind()) { case SEND_HELLO: d("sendHello"); reply = generateHELLOmsg(); broadcast(reply); break; case 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 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 ESP_ACK: d("esp_ack"); reply = handleESP_ACK(msg); broadcast(reply); break; case 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 packets...."<<statistics.sentCtrlPkt); dd("Sent data packets......."<<statistics.sentDataPkt); dd("Delivered data packets.."<<statistics.deliveredDataMsg); if(statistics.deliveredDataMsg > 0) dd("Hops Average..........."<<statistics.hopsSum / statistics.deliveredDataMsg ); PartialStat* cell; fprintf(fout,"Hosts number:............... %d\n",(int)parentModule()->par("numHost")); fprintf(fout,"Sent control packets......... %d\n",statistics.sentCtrlPkt); fprintf(fout,"Sent data packets............ %d\n",statistics.sentDataPkt); fprintf(fout,"Delivered data packets....... %d\n",statistics.deliveredDataMsg); for(int i=0; i<= statistics.maxHop; i++) { cell = (PartialStat*) statistics.hopsV[i]; if(cell) { fprintf(fout,"Per-Hop throughput measured... %d %.0f\n",i, cell->throughSum/cell->samples); dd("Per-Hop throughput measured..."<<i<<" "<<cell->throughSum / cell->samples); fprintf(fout,"Per-Hop latency measured..... %d %.6f\n",i, cell->latencySum / cell->samples); dd("Per-Hop latency measured....."<<i<<" "<<cell->latencySum / cell->samples); } } if(statistics.deliveredDataMsg > 0) fprintf(fout,"Hops Average................ %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 parameter that is common to all the messages if(reply->hasPar("source")) reply->par("source") = (int)parentModule()->id(); else reply->addPar("source") = (int)parentModule()->id(); //so there is not the need of creating a new copy //this->takeOwnership(false); //send(reply,"toMac"); //this->takeOwnership(false); cMessage *copy = new cMessage(*reply); send(copy, "toMac"); //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 ++; delete reply; // We need this because the msg has been copied } else { d("ttl expired! 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",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 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.",BLK_LIST,0,P_BLK_LIST); b->removeEvent->addPar("node") = (cObject*) b; blackList.insert( (BlackListElement*) b ); //schedule 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 // NB: always delete messages inside, they won't be deleted // by simply deleting e if(e->rreqMsg) delete e->rreqMsg; if(e->espireEvent != NULL) { dd("espireEvent != NULL"); delete e->espireEvent; } delete e; return NULL; } else { d("there are more chances left"); //retransmit 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("handle black list"); BlackListElement* e = (BlackListElement*)(cObject*) msg->par("node"); blackList.remove(e); /*NB*/ if(e->removeEvent!=NULL) { delete e->removeEvent; } 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;}/* * If a route is found in the routes table, send data to the destination, * otherwise generate, save in oldReqs, and send a new RREQ message. * Also bufferize and schedule a "RREQ timeout". */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 looking for a route, //returns the event that has to be scheduled to //menage the relative RREQ event re-transmission reply = bufferize(msg->par("dest"),msg->length()); if(reply !=NULL) { //schedule the RREQ failure /* Perche' spedire il timeout cosi' tanto prima rispetto alla spedizione del RREQ??*/ scheduleAt(simTime()+ 2 * TTL_START * NODE_TRAVERSAL_TIME, reply); reply = generateRREQmsg(e,msg->par("dest"),TTL_START); //remember the rreq addNewReq(reply); /* NB: Non sarebbe meglio spostare la scheduleAt qui? */ //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; };}/* * Bufferize "RREQs timeout" messages (kind=FLUSH) in pktBuffer. * If there's still another "RREQ timeout" in the buffer, * increments the number of data packets waiting to be sent * and returns NULL, otherwise returns the generated "RREQ timeout". * The "RREQ" will be generated by the caller (sendData), * that also schedules the future timeout. */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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -