INET Framework for OMNeT++/OMNEST
|
#include <LinkStateRouting.h>
Public Member Functions | |
LinkStateRouting () | |
virtual | ~LinkStateRouting () |
Protected Member Functions | |
virtual void | initialize (int stage) |
virtual int | numInitStages () const |
virtual void | handleMessage (cMessage *msg) |
virtual void | processLINK_STATE_MESSAGE (LinkStateMsg *msg, IPAddress sender) |
virtual void | receiveChangeNotification (int category, const cPolymorphic *details) |
virtual void | sendToPeers (const std::vector< TELinkStateInfo > &list, bool req, IPAddress exceptPeer) |
virtual void | sendToPeer (IPAddress peer, const std::vector< TELinkStateInfo > &list, bool req) |
virtual void | sendToIP (LinkStateMsg *msg, IPAddress destAddr) |
Protected Attributes | |
TED * | tedmod |
cMessage * | announceMsg |
IPAddress | routerId |
IPAddressVector | peerIfAddrs |
Implements a minimalistic link state routing protocol that employs flooding. Flooding works like this:
When a router receives a link state packet, it merges the packet contents into its own link state database (ted). If the packet contained new information (ted got updated), the router broadcasts the ted contents to all its other neighbours; otherwise (when the packet didn't contain any new info), nothing happens.
Also: when the announceMsg timer expires, LinkStateRouting sends out an initial link state message. (Currently this happens only once, at the beginning of the simulation). The "request" bit in the message is set then, asking neighbours to send back their link state databases. (FIXME why's this? redundant messaging: same msg is often sent twice: both as reply and as voluntary "announce").
TODO discover peers by "hello". Peers are those from which the router has received a Hello in the last X seconds. Link info to all peers are maintained; links to ex-peers (those haven't heard of for more than X seconds) are assumed to be down.
See NED file for more info.
LinkStateRouting::LinkStateRouting | ( | ) |
{ announceMsg = NULL; }
LinkStateRouting::~LinkStateRouting | ( | ) | [virtual] |
{ cancelAndDelete(announceMsg); }
void LinkStateRouting::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
{ if (msg == announceMsg) { delete announceMsg; announceMsg = NULL; sendToPeers(tedmod->ted, true, IPAddress()); } else if (!strcmp(msg->getArrivalGate()->getName(), "ipIn")) { EV << "Processing message from IP: " << msg << endl; IPControlInfo *controlInfo = check_and_cast<IPControlInfo *>(msg->getControlInfo()); IPAddress sender = controlInfo->getSrcAddr(); processLINK_STATE_MESSAGE(check_and_cast<LinkStateMsg*>(msg), sender); } else ASSERT(false); }
void LinkStateRouting::initialize | ( | int | stage | ) | [protected, virtual] |
{ // we have to wait until routerId gets assigned in stage 3 if (stage==4) { tedmod = TEDAccess().get(); IRoutingTable *rt = RoutingTableAccess().get(); routerId = rt->getRouterId(); // listen for TED modifications NotificationBoard *nb = NotificationBoardAccess().get(); nb->subscribe(this, NF_TED_CHANGED); // peers are given as interface names in the "peers" module parameter; // store corresponding interface addresses in peerIfAddrs[] cStringTokenizer tokenizer(par("peers")); IInterfaceTable *ift = InterfaceTableAccess().get(); const char *token; while ((token = tokenizer.nextToken())!=NULL) { ASSERT(ift->getInterfaceByName(token)); peerIfAddrs.push_back(ift->getInterfaceByName(token)->ipv4Data()->getIPAddress()); } // schedule start of flooding link state info announceMsg = new cMessage("announce"); scheduleAt(simTime() + exponential(0.01), announceMsg); } }
virtual int LinkStateRouting::numInitStages | ( | ) | const [inline, protected, virtual] |
{return 5;}
void LinkStateRouting::processLINK_STATE_MESSAGE | ( | LinkStateMsg * | msg, |
IPAddress | sender | ||
) | [protected, virtual] |
Referenced by handleMessage().
{ EV << "received LINK_STATE message from " << sender << endl; TELinkStateInfoVector forward; unsigned int n = msg->getLinkInfoArraySize(); bool change = false; // in topology // loop through every link in the message for (unsigned int i = 0; i < n; i++) { const TELinkStateInfo& link = msg->getLinkInfo(i); TELinkStateInfo *match; // process link if we haven't seen this already and timestamp is newer if(tedmod->checkLinkValidity(link, match)) { ASSERT(link.sourceId == link.advrouter.getInt()); EV << "new information found" << endl; if(!match) { // and we have no info on this link so far, store it as it is tedmod->ted.push_back(link); change = true; } else { // copy over the information from it if(match->state != link.state) { match->state = link.state; change = true; } match->messageId = link.messageId; match->sourceId = link.sourceId; match->timestamp = link.timestamp; for(int i = 0; i < 8; i++) match->UnResvBandwidth[i] = link.UnResvBandwidth[i]; match->MaxBandwidth = link.MaxBandwidth; match->metric = link.metric; } forward.push_back(link); } } if(change) tedmod->rebuildRoutingTable(); if(msg->getRequest()) { sendToPeer(sender, tedmod->ted, false); } if(forward.size() > 0) { sendToPeers(forward, false, sender); } delete msg; }
void LinkStateRouting::receiveChangeNotification | ( | int | category, |
const cPolymorphic * | details | ||
) | [protected, virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
{ Enter_Method_Silent(); printNotificationBanner(category, details); ASSERT(category == NF_TED_CHANGED); EV << "TED changed\n"; TEDChangeInfo *d = check_and_cast<TEDChangeInfo *>(details); unsigned int k = d->getTedLinkIndicesArraySize(); ASSERT(k > 0); // build linkinfo list std::vector<TELinkStateInfo> links; for (unsigned int i = 0; i < k; i++) { unsigned int index = d->getTedLinkIndices(i); tedmod->updateTimestamp(&tedmod->ted[index]); links.push_back(tedmod->ted[index]); } sendToPeers(links, false, IPAddress()); }
void LinkStateRouting::sendToIP | ( | LinkStateMsg * | msg, |
IPAddress | destAddr | ||
) | [protected, virtual] |
Referenced by sendToPeer().
{ // attach control info to packet IPControlInfo *controlInfo = new IPControlInfo(); controlInfo->setDestAddr(destAddr); controlInfo->setSrcAddr(routerId); controlInfo->setProtocol(IP_PROT_OSPF); msg->setControlInfo(controlInfo); int length = msg->getLinkInfoArraySize() * 72; msg->setByteLength(length); msg->addPar("color") = TED_TRAFFIC; send(msg, "ipOut"); }
void LinkStateRouting::sendToPeer | ( | IPAddress | peer, |
const std::vector< TELinkStateInfo > & | list, | ||
bool | req | ||
) | [protected, virtual] |
Referenced by processLINK_STATE_MESSAGE(), and sendToPeers().
void LinkStateRouting::sendToPeers | ( | const std::vector< TELinkStateInfo > & | list, |
bool | req, | ||
IPAddress | exceptPeer | ||
) | [protected, virtual] |
Referenced by handleMessage(), processLINK_STATE_MESSAGE(), and receiveChangeNotification().
{ EV << "sending LINK_STATE message to peers" << endl; // send "list" to every peer (linkid in our ted[] entries???) in a LinkStateMsg for (unsigned int i = 0; i < tedmod->ted.size(); i++) { if(tedmod->ted[i].advrouter != routerId) continue; if(tedmod->ted[i].linkid == exceptPeer) continue; if(!tedmod->ted[i].state) continue; if(find(peerIfAddrs.begin(), peerIfAddrs.end(), tedmod->ted[i].local) == peerIfAddrs.end()) continue; // send a copy sendToPeer(tedmod->ted[i].linkid, list, req); } }
cMessage* LinkStateRouting::announceMsg [protected] |
Referenced by handleMessage(), initialize(), LinkStateRouting(), and ~LinkStateRouting().
IPAddressVector LinkStateRouting::peerIfAddrs [protected] |
Referenced by initialize(), and sendToPeers().
IPAddress LinkStateRouting::routerId [protected] |
Referenced by initialize(), sendToIP(), and sendToPeers().
TED* LinkStateRouting::tedmod [protected] |
Referenced by handleMessage(), initialize(), processLINK_STATE_MESSAGE(), receiveChangeNotification(), and sendToPeers().