Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

LDP Class Reference

#include <LDP.h>

Inheritance diagram for LDP:

TCPSocket::CallbackInterface IClassifier INotifiable List of all members.

Detailed Description

LDP (rfc 3036) protocol implementation.


Public Types

typedef std::vector< fec_tFecVector
typedef std::vector< fec_bind_tFecBindVector
typedef std::vector< pending_req_tPendingVector
typedef std::vector< peer_infoPeerVector

Public Member Functions

 LDP ()
virtual ~LDP ()

Protected Member Functions

virtual int numInitStages () const
virtual void initialize (int stage)
virtual void handleMessage (cMessage *msg)
void sendHelloTo (IPAddress dest)
void openTCPConnectionToPeer (int peerIndex)
void processLDPHello (LDPHello *msg)
void processHelloTimeout (cMessage *msg)
void processMessageFromTCP (cMessage *msg)
void processLDPPacketFromTCP (LDPPacket *ldpPacket)
void processLABEL_MAPPING (LDPLabelMapping *packet)
void processLABEL_REQUEST (LDPLabelRequest *packet)
void processLABEL_RELEASE (LDPLabelMapping *packet)
void processLABEL_WITHDRAW (LDPLabelMapping *packet)
void processNOTIFICATION (LDPNotify *packet)
virtual bool lookupLabel (IPDatagram *ipdatagram, LabelOpVector &outLabel, std::string &outInterface, int &color)
virtual void receiveChangeNotification (int category, cPolymorphic *details)
TCPSocket::CallbackInterface callback methods
virtual void socketEstablished (int connId, void *yourPtr)
virtual void socketDataArrived (int connId, void *yourPtr, cMessage *msg, bool urgent)
virtual void socketPeerClosed (int connId, void *yourPtr)
virtual void socketClosed (int connId, void *yourPtr)
virtual void socketFailure (int connId, void *yourPtr, int code)
virtual void socketStatusArrived (int connId, void *yourPtr, TCPStatusInfo *status)

Private Member Functions

IPAddress locateNextHop (IPAddress dest)
IPAddress findPeerAddrFromInterface (std::string interfaceName)
std::string findInterfaceFromPeerAddr (IPAddress peerIP)
int findPeer (IPAddress peerAddr)
TCPSocketpeerSocket (IPAddress peerAddr)
TCPSocketpeerSocketSoft (IPAddress peerAddr)
void sendToPeer (IPAddress dest, cMessage *msg)
FecVector::iterator findFecEntry (FecVector &fecs, IPAddress addr, int length)
FecBindVector::iterator findFecEntry (FecBindVector &fecs, int fecid, IPAddress peer)
void sendMappingRequest (IPAddress dest, IPAddress addr, int length)
void sendMapping (int type, IPAddress dest, int label, IPAddress addr, int length)
void sendNotify (int status, IPAddress dest, IPAddress addr, int length)
void rebuildFecList ()
void updateFecList (IPAddress nextHop)
void updateFecListEntry (fec_t oldItem)
void announceLinkChange (int tedlinkindex)

Private Attributes

double holdTime
double helloInterval
FecVector fecList
FecBindVector fecUp
FecBindVector fecDown
PendingVector pending
PeerVector myPeers
InterfaceTableift
RoutingTablert
LIBTablelt
TEDtedmod
NotificationBoardnb
UDPSocket udpSocket
TCPSocket serverSocket
TCPSocketMap socketMap
cMessage * sendHelloMsg
int maxFecid

Classes

struct  fec_bind_t
struct  fec_t
struct  peer_info
struct  pending_req_t


Member Typedef Documentation

typedef std::vector<fec_bind_t> LDP::FecBindVector
 

typedef std::vector<fec_t> LDP::FecVector
 

typedef std::vector<peer_info> LDP::PeerVector
 

typedef std::vector<pending_req_t> LDP::PendingVector
 


Constructor & Destructor Documentation

LDP::LDP  ) 
 

00085 {
00086     sendHelloMsg = NULL;
00087 }

LDP::~LDP  )  [virtual]
 

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 }


Member Function Documentation

void LDP::announceLinkChange int  tedlinkindex  )  [private]
 

01246 {
01247     TEDChangeInfo d;
01248     d.setTedLinkIndicesArraySize(1);
01249     d.setTedLinkIndices(0, tedlinkindex);
01250     nb->fireChangeNotification(NF_TED_CHANGED, &d);
01251 }

LDP::FecBindVector::iterator LDP::findFecEntry FecBindVector fecs,
int  fecid,
IPAddress  peer
[private]
 

00789 {
00790     FecBindVector::iterator it;
00791     for (it = fecs.begin(); it != fecs.end(); it++)
00792     {
00793         if (it->fecid != fecid)
00794             continue;
00795 
00796         if (it->peer != peer)
00797             continue;
00798 
00799         break;
00800     }
00801     return it;
00802 }

LDP::FecVector::iterator LDP::findFecEntry FecVector fecs,
IPAddress  addr,
int  length
[private]
 

00805 {
00806     FecVector::iterator it;
00807     for (it = fecs.begin(); it != fecs.end(); it++)
00808     {
00809         if (it->length != length)
00810             continue;
00811 
00812         if (it->addr != addr) // XXX compare only relevant part (?)
00813             continue;
00814 
00815         break;
00816     }
00817     return it;
00818 }

std::string LDP::findInterfaceFromPeerAddr IPAddress  peerIP  )  [private]
 

00761 {
00762 /*
00763     int i;
00764     for (unsigned int i=0;i<myPeers.size();i++)
00765     {
00766         if (myPeers[i].peerIP == peerIP)
00767             return string(myPeers[i].linkInterface);
00768     }
00769     return string("X");
00770 */
00771 //    Rely on port index to find the interface name
00772 
00773     // this function is a misnomer, we must recognize our own address too
00774     if (rt->localDeliver(peerIP))
00775         return "lo0";
00776 
00777     InterfaceEntry *ie = rt->interfaceForDestAddr(peerIP);
00778     if (!ie)
00779         error("findInterfaceFromPeerAddr(): %s is not routable", peerIP.str().c_str());
00780     return ie->name();
00781 }

int LDP::findPeer IPAddress  peerAddr  )  [private]
 

Utility: return peer's index in myPeers table, or -1 if not found

01156 {
01157     for (PeerVector::iterator i=myPeers.begin(); i!=myPeers.end(); ++i)
01158         if (i->peerIP==peerAddr)
01159             return i-myPeers.begin();
01160     return -1;
01161 }

IPAddress LDP::findPeerAddrFromInterface std::string  interfaceName  )  [private]
 

This method maps the peerIP with the interface name in routing table. It is expected that for MPLS host, entries linked to MPLS peers are available. In case no corresponding peerIP found, a peerIP (not deterministic) will be returned.

00722 {
00723     int i = 0;
00724     int k = 0;
00725     InterfaceEntry *ie = ift->interfaceByName(interfaceName.c_str());
00726 
00727     RoutingEntry *anEntry;
00728 
00729     for (i = 0; i < rt->numRoutingEntries(); i++)
00730     {
00731         for (k = 0; k < (int)myPeers.size(); k++)
00732         {
00733             anEntry = rt->routingEntry(i);
00734             if (anEntry->host==myPeers[k].peerIP && anEntry->interfacePtr==ie)
00735             {
00736                 return myPeers[k].peerIP;
00737             }
00738             // addresses->push_back(peerIP[k]);
00739         }
00740     }
00741 
00742     // Return any IP which has default route - not in routing table entries
00743     for (i = 0; i < (int)myPeers.size(); i++)
00744     {
00745         for (k = 0; k < rt->numRoutingEntries(); k++)
00746         {
00747             anEntry = rt->routingEntry(i);
00748             if (anEntry->host == myPeers[i].peerIP)
00749                 break;
00750         }
00751         if (k == rt->numRoutingEntries())
00752             break;
00753     }
00754 
00755     // return the peer's address if found, unspecified address otherwise
00756     return i==myPeers.size() ? IPAddress() : myPeers[i].peerIP;
00757 }

void LDP::handleMessage cMessage *  msg  )  [protected, virtual]
 

00143 {
00144     EV << "Received: (" << msg->className() << ")" << msg->name() << "\n";
00145     if (msg==sendHelloMsg)
00146     {
00147         // every LDP capable router periodically sends HELLO messages to the
00148         // "all routers in the sub-network" multicast address
00149         EV << "Multicasting LDP Hello to neighboring routers\n";
00150         sendHelloTo(IPAddress::ALL_ROUTERS_MCAST);
00151 
00152         // schedule next hello
00153         scheduleAt(simTime() + helloInterval, sendHelloMsg);
00154     }
00155     else if (msg->isSelfMessage())
00156     {
00157         EV << "Timer " << msg->name() << " expired\n";
00158         if (!strcmp(msg->name(), "HelloTimeout"))
00159         {
00160             processHelloTimeout(msg);
00161         }
00162         else
00163         {
00164             processNOTIFICATION(check_and_cast<LDPNotify*>(msg));
00165         }
00166     }
00167     else if (!strcmp(msg->arrivalGate()->name(), "udpIn"))
00168     {
00169         // we can only receive LDP Hello from UDP (everything else goes over TCP)
00170         processLDPHello(check_and_cast<LDPHello *>(msg));
00171     }
00172     else if (!strcmp(msg->arrivalGate()->name(), "tcpIn"))
00173     {
00174         processMessageFromTCP(msg);
00175     }
00176 }

void LDP::initialize int  stage  )  [protected, virtual]
 

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_ROUTINGTABLE_CHANGED);
00140 }

IPAddress LDP::locateNextHop IPAddress  dest  )  [private]
 

This method finds next peer in upstream direction

00688 {
00689     // Mapping L3 IP-host of next hop to L2 peer address.
00690 
00691     // Lookup the routing table, rfc3036
00692     // "When the FEC for which a label is requested is a Prefix FEC Element or
00693     //  a Host Address FEC Element, the receiving LSR uses its routing table to determine
00694     //  its response. Unless its routing table includes an entry that exactly matches
00695     //  the requested Prefix or Host Address, the LSR must respond with a
00696     //  No Route Notification message."
00697     //
00698     // FIXME the code below (though seems like that's what the RFC refers to) doesn't work
00699     // -- we can't reasonably expect the destination host to be exaplicitly in an
00700     // LSR's routing table!!! Use simple IP routing instead. --Andras
00701     //
00702     // Wrong code:
00703     //int i;
00704     //for (i=0; i < rt->numRoutingEntries(); i++)
00705     //    if (rt->routingEntry(i)->host == dest)
00706     //        break;
00707     //
00708     //if (i == rt->numRoutingEntries())
00709     //    return IPAddress();  // Signal an NOTIFICATION of NO ROUTE
00710     //
00711     InterfaceEntry *ie = rt->interfaceForDestAddr(dest);
00712     if (!ie)
00713         return IPAddress();  // no route
00714 
00715     std::string iName = ie->name(); // FIXME why use name for lookup?
00716     return findPeerAddrFromInterface(iName);
00717 }

bool LDP::lookupLabel IPDatagram ipdatagram,
LabelOpVector outLabel,
std::string &  outInterface,
int &  color
[protected, virtual]
 

The ipdatagram argument is an input parameter, the rest (outLabel, outInterface, color) are output parameters only.

In subclasses, this function should be implemented to determine the forwarding equivalence class for the IP datagram passed, and map it to an outLabel and outInterface.

The color parameter (which can be set to an arbitrary value) will only be used for the NAM trace if one will be recorded.

Implements IClassifier.

01185 {
01186     IPAddress destAddr = ipdatagram->destAddress();
01187     int protocol = ipdatagram->transportProtocol();
01188 
01189     // never match and always route via L3 if:
01190 
01191     // OSPF traffic (TED)
01192     if (protocol == IP_PROT_OSPF)
01193         return false;
01194 
01195     // LDP traffic (both discovery...
01196     if (protocol == IP_PROT_UDP && check_and_cast<UDPPacket*>(ipdatagram->encapsulatedMsg())->destinationPort() == LDP_PORT)
01197         return false;
01198 
01199     // ...and session)
01200     if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->encapsulatedMsg())->destPort() == LDP_PORT)
01201         return false;
01202     if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->encapsulatedMsg())->srcPort() == LDP_PORT)
01203         return false;
01204 
01205     // regular traffic, classify, label etc.
01206 
01207     FecVector::iterator it;
01208     for (it = fecList.begin(); it != fecList.end(); it++)
01209     {
01210         if (!destAddr.prefixMatches(it->addr, it->length))
01211             continue;
01212 
01213         EV << "FEC matched: " << *it << endl;
01214 
01215         FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop);
01216         if (dit != fecDown.end())
01217         {
01218             outLabel = LIBTable::pushLabel(dit->label);
01219             outInterface = findInterfaceFromPeerAddr(it->nextHop);
01220             color = LDP_USER_TRAFFIC;
01221             EV << "mapping found, outLabel=" << outLabel << ", outInterface=" << outInterface << endl;
01222             return true;
01223         }
01224         else
01225         {
01226             EV << "no mapping for this FEC exists" << endl;
01227             return false;
01228         }
01229     }
01230     return false;
01231 }

virtual int LDP::numInitStages  )  const [inline, protected, virtual]
 

00179 {return 4;}

void LDP::openTCPConnectionToPeer int  peerIndex  )  [protected]
 

00543 {
00544     TCPSocket *socket = new TCPSocket();
00545     socket->setOutputGate(gate("tcpOut"));
00546     socket->setCallbackObject(this, (void*)peerIndex);
00547     socket->bind(rt->routerId(), 0);
00548     socketMap.addSocket(socket);
00549     myPeers[peerIndex].socket = socket;
00550 
00551     socket->connect(myPeers[peerIndex].peerIP, LDP_PORT);
00552 }

TCPSocket * LDP::peerSocket IPAddress  peerAddr  )  [private]
 

Utility: return socket for given peer. Throws error if there's no TCP connection

01176 {
01177     TCPSocket *sock = peerSocketSoft(peerAddr);
01178     ASSERT(sock);
01179     if (!sock)
01180         error("No LDP session to peer %s yet", peerAddr.str().c_str());
01181     return sock;
01182 }

TCPSocket * LDP::peerSocketSoft IPAddress  peerAddr  )  [private]
 

Utility: return socket for given peer and NULL if session doesn't exist

01164 {
01165     // find peer in table and return its socket
01166     int i = findPeer(peerAddr);
01167     if (i==-1 || !(myPeers[i].socket) || myPeers[i].socket->state()!=TCPSocket::CONNECTED)
01168     {
01169         // we don't have an LDP session to this peer
01170         return NULL;
01171     }
01172     return myPeers[i].socket;
01173 }

void LDP::processHelloTimeout cMessage *  msg  )  [protected]
 

00414 {
00415     // peer is gone
00416 
00417     unsigned int i;
00418     for (i = 0; i < myPeers.size(); i++)
00419     {
00420         if (myPeers[i].timeout == msg)
00421             break;
00422     }
00423     ASSERT(i < myPeers.size());
00424 
00425     IPAddress peerIP = myPeers[i].peerIP;
00426 
00427     EV << "peer=" << peerIP << " is gone, removing adjacency" << endl;
00428 
00429     ASSERT(!myPeers[i].timeout->isScheduled());
00430     delete myPeers[i].timeout;
00431     ASSERT(myPeers[i].socket);
00432     myPeers[i].socket->abort(); // should we only close?
00433     delete myPeers[i].socket;
00434     myPeers.erase(myPeers.begin() + i);
00435 
00436     EV << "removing (stale) bindings from fecDown for peer=" << peerIP << endl;
00437 
00438     FecBindVector::iterator dit;
00439     for (dit = fecDown.begin(); dit != fecDown.end(); dit++)
00440     {
00441         if (dit->peer != peerIP)
00442             continue;
00443 
00444         EV << "label=" << dit->label << endl;
00445 
00446         // send release message just in case (?)
00447         // what happens if peer is not really down and
00448         // hello messages just disappeared?
00449         // does the protocol recover on its own (XXX check this)
00450 
00451         fecDown.erase(dit--);
00452     }
00453 
00454     EV << "removing bindings from sent to peer=" << peerIP << " from fecUp" << endl;
00455 
00456     FecBindVector::iterator uit;
00457     for (uit = fecUp.begin(); uit != fecUp.end(); uit++)
00458     {
00459         if (uit->peer != peerIP)
00460             continue;
00461 
00462         EV << "label=" << uit->label << endl;
00463 
00464         // send withdraw message just in case (?)
00465         // see comment above...
00466 
00467         fecUp.erase(uit--);
00468     }
00469 
00470     EV << "updating fecList" << endl;
00471 
00472     updateFecList(peerIP);
00473 
00474     // update TED and routing table
00475 
00476     unsigned int index = tedmod->linkIndex(rt->routerId(), peerIP);
00477     tedmod->ted[index].state = false;
00478     announceLinkChange(index);
00479     tedmod->rebuildRoutingTable();
00480 }

void LDP::processLABEL_MAPPING LDPLabelMapping packet  )  [protected]
 

01100 {
01101     FEC_TLV fec = packet->getFec();
01102     int label = packet->getLabel();
01103     IPAddress fromIP = packet->senderAddress();
01104 
01105     EV << "Label mapping label=" << label << " received for fec=" << fec << " from " << fromIP << endl;
01106 
01107     ASSERT(label > 0);
01108 
01109     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
01110     ASSERT(it != fecList.end());
01111 
01112     FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP);
01113     ASSERT(dit == fecDown.end());
01114 
01115     // insert among received mappings
01116 
01117     fec_bind_t newItem;
01118     newItem.fecid = it->fecid;
01119     newItem.peer = fromIP;
01120     newItem.label = label;
01121     fecDown.push_back(newItem);
01122 
01123     // respond to pending requests
01124 
01125     PendingVector::iterator pit;
01126     for (pit = pending.begin(); pit != pending.end(); pit++)
01127     {
01128         if (pit->fecid != it->fecid)
01129             continue;
01130 
01131         EV << "there's pending request for this FEC from " << pit->peer << ", sending mapping" << endl;
01132 
01133         std::string inInterface = findInterfaceFromPeerAddr(pit->peer);
01134         std::string outInterface = findInterfaceFromPeerAddr(fromIP);
01135         LabelOpVector outLabel = LIBTable::swapLabel(label);
01136 
01137         fec_bind_t newItem;
01138         newItem.fecid = it->fecid;
01139         newItem.peer = pit->peer;
01140         newItem.label = lt->installLibEntry(-1, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
01141         fecUp.push_back(newItem);
01142 
01143         EV << "installed LIB entry inLabel=" << newItem.label << " inInterface=" << inInterface <<
01144                 " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
01145 
01146         sendMapping(LABEL_MAPPING, pit->peer, newItem.label, it->addr, it->length);
01147 
01148         // remove request from the list
01149         pending.erase(pit--);
01150     }
01151 
01152     delete packet;
01153 }

void LDP::processLABEL_RELEASE LDPLabelMapping packet  )  [protected]
 

01016 {
01017     FEC_TLV fec = packet->getFec();
01018     int label = packet->getLabel();
01019     IPAddress fromIP = packet->senderAddress();
01020 
01021     EV << "Mapping release received for label=" << label << " fec=" << fec << " from " << fromIP << endl;
01022 
01023     ASSERT(label > 0);
01024 
01025     // remove label from fecUp
01026 
01027     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
01028     if (it == fecList.end())
01029     {
01030         EV << "FEC no longer recognized here, ignoring" << endl;
01031         delete packet;
01032         return;
01033     }
01034 
01035     FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, fromIP);
01036     if (uit == fecUp.end() || label != uit->label)
01037     {
01038         // this is ok and may happen; e.g. we removed the mapping because downstream
01039         // neighbour withdrew its mapping. we sent withdraw upstream as well and
01040         // this is upstream's response
01041         EV << "mapping not found among sent mappings, ignoring" << endl;
01042         delete packet;
01043         return;
01044     }
01045 
01046     EV << "removing from LIB table label=" << uit->label << endl;
01047     lt->removeLibEntry(uit->label);
01048 
01049     EV << "removing label from list of sent mappings" << endl;
01050     fecUp.erase(uit);
01051 
01052     delete packet;
01053 }

void LDP::processLABEL_REQUEST LDPLabelRequest packet  )  [protected]
 

00920 {
00921     FEC_TLV fec = packet->getFec();
00922     IPAddress srcAddr = packet->senderAddress();
00923 
00924     EV << "Label Request from LSR " << srcAddr << " for FEC " << fec << endl;
00925 
00926     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
00927     if (it == fecList.end())
00928     {
00929         EV << "FEC not recognized, sending back No route message" << endl;
00930 
00931         sendNotify(NO_ROUTE, srcAddr, fec.addr, fec.length);
00932 
00933         delete packet;
00934         return;
00935     }
00936 
00937     // do we already have mapping for this fec from our downstream peer?
00938 
00939     //
00940     // XXX this code duplicates rebuildFecList
00941     //
00942 
00943     // does upstream have mapping from us?
00944     FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, srcAddr);
00945 
00946     // shouldn't!
00947     ASSERT(uit == fecUp.end());
00948 
00949     // do we have mapping from downstream?
00950     FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop);
00951 
00952     // is next hop our LDP peer?
00953     bool ER = !peerSocketSoft(it->nextHop);
00954 
00955     ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time
00956 
00957     if (ER || dit != fecDown.end())
00958     {
00959         fec_bind_t newItem;
00960         newItem.fecid = it->fecid;
00961         newItem.label = -1;
00962         newItem.peer = srcAddr;
00963         fecUp.push_back(newItem);
00964         uit = fecUp.end() - 1;
00965     }
00966 
00967     std::string inInterface = findInterfaceFromPeerAddr(srcAddr);
00968     std::string outInterface = findInterfaceFromPeerAddr(it->nextHop);
00969 
00970     if (ER)
00971     {
00972         // we are egress, that's easy:
00973         LabelOpVector outLabel = LIBTable::popLabel();
00974 
00975         uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, 0);
00976 
00977         EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00978                 " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00979 
00980         // We are egress, let our upstream peer know
00981         // about it by sending back a Label Mapping message
00982 
00983         sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length);
00984 
00985     }
00986     else if (dit != fecDown.end())
00987     {
00988         // we have mapping from DS, that's easy
00989         LabelOpVector outLabel = LIBTable::swapLabel(dit->label);
00990         uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
00991 
00992         EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00993                 " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00994 
00995         // We already have a mapping for this FEC, let our upstream peer know
00996         // about it by sending back a Label Mapping message
00997 
00998         sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length);
00999     }
01000     else
01001     {
01002         // no mapping from DS, mark as pending
01003 
01004         EV << "no mapping for this FEC from the downstream router, marking as pending" << endl;
01005 
01006         pending_req_t newItem;
01007         newItem.fecid = it->fecid;
01008         newItem.peer = srcAddr;
01009         pending.push_back(newItem);
01010     }
01011 
01012     delete packet;
01013 }

void LDP::processLABEL_WITHDRAW LDPLabelMapping packet  )  [protected]
 

01056 {
01057     FEC_TLV fec = packet->getFec();
01058     int label = packet->getLabel();
01059     IPAddress fromIP = packet->senderAddress();
01060 
01061     EV << "Mapping withdraw received for label=" << label << " fec=" << fec << " from " << fromIP << endl;
01062 
01063     ASSERT(label > 0);
01064 
01065     // remove label from fecDown
01066 
01067     FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
01068     if (it == fecList.end())
01069     {
01070         EV << "matching FEC not found, ignoring withdraw message" << endl;
01071         delete packet;
01072         return;
01073     }
01074 
01075     FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP);
01076 
01077     if (dit == fecDown.end() || label != dit->label)
01078     {
01079         EV << "matching mapping not found, ignoring withdraw message" << endl;
01080         delete packet;
01081         return;
01082     }
01083 
01084     ASSERT(dit != fecDown.end());
01085     ASSERT(label == dit->label);
01086 
01087     EV << "removing label from list of received mappings" << endl;
01088     fecDown.erase(dit);
01089 
01090     EV << "sending back relase message" << endl;
01091     packet->setType(LABEL_RELEASE);
01092 
01093     // send msg to peer over TCP
01094     sendToPeer(fromIP, packet);
01095 
01096     updateFecListEntry(*it);
01097 }

void LDP::processLDPHello LDPHello msg  )  [protected]
 

00483 {
00484     UDPControlInfo *controlInfo = check_and_cast<UDPControlInfo *>(msg->controlInfo());
00485     //IPAddress peerAddr = controlInfo->getSrcAddr().get4();
00486     IPAddress peerAddr = msg->senderAddress();
00487     int interfaceId = controlInfo->interfaceId();
00488     delete msg;
00489 
00490     EV << "Received LDP Hello from " << peerAddr << ", ";
00491 
00492     if (peerAddr.isUnspecified() || peerAddr==rt->routerId())
00493     {
00494         // must be ourselves (we're also in the all-routers multicast group), ignore
00495         EV << "that's myself, ignore\n";
00496         return;
00497     }
00498 
00499     // mark link as working if it was failed, and rebuild table
00500     unsigned int index = tedmod->linkIndex(rt->routerId(), peerAddr);
00501     if (!tedmod->ted[index].state)
00502     {
00503         tedmod->ted[index].state = true;
00504         tedmod->rebuildRoutingTable();
00505         announceLinkChange(index);
00506     }
00507 
00508     // peer already in table?
00509     int i = findPeer(peerAddr);
00510     if (i!=-1)
00511     {
00512         EV << "already in my peer table, rescheduling timeout" << endl;
00513         ASSERT(myPeers[i].timeout);
00514         cancelEvent(myPeers[i].timeout);
00515         scheduleAt(simTime() + holdTime, myPeers[i].timeout);
00516         return;
00517     }
00518 
00519     // not in table, add it
00520     peer_info info;
00521     info.peerIP = peerAddr;
00522     info.linkInterface = ift->interfaceAt(interfaceId)->name();
00523     info.activeRole = peerAddr.getInt() > rt->routerId().getInt();
00524     info.socket = NULL;
00525     info.timeout = new cMessage("HelloTimeout");
00526     scheduleAt(simTime() + holdTime, info.timeout);
00527     myPeers.push_back(info);
00528     int peerIndex = myPeers.size()-1;
00529 
00530     EV << "added to peer table\n";
00531     EV << "We'll be " << (info.activeRole ? "ACTIVE" : "PASSIVE") << " in this session\n";
00532 
00533     // introduce ourselves with a Hello, then connect if we're in ACTIVE role
00534     sendHelloTo(peerAddr);
00535     if (info.activeRole)
00536     {
00537         EV << "Establishing session with it\n";
00538         openTCPConnectionToPeer(peerIndex);
00539     }
00540 }

void LDP::processLDPPacketFromTCP LDPPacket ldpPacket  )  [protected]
 

00646 {
00647     switch (ldpPacket->type())
00648     {
00649     case HELLO:
00650         error("Received LDP HELLO over TCP (should arrive over UDP)");
00651 
00652     case ADDRESS:
00653         // processADDRESS(ldpPacket);
00654         error("Received LDP ADDRESS message, unsupported in this version");
00655         break;
00656 
00657     case ADDRESS_WITHDRAW:
00658         // processADDRESS_WITHDRAW(ldpPacket);
00659         error("LDP PROC DEBUG: Received LDP ADDRESS_WITHDRAW message, unsupported in this version");
00660         break;
00661 
00662     case LABEL_MAPPING:
00663         processLABEL_MAPPING(check_and_cast<LDPLabelMapping *>(ldpPacket));
00664         break;
00665 
00666     case LABEL_REQUEST:
00667         processLABEL_REQUEST(check_and_cast<LDPLabelRequest *>(ldpPacket));
00668         break;
00669 
00670     case LABEL_WITHDRAW:
00671         processLABEL_WITHDRAW(check_and_cast<LDPLabelMapping *>(ldpPacket));
00672         break;
00673 
00674     case LABEL_RELEASE:
00675         processLABEL_RELEASE(check_and_cast<LDPLabelMapping *>(ldpPacket));
00676         break;
00677 
00678     case NOTIFICATION:
00679         processNOTIFICATION(check_and_cast<LDPNotify*>(ldpPacket));
00680         break;
00681 
00682     default:
00683         error("LDP PROC DEBUG: Unrecognized LDP Message Type, type is %d", ldpPacket->type());
00684     }
00685 }

void LDP::processMessageFromTCP cMessage *  msg  )  [protected]
 

00555 {
00556     TCPSocket *socket = socketMap.findSocketFor(msg);
00557     if (!socket)
00558     {
00559         // not yet in socketMap, must be new incoming connection.
00560         // find which peer it is and register connection
00561         socket = new TCPSocket(msg);
00562         socket->setOutputGate(gate("tcpOut"));
00563 
00564         // FIXME there seems to be some confusion here. Is it sure that
00565         // routerIds we use as peerAddrs are the same as IP addresses
00566         // the routing is based on? --Andras
00567         IPAddress peerAddr = socket->remoteAddress().get4();
00568 
00569         int i = findPeer(peerAddr);
00570         if (i==-1 || myPeers[i].socket)
00571         {
00572             // nothing known about this guy, or already connected: refuse
00573             socket->close(); // reset()?
00574             delete socket;
00575             delete msg;
00576             return;
00577         }
00578         myPeers[i].socket = socket;
00579         socket->setCallbackObject(this, (void *)i);
00580         socketMap.addSocket(socket);
00581     }
00582 
00583     // dispatch to socketEstablished(), socketDataArrived(), socketPeerClosed()
00584     // or socketFailure()
00585     socket->processMessage(msg);
00586 }

void LDP::processNOTIFICATION LDPNotify packet  )  [protected]
 

00859 {
00860     FEC_TLV fec = packet->getFec();
00861     IPAddress srcAddr = packet->senderAddress();
00862     int status = packet->getStatus();
00863 
00864     // XXX FIXME NO_ROUTE processing should probably be split into two functions,
00865     // this is not the cleanest thing I ever wrote :)   --Vojta
00866 
00867     if (packet->isSelfMessage())
00868     {
00869         // re-scheduled by ourselves
00870         EV << "notification retry for peer=" << srcAddr << " fec=" << fec << " status=" << status << endl;
00871     }
00872     else
00873     {
00874         // received via network
00875         EV << "notification received from=" << srcAddr << " fec=" << fec << " status=" << status << endl;
00876     }
00877 
00878     switch(status)
00879     {
00880         case NO_ROUTE:
00881         {
00882             EV << "route does not exit on that peer" << endl;
00883 
00884             FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
00885             if (it != fecList.end())
00886             {
00887                 if (it->nextHop == srcAddr)
00888                 {
00889                     if (!packet->isSelfMessage())
00890                     {
00891                         EV << "we are still interesed in this mapping, we will retry later" << endl;
00892 
00893                         scheduleAt(simTime() + 1.0 /* XXX FIXME */, packet);
00894                         return;
00895                     }
00896                     else
00897                     {
00898                         EV << "reissuing request" << endl;
00899 
00900                         sendMappingRequest(srcAddr, fec.addr, fec.length);
00901                     }
00902                 }
00903                 else
00904                     EV << "and we still recognize this FEC, but we use different next hop, forget it" << endl;
00905             }
00906             else
00907                 EV << "and we do not recognize this any longer, forget it" << endl;
00908 
00909             break;
00910         }
00911 
00912         default:
00913             ASSERT(false);
00914     }
00915 
00916     delete packet;
00917 }

void LDP::rebuildFecList  )  [private]
 

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->numRoutingEntries(); i++)
00270     {
00271         // every entry in the routing table
00272 
00273         RoutingEntry *re = rt->routingEntry(i);
00274 
00275         // ignore multicast routes
00276         if (re->host.isMulticast())
00277             continue;
00278 
00279         // find out current next hop according to routing table
00280         IPAddress nextHop = (re->type == RoutingEntry::DIRECT)? re->host: re->gateway;
00281         ASSERT(!nextHop.isUnspecified());
00282 
00283         EV << "nextHop <-- " << nextHop << endl;
00284 
00285         FecVector::iterator it = findFecEntry(oldList, re->host, re->netmask.netmaskLength());
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->host;
00293             newItem.length = re->netmask.netmaskLength();
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->numInterfaces(); ++i)
00319     {
00320         InterfaceEntry *ie = ift->interfaceAt(i);
00321         if (ie->networkLayerGateIndex() < 0)
00322             continue;
00323 
00324         FecVector::iterator it = findFecEntry(oldList, ie->ipv4()->inetAddress(), 32);
00325         if (it == oldList.end())
00326         {
00327             fec_t newItem;
00328             newItem.fecid = ++maxFecid;
00329             newItem.addr = ie->ipv4()->inetAddress();
00330             newItem.length = 32;
00331             newItem.nextHop = ie->ipv4()->inetAddress();
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 
00382     std::sort(fecList.begin(), fecList.end(), fecPrefixCompare);
00383 
00384 }

void LDP::receiveChangeNotification int  category,
cPolymorphic *  details
[protected, virtual]
 

Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.

Implements INotifiable.

01234 {
01235     Enter_Method_Silent();
01236     printNotificationBanner(category, details);
01237 
01238     ASSERT(category == NF_IPv4_ROUTINGTABLE_CHANGED);
01239 
01240     EV << "routing table changed, rebuild list of known FEC" << endl;
01241 
01242     rebuildFecList();
01243 }

void LDP::sendHelloTo IPAddress  dest  )  [protected]
 

00399 {
00400     LDPHello *hello = new LDPHello("LDP-Hello");
00401     hello->setByteLength(LDP_HEADER_BYTES);
00402     hello->setType(HELLO);
00403     hello->setSenderAddress(rt->routerId());
00404     //hello->setReceiverAddress(...);
00405     hello->setHoldTime(holdTime);
00406     //hello->setRbit(...);
00407     //hello->setTbit(...);
00408     hello->addPar("color") = LDP_HELLO_TRAFFIC;
00409 
00410     udpSocket.sendTo(hello, dest, LDP_PORT);
00411 }

void LDP::sendMapping int  type,
IPAddress  dest,
int  label,
IPAddress  addr,
int  length
[private]
 

00840 {
00841     // Send LABEL MAPPING downstream
00842     LDPLabelMapping *lmMessage = new LDPLabelMapping("Lb-Mapping");
00843     lmMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
00844     lmMessage->setType(type);
00845     lmMessage->setReceiverAddress(dest);
00846     lmMessage->setSenderAddress(rt->routerId());
00847     lmMessage->setLabel(label);
00848 
00849     FEC_TLV fec;
00850     fec.addr = addr;
00851     fec.length = length;
00852 
00853     lmMessage->setFec(fec);
00854 
00855     sendToPeer(dest, lmMessage);
00856 }

void LDP::sendMappingRequest IPAddress  dest,
IPAddress  addr,
int  length
[private]
 

00184 {
00185     LDPLabelRequest *requestMsg = new LDPLabelRequest("Lb-Req");
00186     requestMsg->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
00187     requestMsg->setType(LABEL_REQUEST);
00188 
00189     FEC_TLV fec;
00190     fec.addr = addr;
00191     fec.length = length;
00192     requestMsg->setFec(fec);
00193 
00194     requestMsg->setReceiverAddress(dest);
00195     requestMsg->setSenderAddress(rt->routerId());
00196 
00197     sendToPeer(dest, requestMsg);
00198 }

void LDP::sendNotify int  status,
IPAddress  dest,
IPAddress  addr,
int  length
[private]
 

00821 {
00822     // Send NOTIFY message
00823     LDPNotify *lnMessage = new LDPNotify("Lb-Notify");
00824     lnMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
00825     lnMessage->setType(NOTIFICATION);
00826     lnMessage->setStatus(NO_ROUTE);
00827     lnMessage->setReceiverAddress(dest);
00828     lnMessage->setSenderAddress(rt->routerId());
00829 
00830     FEC_TLV fec;
00831     fec.addr = addr;
00832     fec.length = length;
00833 
00834     lnMessage->setFec(fec);
00835 
00836     sendToPeer(dest, lnMessage);
00837 }

void LDP::sendToPeer IPAddress  dest,
cMessage *  msg
[private]
 

00179 {
00180     peerSocket(dest)->send(msg);
00181 }

void LDP::socketClosed int  connId,
void *  yourPtr
[protected, virtual]
 

Reimplemented from TCPSocket::CallbackInterface.

00626 {
00627     peer_info& peer = myPeers[(long)yourPtr];
00628     EV << "TCP connection to peer " << peer.peerIP << " closed\n";
00629 
00630     ASSERT(false);
00631 
00632     // FIXME what now? reconnect after a delay?
00633 }

void LDP::socketDataArrived int  connId,
void *  yourPtr,
cMessage *  msg,
bool  urgent
[protected, virtual]
 

Implements TCPSocket::CallbackInterface.

00600 {
00601     peer_info& peer = myPeers[(long)yourPtr];
00602     EV << "Message arrived over TCP from peer " << peer.peerIP << "\n";
00603 
00604     delete msg->removeControlInfo();
00605     processLDPPacketFromTCP(check_and_cast<LDPPacket *>(msg));
00606 }

void LDP::socketEstablished int  connId,
void *  yourPtr
[protected, virtual]
 

Reimplemented from TCPSocket::CallbackInterface.

00589 {
00590     peer_info& peer = myPeers[(long)yourPtr];
00591     EV << "TCP connection established with peer " << peer.peerIP << "\n";
00592 
00593     // we must update all entries with nextHop == peerIP
00594     updateFecList(peer.peerIP);
00595 
00596     // FIXME start LDP session setup (if we're on the active side?)
00597 }

void LDP::socketFailure int  connId,
void *  yourPtr,
int  code
[protected, virtual]
 

Reimplemented from TCPSocket::CallbackInterface.

00636 {
00637     peer_info& peer = myPeers[(long)yourPtr];
00638     EV << "TCP connection to peer " << peer.peerIP << " broken\n";
00639 
00640     ASSERT(false);
00641 
00642     // FIXME what now? reconnect after a delay?
00643 }

void LDP::socketPeerClosed int  connId,
void *  yourPtr
[protected, virtual]
 

Reimplemented from TCPSocket::CallbackInterface.

00609 {
00610     peer_info& peer = myPeers[(long)yourPtr];
00611     EV << "Peer " << peer.peerIP << " closed TCP connection\n";
00612 
00613     ASSERT(false);
00614 
00615 /*
00616     // close the connection (if not already closed)
00617     if (socket.state()==TCPSocket::PEER_CLOSED)
00618     {
00619         EV << "remote TCP closed, closing here as well\n";
00620         close();
00621     }
00622 */
00623 }

virtual void LDP::socketStatusArrived int  connId,
void *  yourPtr,
TCPStatusInfo status
[inline, protected, virtual]
 

Reimplemented from TCPSocket::CallbackInterface.

00204 {delete status;}

void LDP::updateFecList IPAddress  nextHop  )  [private]
 

00387 {
00388     FecVector::iterator it;
00389     for (it = fecList.begin(); it != fecList.end(); it++)
00390     {
00391         if (it->nextHop != nextHop)
00392             continue;
00393 
00394         updateFecListEntry(*it);
00395     }
00396 }

void LDP::updateFecListEntry fec_t  oldItem  )  [private]
 

00201 {
00202     // do we have mapping from downstream?
00203     FecBindVector::iterator dit = findFecEntry(fecDown, oldItem.fecid, oldItem.nextHop);
00204 
00205     // is next hop our LDP peer?
00206     bool ER = !peerSocketSoft(oldItem.nextHop);
00207 
00208     ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time
00209 
00210     // adjust upstream mappings
00211     FecBindVector::iterator uit;
00212     for (uit = fecUp.begin(); uit != fecUp.end(); uit++)
00213     {
00214         if (uit->fecid != oldItem.fecid)
00215             continue;
00216 
00217         std::string inInterface = findInterfaceFromPeerAddr(uit->peer);
00218         std::string outInterface = findInterfaceFromPeerAddr(oldItem.nextHop);
00219         if (ER)
00220         {
00221             // we are egress, that's easy:
00222             LabelOpVector outLabel = LIBTable::popLabel();
00223             uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
00224 
00225             EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00226                     " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00227         }
00228         else if (dit != fecDown.end())
00229         {
00230             // we have mapping from DS, that's easy
00231             LabelOpVector outLabel = LIBTable::swapLabel(dit->label);
00232             uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
00233 
00234             EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
00235                     " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
00236 
00237         }
00238         else
00239         {
00240             // no mapping from DS, withdraw mapping US
00241 
00242             EV << "sending withdraw message upstream" << endl;
00243 
00244             sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, oldItem.addr, oldItem.length);
00245 
00246             // remove from US mappings
00247 
00248             fecUp.erase(uit--);
00249         }
00250     }
00251 
00252     if (!ER && dit == fecDown.end())
00253     {
00254         // and ask DS for mapping
00255 
00256         EV << "sending request message downstream" << endl;
00257 
00258         sendMappingRequest(oldItem.nextHop, oldItem.addr, oldItem.length);
00259     }
00260 }


Member Data Documentation

FecBindVector LDP::fecDown [private]
 

FecVector LDP::fecList [private]
 

FecBindVector LDP::fecUp [private]
 

double LDP::helloInterval [private]
 

double LDP::holdTime [private]
 

InterfaceTable* LDP::ift [private]
 

LIBTable* LDP::lt [private]
 

int LDP::maxFecid [private]
 

PeerVector LDP::myPeers [private]
 

NotificationBoard* LDP::nb [private]
 

PendingVector LDP::pending [private]
 

RoutingTable* LDP::rt [private]
 

cMessage* LDP::sendHelloMsg [private]
 

TCPSocket LDP::serverSocket [private]
 

TCPSocketMap LDP::socketMap [private]
 

TED* LDP::tedmod [private]
 

UDPSocket LDP::udpSocket [private]
 


The documentation for this class was generated from the following files:
Generated on Thu Oct 19 18:22:26 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.0