#include <LDP.h>
Inheritance diagram for LDP:

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 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) |
| TCPSocket * | peerSocket (IPAddress peerAddr) |
| TCPSocket * | peerSocketSoft (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 |
| InterfaceTable * | ift |
| RoutingTable * | rt |
| LIBTable * | lt |
| TED * | tedmod |
| NotificationBoard * | nb |
| 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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00085 {
00086 sendHelloMsg = NULL;
00087 }
|
|
|
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 }
|
|
|
01245 {
01246 TEDChangeInfo d;
01247 d.setTedLinkIndicesArraySize(1);
01248 d.setTedLinkIndices(0, tedlinkindex);
01249 nb->fireChangeNotification(NF_TED_CHANGED, &d);
01250 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
|
00179 {return 4;}
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
|
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 }
|
|
||||||||||||
|
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
01237 ASSERT(category == NF_IPv4_ROUTINGTABLE_CHANGED);
01238
01239 EV << "routing table changed, rebuild list of known FEC" << endl;
01240
01241 rebuildFecList();
01242 }
|
|
|
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 }
|
|
||||||||||||||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||
|
00179 {
00180 peerSocket(dest)->send(msg);
00181 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
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 }
|
|
||||||||||||
|
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 }
|
|
||||||||||||||||
|
Reimplemented from TCPSocket::CallbackInterface. 00204 {delete status;}
|
|
|
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 }
|
|
|
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 }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1.4.1