Flood.cc

00001 /* -*- mode:c++ -*- ********************************************************
00002  * file:        Flood.cc
00003  *
00004  * author:      Daniel Willkomm
00005  *
00006  * copyright:   (C) 2004 Telecommunication Networks Group (TKN) at
00007  *              Technische Universitaet Berlin, Germany.
00008  *
00009  *              This program is free software; you can redistribute it 
00010  *              and/or modify it under the terms of the GNU General Public 
00011  *              License as published by the Free Software Foundation; either
00012  *              version 2 of the License, or (at your option) any later 
00013  *              version.
00014  *              For further information see file COPYING 
00015  *              in the top level directory
00016  *
00017  ***************************************************************************
00018  * part of:     framework implementation developed by tkn
00019  * description: a simple flooding protocol
00020  *              the user can decide whether to use plain flooding or not
00021  **************************************************************************/
00022 
00023 #include "Flood.h"
00024 #include <NetwPkt_m.h>
00025 #include "NetwControlInfo.h"
00026 #include "NetwToMacControlInfo.h"
00027 #include <cassert>
00028 
00029 Define_Module(Flood)
00030 ;
00031 
00036 void Flood::initialize(int stage) {
00037   BaseNetwLayer::initialize(stage);
00038 
00039   if (stage == 0) {
00040     //initialize seqence number to 0
00041     seqNum = 0;
00042     nbDataPacketsReceived = 0;
00043     nbDataPacketsSent = 0;
00044     nbDataPacketsForwarded = 0;
00045     nbHops = 0;
00046     hasPar("defaultTtl") ? defaultTtl = par("defaultTtl") : defaultTtl = 5;
00047     hasPar("plainFlooding") ? plainFlooding = par("plainFlooding")
00048         : plainFlooding = true;
00049 
00050     EV<< "defaultTtl = " << defaultTtl
00051     << " plainFlooding = " << plainFlooding << endl;
00052 
00053     if(plainFlooding) {
00054       //these parameters are only needed for plain flooding
00055       hasPar("bcMaxEntries") ? bcMaxEntries = par("bcMaxEntries") : bcMaxEntries = 30;
00056 
00057       hasPar("bcDelTime") ? bcDelTime = par("bcDelTime") : bcDelTime = 3.0;
00058       EV <<"bcMaxEntries = "<<bcMaxEntries
00059       <<" bcDelTime = "<<bcDelTime<<endl;
00060     }
00061   }
00062 }
00063 
00064 void Flood::finish() {
00065   if (plainFlooding) {
00066     bcMsgs.clear();
00067   }
00068   recordScalar("nbDataPacketsReceived", nbDataPacketsReceived);
00069   recordScalar("nbDataPacketsSent", nbDataPacketsSent);
00070   recordScalar("nbDataPacketsForwarded", nbDataPacketsForwarded);
00071   if (nbDataPacketsReceived > 0) {
00072     recordScalar("meanNbHops", (double) nbHops / (double) nbDataPacketsReceived);
00073   } else {
00074     recordScalar("meanNbHops", 0);
00075   }
00076 }
00077 
00092 void Flood::handleUpperMsg(cMessage* m) {
00093 
00094   assert(dynamic_cast<cPacket*> (m));
00095   NetwPkt *msg = encapsMsg(static_cast<cPacket*> (m));
00096 
00097   msg->setSeqNum(seqNum);
00098   seqNum++;
00099   msg->setTtl(defaultTtl);
00100 
00101   if (plainFlooding) {
00102     if (bcMsgs.size() >= bcMaxEntries) {
00103       cBroadcastList::iterator it;
00104 
00105       //serach the broadcast list of outdated entries and delete them
00106       for (it = bcMsgs.begin(); it != bcMsgs.end(); ++it) {
00107         if (it->delTime < simTime()) {
00108           bcMsgs.erase(it);
00109           it--;
00110           break;
00111         }
00112       }
00113       //delete oldest entry if max size is reached
00114       if (bcMsgs.size() >= bcMaxEntries) {
00115         EV<<"bcMsgs is full, delete oldest entry"<<endl;
00116         bcMsgs.pop_front();
00117       }
00118     }
00119     bcMsgs.push_back(Bcast(msg->getSeqNum(), msg->getSrcAddr(), simTime() +bcDelTime));
00120     }
00121         //there is no routing so all messages are broadacst for the mac layer
00122 
00123         sendDown(msg);
00124         nbDataPacketsSent++;
00125       }
00126 
00140 void Flood::handleLowerMsg(cMessage* m) {
00141   NetwPkt *msg = static_cast<NetwPkt *> (m);
00142 
00143   //msg not broadcastes yet
00144   if (notBroadcasted(msg)) {
00145     //msg is for me
00146     if (msg->getDestAddr() == myNetwAddr) {
00147       EV<<" data msg for me! send to Upper"<<endl;
00148       nbHops = nbHops + (defaultTtl + 1 - msg->getTtl());
00149       sendUp( decapsMsg(msg) );
00150       nbDataPacketsReceived++;
00151     }
00152     //broadcast message
00153     else if( msg->getDestAddr() == L3BROADCAST ) {
00154       //check ttl and rebroadcast
00155       if( msg->getTtl() > 1 ) {
00156         NetwPkt *dMsg;
00157         EV <<" data msg BROADCAST! ttl = "<<msg->getTtl()
00158         <<" > 1 -> rebroadcast msg & send to upper\n";
00159         msg->setTtl( msg->getTtl()-1 );
00160         dMsg = static_cast<NetwPkt*>(msg->dup());
00161         dMsg->setControlInfo(new NetwToMacControlInfo(L2BROADCAST));
00162         sendDown(dMsg);
00163         nbDataPacketsForwarded++;
00164       }
00165       else
00166       EV <<" max hops reached (ttl = "<<msg->getTtl()<<") -> only send to upper\n";
00167 
00168       // message has to be forwarded to upper layer
00169       nbHops = nbHops + (defaultTtl + 1 - msg->getTtl());
00170       sendUp( decapsMsg(msg) );
00171       nbDataPacketsReceived++;
00172     }
00173     //not for me -> rebroadcast
00174     else {
00175       //check ttl and rebroadcast
00176       if( msg->getTtl() > 1 ) {
00177         EV <<" data msg not for me! ttl = "<<msg->getTtl()
00178         <<" > 1 -> forward\n";
00179         msg->setTtl( msg->getTtl()-1 );
00180         // needs to set the next hop address again to broadcast
00181         msg->removeControlInfo();
00182         msg->setControlInfo(new NetwToMacControlInfo(L2BROADCAST));
00183         //            EV << static_cast<NetwToMacControlInfo*>(msg->getControlInfo())->getNextHopMac() << "\n";
00184         sendDown( msg );
00185         nbDataPacketsForwarded++;
00186       }
00187       else {
00188         //max hops reached -> delete
00189         EV <<" max hops reached (ttl = "<<msg->getTtl()<<") -> delete msg\n";
00190         delete msg;
00191       }
00192     }
00193   }
00194   else {
00195     EV <<" data msg already BROADCASTed! delete msg\n";
00196     delete msg;
00197   }
00198 }
00199 
00209 bool Flood::notBroadcasted(NetwPkt* msg) {
00210   if (!plainFlooding)
00211     return true;
00212 
00213   cBroadcastList::iterator it;
00214 
00215   //serach the broadcast list of outdated entries and delete them
00216   for (it = bcMsgs.begin(); it != bcMsgs.end(); it++) {
00217     if (it->delTime < simTime()) {
00218       bcMsgs.erase(it);
00219       it--;
00220     }
00221     //message was already broadcasted
00222     if ((it->srcAddr == msg->getSrcAddr()) && (it->seqNum
00223         == msg->getSeqNum())) {
00224       // update entry
00225       it->delTime = simTime() + bcDelTime;
00226       return false;
00227     }
00228   }
00229 
00230   //delete oldest entry if max size is reached
00231   if (bcMsgs.size() >= bcMaxEntries) {
00232     EV<<"bcMsgs is full, delete oldest entry\n";
00233     bcMsgs.pop_front();
00234   }
00235 
00236   bcMsgs.push_back(Bcast(msg->getSeqNum(), msg->getSrcAddr(), simTime() +bcDelTime));
00237     return true;
00238 }
00239 
00240 NetwPkt* Flood::encapsMsg(cPacket *appPkt) {
00241   int macAddr;
00242   int netwAddr;
00243 
00244   EV<<"in encaps...\n";
00245 
00246   NetwPkt *pkt = new NetwPkt(appPkt->getName(), appPkt->getKind());
00247   pkt->setBitLength(headerLength);
00248 
00249   NetwControlInfo* cInfo = dynamic_cast<NetwControlInfo*>(appPkt->removeControlInfo());
00250 
00251     if(cInfo == 0){
00252   EV << "warning: Application layer did not specifiy a destination L3 address\n"
00253      << "\tusing broadcast address instead\n";
00254   netwAddr = L3BROADCAST;
00255     } else {
00256   EV <<"CInfo removed, netw addr="<< cInfo->getNetwAddr()<<endl;
00257         netwAddr = cInfo->getNetwAddr();
00258   delete cInfo;
00259     }
00260 
00261     pkt->setSrcAddr(myNetwAddr);
00262     pkt->setDestAddr(netwAddr);
00263     EV << " netw "<< myNetwAddr << " sending packet" <<endl;
00264 
00265         EV << "sendDown: nHop=L3BROADCAST -> message has to be broadcasted"
00266            << " -> set destMac=L2BROADCAST\n";
00267         macAddr = L2BROADCAST;
00268 
00269 
00270     pkt->setControlInfo(new NetwToMacControlInfo(macAddr));
00271 
00272     //encapsulate the application packet
00273     pkt->encapsulate(appPkt);
00274     EV <<" pkt encapsulated\n";
00275     return pkt;
00276 }