Classes | Public Types | Public Member Functions | Protected Member Functions | Protected Attributes

LDP Class Reference

#include <LDP.h>

Inheritance diagram for LDP:
TCPSocket::CallbackInterface IClassifier INotifiable

List of all members.

Classes

struct  fec_bind_t
struct  fec_t
struct  peer_info
struct  pending_req_t

Public Types

typedef std::vector< fec_tFecVector
typedef std::vector< fec_bind_tFecBindVector
typedef std::vector
< pending_req_t
PendingVector
typedef std::vector< peer_infoPeerVector

Public Member Functions

 LDP ()
virtual ~LDP ()

Protected Member Functions

virtual IPAddress locateNextHop (IPAddress dest)
virtual IPAddress findPeerAddrFromInterface (std::string interfaceName)
std::string findInterfaceFromPeerAddr (IPAddress peerIP)
virtual int findPeer (IPAddress peerAddr)
virtual TCPSocketgetPeerSocket (IPAddress peerAddr)
virtual TCPSocketfindPeerSocket (IPAddress peerAddr)
virtual void sendToPeer (IPAddress dest, cMessage *msg)
FecVector::iterator findFecEntry (FecVector &fecs, IPAddress addr, int length)
FecBindVector::iterator findFecEntry (FecBindVector &fecs, int fecid, IPAddress peer)
virtual void sendMappingRequest (IPAddress dest, IPAddress addr, int length)
virtual void sendMapping (int type, IPAddress dest, int label, IPAddress addr, int length)
virtual void sendNotify (int status, IPAddress dest, IPAddress addr, int length)
virtual void rebuildFecList ()
virtual void updateFecList (IPAddress nextHop)
virtual void updateFecListEntry (fec_t oldItem)
virtual void announceLinkChange (int tedlinkindex)
virtual int numInitStages () const
virtual void initialize (int stage)
virtual void handleMessage (cMessage *msg)
virtual void sendHelloTo (IPAddress dest)
virtual void openTCPConnectionToPeer (int peerIndex)
virtual void processLDPHello (LDPHello *msg)
virtual void processHelloTimeout (cMessage *msg)
virtual void processMessageFromTCP (cMessage *msg)
virtual void processLDPPacketFromTCP (LDPPacket *ldpPacket)
virtual void processLABEL_MAPPING (LDPLabelMapping *packet)
virtual void processLABEL_REQUEST (LDPLabelRequest *packet)
virtual void processLABEL_RELEASE (LDPLabelMapping *packet)
virtual void processLABEL_WITHDRAW (LDPLabelMapping *packet)
virtual void processNOTIFICATION (LDPNotify *packet)
virtual bool lookupLabel (IPDatagram *ipdatagram, LabelOpVector &outLabel, std::string &outInterface, int &color)
virtual void receiveChangeNotification (int category, const cPolymorphic *details)
TCPSocket::CallbackInterface callback methods

virtual void socketEstablished (int connId, void *yourPtr)
virtual void socketDataArrived (int connId, void *yourPtr, cPacket *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)

Protected Attributes

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

Detailed Description

LDP (rfc 3036) protocol implementation.

Definition at line 48 of file LDP.h.


Member Typedef Documentation

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

Definition at line 76 of file LDP.h.

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

Definition at line 66 of file LDP.h.

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

Definition at line 94 of file LDP.h.

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

Definition at line 84 of file LDP.h.


Constructor & Destructor Documentation

LDP::LDP (  ) 

Definition at line 84 of file LDP.cc.

{
    sendHelloMsg = NULL;
}

LDP::~LDP (  )  [virtual]

Definition at line 89 of file LDP.cc.

{
    for (unsigned int i=0; i<myPeers.size(); i++)
        cancelAndDelete(myPeers[i].timeout);

    cancelAndDelete(sendHelloMsg);
    //this causes segfault at the end of simulation       -- Vojta
    //socketMap.deleteSockets();
}


Member Function Documentation

void LDP::announceLinkChange ( int  tedlinkindex  )  [protected, virtual]

Definition at line 1247 of file LDP.cc.

Referenced by processHelloTimeout(), and processLDPHello().

{
    TEDChangeInfo d;
    d.setTedLinkIndicesArraySize(1);
    d.setTedLinkIndices(0, tedlinkindex);
    nb->fireChangeNotification(NF_TED_CHANGED, &d);
}

LDP::FecVector::iterator LDP::findFecEntry ( FecVector fecs,
IPAddress  addr,
int  length 
) [protected]

Definition at line 806 of file LDP.cc.

Referenced by lookupLabel(), processLABEL_MAPPING(), processLABEL_RELEASE(), processLABEL_REQUEST(), processLABEL_WITHDRAW(), processNOTIFICATION(), rebuildFecList(), and updateFecListEntry().

{
    FecVector::iterator it;
    for (it = fecs.begin(); it != fecs.end(); it++)
    {
        if (it->length != length)
            continue;

        if (it->addr != addr) // XXX compare only relevant part (?)
            continue;

        break;
    }
    return it;
}

LDP::FecBindVector::iterator LDP::findFecEntry ( FecBindVector fecs,
int  fecid,
IPAddress  peer 
) [protected]

Definition at line 790 of file LDP.cc.

{
    FecBindVector::iterator it;
    for (it = fecs.begin(); it != fecs.end(); it++)
    {
        if (it->fecid != fecid)
            continue;

        if (it->peer != peer)
            continue;

        break;
    }
    return it;
}

std::string LDP::findInterfaceFromPeerAddr ( IPAddress  peerIP  )  [protected]

Definition at line 762 of file LDP.cc.

Referenced by lookupLabel(), processLABEL_MAPPING(), processLABEL_REQUEST(), and updateFecListEntry().

{
/*
    int i;
    for (unsigned int i=0;i<myPeers.size();i++)
    {
        if (myPeers[i].peerIP == peerIP)
            return string(myPeers[i].linkInterface);
    }
    return string("X");
*/
//    Rely on port index to find the interface name

    // this function is a misnomer, we must recognize our own address too
    if (rt->isLocalAddress(peerIP))
        return "lo0";

    InterfaceEntry *ie = rt->getInterfaceForDestAddr(peerIP);
    if (!ie)
        error("findInterfaceFromPeerAddr(): %s is not routable", peerIP.str().c_str());
    return ie->getName();
}

int LDP::findPeer ( IPAddress  peerAddr  )  [protected, virtual]

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

Definition at line 1160 of file LDP.cc.

Referenced by findPeerSocket(), processLDPHello(), and processMessageFromTCP().

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

IPAddress LDP::findPeerAddrFromInterface ( std::string  interfaceName  )  [protected, virtual]

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.

Definition at line 723 of file LDP.cc.

Referenced by locateNextHop().

{
    int i = 0;
    int k = 0;
    InterfaceEntry *ie = ift->getInterfaceByName(interfaceName.c_str());

    const IPRoute *anEntry;

    for (i = 0; i < rt->getNumRoutes(); i++)
    {
        for (k = 0; k < (int)myPeers.size(); k++)
        {
            anEntry = rt->getRoute(i);
            if (anEntry->getHost()==myPeers[k].peerIP && anEntry->getInterface()==ie)
            {
                return myPeers[k].peerIP;
            }
            // addresses->push_back(peerIP[k]);
        }
    }

    // Return any IP which has default route - not in routing table entries
    for (i = 0; i < (int)myPeers.size(); i++)
    {
        for (k = 0; k < rt->getNumRoutes(); k++)
        {
            anEntry = rt->getRoute(i);
            if (anEntry->getHost() == myPeers[i].peerIP)
                break;
        }
        if (k == rt->getNumRoutes())
            break;
    }

    // return the peer's address if found, unspecified address otherwise
    return i==(int)myPeers.size() ? IPAddress() : myPeers[i].peerIP;
}

TCPSocket * LDP::findPeerSocket ( IPAddress  peerAddr  )  [protected, virtual]

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

Definition at line 1168 of file LDP.cc.

Referenced by getPeerSocket(), processLABEL_REQUEST(), and updateFecListEntry().

{
    // find peer in table and return its socket
    int i = findPeer(peerAddr);
    if (i==-1 || !(myPeers[i].socket) || myPeers[i].socket->getState()!=TCPSocket::CONNECTED)
        return NULL; // we don't have an LDP session to this peer
    return myPeers[i].socket;
}

TCPSocket * LDP::getPeerSocket ( IPAddress  peerAddr  )  [protected, virtual]

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

Definition at line 1177 of file LDP.cc.

Referenced by sendToPeer().

{
    TCPSocket *sock = findPeerSocket(peerAddr);
    ASSERT(sock);
    if (!sock)
        error("No LDP session to peer %s yet", peerAddr.str().c_str());
    return sock;
}

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

Definition at line 143 of file LDP.cc.

{
    EV << "Received: (" << msg->getClassName() << ")" << msg->getName() << "\n";
    if (msg==sendHelloMsg)
    {
        // every LDP capable router periodically sends HELLO messages to the
        // "all routers in the sub-network" multicast address
        EV << "Multicasting LDP Hello to neighboring routers\n";
        sendHelloTo(IPAddress::ALL_ROUTERS_MCAST);

        // schedule next hello
        scheduleAt(simTime() + helloInterval, sendHelloMsg);
    }
    else if (msg->isSelfMessage())
    {
        EV << "Timer " << msg->getName() << " expired\n";
        if (!strcmp(msg->getName(), "HelloTimeout"))
        {
            processHelloTimeout(msg);
        }
        else
        {
            processNOTIFICATION(check_and_cast<LDPNotify*>(msg));
        }
    }
    else if (!strcmp(msg->getArrivalGate()->getName(), "udpIn"))
    {
        // we can only receive LDP Hello from UDP (everything else goes over TCP)
        processLDPHello(check_and_cast<LDPHello *>(msg));
    }
    else if (!strcmp(msg->getArrivalGate()->getName(), "tcpIn"))
    {
        processMessageFromTCP(msg);
    }
}

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

Definition at line 99 of file LDP.cc.

{
    if (stage != 3)
        return; // wait for routing table to initialize first

    holdTime = par("holdTime").doubleValue();
    helloInterval = par("helloInterval").doubleValue();

    ift = InterfaceTableAccess().get();
    rt = RoutingTableAccess().get();
    lt = LIBTableAccess().get();
    tedmod = TEDAccess().get();
    nb = NotificationBoardAccess().get();

    WATCH_VECTOR(myPeers);
    WATCH_VECTOR(fecUp);
    WATCH_VECTOR(fecDown);
    WATCH_VECTOR(fecList);
    WATCH_VECTOR(pending);

    maxFecid = 0;

    // schedule first hello
    sendHelloMsg = new cMessage("LDPSendHello");
    scheduleAt(simTime() + exponential(0.1), sendHelloMsg);

    // bind UDP socket
    udpSocket.setOutputGate(gate("udpOut"));
    udpSocket.bind(LDP_PORT);

    // start listening for incoming TCP conns
    EV << "Starting to listen on port " << LDP_PORT << " for incoming LDP sessions\n";
    serverSocket.setOutputGate(gate("tcpOut"));
    serverSocket.bind(LDP_PORT);
    serverSocket.listen();

    // build list of recognized FECs
    rebuildFecList();

    // listen for routing table modifications
    nb->subscribe(this, NF_IPv4_ROUTE_ADDED);
    nb->subscribe(this, NF_IPv4_ROUTE_DELETED);
}

IPAddress LDP::locateNextHop ( IPAddress  dest  )  [protected, virtual]

This method finds next peer in upstream direction

Definition at line 689 of file LDP.cc.

{
    // Mapping L3 IP-host of next hop to L2 peer address.

    // Lookup the routing table, rfc3036
    // "When the FEC for which a label is requested is a Prefix FEC Element or
    //  a Host Address FEC Element, the receiving LSR uses its routing table to determine
    //  its response. Unless its routing table includes an entry that exactly matches
    //  the requested Prefix or Host Address, the LSR must respond with a
    //  No Route Notification message."
    //
    // FIXME the code below (though seems like that's what the RFC refers to) doesn't work
    // -- we can't reasonably expect the destination host to be exaplicitly in an
    // LSR's routing table!!! Use simple IP routing instead. --Andras
    //
    // Wrong code:
    //int i;
    //for (i=0; i < rt->getNumRoutes(); i++)
    //    if (rt->getRoute(i)->host == dest)
    //        break;
    //
    //if (i == rt->getNumRoutes())
    //    return IPAddress();  // Signal an NOTIFICATION of NO ROUTE
    //
    InterfaceEntry *ie = rt->getInterfaceForDestAddr(dest);
    if (!ie)
        return IPAddress();  // no route

    std::string iName = ie->getName(); // FIXME why use name for lookup?
    return findPeerAddrFromInterface(iName);
}

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

Definition at line 1186 of file LDP.cc.

{
    IPAddress destAddr = ipdatagram->getDestAddress();
    int protocol = ipdatagram->getTransportProtocol();

    // never match and always route via L3 if:

    // OSPF traffic (TED)
    if (protocol == IP_PROT_OSPF)
        return false;

    // LDP traffic (both discovery...
    if (protocol == IP_PROT_UDP && check_and_cast<UDPPacket*>(ipdatagram->getEncapsulatedMsg())->getDestinationPort() == LDP_PORT)
        return false;

    // ...and session)
    if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedMsg())->getDestPort() == LDP_PORT)
        return false;
    if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedMsg())->getSrcPort() == LDP_PORT)
        return false;

    // regular traffic, classify, label etc.

    FecVector::iterator it;
    for (it = fecList.begin(); it != fecList.end(); it++)
    {
        if (!destAddr.prefixMatches(it->addr, it->length))
            continue;

        EV << "FEC matched: " << *it << endl;

        FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop);
        if (dit != fecDown.end())
        {
            outLabel = LIBTable::pushLabel(dit->label);
            outInterface = findInterfaceFromPeerAddr(it->nextHop);
            color = LDP_USER_TRAFFIC;
            EV << "mapping found, outLabel=" << outLabel << ", outInterface=" << outInterface << endl;
            return true;
        }
        else
        {
            EV << "no mapping for this FEC exists" << endl;
            return false;
        }
    }
    return false;
}

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

Definition at line 180 of file LDP.h.

{return 4;}

void LDP::openTCPConnectionToPeer ( int  peerIndex  )  [protected, virtual]

Definition at line 544 of file LDP.cc.

Referenced by processLDPHello().

{
    TCPSocket *socket = new TCPSocket();
    socket->setOutputGate(gate("tcpOut"));
    socket->setCallbackObject(this, (void*)peerIndex);
    socket->bind(rt->getRouterId(), 0);
    socketMap.addSocket(socket);
    myPeers[peerIndex].socket = socket;

    socket->connect(myPeers[peerIndex].peerIP, LDP_PORT);
}

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

Definition at line 411 of file LDP.cc.

Referenced by handleMessage().

{
    // peer is gone

    unsigned int i;
    for (i = 0; i < myPeers.size(); i++)
        if (myPeers[i].timeout == msg)
            break;
    ASSERT(i < myPeers.size());

    IPAddress peerIP = myPeers[i].peerIP;

    EV << "peer=" << peerIP << " is gone, removing adjacency" << endl;

    ASSERT(!myPeers[i].timeout->isScheduled());
    delete myPeers[i].timeout;
    ASSERT(myPeers[i].socket);
    myPeers[i].socket->abort(); // should we only close?
    delete myPeers[i].socket;
    myPeers.erase(myPeers.begin() + i);

    EV << "removing (stale) bindings from fecDown for peer=" << peerIP << endl;

    FecBindVector::iterator dit;
    for (dit = fecDown.begin(); dit != fecDown.end();)
    {
        if (dit->peer != peerIP)
        {
            dit++;
            continue;
        }

        EV << "label=" << dit->label << endl;

        // send release message just in case (?)
        // what happens if peer is not really down and
        // hello messages just disappeared?
        // does the protocol recover on its own (XXX check this)

        dit = fecDown.erase(dit);
    }

    EV << "removing bindings from sent to peer=" << peerIP << " from fecUp" << endl;

    FecBindVector::iterator uit;
    for (uit = fecUp.begin(); uit != fecUp.end();)
    {
        if (uit->peer != peerIP)
        {
            uit++;
            continue;
        }

        EV << "label=" << uit->label << endl;

        // send withdraw message just in case (?)
        // see comment above...

        uit = fecUp.erase(uit);
    }

    EV << "updating fecList" << endl;

    updateFecList(peerIP);

    // update TED and routing table

    unsigned int index = tedmod->linkIndex(rt->getRouterId(), peerIP);
    tedmod->ted[index].state = false;
    announceLinkChange(index);
    tedmod->rebuildRoutingTable();
}

void LDP::processLABEL_MAPPING ( LDPLabelMapping *  packet  )  [protected, virtual]

Definition at line 1101 of file LDP.cc.

Referenced by processLDPPacketFromTCP().

{
    FEC_TLV fec = packet->getFec();
    int label = packet->getLabel();
    IPAddress fromIP = packet->getSenderAddress();

    EV << "Label mapping label=" << label << " received for fec=" << fec << " from " << fromIP << endl;

    ASSERT(label > 0);

    FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
    ASSERT(it != fecList.end());

    FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP);
    ASSERT(dit == fecDown.end());

    // insert among received mappings

    fec_bind_t newItem;
    newItem.fecid = it->fecid;
    newItem.peer = fromIP;
    newItem.label = label;
    fecDown.push_back(newItem);

    // respond to pending requests

    PendingVector::iterator pit;
    for (pit = pending.begin(); pit != pending.end();)
    {
        if (pit->fecid != it->fecid)
        {
            pit++;
            continue;
        }

        EV << "there's pending request for this FEC from " << pit->peer << ", sending mapping" << endl;

        std::string inInterface = findInterfaceFromPeerAddr(pit->peer);
        std::string outInterface = findInterfaceFromPeerAddr(fromIP);
        LabelOpVector outLabel = LIBTable::swapLabel(label);

        fec_bind_t newItem;
        newItem.fecid = it->fecid;
        newItem.peer = pit->peer;
        newItem.label = lt->installLibEntry(-1, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);
        fecUp.push_back(newItem);

        EV << "installed LIB entry inLabel=" << newItem.label << " inInterface=" << inInterface <<
                " outLabel=" << outLabel << " outInterface=" << outInterface << endl;

        sendMapping(LABEL_MAPPING, pit->peer, newItem.label, it->addr, it->length);

        // remove request from the list
        pit = pending.erase(pit);
    }

    delete packet;
}

void LDP::processLABEL_RELEASE ( LDPLabelMapping *  packet  )  [protected, virtual]

Definition at line 1017 of file LDP.cc.

Referenced by processLDPPacketFromTCP().

{
    FEC_TLV fec = packet->getFec();
    int label = packet->getLabel();
    IPAddress fromIP = packet->getSenderAddress();

    EV << "Mapping release received for label=" << label << " fec=" << fec << " from " << fromIP << endl;

    ASSERT(label > 0);

    // remove label from fecUp

    FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
    if (it == fecList.end())
    {
        EV << "FEC no longer recognized here, ignoring" << endl;
        delete packet;
        return;
    }

    FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, fromIP);
    if (uit == fecUp.end() || label != uit->label)
    {
        // this is ok and may happen; e.g. we removed the mapping because downstream
        // neighbour withdrew its mapping. we sent withdraw upstream as well and
        // this is upstream's response
        EV << "mapping not found among sent mappings, ignoring" << endl;
        delete packet;
        return;
    }

    EV << "removing from LIB table label=" << uit->label << endl;
    lt->removeLibEntry(uit->label);

    EV << "removing label from list of sent mappings" << endl;
    fecUp.erase(uit);

    delete packet;
}

void LDP::processLABEL_REQUEST ( LDPLabelRequest *  packet  )  [protected, virtual]

Definition at line 921 of file LDP.cc.

Referenced by processLDPPacketFromTCP().

{
    FEC_TLV fec = packet->getFec();
    IPAddress srcAddr = packet->getSenderAddress();

    EV << "Label Request from LSR " << srcAddr << " for FEC " << fec << endl;

    FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
    if (it == fecList.end())
    {
        EV << "FEC not recognized, sending back No route message" << endl;

        sendNotify(NO_ROUTE, srcAddr, fec.addr, fec.length);

        delete packet;
        return;
    }

    // do we already have mapping for this fec from our downstream peer?

    //
    // XXX this code duplicates rebuildFecList
    //

    // does upstream have mapping from us?
    FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, srcAddr);

    // shouldn't!
    ASSERT(uit == fecUp.end());

    // do we have mapping from downstream?
    FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop);

    // is next hop our LDP peer?
    bool ER = !findPeerSocket(it->nextHop);

    ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time

    if (ER || dit != fecDown.end())
    {
        fec_bind_t newItem;
        newItem.fecid = it->fecid;
        newItem.label = -1;
        newItem.peer = srcAddr;
        fecUp.push_back(newItem);
        uit = fecUp.end() - 1;
    }

    std::string inInterface = findInterfaceFromPeerAddr(srcAddr);
    std::string outInterface = findInterfaceFromPeerAddr(it->nextHop);

    if (ER)
    {
        // we are egress, that's easy:
        LabelOpVector outLabel = LIBTable::popLabel();

        uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, 0);

        EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
                " outLabel=" << outLabel << " outInterface=" << outInterface << endl;

        // We are egress, let our upstream peer know
        // about it by sending back a Label Mapping message

        sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length);

    }
    else if (dit != fecDown.end())
    {
        // we have mapping from DS, that's easy
        LabelOpVector outLabel = LIBTable::swapLabel(dit->label);
        uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);

        EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
                " outLabel=" << outLabel << " outInterface=" << outInterface << endl;

        // We already have a mapping for this FEC, let our upstream peer know
        // about it by sending back a Label Mapping message

        sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length);
    }
    else
    {
        // no mapping from DS, mark as pending

        EV << "no mapping for this FEC from the downstream router, marking as pending" << endl;

        pending_req_t newItem;
        newItem.fecid = it->fecid;
        newItem.peer = srcAddr;
        pending.push_back(newItem);
    }

    delete packet;
}

void LDP::processLABEL_WITHDRAW ( LDPLabelMapping *  packet  )  [protected, virtual]

Definition at line 1057 of file LDP.cc.

Referenced by processLDPPacketFromTCP().

{
    FEC_TLV fec = packet->getFec();
    int label = packet->getLabel();
    IPAddress fromIP = packet->getSenderAddress();

    EV << "Mapping withdraw received for label=" << label << " fec=" << fec << " from " << fromIP << endl;

    ASSERT(label > 0);

    // remove label from fecDown

    FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
    if (it == fecList.end())
    {
        EV << "matching FEC not found, ignoring withdraw message" << endl;
        delete packet;
        return;
    }

    FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP);

    if (dit == fecDown.end() || label != dit->label)
    {
        EV << "matching mapping not found, ignoring withdraw message" << endl;
        delete packet;
        return;
    }

    ASSERT(dit != fecDown.end());
    ASSERT(label == dit->label);

    EV << "removing label from list of received mappings" << endl;
    fecDown.erase(dit);

    EV << "sending back relase message" << endl;
    packet->setType(LABEL_RELEASE);

    // send msg to peer over TCP
    sendToPeer(fromIP, packet);

    updateFecListEntry(*it);
}

void LDP::processLDPHello ( LDPHello *  msg  )  [protected, virtual]

Definition at line 484 of file LDP.cc.

Referenced by handleMessage().

{
    UDPControlInfo *controlInfo = check_and_cast<UDPControlInfo *>(msg->getControlInfo());
    //IPAddress peerAddr = controlInfo->getSrcAddr().get4();
    IPAddress peerAddr = msg->getSenderAddress();
    int interfaceId = controlInfo->getInterfaceId();
    delete msg;

    EV << "Received LDP Hello from " << peerAddr << ", ";

    if (peerAddr.isUnspecified() || peerAddr==rt->getRouterId())
    {
        // must be ourselves (we're also in the all-routers multicast group), ignore
        EV << "that's myself, ignore\n";
        return;
    }

    // mark link as working if it was failed, and rebuild table
    unsigned int index = tedmod->linkIndex(rt->getRouterId(), peerAddr);
    if (!tedmod->ted[index].state)
    {
        tedmod->ted[index].state = true;
        tedmod->rebuildRoutingTable();
        announceLinkChange(index);
    }

    // peer already in table?
    int i = findPeer(peerAddr);
    if (i!=-1)
    {
        EV << "already in my peer table, rescheduling timeout" << endl;
        ASSERT(myPeers[i].timeout);
        cancelEvent(myPeers[i].timeout);
        scheduleAt(simTime() + holdTime, myPeers[i].timeout);
        return;
    }

    // not in table, add it
    peer_info info;
    info.peerIP = peerAddr;
    info.linkInterface = ift->getInterfaceById(interfaceId)->getName();
    info.activeRole = peerAddr.getInt() > rt->getRouterId().getInt();
    info.socket = NULL;
    info.timeout = new cMessage("HelloTimeout");
    scheduleAt(simTime() + holdTime, info.timeout);
    myPeers.push_back(info);
    int peerIndex = myPeers.size()-1;

    EV << "added to peer table\n";
    EV << "We'll be " << (info.activeRole ? "ACTIVE" : "PASSIVE") << " in this session\n";

    // introduce ourselves with a Hello, then connect if we're in ACTIVE role
    sendHelloTo(peerAddr);
    if (info.activeRole)
    {
        EV << "Establishing session with it\n";
        openTCPConnectionToPeer(peerIndex);
    }
}

void LDP::processLDPPacketFromTCP ( LDPPacket *  ldpPacket  )  [protected, virtual]

Definition at line 647 of file LDP.cc.

Referenced by socketDataArrived().

{
    switch (ldpPacket->getType())
    {
    case HELLO:
        error("Received LDP HELLO over TCP (should arrive over UDP)");

    case ADDRESS:
        // processADDRESS(ldpPacket);
        error("Received LDP ADDRESS message, unsupported in this version");
        break;

    case ADDRESS_WITHDRAW:
        // processADDRESS_WITHDRAW(ldpPacket);
        error("LDP PROC DEBUG: Received LDP ADDRESS_WITHDRAW message, unsupported in this version");
        break;

    case LABEL_MAPPING:
        processLABEL_MAPPING(check_and_cast<LDPLabelMapping *>(ldpPacket));
        break;

    case LABEL_REQUEST:
        processLABEL_REQUEST(check_and_cast<LDPLabelRequest *>(ldpPacket));
        break;

    case LABEL_WITHDRAW:
        processLABEL_WITHDRAW(check_and_cast<LDPLabelMapping *>(ldpPacket));
        break;

    case LABEL_RELEASE:
        processLABEL_RELEASE(check_and_cast<LDPLabelMapping *>(ldpPacket));
        break;

    case NOTIFICATION:
        processNOTIFICATION(check_and_cast<LDPNotify*>(ldpPacket));
        break;

    default:
        error("LDP PROC DEBUG: Unrecognized LDP Message Type, type is %d", ldpPacket->getType());
    }
}

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

Definition at line 556 of file LDP.cc.

Referenced by handleMessage().

{
    TCPSocket *socket = socketMap.findSocketFor(msg);
    if (!socket)
    {
        // not yet in socketMap, must be new incoming connection.
        // find which peer it is and register connection
        socket = new TCPSocket(msg);
        socket->setOutputGate(gate("tcpOut"));

        // FIXME there seems to be some confusion here. Is it sure that
        // routerIds we use as peerAddrs are the same as IP addresses
        // the routing is based on? --Andras
        IPAddress peerAddr = socket->getRemoteAddress().get4();

        int i = findPeer(peerAddr);
        if (i==-1 || myPeers[i].socket)
        {
            // nothing known about this guy, or already connected: refuse
            socket->close(); // reset()?
            delete socket;
            delete msg;
            return;
        }
        myPeers[i].socket = socket;
        socket->setCallbackObject(this, (void *)i);
        socketMap.addSocket(socket);
    }

    // dispatch to socketEstablished(), socketDataArrived(), socketPeerClosed()
    // or socketFailure()
    socket->processMessage(msg);
}

void LDP::processNOTIFICATION ( LDPNotify *  packet  )  [protected, virtual]

Definition at line 860 of file LDP.cc.

Referenced by handleMessage(), and processLDPPacketFromTCP().

{
    FEC_TLV fec = packet->getFec();
    IPAddress srcAddr = packet->getSenderAddress();
    int status = packet->getStatus();

    // XXX FIXME NO_ROUTE processing should probably be split into two functions,
    // this is not the cleanest thing I ever wrote :)   --Vojta

    if (packet->isSelfMessage())
    {
        // re-scheduled by ourselves
        EV << "notification retry for peer=" << srcAddr << " fec=" << fec << " status=" << status << endl;
    }
    else
    {
        // received via network
        EV << "notification received from=" << srcAddr << " fec=" << fec << " status=" << status << endl;
    }

    switch(status)
    {
        case NO_ROUTE:
        {
            EV << "route does not exit on that peer" << endl;

            FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length);
            if (it != fecList.end())
            {
                if (it->nextHop == srcAddr)
                {
                    if (!packet->isSelfMessage())
                    {
                        EV << "we are still interesed in this mapping, we will retry later" << endl;

                        scheduleAt(simTime() + 1.0 /* XXX FIXME */, packet);
                        return;
                    }
                    else
                    {
                        EV << "reissuing request" << endl;

                        sendMappingRequest(srcAddr, fec.addr, fec.length);
                    }
                }
                else
                    EV << "and we still recognize this FEC, but we use different next hop, forget it" << endl;
            }
            else
                EV << "and we do not recognize this any longer, forget it" << endl;

            break;
        }

        default:
            ASSERT(false);
    }

    delete packet;
}

void LDP::rebuildFecList (  )  [protected, virtual]

Definition at line 262 of file LDP.cc.

Referenced by initialize(), and receiveChangeNotification().

{
    EV << "make list of recognized FECs" << endl;

    FecVector oldList = fecList;
    fecList.clear();

    for (int i = 0; i < rt->getNumRoutes(); i++)
    {
        // every entry in the routing table

        const IPRoute *re = rt->getRoute(i);

        // ignore multicast routes
        if (re->getHost().isMulticast())
            continue;

        // find out current next hop according to routing table
        IPAddress nextHop = (re->getType() == IPRoute::DIRECT) ? re->getHost() : re->getGateway();
        ASSERT(!nextHop.isUnspecified());

        EV << "nextHop <-- " << nextHop << endl;

        FecVector::iterator it = findFecEntry(oldList, re->getHost(), re->getNetmask().getNetmaskLength());

        if (it == oldList.end())
        {
            // fec didn't exist, it was just created
            fec_t newItem;
            newItem.fecid = ++maxFecid;
            newItem.addr = re->getHost();
            newItem.length = re->getNetmask().getNetmaskLength();
            newItem.nextHop = nextHop;
            updateFecListEntry(newItem);
            fecList.push_back(newItem);
        }
        else if (it->nextHop != nextHop)
        {
            // next hop for this FEC changed,
            it->nextHop = nextHop;
            updateFecListEntry(*it);
            fecList.push_back(*it);
            oldList.erase(it);
        }
        else
        {
            // FEC didn't change, reusing old values
            fecList.push_back(*it);
            oldList.erase(it);
            continue;
        }
    }


    // our own addresses (XXX is it needed?)

    for (int i = 0; i< ift->getNumInterfaces(); ++i)
    {
        InterfaceEntry *ie = ift->getInterface(i);
        if (ie->getNetworkLayerGateIndex() < 0)
            continue;

        FecVector::iterator it = findFecEntry(oldList, ie->ipv4Data()->getIPAddress(), 32);
        if (it == oldList.end())
        {
            fec_t newItem;
            newItem.fecid = ++maxFecid;
            newItem.addr = ie->ipv4Data()->getIPAddress();
            newItem.length = 32;
            newItem.nextHop = ie->ipv4Data()->getIPAddress();
            fecList.push_back(newItem);
        }
        else
        {
            fecList.push_back(*it);
            oldList.erase(it);
        }
    }

    if (oldList.size() > 0)
    {
        EV << "there are " << oldList.size() << " deprecated FECs, removing them" << endl;

        FecVector::iterator it;
        for (it = oldList.begin(); it != oldList.end(); it++)
        {
            EV << "removing FEC= " << *it << endl;

            FecBindVector::iterator dit;
            for (dit = fecDown.begin(); dit != fecDown.end(); dit++)
            {
                if (dit->fecid != it->fecid)
                    continue;

                EV << "sending release label=" << dit->label << " downstream to " << dit->peer << endl;

                sendMapping(LABEL_RELEASE, dit->peer, dit->label, it->addr, it->length);
            }

            FecBindVector::iterator uit;
            for (uit = fecUp.begin(); uit != fecUp.end(); uit++)
            {
                if (uit->fecid != it->fecid)
                    continue;

                EV << "sending withdraw label=" << uit->label << " upstream to " << uit->peer << endl;

                sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, it->addr, it->length);

                EV << "removing entry inLabel=" << uit->label << " from LIB" << endl;

                lt->removeLibEntry(uit->label);
            }

        }
    }

    // we must keep this list sorted for matching to work correctly
    // this is probably slower than it must be
    std::sort(fecList.begin(), fecList.end(), fecPrefixCompare);
}

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

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

Implements INotifiable.

Definition at line 1235 of file LDP.cc.

{
    Enter_Method_Silent();
    printNotificationBanner(category, details);

    ASSERT(category==NF_IPv4_ROUTE_ADDED || category==NF_IPv4_ROUTE_DELETED);

    EV << "routing table changed, rebuild list of known FEC" << endl;

    rebuildFecList();
}

void LDP::sendHelloTo ( IPAddress  dest  )  [protected, virtual]

Definition at line 396 of file LDP.cc.

Referenced by handleMessage(), and processLDPHello().

{
    LDPHello *hello = new LDPHello("LDP-Hello");
    hello->setByteLength(LDP_HEADER_BYTES);
    hello->setType(HELLO);
    hello->setSenderAddress(rt->getRouterId());
    //hello->setReceiverAddress(...);
    hello->setHoldTime(SIMTIME_DBL(holdTime));
    //hello->setRbit(...);
    //hello->setTbit(...);
    hello->addPar("color") = LDP_HELLO_TRAFFIC;

    udpSocket.sendTo(hello, dest, LDP_PORT);
}

void LDP::sendMapping ( int  type,
IPAddress  dest,
int  label,
IPAddress  addr,
int  length 
) [protected, virtual]

Definition at line 841 of file LDP.cc.

Referenced by processLABEL_MAPPING(), processLABEL_REQUEST(), rebuildFecList(), and updateFecListEntry().

{
    // Send LABEL MAPPING downstream
    LDPLabelMapping *lmMessage = new LDPLabelMapping("Lb-Mapping");
    lmMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
    lmMessage->setType(type);
    lmMessage->setReceiverAddress(dest);
    lmMessage->setSenderAddress(rt->getRouterId());
    lmMessage->setLabel(label);

    FEC_TLV fec;
    fec.addr = addr;
    fec.length = length;

    lmMessage->setFec(fec);

    sendToPeer(dest, lmMessage);
}

void LDP::sendMappingRequest ( IPAddress  dest,
IPAddress  addr,
int  length 
) [protected, virtual]

Definition at line 184 of file LDP.cc.

Referenced by processNOTIFICATION(), and updateFecListEntry().

{
    LDPLabelRequest *requestMsg = new LDPLabelRequest("Lb-Req");
    requestMsg->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
    requestMsg->setType(LABEL_REQUEST);

    FEC_TLV fec;
    fec.addr = addr;
    fec.length = length;
    requestMsg->setFec(fec);

    requestMsg->setReceiverAddress(dest);
    requestMsg->setSenderAddress(rt->getRouterId());

    sendToPeer(dest, requestMsg);
}

void LDP::sendNotify ( int  status,
IPAddress  dest,
IPAddress  addr,
int  length 
) [protected, virtual]

Definition at line 822 of file LDP.cc.

Referenced by processLABEL_REQUEST().

{
    // Send NOTIFY message
    LDPNotify *lnMessage = new LDPNotify("Lb-Notify");
    lnMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length
    lnMessage->setType(NOTIFICATION);
    lnMessage->setStatus(NO_ROUTE);
    lnMessage->setReceiverAddress(dest);
    lnMessage->setSenderAddress(rt->getRouterId());

    FEC_TLV fec;
    fec.addr = addr;
    fec.length = length;

    lnMessage->setFec(fec);

    sendToPeer(dest, lnMessage);
}

void LDP::sendToPeer ( IPAddress  dest,
cMessage *  msg 
) [protected, virtual]

Definition at line 179 of file LDP.cc.

Referenced by processLABEL_WITHDRAW(), sendMapping(), sendMappingRequest(), and sendNotify().

{
    getPeerSocket(dest)->send(msg);
}

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

Definition at line 627 of file LDP.cc.

{
    peer_info& peer = myPeers[(long)yourPtr];
    EV << "TCP connection to peer " << peer.peerIP << " closed\n";

    ASSERT(false);

    // FIXME what now? reconnect after a delay?
}

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

Definition at line 601 of file LDP.cc.

{
    peer_info& peer = myPeers[(long)yourPtr];
    EV << "Message arrived over TCP from peer " << peer.peerIP << "\n";

    delete msg->removeControlInfo();
    processLDPPacketFromTCP(check_and_cast<LDPPacket *>(msg));
}

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

Definition at line 590 of file LDP.cc.

{
    peer_info& peer = myPeers[(long)yourPtr];
    EV << "TCP connection established with peer " << peer.peerIP << "\n";

    // we must update all entries with nextHop == peerIP
    updateFecList(peer.peerIP);

    // FIXME start LDP session setup (if we're on the active side?)
}

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

Definition at line 637 of file LDP.cc.

{
    peer_info& peer = myPeers[(long)yourPtr];
    EV << "TCP connection to peer " << peer.peerIP << " broken\n";

    ASSERT(false);

    // FIXME what now? reconnect after a delay?
}

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

Definition at line 610 of file LDP.cc.

{
    peer_info& peer = myPeers[(long)yourPtr];
    EV << "Peer " << peer.peerIP << " closed TCP connection\n";

    ASSERT(false);

/*
    // close the connection (if not already closed)
    if (socket.getState()==TCPSocket::PEER_CLOSED)
    {
        EV << "remote TCP closed, closing here as well\n";
        close();
    }
*/
}

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

Definition at line 205 of file LDP.h.

{delete status;}

void LDP::updateFecList ( IPAddress  nextHop  )  [protected, virtual]

Definition at line 384 of file LDP.cc.

Referenced by processHelloTimeout(), and socketEstablished().

{
    FecVector::iterator it;
    for (it = fecList.begin(); it != fecList.end(); it++)
    {
        if (it->nextHop != nextHop)
            continue;

        updateFecListEntry(*it);
    }
}

void LDP::updateFecListEntry ( LDP::fec_t  oldItem  )  [protected, virtual]

Definition at line 201 of file LDP.cc.

Referenced by processLABEL_WITHDRAW(), rebuildFecList(), and updateFecList().

{
    // do we have mapping from downstream?
    FecBindVector::iterator dit = findFecEntry(fecDown, oldItem.fecid, oldItem.nextHop);

    // is next hop our LDP peer?
    bool ER = findPeerSocket(oldItem.nextHop)==NULL;

    ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time

    // adjust upstream mappings
    FecBindVector::iterator uit;
    for (uit = fecUp.begin(); uit != fecUp.end();)
    {
        if (uit->fecid != oldItem.fecid)
        {
            uit++;
            continue;
        }

        std::string inInterface = findInterfaceFromPeerAddr(uit->peer);
        std::string outInterface = findInterfaceFromPeerAddr(oldItem.nextHop);
        if (ER)
        {
            // we are egress, that's easy:
            LabelOpVector outLabel = LIBTable::popLabel();
            uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);

            EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
                    " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
            uit++;
        }
        else if (dit != fecDown.end())
        {
            // we have mapping from DS, that's easy
            LabelOpVector outLabel = LIBTable::swapLabel(dit->label);
            uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC);

            EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface <<
                    " outLabel=" << outLabel << " outInterface=" << outInterface << endl;
            uit++;
        }
        else
        {
            // no mapping from DS, withdraw mapping US
            EV << "sending withdraw message upstream" << endl;
            sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, oldItem.addr, oldItem.length);

            // remove from US mappings
            uit = fecUp.erase(uit);
        }
    }

    if (!ER && dit == fecDown.end())
    {
        // and ask DS for mapping
        EV << "sending request message downstream" << endl;
        sendMappingRequest(oldItem.nextHop, oldItem.addr, oldItem.length);
    }
}


Member Data Documentation

simtime_t LDP::helloInterval [protected]

Definition at line 99 of file LDP.h.

Referenced by handleMessage(), and initialize().

simtime_t LDP::holdTime [protected]

Definition at line 98 of file LDP.h.

Referenced by initialize(), processLDPHello(), and sendHelloTo().

IInterfaceTable* LDP::ift [protected]

Definition at line 116 of file LDP.h.

Referenced by findPeerAddrFromInterface(), initialize(), processLDPHello(), and rebuildFecList().

int LDP::maxFecid [protected]

Definition at line 129 of file LDP.h.

Referenced by initialize(), and rebuildFecList().

NotificationBoard* LDP::nb [protected]

Definition at line 120 of file LDP.h.

Referenced by announceLinkChange(), and initialize().

Definition at line 108 of file LDP.h.

Referenced by initialize(), processLABEL_MAPPING(), and processLABEL_REQUEST().

cMessage* LDP::sendHelloMsg [protected]

Definition at line 127 of file LDP.h.

Referenced by handleMessage(), initialize(), LDP(), and ~LDP().

Definition at line 123 of file LDP.h.

Referenced by initialize().

Definition at line 124 of file LDP.h.

Referenced by openTCPConnectionToPeer(), and processMessageFromTCP().

TED* LDP::tedmod [protected]

Definition at line 119 of file LDP.h.

Referenced by initialize(), processHelloTimeout(), and processLDPHello().

Definition at line 122 of file LDP.h.

Referenced by initialize(), and sendHelloTo().


The documentation for this class was generated from the following files: