#include <LDP.h>
Classes | |
struct | fec_bind_t |
struct | fec_t |
struct | peer_info |
struct | pending_req_t |
Public Types | |
typedef std::vector< fec_t > | FecVector |
typedef std::vector< fec_bind_t > | FecBindVector |
typedef std::vector < pending_req_t > | PendingVector |
typedef std::vector< peer_info > | PeerVector |
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 TCPSocket * | getPeerSocket (IPAddress peerAddr) |
virtual TCPSocket * | findPeerSocket (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 |
IInterfaceTable * | ift |
IRoutingTable * | rt |
LIBTable * | lt |
TED * | tedmod |
NotificationBoard * | nb |
UDPSocket | udpSocket |
TCPSocket | serverSocket |
TCPSocketMap | socketMap |
cMessage * | sendHelloMsg |
int | maxFecid |
LDP (rfc 3036) protocol implementation.
Definition at line 48 of file LDP.h.
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 |
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(); }
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] |
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().
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; }
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().
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); }
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] |
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); }
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] |
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] |
void LDP::socketPeerClosed | ( | int | connId, | |
void * | yourPtr | |||
) | [protected, virtual] |
virtual void LDP::socketStatusArrived | ( | int | connId, | |
void * | yourPtr, | |||
TCPStatusInfo * | status | |||
) | [inline, protected, virtual] |
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); } }
FecBindVector LDP::fecDown [protected] |
Definition at line 106 of file LDP.h.
Referenced by initialize(), lookupLabel(), processHelloTimeout(), processLABEL_MAPPING(), processLABEL_REQUEST(), processLABEL_WITHDRAW(), rebuildFecList(), and updateFecListEntry().
FecVector LDP::fecList [protected] |
Definition at line 102 of file LDP.h.
Referenced by initialize(), lookupLabel(), processLABEL_MAPPING(), processLABEL_RELEASE(), processLABEL_REQUEST(), processLABEL_WITHDRAW(), processNOTIFICATION(), rebuildFecList(), and updateFecList().
FecBindVector LDP::fecUp [protected] |
Definition at line 104 of file LDP.h.
Referenced by initialize(), processHelloTimeout(), processLABEL_MAPPING(), processLABEL_RELEASE(), processLABEL_REQUEST(), rebuildFecList(), and updateFecListEntry().
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().
Definition at line 118 of file LDP.h.
Referenced by initialize(), processLABEL_MAPPING(), processLABEL_RELEASE(), processLABEL_REQUEST(), rebuildFecList(), and updateFecListEntry().
int LDP::maxFecid [protected] |
Definition at line 129 of file LDP.h.
Referenced by initialize(), and rebuildFecList().
PeerVector LDP::myPeers [protected] |
Definition at line 111 of file LDP.h.
Referenced by findPeer(), findPeerAddrFromInterface(), findPeerSocket(), initialize(), openTCPConnectionToPeer(), processHelloTimeout(), processLDPHello(), processMessageFromTCP(), socketClosed(), socketDataArrived(), socketEstablished(), socketFailure(), socketPeerClosed(), and ~LDP().
NotificationBoard* LDP::nb [protected] |
Definition at line 120 of file LDP.h.
Referenced by announceLinkChange(), and initialize().
PendingVector LDP::pending [protected] |
Definition at line 108 of file LDP.h.
Referenced by initialize(), processLABEL_MAPPING(), and processLABEL_REQUEST().
IRoutingTable* LDP::rt [protected] |
Definition at line 117 of file LDP.h.
Referenced by findInterfaceFromPeerAddr(), findPeerAddrFromInterface(), initialize(), locateNextHop(), openTCPConnectionToPeer(), processHelloTimeout(), processLDPHello(), rebuildFecList(), sendHelloTo(), sendMapping(), sendMappingRequest(), and sendNotify().
cMessage* LDP::sendHelloMsg [protected] |
Definition at line 127 of file LDP.h.
Referenced by handleMessage(), initialize(), LDP(), and ~LDP().
TCPSocket LDP::serverSocket [protected] |
Definition at line 123 of file LDP.h.
Referenced by initialize().
TCPSocketMap LDP::socketMap [protected] |
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().
UDPSocket LDP::udpSocket [protected] |
Definition at line 122 of file LDP.h.
Referenced by initialize(), and sendHelloTo().