LDP.cc

Go to the documentation of this file.
00001 //
00002 // (C) 2005 Vojtech Janota
00003 // (C) 2004 Andras Varga
00004 //
00005 // This library is free software, you can redistribute it
00006 // and/or modify
00007 // it under  the terms of the GNU Lesser General Public License
00008 // as published by the Free Software Foundation;
00009 // either version 2 of the License, or any later version.
00010 // The library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00013 // See the GNU Lesser General Public License for more details.
00014 //
00015 
00016 #include <omnetpp.h>
00017 #include <iostream>
00018 #include <fstream>
00019 #include <algorithm>
00020 #include "ConstType.h"
00021 #include "LDP.h"
00022 #include "LIBTable.h"
00023 #include "InterfaceTableAccess.h"
00024 #include "IPv4InterfaceData.h"
00025 #include "RoutingTableAccess.h"
00026 #include "LIBTableAccess.h"
00027 #include "TEDAccess.h"
00028 #include "NotifierConsts.h"
00029 #include "UDPPacket.h"
00030 #include "TCPSegment.h"
00031 
00032 
00033 Define_Module(LDP);
00034 
00035 
00036 std::ostream& operator<<(std::ostream& os, const LDP::fec_bind_t& f)
00037 {
00038     os << "fecid=" << f.fecid << "  peer=" << f.peer << " label=" << f.label;
00039     return os;
00040 }
00041 
00042 bool fecPrefixCompare(const LDP::fec_t& a, const LDP::fec_t& b)
00043 {
00044     return a.length > b.length;
00045 }
00046 
00047 std::ostream& operator<<(std::ostream& os, const LDP::fec_t& f)
00048 {
00049     os << "fecid=" << f.fecid << "  addr=" << f.addr << "  length=" << f.length << "  nextHop=" << f.nextHop;
00050     return os;
00051 }
00052 
00053 std::ostream& operator<<(std::ostream& os, const LDP::pending_req_t& r)
00054 {
00055     os << "fecid=" << r.fecid << "  peer=" << r.peer;
00056     return os;
00057 }
00058 
00059 std::ostream& operator<<(std::ostream& os, const LDP::peer_info& p)
00060 {
00061     os << "peerIP=" << p.peerIP << "  interface=" << p.linkInterface <<
00062           "  activeRole=" << (p.activeRole ? "true" : "false") <<
00063           "  socket=" << (p.socket ? TCPSocket::stateName(p.socket->getState()) : "NULL");
00064     return os;
00065 }
00066 
00067 bool operator==(const FEC_TLV& a, const FEC_TLV& b)
00068 {
00069     return a.length == b.length && a.addr == b.addr;
00070 }
00071 
00072 bool operator!=(const FEC_TLV& a, const FEC_TLV& b)
00073 {
00074     return !operator==(a, b);
00075 }
00076 
00077 std::ostream& operator<<(std::ostream& os, const FEC_TLV& a)
00078 {
00079     os << "addr=" << a.addr << "  length=" << a.length;
00080     return os;
00081 }
00082 
00083 
00084 LDP::LDP()
00085 {
00086     sendHelloMsg = NULL;
00087 }
00088 
00089 LDP::~LDP()
00090 {
00091     for (unsigned int i=0; i<myPeers.size(); i++)
00092         cancelAndDelete(myPeers[i].timeout);
00093 
00094     cancelAndDelete(sendHelloMsg);
00095     //this causes segfault at the end of simulation       -- Vojta
00096     //socketMap.deleteSockets();
00097 }
00098 
00099 void LDP::initialize(int stage)
00100 {
00101     if (stage != 3)
00102         return; // wait for routing table to initialize first
00103 
00104     holdTime = par("holdTime").doubleValue();
00105     helloInterval = par("helloInterval").doubleValue();
00106 
00107     ift = InterfaceTableAccess().get();
00108     rt = RoutingTableAccess().get();
00109     lt = LIBTableAccess().get();
00110     tedmod = TEDAccess().get();
00111     nb = NotificationBoardAccess().get();
00112 
00113     WATCH_VECTOR(myPeers);
00114     WATCH_VECTOR(fecUp);
00115     WATCH_VECTOR(fecDown);
00116     WATCH_VECTOR(fecList);
00117     WATCH_VECTOR(pending);
00118 
00119     maxFecid = 0;
00120 
00121     // schedule first hello
00122     sendHelloMsg = new cMessage("LDPSendHello");
00123     scheduleAt(simTime() + exponential(0.1), sendHelloMsg);
00124 
00125     // bind UDP socket
00126     udpSocket.setOutputGate(gate("udpOut"));
00127     udpSocket.bind(LDP_PORT);
00128 
00129     // start listening for incoming TCP conns
00130     EV << "Starting to listen on port " << LDP_PORT << " for incoming LDP sessions\n";
00131     serverSocket.setOutputGate(gate("tcpOut"));
00132     serverSocket.bind(LDP_PORT);
00133     serverSocket.listen();
00134 
00135     // build list of recognized FECs
00136     rebuildFecList();
00137 
00138     // listen for routing table modifications
00139     nb->subscribe(this, NF_IPv4_ROUTE_ADDED);
00140     nb->subscribe(this, NF_IPv4_ROUTE_DELETED);
00141 }
00142 
00143 void LDP::handleMessage(cMessage *msg)
00144 {
00145     EV << "Received: (" << msg->getClassName() << ")" << msg->getName() << "\n";
00146     if (msg==sendHelloMsg)
00147     {
00148         // every LDP capable router periodically sends HELLO messages to the
00149         // "all routers in the sub-network" multicast address
00150         EV << "Multicasting LDP Hello to neighboring routers\n";
00151         sendHelloTo(IPAddress::ALL_ROUTERS_MCAST);
00152 
00153         // schedule next hello
00154         scheduleAt(simTime() + helloInterval, sendHelloMsg);
00155     }
00156     else if (msg->isSelfMessage())
00157     {
00158         EV << "Timer " << msg->getName() << " expired\n";
00159         if (!strcmp(msg->getName(), "HelloTimeout"))
00160         {
00161             processHelloTimeout(msg);
00162         }
00163         else
00164         {
00165             processNOTIFICATION(check_and_cast<LDPNotify*>(msg));
00166         }
00167     }
00168     else if (!strcmp(msg->getArrivalGate()->getName(), "udpIn"))
00169     {
00170         // we can only receive LDP Hello from UDP (everything else goes over TCP)
00171         processLDPHello(check_and_cast<LDPHello *>(msg));
00172     }
00173     else if (!strcmp(msg->getArrivalGate()->getName(), "tcpIn"))
00174     {
00175         processMessageFromTCP(msg);
00176     }
00177 }
00178 
00179 void LDP::sendToPeer(IPAddress dest, cMessage *msg)
00180 {
00181     getPeerSocket(dest)->send(msg);
00182 }
00183 
00184 void LDP::sendMappingRequest(IPAddress dest, IPAddress addr, int length)
00185 {
00186     LDPLabelRequest *requestMsg = new LDPLabelRequest("Lb-Req");
00187     requestMsg->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
00188     requestMsg->setType(LABEL_REQUEST);
00189 
00190     FEC_TLV fec;
00191     fec.addr = addr;
00192     fec.length = length;
00193     requestMsg->setFec(fec);
00194 
00195     requestMsg->setReceiverAddress(dest);
00196     requestMsg->setSenderAddress(rt->getRouterId());
00197 
00198     sendToPeer(dest, requestMsg);
00199 }
00200 
00201 void LDP::updateFecListEntry(LDP::fec_t oldItem)
00202 {
00203     // do we have mapping from downstream?
00204     FecBindVector::iterator dit = findFecEntry(fecDown, oldItem.fecid, oldItem.nextHop);
00205 
00206     // is next hop our LDP peer?
00207     bool ER = findPeerSocket(oldItem.nextHop)==NULL;
00208 
00209     ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time
00210 
00211     // adjust upstream mappings
00212     FecBindVector::iterator uit;
00213     for (uit = fecUp.begin(); uit != fecUp.end();)
00214     {
00215         if (uit->fecid != oldItem.fecid)
00216         {
00217             uit++;
00218             continue;
00219         }
00220 
00221         std::string inInterface = findInterfaceFromPeerAddr(uit->peer);
00222         std::string outInterface = findInterfaceFromPeerAddr(oldItem.nextHop);
00223         if (ER)
00224         {
00225             // we are egress, that's easy:
00226             LabelOpVector outLabel = LIBTable::popLabel();
00227             uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
00228 
00229             EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00230                     " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00231             uit++;
00232         }
00233         else if (dit != fecDown.end())
00234         {
00235             // we have mapping from DS, that's easy
00236             LabelOpVector outLabel = LIBTable::swapLabel(dit->label);
00237             uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
00238 
00239             EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00240                     " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00241             uit++;
00242         }
00243         else
00244         {
00245             // no mapping from DS, withdraw mapping US
00246             EV << "sending withdraw message upstream" << endl;
00247             sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, oldItem.addr, oldItem.length);
00248 
00249             // remove from US mappings
00250             uit = fecUp.erase(uit);
00251         }
00252     }
00253 
00254     if (!ER && dit == fecDown.end())
00255     {
00256         // and ask DS for mapping
00257         EV << "sending request message downstream" << endl;
00258         sendMappingRequest(oldItem.nextHop, oldItem.addr, oldItem.length);
00259     }
00260 }
00261 
00262 void LDP::rebuildFecList()
00263 {
00264     EV << "make list of recognized FECs" << endl;
00265 
00266     FecVector oldList = fecList;
00267     fecList.clear();
00268 
00269     for (int i = 0; i < rt->getNumRoutes(); i++)
00270     {
00271         // every entry in the routing table
00272 
00273         const IPRoute *re = rt->getRoute(i);
00274 
00275         // ignore multicast routes
00276         if (re->getHost().isMulticast())
00277             continue;
00278 
00279         // find out current next hop according to routing table
00280         IPAddress nextHop = (re->getType() == IPRoute::DIRECT) ? re->getHost() : re->getGateway();
00281         ASSERT(!nextHop.isUnspecified());
00282 
00283         EV << "nextHop <-- " << nextHop << endl;
00284 
00285         FecVector::iterator it = findFecEntry(oldList, re->getHost(), re->getNetmask().getNetmaskLength());
00286 
00287         if (it == oldList.end())
00288         {
00289             // fec didn't exist, it was just created
00290             fec_t newItem;
00291             newItem.fecid = ++maxFecid;
00292             newItem.addr = re->getHost();
00293             newItem.length = re->getNetmask().getNetmaskLength();
00294             newItem.nextHop = nextHop;
00295             updateFecListEntry(newItem);
00296             fecList.push_back(newItem);
00297         }
00298         else if (it->nextHop != nextHop)
00299         {
00300             // next hop for this FEC changed,
00301             it->nextHop = nextHop;
00302             updateFecListEntry(*it);
00303             fecList.push_back(*it);
00304             oldList.erase(it);
00305         }
00306         else
00307         {
00308             // FEC didn't change, reusing old values
00309             fecList.push_back(*it);
00310             oldList.erase(it);
00311             continue;
00312         }
00313     }
00314 
00315 
00316     // our own addresses (XXX is it needed?)
00317 
00318     for (int i = 0; i< ift->getNumInterfaces(); ++i)
00319     {
00320         InterfaceEntry *ie = ift->getInterface(i);
00321         if (ie->getNetworkLayerGateIndex() < 0)
00322             continue;
00323 
00324         FecVector::iterator it = findFecEntry(oldList, ie->ipv4Data()->getIPAddress(), 32);
00325         if (it == oldList.end())
00326         {
00327             fec_t newItem;
00328             newItem.fecid = ++maxFecid;
00329             newItem.addr = ie->ipv4Data()->getIPAddress();
00330             newItem.length = 32;
00331             newItem.nextHop = ie->ipv4Data()->getIPAddress();
00332             fecList.push_back(newItem);
00333         }
00334         else
00335         {
00336             fecList.push_back(*it);
00337             oldList.erase(it);
00338         }
00339     }
00340 
00341     if (oldList.size() > 0)
00342     {
00343         EV << "there are " << oldList.size() << " deprecated FECs, removing them" << endl;
00344 
00345         FecVector::iterator it;
00346         for (it = oldList.begin(); it != oldList.end(); it++)
00347         {
00348             EV << "removing FEC= " << *it << endl;
00349 
00350             FecBindVector::iterator dit;
00351             for (dit = fecDown.begin(); dit != fecDown.end(); dit++)
00352             {
00353                 if (dit->fecid != it->fecid)
00354                     continue;
00355 
00356                 EV << "sending release label=" << dit->label << " downstream to " << dit->peer << endl;
00357 
00358                 sendMapping(LABEL_RELEASE, dit->peer, dit->label, it->addr, it->length);
00359             }
00360 
00361             FecBindVector::iterator uit;
00362             for (uit = fecUp.begin(); uit != fecUp.end(); uit++)
00363             {
00364                 if (uit->fecid != it->fecid)
00365                     continue;
00366 
00367                 EV << "sending withdraw label=" << uit->label << " upstream to " << uit->peer << endl;
00368 
00369                 sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, it->addr, it->length);
00370 
00371                 EV << "removing entry inLabel=" << uit->label << " from LIB" << endl;
00372 
00373                 lt->removeLibEntry(uit->label);
00374             }
00375 
00376         }
00377     }
00378 
00379     // we must keep this list sorted for matching to work correctly
00380     // this is probably slower than it must be
00381     std::sort(fecList.begin(), fecList.end(), fecPrefixCompare);
00382 }
00383 
00384 void LDP::updateFecList(IPAddress nextHop)
00385 {
00386     FecVector::iterator it;
00387     for (it = fecList.begin(); it != fecList.end(); it++)
00388     {
00389         if (it->nextHop != nextHop)
00390             continue;
00391 
00392         updateFecListEntry(*it);
00393     }
00394 }
00395 
00396 void LDP::sendHelloTo(IPAddress dest)
00397 {
00398     LDPHello *hello = new LDPHello("LDP-Hello");
00399     hello->setByteLength(LDP_HEADER_BYTES);
00400     hello->setType(HELLO);
00401     hello->setSenderAddress(rt->getRouterId());
00402     //hello->setReceiverAddress(...);
00403     hello->setHoldTime(SIMTIME_DBL(holdTime));
00404     //hello->setRbit(...);
00405     //hello->setTbit(...);
00406     hello->addPar("color") = LDP_HELLO_TRAFFIC;
00407 
00408     udpSocket.sendTo(hello, dest, LDP_PORT);
00409 }
00410 
00411 void LDP::processHelloTimeout(cMessage *msg)
00412 {
00413     // peer is gone
00414 
00415     unsigned int i;
00416     for (i = 0; i < myPeers.size(); i++)
00417         if (myPeers[i].timeout == msg)
00418             break;
00419     ASSERT(i < myPeers.size());
00420 
00421     IPAddress peerIP = myPeers[i].peerIP;
00422 
00423     EV << "peer=" << peerIP << " is gone, removing adjacency" << endl;
00424 
00425     ASSERT(!myPeers[i].timeout->isScheduled());
00426     delete myPeers[i].timeout;
00427     ASSERT(myPeers[i].socket);
00428     myPeers[i].socket->abort(); // should we only close?
00429     delete myPeers[i].socket;
00430     myPeers.erase(myPeers.begin() + i);
00431 
00432     EV << "removing (stale) bindings from fecDown for peer=" << peerIP << endl;
00433 
00434     FecBindVector::iterator dit;
00435     for (dit = fecDown.begin(); dit != fecDown.end();)
00436     {
00437         if (dit->peer != peerIP)
00438         {
00439             dit++;
00440             continue;
00441         }
00442 
00443         EV << "label=" << dit->label << endl;
00444 
00445         // send release message just in case (?)
00446         // what happens if peer is not really down and
00447         // hello messages just disappeared?
00448         // does the protocol recover on its own (XXX check this)
00449 
00450         dit = fecDown.erase(dit);
00451     }
00452 
00453     EV << "removing bindings from sent to peer=" << peerIP << " from fecUp" << endl;
00454 
00455     FecBindVector::iterator uit;
00456     for (uit = fecUp.begin(); uit != fecUp.end();)
00457     {
00458         if (uit->peer != peerIP)
00459         {
00460             uit++;
00461             continue;
00462         }
00463 
00464         EV << "label=" << uit->label << endl;
00465 
00466         // send withdraw message just in case (?)
00467         // see comment above...
00468 
00469         uit = fecUp.erase(uit);
00470     }
00471 
00472     EV << "updating fecList" << endl;
00473 
00474     updateFecList(peerIP);
00475 
00476     // update TED and routing table
00477 
00478     unsigned int index = tedmod->linkIndex(rt->getRouterId(), peerIP);
00479     tedmod->ted[index].state = false;
00480     announceLinkChange(index);
00481     tedmod->rebuildRoutingTable();
00482 }
00483 
00484 void LDP::processLDPHello(LDPHello *msg)
00485 {
00486     UDPControlInfo *controlInfo = check_and_cast<UDPControlInfo *>(msg->getControlInfo());
00487     //IPAddress peerAddr = controlInfo->getSrcAddr().get4();
00488     IPAddress peerAddr = msg->getSenderAddress();
00489     int interfaceId = controlInfo->getInterfaceId();
00490     delete msg;
00491 
00492     EV << "Received LDP Hello from " << peerAddr << ", ";
00493 
00494     if (peerAddr.isUnspecified() || peerAddr==rt->getRouterId())
00495     {
00496         // must be ourselves (we're also in the all-routers multicast group), ignore
00497         EV << "that's myself, ignore\n";
00498         return;
00499     }
00500 
00501     // mark link as working if it was failed, and rebuild table
00502     unsigned int index = tedmod->linkIndex(rt->getRouterId(), peerAddr);
00503     if (!tedmod->ted[index].state)
00504     {
00505         tedmod->ted[index].state = true;
00506         tedmod->rebuildRoutingTable();
00507         announceLinkChange(index);
00508     }
00509 
00510     // peer already in table?
00511     int i = findPeer(peerAddr);
00512     if (i!=-1)
00513     {
00514         EV << "already in my peer table, rescheduling timeout" << endl;
00515         ASSERT(myPeers[i].timeout);
00516         cancelEvent(myPeers[i].timeout);
00517         scheduleAt(simTime() + holdTime, myPeers[i].timeout);
00518         return;
00519     }
00520 
00521     // not in table, add it
00522     peer_info info;
00523     info.peerIP = peerAddr;
00524     info.linkInterface = ift->getInterfaceById(interfaceId)->getName();
00525     info.activeRole = peerAddr.getInt() > rt->getRouterId().getInt();
00526     info.socket = NULL;
00527     info.timeout = new cMessage("HelloTimeout");
00528     scheduleAt(simTime() + holdTime, info.timeout);
00529     myPeers.push_back(info);
00530     int peerIndex = myPeers.size()-1;
00531 
00532     EV << "added to peer table\n";
00533     EV << "We'll be " << (info.activeRole ? "ACTIVE" : "PASSIVE") << " in this session\n";
00534 
00535     // introduce ourselves with a Hello, then connect if we're in ACTIVE role
00536     sendHelloTo(peerAddr);
00537     if (info.activeRole)
00538     {
00539         EV << "Establishing session with it\n";
00540         openTCPConnectionToPeer(peerIndex);
00541     }
00542 }
00543 
00544 void LDP::openTCPConnectionToPeer(int peerIndex)
00545 {
00546     TCPSocket *socket = new TCPSocket();
00547     socket->setOutputGate(gate("tcpOut"));
00548     socket->setCallbackObject(this, (void*)peerIndex);
00549     socket->bind(rt->getRouterId(), 0);
00550     socketMap.addSocket(socket);
00551     myPeers[peerIndex].socket = socket;
00552 
00553     socket->connect(myPeers[peerIndex].peerIP, LDP_PORT);
00554 }
00555 
00556 void LDP::processMessageFromTCP(cMessage *msg)
00557 {
00558     TCPSocket *socket = socketMap.findSocketFor(msg);
00559     if (!socket)
00560     {
00561         // not yet in socketMap, must be new incoming connection.
00562         // find which peer it is and register connection
00563         socket = new TCPSocket(msg);
00564         socket->setOutputGate(gate("tcpOut"));
00565 
00566         // FIXME there seems to be some confusion here. Is it sure that
00567         // routerIds we use as peerAddrs are the same as IP addresses
00568         // the routing is based on? --Andras
00569         IPAddress peerAddr = socket->getRemoteAddress().get4();
00570 
00571         int i = findPeer(peerAddr);
00572         if (i==-1 || myPeers[i].socket)
00573         {
00574             // nothing known about this guy, or already connected: refuse
00575             socket->close(); // reset()?
00576             delete socket;
00577             delete msg;
00578             return;
00579         }
00580         myPeers[i].socket = socket;
00581         socket->setCallbackObject(this, (void *)i);
00582         socketMap.addSocket(socket);
00583     }
00584 
00585     // dispatch to socketEstablished(), socketDataArrived(), socketPeerClosed()
00586     // or socketFailure()
00587     socket->processMessage(msg);
00588 }
00589 
00590 void LDP::socketEstablished(int, void *yourPtr)
00591 {
00592     peer_info& peer = myPeers[(long)yourPtr];
00593     EV << "TCP connection established with peer " << peer.peerIP << "\n";
00594 
00595     // we must update all entries with nextHop == peerIP
00596     updateFecList(peer.peerIP);
00597 
00598     // FIXME start LDP session setup (if we're on the active side?)
00599 }
00600 
00601 void LDP::socketDataArrived(int, void *yourPtr, cPacket *msg, bool)
00602 {
00603     peer_info& peer = myPeers[(long)yourPtr];
00604     EV << "Message arrived over TCP from peer " << peer.peerIP << "\n";
00605 
00606     delete msg->removeControlInfo();
00607     processLDPPacketFromTCP(check_and_cast<LDPPacket *>(msg));
00608 }
00609 
00610 void LDP::socketPeerClosed(int, void *yourPtr)
00611 {
00612     peer_info& peer = myPeers[(long)yourPtr];
00613     EV << "Peer " << peer.peerIP << " closed TCP connection\n";
00614 
00615     ASSERT(false);
00616 
00617 /*
00618     // close the connection (if not already closed)
00619     if (socket.getState()==TCPSocket::PEER_CLOSED)
00620     {
00621         EV << "remote TCP closed, closing here as well\n";
00622         close();
00623     }
00624 */
00625 }
00626 
00627 void LDP::socketClosed(int, void *yourPtr)
00628 {
00629     peer_info& peer = myPeers[(long)yourPtr];
00630     EV << "TCP connection to peer " << peer.peerIP << " closed\n";
00631 
00632     ASSERT(false);
00633 
00634     // FIXME what now? reconnect after a delay?
00635 }
00636 
00637 void LDP::socketFailure(int, void *yourPtr, int code)
00638 {
00639     peer_info& peer = myPeers[(long)yourPtr];
00640     EV << "TCP connection to peer " << peer.peerIP << " broken\n";
00641 
00642     ASSERT(false);
00643 
00644     // FIXME what now? reconnect after a delay?
00645 }
00646 
00647 void LDP::processLDPPacketFromTCP(LDPPacket *ldpPacket)
00648 {
00649     switch (ldpPacket->getType())
00650     {
00651     case HELLO:
00652         error("Received LDP HELLO over TCP (should arrive over UDP)");
00653 
00654     case ADDRESS:
00655         // processADDRESS(ldpPacket);
00656         error("Received LDP ADDRESS message, unsupported in this version");
00657         break;
00658 
00659     case ADDRESS_WITHDRAW:
00660         // processADDRESS_WITHDRAW(ldpPacket);
00661         error("LDP PROC DEBUG: Received LDP ADDRESS_WITHDRAW message, unsupported in this version");
00662         break;
00663 
00664     case LABEL_MAPPING:
00665         processLABEL_MAPPING(check_and_cast<LDPLabelMapping *>(ldpPacket));
00666         break;
00667 
00668     case LABEL_REQUEST:
00669         processLABEL_REQUEST(check_and_cast<LDPLabelRequest *>(ldpPacket));
00670         break;
00671 
00672     case LABEL_WITHDRAW:
00673         processLABEL_WITHDRAW(check_and_cast<LDPLabelMapping *>(ldpPacket));
00674         break;
00675 
00676     case LABEL_RELEASE:
00677         processLABEL_RELEASE(check_and_cast<LDPLabelMapping *>(ldpPacket));
00678         break;
00679 
00680     case NOTIFICATION:
00681         processNOTIFICATION(check_and_cast<LDPNotify*>(ldpPacket));
00682         break;
00683 
00684     default:
00685         error("LDP PROC DEBUG: Unrecognized LDP Message Type, type is %d", ldpPacket->getType());
00686     }
00687 }
00688 
00689 IPAddress LDP::locateNextHop(IPAddress dest)
00690 {
00691     // Mapping L3 IP-host of next hop to L2 peer address.
00692 
00693     // Lookup the routing table, rfc3036
00694     // "When the FEC for which a label is requested is a Prefix FEC Element or
00695     //  a Host Address FEC Element, the receiving LSR uses its routing table to determine
00696     //  its response. Unless its routing table includes an entry that exactly matches
00697     //  the requested Prefix or Host Address, the LSR must respond with a
00698     //  No Route Notification message."
00699     //
00700     // FIXME the code below (though seems like that's what the RFC refers to) doesn't work
00701     // -- we can't reasonably expect the destination host to be exaplicitly in an
00702     // LSR's routing table!!! Use simple IP routing instead. --Andras
00703     //
00704     // Wrong code:
00705     //int i;
00706     //for (i=0; i < rt->getNumRoutes(); i++)
00707     //    if (rt->getRoute(i)->host == dest)
00708     //        break;
00709     //
00710     //if (i == rt->getNumRoutes())
00711     //    return IPAddress();  // Signal an NOTIFICATION of NO ROUTE
00712     //
00713     InterfaceEntry *ie = rt->getInterfaceForDestAddr(dest);
00714     if (!ie)
00715         return IPAddress();  // no route
00716 
00717     std::string iName = ie->getName(); // FIXME why use name for lookup?
00718     return findPeerAddrFromInterface(iName);
00719 }
00720 
00721 // FIXME To allow this to work, make sure there are entries of hosts for all peers
00722 
00723 IPAddress LDP::findPeerAddrFromInterface(std::string interfaceName)
00724 {
00725     int i = 0;
00726     int k = 0;
00727     InterfaceEntry *ie = ift->getInterfaceByName(interfaceName.c_str());
00728 
00729     const IPRoute *anEntry;
00730 
00731     for (i = 0; i < rt->getNumRoutes(); i++)
00732     {
00733         for (k = 0; k < (int)myPeers.size(); k++)
00734         {
00735             anEntry = rt->getRoute(i);
00736             if (anEntry->getHost()==myPeers[k].peerIP && anEntry->getInterface()==ie)
00737             {
00738                 return myPeers[k].peerIP;
00739             }
00740             // addresses->push_back(peerIP[k]);
00741         }
00742     }
00743 
00744     // Return any IP which has default route - not in routing table entries
00745     for (i = 0; i < (int)myPeers.size(); i++)
00746     {
00747         for (k = 0; k < rt->getNumRoutes(); k++)
00748         {
00749             anEntry = rt->getRoute(i);
00750             if (anEntry->getHost() == myPeers[i].peerIP)
00751                 break;
00752         }
00753         if (k == rt->getNumRoutes())
00754             break;
00755     }
00756 
00757     // return the peer's address if found, unspecified address otherwise
00758     return i==(int)myPeers.size() ? IPAddress() : myPeers[i].peerIP;
00759 }
00760 
00761 // Pre-condition: myPeers vector is finalized
00762 std::string LDP::findInterfaceFromPeerAddr(IPAddress peerIP)
00763 {
00764 /*
00765     int i;
00766     for (unsigned int i=0;i<myPeers.size();i++)
00767     {
00768         if (myPeers[i].peerIP == peerIP)
00769             return string(myPeers[i].linkInterface);
00770     }
00771     return string("X");
00772 */
00773 //    Rely on port index to find the interface name
00774 
00775     // this function is a misnomer, we must recognize our own address too
00776     if (rt->isLocalAddress(peerIP))
00777         return "lo0";
00778 
00779     InterfaceEntry *ie = rt->getInterfaceForDestAddr(peerIP);
00780     if (!ie)
00781         error("findInterfaceFromPeerAddr(): %s is not routable", peerIP.str().c_str());
00782     return ie->getName();
00783 }
00784 
00785 //bool LDP::matches(const FEC_TLV& a, const FEC_TLV& b)
00786 //{
00787 //  return b.addr.prefixMatches(a, b.length);
00788 //}
00789 
00790 LDP::FecBindVector::iterator LDP::findFecEntry(FecBindVector& fecs, int fecid, IPAddress peer)
00791 {
00792     FecBindVector::iterator it;
00793     for (it = fecs.begin(); it != fecs.end(); it++)
00794     {
00795         if (it->fecid != fecid)
00796             continue;
00797 
00798         if (it->peer != peer)
00799             continue;
00800 
00801         break;
00802     }
00803     return it;
00804 }
00805 
00806 LDP::FecVector::iterator LDP::findFecEntry(FecVector& fecs, IPAddress addr, int length)
00807 {
00808     FecVector::iterator it;
00809     for (it = fecs.begin(); it != fecs.end(); it++)
00810     {
00811         if (it->length != length)
00812             continue;
00813 
00814         if (it->addr != addr) // XXX compare only relevant part (?)
00815             continue;
00816 
00817         break;
00818     }
00819     return it;
00820 }
00821 
00822 void LDP::sendNotify(int status, IPAddress dest, IPAddress addr, int length)
00823 {
00824     // Send NOTIFY message
00825     LDPNotify *lnMessage = new LDPNotify("Lb-Notify");
00826     lnMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
00827     lnMessage->setType(NOTIFICATION);
00828     lnMessage->setStatus(NO_ROUTE);
00829     lnMessage->setReceiverAddress(dest);
00830     lnMessage->setSenderAddress(rt->getRouterId());
00831 
00832     FEC_TLV fec;
00833     fec.addr = addr;
00834     fec.length = length;
00835 
00836     lnMessage->setFec(fec);
00837 
00838     sendToPeer(dest, lnMessage);
00839 }
00840 
00841 void LDP::sendMapping(int type, IPAddress dest, int label, IPAddress addr, int length)
00842 {
00843     // Send LABEL MAPPING downstream
00844     LDPLabelMapping *lmMessage = new LDPLabelMapping("Lb-Mapping");
00845     lmMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
00846     lmMessage->setType(type);
00847     lmMessage->setReceiverAddress(dest);
00848     lmMessage->setSenderAddress(rt->getRouterId());
00849     lmMessage->setLabel(label);
00850 
00851     FEC_TLV fec;
00852     fec.addr = addr;
00853     fec.length = length;
00854 
00855     lmMessage->setFec(fec);
00856 
00857     sendToPeer(dest, lmMessage);
00858 }
00859 
00860 void LDP::processNOTIFICATION(LDPNotify *packet)
00861 {
00862     FEC_TLV fec = packet->getFec();
00863     IPAddress srcAddr = packet->getSenderAddress();
00864     int status = packet->getStatus();
00865 
00866     // XXX FIXME NO_ROUTE processing should probably be split into two functions,
00867     // this is not the cleanest thing I ever wrote :)   --Vojta
00868 
00869     if (packet->isSelfMessage())
00870     {
00871         // re-scheduled by ourselves
00872         EV << "notification retry for peer=" << srcAddr << " fec=" << fec << " status=" << status << endl;
00873     }
00874     else
00875     {
00876         // received via network
00877         EV << "notification received from=" << srcAddr << " fec=" << fec << " status=" << status << endl;
00878     }
00879 
00880     switch(status)
00881     {
00882         case NO_ROUTE:
00883         {
00884             EV << "route does not exit on that peer" << endl;
00885 
00886             FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
00887             if (it != fecList.end())
00888             {
00889                 if (it->nextHop == srcAddr)
00890                 {
00891                     if (!packet->isSelfMessage())
00892                     {
00893                         EV << "we are still interesed in this mapping, we will retry later" << endl;
00894 
00895                         scheduleAt(simTime() + 1.0 /* XXX FIXME */, packet);
00896                         return;
00897                     }
00898                     else
00899                     {
00900                         EV << "reissuing request" << endl;
00901 
00902                         sendMappingRequest(srcAddr, fec.addr, fec.length);
00903                     }
00904                 }
00905                 else
00906                     EV << "and we still recognize this FEC, but we use different next hop, forget it" << endl;
00907             }
00908             else
00909                 EV << "and we do not recognize this any longer, forget it" << endl;
00910 
00911             break;
00912         }
00913 
00914         default:
00915             ASSERT(false);
00916     }
00917 
00918     delete packet;
00919 }
00920 
00921 void LDP::processLABEL_REQUEST(LDPLabelRequest *packet)
00922 {
00923     FEC_TLV fec = packet->getFec();
00924     IPAddress srcAddr = packet->getSenderAddress();
00925 
00926     EV << "Label Request from LSR " << srcAddr << " for FEC " << fec << endl;
00927 
00928     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
00929     if (it == fecList.end())
00930     {
00931         EV << "FEC not recognized, sending back No route message" << endl;
00932 
00933         sendNotify(NO_ROUTE, srcAddr, fec.addr, fec.length);
00934 
00935         delete packet;
00936         return;
00937     }
00938 
00939     // do we already have mapping for this fec from our downstream peer?
00940 
00941     //
00942     // XXX this code duplicates rebuildFecList
00943     //
00944 
00945     // does upstream have mapping from us?
00946     FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, srcAddr);
00947 
00948     // shouldn't!
00949     ASSERT(uit == fecUp.end());
00950 
00951     // do we have mapping from downstream?
00952     FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop);
00953 
00954     // is next hop our LDP peer?
00955     bool ER = !findPeerSocket(it->nextHop);
00956 
00957     ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time
00958 
00959     if (ER || dit != fecDown.end())
00960     {
00961         fec_bind_t newItem;
00962         newItem.fecid = it->fecid;
00963         newItem.label = -1;
00964         newItem.peer = srcAddr;
00965         fecUp.push_back(newItem);
00966         uit = fecUp.end() - 1;
00967     }
00968 
00969     std::string inInterface = findInterfaceFromPeerAddr(srcAddr);
00970     std::string outInterface = findInterfaceFromPeerAddr(it->nextHop);
00971 
00972     if (ER)
00973     {
00974         // we are egress, that's easy:
00975         LabelOpVector outLabel = LIBTable::popLabel();
00976 
00977         uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, 0);
00978 
00979         EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00980                 " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00981 
00982         // We are egress, let our upstream peer know
00983         // about it by sending back a Label Mapping message
00984 
00985         sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length);
00986 
00987     }
00988     else if (dit != fecDown.end())
00989     {
00990         // we have mapping from DS, that's easy
00991         LabelOpVector outLabel = LIBTable::swapLabel(dit->label);
00992         uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
00993 
00994         EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00995                 " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00996 
00997         // We already have a mapping for this FEC, let our upstream peer know
00998         // about it by sending back a Label Mapping message
00999 
01000         sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length);
01001     }
01002     else
01003     {
01004         // no mapping from DS, mark as pending
01005 
01006         EV << "no mapping for this FEC from the downstream router, marking as pending" << endl;
01007 
01008         pending_req_t newItem;
01009         newItem.fecid = it->fecid;
01010         newItem.peer = srcAddr;
01011         pending.push_back(newItem);
01012     }
01013 
01014     delete packet;
01015 }
01016 
01017 void LDP::processLABEL_RELEASE(LDPLabelMapping *packet)
01018 {
01019     FEC_TLV fec = packet->getFec();
01020     int label = packet->getLabel();
01021     IPAddress fromIP = packet->getSenderAddress();
01022 
01023     EV << "Mapping release received for label=" << label << " fec=" << fec << " from " << fromIP << endl;
01024 
01025     ASSERT(label > 0);
01026 
01027     // remove label from fecUp
01028 
01029     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
01030     if (it == fecList.end())
01031     {
01032         EV << "FEC no longer recognized here, ignoring" << endl;
01033         delete packet;
01034         return;
01035     }
01036 
01037     FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, fromIP);
01038     if (uit == fecUp.end() || label != uit->label)
01039     {
01040         // this is ok and may happen; e.g. we removed the mapping because downstream
01041         // neighbour withdrew its mapping. we sent withdraw upstream as well and
01042         // this is upstream's response
01043         EV << "mapping not found among sent mappings, ignoring" << endl;
01044         delete packet;
01045         return;
01046     }
01047 
01048     EV << "removing from LIB table label=" << uit->label << endl;
01049     lt->removeLibEntry(uit->label);
01050 
01051     EV << "removing label from list of sent mappings" << endl;
01052     fecUp.erase(uit);
01053 
01054     delete packet;
01055 }
01056 
01057 void LDP::processLABEL_WITHDRAW(LDPLabelMapping *packet)
01058 {
01059     FEC_TLV fec = packet->getFec();
01060     int label = packet->getLabel();
01061     IPAddress fromIP = packet->getSenderAddress();
01062 
01063     EV << "Mapping withdraw received for label=" << label << " fec=" << fec << " from " << fromIP << endl;
01064 
01065     ASSERT(label > 0);
01066 
01067     // remove label from fecDown
01068 
01069     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
01070     if (it == fecList.end())
01071     {
01072         EV << "matching FEC not found, ignoring withdraw message" << endl;
01073         delete packet;
01074         return;
01075     }
01076 
01077     FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP);
01078 
01079     if (dit == fecDown.end() || label != dit->label)
01080     {
01081         EV << "matching mapping not found, ignoring withdraw message" << endl;
01082         delete packet;
01083         return;
01084     }
01085 
01086     ASSERT(dit != fecDown.end());
01087     ASSERT(label == dit->label);
01088 
01089     EV << "removing label from list of received mappings" << endl;
01090     fecDown.erase(dit);
01091 
01092     EV << "sending back relase message" << endl;
01093     packet->setType(LABEL_RELEASE);
01094 
01095     // send msg to peer over TCP
01096     sendToPeer(fromIP, packet);
01097 
01098     updateFecListEntry(*it);
01099 }
01100 
01101 void LDP::processLABEL_MAPPING(LDPLabelMapping *packet)
01102 {
01103     FEC_TLV fec = packet->getFec();
01104     int label = packet->getLabel();
01105     IPAddress fromIP = packet->getSenderAddress();
01106 
01107     EV << "Label mapping label=" << label << " received for fec=" << fec << " from " << fromIP << endl;
01108 
01109     ASSERT(label > 0);
01110 
01111     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
01112     ASSERT(it != fecList.end());
01113 
01114     FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP);
01115     ASSERT(dit == fecDown.end());
01116 
01117     // insert among received mappings
01118 
01119     fec_bind_t newItem;
01120     newItem.fecid = it->fecid;
01121     newItem.peer = fromIP;
01122     newItem.label = label;
01123     fecDown.push_back(newItem);
01124 
01125     // respond to pending requests
01126 
01127     PendingVector::iterator pit;
01128     for (pit = pending.begin(); pit != pending.end();)
01129     {
01130         if (pit->fecid != it->fecid)
01131         {
01132             pit++;
01133             continue;
01134         }
01135 
01136         EV << "there's pending request for this FEC from " << pit->peer << ", sending mapping" << endl;
01137 
01138         std::string inInterface = findInterfaceFromPeerAddr(pit->peer);
01139         std::string outInterface = findInterfaceFromPeerAddr(fromIP);
01140         LabelOpVector outLabel = LIBTable::swapLabel(label);
01141 
01142         fec_bind_t newItem;
01143         newItem.fecid = it->fecid;
01144         newItem.peer = pit->peer;
01145         newItem.label = lt->installLibEntry(-1, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
01146         fecUp.push_back(newItem);
01147 
01148         EV << "installed LIB entry inLabel=" << newItem.label << " inInterface=" << inInterface <<
01149                 " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
01150 
01151         sendMapping(LABEL_MAPPING, pit->peer, newItem.label, it->addr, it->length);
01152 
01153         // remove request from the list
01154         pit = pending.erase(pit);
01155     }
01156 
01157     delete packet;
01158 }
01159 
01160 int LDP::findPeer(IPAddress peerAddr)
01161 {
01162     for (PeerVector::iterator i=myPeers.begin(); i!=myPeers.end(); ++i)
01163         if (i->peerIP==peerAddr)
01164             return i-myPeers.begin();
01165     return -1;
01166 }
01167 
01168 TCPSocket *LDP::findPeerSocket(IPAddress peerAddr)
01169 {
01170     // find peer in table and return its socket
01171     int i = findPeer(peerAddr);
01172     if (i==-1 || !(myPeers[i].socket) || myPeers[i].socket->getState()!=TCPSocket::CONNECTED)
01173         return NULL; // we don't have an LDP session to this peer
01174     return myPeers[i].socket;
01175 }
01176 
01177 TCPSocket *LDP::getPeerSocket(IPAddress peerAddr)
01178 {
01179     TCPSocket *sock = findPeerSocket(peerAddr);
01180     ASSERT(sock);
01181     if (!sock)
01182         error("No LDP session to peer %s yet", peerAddr.str().c_str());
01183     return sock;
01184 }
01185 
01186 bool LDP::lookupLabel(IPDatagram *ipdatagram, LabelOpVector& outLabel, std::string& outInterface, int& color)
01187 {
01188     IPAddress destAddr = ipdatagram->getDestAddress();
01189     int protocol = ipdatagram->getTransportProtocol();
01190 
01191     // never match and always route via L3 if:
01192 
01193     // OSPF traffic (TED)
01194     if (protocol == IP_PROT_OSPF)
01195         return false;
01196 
01197     // LDP traffic (both discovery...
01198     if (protocol == IP_PROT_UDP && check_and_cast<UDPPacket*>(ipdatagram->getEncapsulatedMsg())->getDestinationPort() == LDP_PORT)
01199         return false;
01200 
01201     // ...and session)
01202     if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedMsg())->getDestPort() == LDP_PORT)
01203         return false;
01204     if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedMsg())->getSrcPort() == LDP_PORT)
01205         return false;
01206 
01207     // regular traffic, classify, label etc.
01208 
01209     FecVector::iterator it;
01210     for (it = fecList.begin(); it != fecList.end(); it++)
01211     {
01212         if (!destAddr.prefixMatches(it->addr, it->length))
01213             continue;
01214 
01215         EV << "FEC matched: " << *it << endl;
01216 
01217         FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop);
01218         if (dit != fecDown.end())
01219         {
01220             outLabel = LIBTable::pushLabel(dit->label);
01221             outInterface = findInterfaceFromPeerAddr(it->nextHop);
01222             color = LDP_USER_TRAFFIC;
01223             EV << "mapping found, outLabel=" << outLabel << ", outInterface=" << outInterface << endl;
01224             return true;
01225         }
01226         else
01227         {
01228             EV << "no mapping for this FEC exists" << endl;
01229             return false;
01230         }
01231     }
01232     return false;
01233 }
01234 
01235 void LDP::receiveChangeNotification(int category, const cPolymorphic *details)
01236 {
01237     Enter_Method_Silent();
01238     printNotificationBanner(category, details);
01239 
01240     ASSERT(category==NF_IPv4_ROUTE_ADDED || category==NF_IPv4_ROUTE_DELETED);
01241 
01242     EV << "routing table changed, rebuild list of known FEC" << endl;
01243 
01244     rebuildFecList();
01245 }
01246 
01247 void LDP::announceLinkChange(int tedlinkindex)
01248 {
01249     TEDChangeInfo d;
01250     d.setTedLinkIndicesArraySize(1);
01251     d.setTedLinkIndices(0, tedlinkindex);
01252     nb->fireChangeNotification(NF_TED_CHANGED, &d);
01253 }
01254 
01255