LinkStateRouting.cc

Go to the documentation of this file.
00001 //
00002 // (C) 2005 Vojtech Janota, Andras Varga
00003 //
00004 // This library is free software, you can redistribute it
00005 // and/or modify
00006 // it under  the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation;
00008 // either version 2 of the License, or any later version.
00009 // The library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00012 // See the GNU Lesser General Public License for more details.
00013 //
00014 
00015 #include <omnetpp.h>
00016 #include <algorithm>
00017 
00018 #include "LinkStateRouting.h"
00019 #include "IPControlInfo.h"
00020 #include "IPv4InterfaceData.h"
00021 #include "NotifierConsts.h"
00022 #include "RoutingTableAccess.h"
00023 #include "InterfaceTableAccess.h"
00024 #include "NotificationBoard.h"
00025 #include "TED.h"
00026 #include "TEDAccess.h"
00027 
00028 Define_Module(LinkStateRouting);
00029 
00030 LinkStateRouting::LinkStateRouting()
00031 {
00032     announceMsg = NULL;
00033 }
00034 
00035 LinkStateRouting::~LinkStateRouting()
00036 {
00037     cancelAndDelete(announceMsg);
00038 }
00039 
00040 void LinkStateRouting::initialize(int stage)
00041 {
00042     // we have to wait until routerId gets assigned in stage 3
00043     if (stage==4)
00044     {
00045         tedmod = TEDAccess().get();
00046 
00047         IRoutingTable *rt = RoutingTableAccess().get();
00048         routerId = rt->getRouterId();
00049 
00050         // listen for TED modifications
00051         NotificationBoard *nb = NotificationBoardAccess().get();
00052         nb->subscribe(this, NF_TED_CHANGED);
00053 
00054         // peers are given as interface names in the "peers" module parameter;
00055         // store corresponding interface addresses in peerIfAddrs[]
00056         cStringTokenizer tokenizer(par("peers"));
00057         IInterfaceTable *ift = InterfaceTableAccess().get();
00058         const char *token;
00059         while ((token = tokenizer.nextToken())!=NULL)
00060         {
00061             ASSERT(ift->getInterfaceByName(token));
00062             peerIfAddrs.push_back(ift->getInterfaceByName(token)->ipv4Data()->getIPAddress());
00063         }
00064 
00065         // schedule start of flooding link state info
00066         announceMsg = new cMessage("announce");
00067         scheduleAt(simTime() + exponential(0.01), announceMsg);
00068     }
00069 }
00070 
00071 void LinkStateRouting::handleMessage(cMessage * msg)
00072 {
00073     if (msg == announceMsg)
00074     {
00075         delete announceMsg;
00076         announceMsg = NULL;
00077         sendToPeers(tedmod->ted, true, IPAddress());
00078     }
00079     else if (!strcmp(msg->getArrivalGate()->getName(), "ipIn"))
00080     {
00081         EV << "Processing message from IP: " << msg << endl;
00082         IPControlInfo *controlInfo = check_and_cast<IPControlInfo *>(msg->getControlInfo());
00083         IPAddress sender = controlInfo->getSrcAddr();
00084         processLINK_STATE_MESSAGE(check_and_cast<LinkStateMsg*>(msg), sender);
00085     }
00086     else
00087         ASSERT(false);
00088 }
00089 
00090 void LinkStateRouting::receiveChangeNotification(int category, const cPolymorphic *details)
00091 {
00092     Enter_Method_Silent();
00093     printNotificationBanner(category, details);
00094 
00095     ASSERT(category == NF_TED_CHANGED);
00096 
00097     EV << "TED changed\n";
00098 
00099     TEDChangeInfo *d = check_and_cast<TEDChangeInfo *>(details);
00100 
00101     unsigned int k = d->getTedLinkIndicesArraySize();
00102 
00103     ASSERT(k > 0);
00104 
00105     // build linkinfo list
00106     std::vector<TELinkStateInfo> links;
00107     for (unsigned int i = 0; i < k; i++)
00108     {
00109         unsigned int index = d->getTedLinkIndices(i);
00110 
00111         tedmod->updateTimestamp(&tedmod->ted[index]);
00112         links.push_back(tedmod->ted[index]);
00113     }
00114 
00115     sendToPeers(links, false, IPAddress());
00116 }
00117 
00118 void LinkStateRouting::processLINK_STATE_MESSAGE(LinkStateMsg* msg, IPAddress sender)
00119 {
00120     EV << "received LINK_STATE message from " << sender << endl;
00121 
00122     TELinkStateInfoVector forward;
00123 
00124     unsigned int n = msg->getLinkInfoArraySize();
00125 
00126     bool change = false; // in topology
00127 
00128     // loop through every link in the message
00129     for (unsigned int i = 0; i < n; i++)
00130     {
00131         const TELinkStateInfo& link = msg->getLinkInfo(i);
00132 
00133         TELinkStateInfo *match;
00134 
00135         // process link if we haven't seen this already and timestamp is newer
00136         if(tedmod->checkLinkValidity(link, match))
00137         {
00138             ASSERT(link.sourceId == link.advrouter.getInt());
00139 
00140             EV << "new information found" << endl;
00141 
00142             if(!match)
00143             {
00144                 // and we have no info on this link so far, store it as it is
00145                 tedmod->ted.push_back(link);
00146                 change = true;
00147             }
00148             else
00149             {
00150                 // copy over the information from it
00151                 if(match->state != link.state)
00152                 {
00153                     match->state = link.state;
00154                     change = true;
00155                 }
00156                 match->messageId = link.messageId;
00157                 match->sourceId = link.sourceId;
00158                 match->timestamp = link.timestamp;
00159                 for(int i = 0; i < 8; i++)
00160                     match->UnResvBandwidth[i] = link.UnResvBandwidth[i];
00161                 match->MaxBandwidth = link.MaxBandwidth;
00162                 match->metric = link.metric;
00163             }
00164 
00165             forward.push_back(link);
00166         }
00167     }
00168 
00169     if(change)
00170         tedmod->rebuildRoutingTable();
00171 
00172     if(msg->getRequest())
00173     {
00174         sendToPeer(sender, tedmod->ted, false);
00175     }
00176 
00177     if(forward.size() > 0)
00178     {
00179         sendToPeers(forward, false, sender);
00180     }
00181 
00182     delete msg;
00183 }
00184 
00185 void LinkStateRouting::sendToPeers(const std::vector<TELinkStateInfo>& list, bool req, IPAddress exceptPeer)
00186 {
00187     EV << "sending LINK_STATE message to peers" << endl;
00188 
00189     // send "list" to every peer (linkid in our ted[] entries???) in a LinkStateMsg
00190     for (unsigned int i = 0; i < tedmod->ted.size(); i++)
00191     {
00192         if(tedmod->ted[i].advrouter != routerId)
00193             continue;
00194 
00195         if(tedmod->ted[i].linkid == exceptPeer)
00196             continue;
00197 
00198         if(!tedmod->ted[i].state)
00199             continue;
00200 
00201         if(find(peerIfAddrs.begin(), peerIfAddrs.end(), tedmod->ted[i].local) == peerIfAddrs.end())
00202             continue;
00203 
00204         // send a copy
00205         sendToPeer(tedmod->ted[i].linkid, list, req);
00206     }
00207 }
00208 
00209 void LinkStateRouting::sendToPeer(IPAddress peer, const std::vector<TELinkStateInfo> & list, bool req)
00210 {
00211     EV << "sending LINK_STATE message to " << peer << endl;
00212 
00213     LinkStateMsg *out = new LinkStateMsg("link state");
00214 
00215     out->setLinkInfoArraySize(list.size());
00216     for (unsigned int j = 0; j < list.size(); j++)
00217         out->setLinkInfo(j, list[j]);
00218 
00219     out->setRequest(req);
00220 
00221     sendToIP(out, peer);
00222 }
00223 
00224 void LinkStateRouting::sendToIP(LinkStateMsg *msg, IPAddress destAddr)
00225 {
00226     // attach control info to packet
00227     IPControlInfo *controlInfo = new IPControlInfo();
00228     controlInfo->setDestAddr(destAddr);
00229     controlInfo->setSrcAddr(routerId);
00230     controlInfo->setProtocol(IP_PROT_OSPF);
00231     msg->setControlInfo(controlInfo);
00232 
00233     int length = msg->getLinkInfoArraySize() * 72;
00234     msg->setByteLength(length);
00235 
00236     msg->addPar("color") = TED_TRAFFIC;
00237 
00238     send(msg, "ipOut");
00239 }
00240