WiseRoute.cc

00001 /***************************************************************************
00002  * file:        WiseRoute.cc
00003  *
00004  * author:      Damien Piguet, Jerome Rousselot
00005  *
00006  * copyright:   (C) 2007-2008 CSEM SA, Neuchatel, Switzerland.
00007  *
00008  * description: Implementation of the routing protocol of WiseStack.
00009  *
00010  *              This program is free software; you can redistribute it
00011  *              and/or modify it under the terms of the GNU General Public
00012  *              License as published by the Free Software Foundation; either
00013  *              version 2 of the License, or (at your option) any later
00014  *              version.
00015  *              For further information see file COPYING
00016  *              in the top level directory
00017  *
00018  *
00019  * Funding: This work was partially financed by the European Commission under the
00020  * Framework 6 IST Project "Wirelessly Accessible Sensor Populations"
00021  * (WASP) under contract IST-034963.
00022  ***************************************************************************
00023  * ported to Mixim 2.0.1 by Theodoros Kapourniotis
00024  * last modification: 06/02/11
00025  **************************************************************************/
00026 
00027 #include <limits>
00028 #include <algorithm>
00029 
00030 #include "WiseRoute.h"
00031 #include <cassert>
00032 
00033 Define_Module(WiseRoute);
00034 
00035 void WiseRoute::initialize(int stage)
00036 {
00037   BaseNetwLayer::initialize(stage);
00038 
00039   if(stage == 1) {
00040 
00041     EV << "Host index=" << findHost()->getIndex() << ", Id="
00042     << findHost()->getId() << endl;
00043 
00044 
00045     EV << "  host IP address=" << myNetwAddr << endl;
00046     EV << "  host macaddress=" << arp->getMacAddr(myNetwAddr) << endl;
00047     macaddress = arp->getMacAddr(myNetwAddr);
00048 
00049     sinkAddress = par("sinkAddress"); // 0
00050     headerLength = par ("headerLength");
00051     rssiThreshold = par("rssiThreshold");
00052     routeFloodsInterval = par("routeFloodsInterval");
00053 
00054     stats = par("stats");
00055     trace = par("trace");
00056     debug = par("debug");
00057     useSimTracer = par("useSimTracer");
00058     floodSeqNumber = 0;
00059 
00060     nbDataPacketsForwarded = 0;
00061     nbDataPacketsReceived = 0;
00062     nbDataPacketsSent = 0;
00063     nbDuplicatedFloodsReceived = 0;
00064     nbFloodsSent = 0;
00065     nbPureUnicastSent = 0;
00066     nbRouteFloodsSent = 0;
00067     nbRouteFloodsReceived = 0;
00068     nbUnicastFloodForwarded = 0;
00069     nbPureUnicastForwarded = 0;
00070     nbGetRouteFailures = 0;
00071     nbRoutesRecorded = 0;
00072     nbHops = 0;
00073     receivedRSSI.setName("receivedRSSI");
00074     routeRSSI.setName("routeRSSI");
00075     allReceivedRSSI.setName("allReceivedRSSI");
00076     receivedBER.setName("receivedBER");
00077     routeBER.setName("routeBER");
00078     allReceivedBER.setName("allReceivedBER");
00079     nextHopSelectionForSink.setName("nextHopSelectionForSink");
00080 
00081     routeFloodTimer = new cMessage("route-flood-timer", SEND_ROUTE_FLOOD_TIMER);
00082     // only schedule a flood of the node is a sink!!
00083     if (routeFloodsInterval > 0 && myNetwAddr==sinkAddress)
00084       scheduleAt(simTime() + uniform(0.5, 1.5), routeFloodTimer);
00085 
00086     if(useSimTracer) {
00087       // Get a handle to the tracer module
00088       const char *tracerModulePath = "sim.simTracer";
00089       cModule *modp = simulation.getModuleByPath(tracerModulePath);
00090       tracer = check_and_cast<SimTracer *>(modp);
00091     }
00092     // log node position
00093     BaseMobility * mobility;
00094     mobility = check_and_cast<BaseMobility*>(getParentModule()->getSubmodule("mobility"));
00095     if(useSimTracer) {
00096 //      tracer->logPosition(myNetwAddr, mobility->getX(), mobility->getY());
00097     }
00098   }
00099 }
00100 
00101 WiseRoute::~WiseRoute()
00102 {
00103   cancelAndDelete(routeFloodTimer);
00104 }
00105 
00106 void WiseRoute::handleSelfMsg(cMessage* msg)
00107 {
00108   if (msg->getKind() == SEND_ROUTE_FLOOD_TIMER) {
00109     // Send route flood packet and restart the timer
00110     int macBcastAddr = L2BROADCAST;
00111     int ipBcastAddr = L3BROADCAST;
00112     WiseRoutePkt* pkt = new WiseRoutePkt("route-flood", ROUTE_FLOOD);
00113     pkt->setByteLength(headerLength);
00114     pkt->setInitialSrcAddr(myNetwAddr);
00115     pkt->setFinalDestAddr(ipBcastAddr);
00116     pkt->setSrcAddr(myNetwAddr);
00117     pkt->setDestAddr(ipBcastAddr);
00118     pkt->setNbHops(0);
00119     floodTable.insert(make_pair(myNetwAddr, floodSeqNumber));
00120     pkt->setSeqNum(floodSeqNumber);
00121     floodSeqNumber++;
00122     pkt->setIsFlood(1);
00123     pkt->setControlInfo(new NetwToMacControlInfo(macBcastAddr));
00124     sendDown(pkt);
00125     nbFloodsSent++;
00126     nbRouteFloodsSent++;
00127     scheduleAt(simTime() + routeFloodsInterval + uniform(0, 1), routeFloodTimer);
00128   }
00129   else {
00130     EV << "WiseRoute - handleSelfMessage: got unexpected message of kind " << msg->getKind() << endl;
00131     delete msg;
00132   }
00133 }
00134 
00135 
00136 void WiseRoute::handleLowerMsg(cMessage* msg)
00137 {
00138   int macBcastAddr = L3BROADCAST;
00139   int bcastIpAddr = L2BROADCAST;
00140   WiseRoutePkt* netwMsg = check_and_cast<WiseRoutePkt*>(msg);
00141   int finalDestAddr = netwMsg->getFinalDestAddr();
00142   int initialSrcAddr = netwMsg->getInitialSrcAddr();
00143   int srcAddr = netwMsg->getSrcAddr();
00144   double rssi = static_cast<MacToNetwControlInfo*>(netwMsg->getControlInfo())->getRSSI();
00145   double ber = static_cast<MacToNetwControlInfo*>(netwMsg->getControlInfo())->getBitErrorRate();
00146   // Check whether the message is a flood and if it has to be forwarded.
00147   floodTypes floodType = updateFloodTable(netwMsg->getIsFlood(), initialSrcAddr, finalDestAddr,
00148                         netwMsg->getSeqNum());
00149   if(trace) {
00150     allReceivedRSSI.record(rssi);
00151     allReceivedBER.record(ber);
00152   }
00153   if (floodType == DUPLICATE) {
00154     nbDuplicatedFloodsReceived++;
00155     delete netwMsg;
00156   }
00157   else {
00158     // If the message is a route flood, update the routing table.
00159     if (netwMsg->getKind() == ROUTE_FLOOD)
00160       updateRouteTable(initialSrcAddr, srcAddr, rssi, ber);
00161 
00162     if (finalDestAddr == myNetwAddr || finalDestAddr == bcastIpAddr) {
00163       WiseRoutePkt* msgCopy;
00164       if (floodType == FORWARD) {
00165         // it's a flood. copy for delivery, forward original.
00166         // if we are here (see updateFloodTable()), finalDestAddr == IP Broadcast. Hence finalDestAddr,
00167         // initialSrcAddr, and destAddr have already been correctly set
00168         // at origin, as well as the MAC control info. Hence only update
00169         // local hop source address.
00170         msgCopy = check_and_cast<WiseRoutePkt*>(netwMsg->dup());
00171         netwMsg->setSrcAddr(myNetwAddr);
00172 //        ((NetwToMacControlInfo*) netwMsg->getControlInfo())->setNextHopMac(macBcastAddr);
00173         netwMsg->removeControlInfo();
00174         netwMsg->setControlInfo(new NetwToMacControlInfo(macBcastAddr));
00175         netwMsg->setNbHops(netwMsg->getNbHops()+1);
00176         sendDown(netwMsg);
00177         nbDataPacketsForwarded++;
00178       }
00179       else
00180         msgCopy = netwMsg;
00181       if (msgCopy->getKind() == DATA) {
00182         sendUp(decapsMsg(msgCopy));
00183         nbDataPacketsReceived++;
00184       }
00185       else {
00186         nbRouteFloodsReceived++;
00187         delete msgCopy;
00188       }
00189     }
00190     else {
00191       // not for me. if flood, forward as flood. else select a route
00192       if (floodType == FORWARD) {
00193         netwMsg->setSrcAddr(myNetwAddr);
00194 //        ((NetwToMacControlInfo*) netwMsg->getControlInfo())->setNextHopMac(macBcastAddr);
00195         netwMsg->removeControlInfo();
00196         netwMsg->setControlInfo(new NetwToMacControlInfo(macBcastAddr));
00197         netwMsg->setNbHops(netwMsg->getNbHops()+1);
00198         sendDown(netwMsg);
00199         nbDataPacketsForwarded++;
00200         nbUnicastFloodForwarded++;
00201       }
00202       else {
00203         int nextHop = getRoute(finalDestAddr);
00204         if (nextHop == bcastIpAddr) {
00205           // no route exist to destination, attempt to send to final destination
00206           nextHop = finalDestAddr;
00207           nbGetRouteFailures++;
00208         }
00209         netwMsg->setSrcAddr(myNetwAddr);
00210         netwMsg->setDestAddr(nextHop);
00211 //        ((NetwToMacControlInfo*) netwMsg->getControlInfo())->setNextHopMac(arp->getMacAddr(nextHop));
00212         netwMsg->removeControlInfo();
00213         netwMsg->setControlInfo(new NetwToMacControlInfo(arp->getMacAddr(nextHop)));
00214         netwMsg->setNbHops(netwMsg->getNbHops()+1);
00215         sendDown(netwMsg);
00216         nbDataPacketsForwarded++;
00217         nbPureUnicastForwarded++;
00218       }
00219     }
00220   }
00221 }
00222 
00223 void WiseRoute::handleLowerControl(cMessage *msg)
00224 {
00225     delete msg;
00226 }
00227 
00228 void WiseRoute::handleUpperMsg(cMessage* msg)
00229 {
00230   int finalDestAddr;
00231   int nextHopAddr;
00232   unsigned long nextHopMacAddr;
00233   WiseRoutePkt* pkt = new WiseRoutePkt(msg->getName(), DATA);
00234   NetwControlInfo* cInfo = dynamic_cast<NetwControlInfo*>(msg->removeControlInfo());
00235   int ipBcastAddr = L3BROADCAST;
00236 
00237   pkt->setByteLength(headerLength);
00238 
00239   if ( cInfo == 0 ) {
00240       EV << "WiseRoute warning: Application layer did not specifiy a destination L3 address\n"
00241          << "\tusing broadcast address instead\n";
00242       finalDestAddr = ipBcastAddr;
00243   }
00244   else {
00245     EV <<"WiseRoute: CInfo removed, netw addr="<< cInfo->getNetwAddr() <<endl;
00246     finalDestAddr = cInfo->getNetwAddr();
00247     delete cInfo;
00248   }
00249 
00250   pkt->setFinalDestAddr(finalDestAddr);
00251   pkt->setInitialSrcAddr(myNetwAddr);
00252   pkt->setSrcAddr(myNetwAddr);
00253   pkt->setNbHops(0);
00254 
00255   if (finalDestAddr == ipBcastAddr)
00256     nextHopAddr = ipBcastAddr;
00257   else
00258     nextHopAddr = getRoute(finalDestAddr, true);
00259   pkt->setDestAddr(nextHopAddr);
00260   if (nextHopAddr == ipBcastAddr) {
00261     // it's a flood.
00262     nextHopMacAddr = L2BROADCAST;
00263     pkt->setIsFlood(1);
00264     nbFloodsSent++;
00265     // record flood in flood table
00266     floodTable.insert(make_pair(myNetwAddr, floodSeqNumber));
00267     pkt->setSeqNum(floodSeqNumber);
00268     floodSeqNumber++;
00269     nbGetRouteFailures++;
00270   }
00271   else {
00272     pkt->setIsFlood(0);
00273     nbPureUnicastSent++;
00274     nextHopMacAddr = arp->getMacAddr(nextHopAddr);
00275   }
00276   pkt->setControlInfo(new NetwToMacControlInfo(nextHopMacAddr));
00277   assert(static_cast<cPacket*>(msg));
00278   pkt->encapsulate(static_cast<cPacket*>(msg));
00279   sendDown(pkt);
00280   nbDataPacketsSent++;
00281 }
00282 
00283 void WiseRoute::finish()
00284 {
00285   if (stats) {
00286     recordScalar("nbDataPacketsForwarded", nbDataPacketsForwarded);
00287     recordScalar("nbDataPacketsReceived", nbDataPacketsReceived);
00288     recordScalar("nbDataPacketsSent", nbDataPacketsSent);
00289     recordScalar("nbDuplicatedFloodsReceived", nbDuplicatedFloodsReceived);
00290     recordScalar("nbFloodsSent", nbFloodsSent);
00291     recordScalar("nbPureUnicastSent", nbPureUnicastSent);
00292     recordScalar("nbRouteFloodsSent", nbRouteFloodsSent);
00293     recordScalar("nbRouteFloodsReceived", nbRouteFloodsReceived);
00294     recordScalar("nbUnicastFloodForwarded", nbUnicastFloodForwarded);
00295     recordScalar("nbPureUnicastForwarded", nbPureUnicastForwarded);
00296     recordScalar("nbGetRouteFailures", nbGetRouteFailures);
00297     recordScalar("nbRoutesRecorded", nbRoutesRecorded);
00298     recordScalar("meanNbHops", (double) nbHops / (double) nbDataPacketsReceived);
00299   }
00300 }
00301 
00302 void WiseRoute::updateRouteTable(int origin, int lastHop, double rssi, double ber)
00303 {
00304   tRouteTable::iterator pos;
00305 
00306   pos = routeTable.find(origin);
00307   if(trace) {
00308     receivedRSSI.record(rssi);
00309     receivedBER.record(ber);
00310   }
00311   if (pos == routeTable.end()) {
00312     // A route towards origin does not exist yet. Insert the currently discovered one
00313     // only if the received RSSI is above the threshold.
00314     if (rssi > rssiThreshold) {
00315       tRouteTableEntry newEntry;
00316 
00317       // last hop from origin means next hop towards origin.
00318       newEntry.nextHop = lastHop;
00319       newEntry.rssi = rssi;
00320       if(trace) {
00321         routeRSSI.record(rssi);
00322         routeBER.record(ber);
00323       }
00324       routeTable.insert(make_pair(origin, newEntry));
00325       if(useSimTracer) {
00326         tracer->logLink(myNetwAddr, lastHop);
00327       }
00328       nbRoutesRecorded++;
00329       if (origin == 0 && trace) {
00330         nextHopSelectionForSink.record(lastHop);
00331       }
00332     }
00333   }
00334   else {
00335     // A route towards the node which originated the received packet already exists.
00336     // Replace its entry only if the route proposal that we just received has a stronger
00337     // RSSI.
00338 //    tRouteTableEntry entry = pos->second;
00339 //    if (entry.rssi > rssiThreshold) {
00340 //      entry.nextHop = lastHop;
00341 //      entry.rssi = rssi;
00342 //      if (origin == 0)
00343 //        nextHopSelectionForSink.record(lastHop);
00344 //    }
00345   }
00346 }
00347 
00348 cMessage* WiseRoute::decapsMsg(WiseRoutePkt *msg)
00349 {
00350   cMessage *m = msg->decapsulate();
00351   m->setControlInfo(new NetwControlInfo(msg->getSrcAddr()));
00352   nbHops = nbHops + msg->getNbHops();
00353   // delete the netw packet
00354   delete msg;
00355   return m;
00356 }
00357 
00358 WiseRoute::floodTypes WiseRoute::updateFloodTable(bool isFlood, int srcAddr, int destAddr, unsigned long seqNum)
00359 {
00360   if (isFlood) {
00361     tFloodTable::iterator pos = floodTable.lower_bound(srcAddr);
00362     tFloodTable::iterator posEnd = floodTable.upper_bound(srcAddr);
00363 
00364     while (pos != posEnd) {
00365       if (seqNum == pos->second)
00366         return DUPLICATE;  // this flood is known, don't forward it.
00367       ++pos;
00368     }
00369     floodTable.insert(make_pair(srcAddr, seqNum));
00370     if (destAddr == myNetwAddr)
00371       return FORME;
00372     else
00373       return FORWARD;
00374   }
00375   else
00376     return NOTAFLOOD;
00377 }
00378 
00379 int WiseRoute::getRoute(int destAddr, bool iAmOrigin)
00380 {
00381   // Find a route to dest address. As in the embedded code, if no route exists, indicate
00382   // final destination as next hop. If we'are lucky, final destination is one hop away...
00383   // If I am the origin of the packet and no route exists, use flood, hence return broadcast
00384   // address for next hop.
00385   tRouteTable::iterator pos = routeTable.find(destAddr);
00386   if (pos != routeTable.end())
00387     return pos->second.nextHop;
00388   else
00389     return L3BROADCAST;
00390 }