#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 |
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 | ( | ) |
LDP::~LDP | ( | ) | [virtual] |
00090 { 00091 for (unsigned int i=0; i<myPeers.size(); i++) 00092 cancelAndDelete(myPeers[i].timeout); 00093 00094 cancelAndDelete(sendHelloMsg); 00095 //this causes segfault at the end of simulation -- Vojta 00096 //socketMap.deleteSockets(); 00097 }
void LDP::announceLinkChange | ( | int | tedlinkindex | ) | [private] |
01246 { 01247 TEDChangeInfo d; 01248 d.setTedLinkIndicesArraySize(1); 01249 d.setTedLinkIndices(0, tedlinkindex); 01250 nb->fireChangeNotification(NF_TED_CHANGED, &d); 01251 }
LDP::FecBindVector::iterator LDP::findFecEntry | ( | FecBindVector & | fecs, | |
int | fecid, | |||
IPAddress | peer | |||
) | [private] |
std::string LDP::findInterfaceFromPeerAddr | ( | IPAddress | peerIP | ) | [private] |
00761 { 00762 /* 00763 int i; 00764 for (unsigned int i=0;i<myPeers.size();i++) 00765 { 00766 if (myPeers[i].peerIP == peerIP) 00767 return string(myPeers[i].linkInterface); 00768 } 00769 return string("X"); 00770 */ 00771 // Rely on port index to find the interface name 00772 00773 // this function is a misnomer, we must recognize our own address too 00774 if (rt->localDeliver(peerIP)) 00775 return "lo0"; 00776 00777 InterfaceEntry *ie = rt->interfaceForDestAddr(peerIP); 00778 if (!ie) 00779 error("findInterfaceFromPeerAddr(): %s is not routable", peerIP.str().c_str()); 00780 return ie->name(); 00781 }
int LDP::findPeer | ( | IPAddress | peerAddr | ) | [private] |
IPAddress LDP::findPeerAddrFromInterface | ( | std::string | interfaceName | ) | [private] |
This method maps the peerIP with the interface name in routing table. It is expected that for MPLS host, entries linked to MPLS peers are available. In case no corresponding peerIP found, a peerIP (not deterministic) will be returned.
00722 { 00723 int i = 0; 00724 int k = 0; 00725 InterfaceEntry *ie = ift->interfaceByName(interfaceName.c_str()); 00726 00727 RoutingEntry *anEntry; 00728 00729 for (i = 0; i < rt->numRoutingEntries(); i++) 00730 { 00731 for (k = 0; k < (int)myPeers.size(); k++) 00732 { 00733 anEntry = rt->routingEntry(i); 00734 if (anEntry->host==myPeers[k].peerIP && anEntry->interfacePtr==ie) 00735 { 00736 return myPeers[k].peerIP; 00737 } 00738 // addresses->push_back(peerIP[k]); 00739 } 00740 } 00741 00742 // Return any IP which has default route - not in routing table entries 00743 for (i = 0; i < (int)myPeers.size(); i++) 00744 { 00745 for (k = 0; k < rt->numRoutingEntries(); k++) 00746 { 00747 anEntry = rt->routingEntry(i); 00748 if (anEntry->host == myPeers[i].peerIP) 00749 break; 00750 } 00751 if (k == rt->numRoutingEntries()) 00752 break; 00753 } 00754 00755 // return the peer's address if found, unspecified address otherwise 00756 return i==myPeers.size() ? IPAddress() : myPeers[i].peerIP; 00757 }
void LDP::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
00143 { 00144 EV << "Received: (" << msg->className() << ")" << msg->name() << "\n"; 00145 if (msg==sendHelloMsg) 00146 { 00147 // every LDP capable router periodically sends HELLO messages to the 00148 // "all routers in the sub-network" multicast address 00149 EV << "Multicasting LDP Hello to neighboring routers\n"; 00150 sendHelloTo(IPAddress::ALL_ROUTERS_MCAST); 00151 00152 // schedule next hello 00153 scheduleAt(simTime() + helloInterval, sendHelloMsg); 00154 } 00155 else if (msg->isSelfMessage()) 00156 { 00157 EV << "Timer " << msg->name() << " expired\n"; 00158 if (!strcmp(msg->name(), "HelloTimeout")) 00159 { 00160 processHelloTimeout(msg); 00161 } 00162 else 00163 { 00164 processNOTIFICATION(check_and_cast<LDPNotify*>(msg)); 00165 } 00166 } 00167 else if (!strcmp(msg->arrivalGate()->name(), "udpIn")) 00168 { 00169 // we can only receive LDP Hello from UDP (everything else goes over TCP) 00170 processLDPHello(check_and_cast<LDPHello *>(msg)); 00171 } 00172 else if (!strcmp(msg->arrivalGate()->name(), "tcpIn")) 00173 { 00174 processMessageFromTCP(msg); 00175 } 00176 }
void LDP::initialize | ( | int | stage | ) | [protected, virtual] |
00100 { 00101 if (stage != 3) 00102 return; // wait for routing table to initialize first 00103 00104 holdTime = par("holdTime").doubleValue(); 00105 helloInterval = par("helloInterval").doubleValue(); 00106 00107 ift = InterfaceTableAccess().get(); 00108 rt = RoutingTableAccess().get(); 00109 lt = LIBTableAccess().get(); 00110 tedmod = TEDAccess().get(); 00111 nb = NotificationBoardAccess().get(); 00112 00113 WATCH_VECTOR(myPeers); 00114 WATCH_VECTOR(fecUp); 00115 WATCH_VECTOR(fecDown); 00116 WATCH_VECTOR(fecList); 00117 WATCH_VECTOR(pending); 00118 00119 maxFecid = 0; 00120 00121 // schedule first hello 00122 sendHelloMsg = new cMessage("LDPSendHello"); 00123 scheduleAt(simTime() + exponential(0.1), sendHelloMsg); 00124 00125 // bind UDP socket 00126 udpSocket.setOutputGate(gate("udpOut")); 00127 udpSocket.bind(LDP_PORT); 00128 00129 // start listening for incoming TCP conns 00130 EV << "Starting to listen on port " << LDP_PORT << " for incoming LDP sessions\n"; 00131 serverSocket.setOutputGate(gate("tcpOut")); 00132 serverSocket.bind(LDP_PORT); 00133 serverSocket.listen(); 00134 00135 // build list of recognized FECs 00136 rebuildFecList(); 00137 00138 // listen for routing table modifications 00139 nb->subscribe(this, NF_IPv4_ROUTINGTABLE_CHANGED); 00140 }
This method finds next peer in upstream direction
00688 { 00689 // Mapping L3 IP-host of next hop to L2 peer address. 00690 00691 // Lookup the routing table, rfc3036 00692 // "When the FEC for which a label is requested is a Prefix FEC Element or 00693 // a Host Address FEC Element, the receiving LSR uses its routing table to determine 00694 // its response. Unless its routing table includes an entry that exactly matches 00695 // the requested Prefix or Host Address, the LSR must respond with a 00696 // No Route Notification message." 00697 // 00698 // FIXME the code below (though seems like that's what the RFC refers to) doesn't work 00699 // -- we can't reasonably expect the destination host to be exaplicitly in an 00700 // LSR's routing table!!! Use simple IP routing instead. --Andras 00701 // 00702 // Wrong code: 00703 //int i; 00704 //for (i=0; i < rt->numRoutingEntries(); i++) 00705 // if (rt->routingEntry(i)->host == dest) 00706 // break; 00707 // 00708 //if (i == rt->numRoutingEntries()) 00709 // return IPAddress(); // Signal an NOTIFICATION of NO ROUTE 00710 // 00711 InterfaceEntry *ie = rt->interfaceForDestAddr(dest); 00712 if (!ie) 00713 return IPAddress(); // no route 00714 00715 std::string iName = ie->name(); // FIXME why use name for lookup? 00716 return findPeerAddrFromInterface(iName); 00717 }
bool LDP::lookupLabel | ( | IPDatagram * | ipdatagram, | |
LabelOpVector & | outLabel, | |||
std::string & | outInterface, | |||
int & | color | |||
) | [protected, virtual] |
The ipdatagram argument is an input parameter, the rest (outLabel, outInterface, color) are output parameters only.
In subclasses, this function should be implemented to determine the forwarding equivalence class for the IP datagram passed, and map it to an outLabel and outInterface.
The color parameter (which can be set to an arbitrary value) will only be used for the NAM trace if one will be recorded.
Implements IClassifier.
01185 { 01186 IPAddress destAddr = ipdatagram->destAddress(); 01187 int protocol = ipdatagram->transportProtocol(); 01188 01189 // never match and always route via L3 if: 01190 01191 // OSPF traffic (TED) 01192 if (protocol == IP_PROT_OSPF) 01193 return false; 01194 01195 // LDP traffic (both discovery... 01196 if (protocol == IP_PROT_UDP && check_and_cast<UDPPacket*>(ipdatagram->encapsulatedMsg())->destinationPort() == LDP_PORT) 01197 return false; 01198 01199 // ...and session) 01200 if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->encapsulatedMsg())->destPort() == LDP_PORT) 01201 return false; 01202 if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->encapsulatedMsg())->srcPort() == LDP_PORT) 01203 return false; 01204 01205 // regular traffic, classify, label etc. 01206 01207 FecVector::iterator it; 01208 for (it = fecList.begin(); it != fecList.end(); it++) 01209 { 01210 if (!destAddr.prefixMatches(it->addr, it->length)) 01211 continue; 01212 01213 EV << "FEC matched: " << *it << endl; 01214 01215 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop); 01216 if (dit != fecDown.end()) 01217 { 01218 outLabel = LIBTable::pushLabel(dit->label); 01219 outInterface = findInterfaceFromPeerAddr(it->nextHop); 01220 color = LDP_USER_TRAFFIC; 01221 EV << "mapping found, outLabel=" << outLabel << ", outInterface=" << outInterface << endl; 01222 return true; 01223 } 01224 else 01225 { 01226 EV << "no mapping for this FEC exists" << endl; 01227 return false; 01228 } 01229 } 01230 return false; 01231 }
void LDP::openTCPConnectionToPeer | ( | int | peerIndex | ) | [protected] |
00543 { 00544 TCPSocket *socket = new TCPSocket(); 00545 socket->setOutputGate(gate("tcpOut")); 00546 socket->setCallbackObject(this, (void*)peerIndex); 00547 socket->bind(rt->routerId(), 0); 00548 socketMap.addSocket(socket); 00549 myPeers[peerIndex].socket = socket; 00550 00551 socket->connect(myPeers[peerIndex].peerIP, LDP_PORT); 00552 }
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 }
void LDP::processHelloTimeout | ( | cMessage * | msg | ) | [protected] |
00414 { 00415 // peer is gone 00416 00417 unsigned int i; 00418 for (i = 0; i < myPeers.size(); i++) 00419 { 00420 if (myPeers[i].timeout == msg) 00421 break; 00422 } 00423 ASSERT(i < myPeers.size()); 00424 00425 IPAddress peerIP = myPeers[i].peerIP; 00426 00427 EV << "peer=" << peerIP << " is gone, removing adjacency" << endl; 00428 00429 ASSERT(!myPeers[i].timeout->isScheduled()); 00430 delete myPeers[i].timeout; 00431 ASSERT(myPeers[i].socket); 00432 myPeers[i].socket->abort(); // should we only close? 00433 delete myPeers[i].socket; 00434 myPeers.erase(myPeers.begin() + i); 00435 00436 EV << "removing (stale) bindings from fecDown for peer=" << peerIP << endl; 00437 00438 FecBindVector::iterator dit; 00439 for (dit = fecDown.begin(); dit != fecDown.end(); dit++) 00440 { 00441 if (dit->peer != peerIP) 00442 continue; 00443 00444 EV << "label=" << dit->label << endl; 00445 00446 // send release message just in case (?) 00447 // what happens if peer is not really down and 00448 // hello messages just disappeared? 00449 // does the protocol recover on its own (XXX check this) 00450 00451 fecDown.erase(dit--); 00452 } 00453 00454 EV << "removing bindings from sent to peer=" << peerIP << " from fecUp" << endl; 00455 00456 FecBindVector::iterator uit; 00457 for (uit = fecUp.begin(); uit != fecUp.end(); uit++) 00458 { 00459 if (uit->peer != peerIP) 00460 continue; 00461 00462 EV << "label=" << uit->label << endl; 00463 00464 // send withdraw message just in case (?) 00465 // see comment above... 00466 00467 fecUp.erase(uit--); 00468 } 00469 00470 EV << "updating fecList" << endl; 00471 00472 updateFecList(peerIP); 00473 00474 // update TED and routing table 00475 00476 unsigned int index = tedmod->linkIndex(rt->routerId(), peerIP); 00477 tedmod->ted[index].state = false; 00478 announceLinkChange(index); 00479 tedmod->rebuildRoutingTable(); 00480 }
void LDP::processLABEL_MAPPING | ( | LDPLabelMapping * | packet | ) | [protected] |
01100 { 01101 FEC_TLV fec = packet->getFec(); 01102 int label = packet->getLabel(); 01103 IPAddress fromIP = packet->senderAddress(); 01104 01105 EV << "Label mapping label=" << label << " received for fec=" << fec << " from " << fromIP << endl; 01106 01107 ASSERT(label > 0); 01108 01109 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 01110 ASSERT(it != fecList.end()); 01111 01112 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP); 01113 ASSERT(dit == fecDown.end()); 01114 01115 // insert among received mappings 01116 01117 fec_bind_t newItem; 01118 newItem.fecid = it->fecid; 01119 newItem.peer = fromIP; 01120 newItem.label = label; 01121 fecDown.push_back(newItem); 01122 01123 // respond to pending requests 01124 01125 PendingVector::iterator pit; 01126 for (pit = pending.begin(); pit != pending.end(); pit++) 01127 { 01128 if (pit->fecid != it->fecid) 01129 continue; 01130 01131 EV << "there's pending request for this FEC from " << pit->peer << ", sending mapping" << endl; 01132 01133 std::string inInterface = findInterfaceFromPeerAddr(pit->peer); 01134 std::string outInterface = findInterfaceFromPeerAddr(fromIP); 01135 LabelOpVector outLabel = LIBTable::swapLabel(label); 01136 01137 fec_bind_t newItem; 01138 newItem.fecid = it->fecid; 01139 newItem.peer = pit->peer; 01140 newItem.label = lt->installLibEntry(-1, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 01141 fecUp.push_back(newItem); 01142 01143 EV << "installed LIB entry inLabel=" << newItem.label << " inInterface=" << inInterface << 01144 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 01145 01146 sendMapping(LABEL_MAPPING, pit->peer, newItem.label, it->addr, it->length); 01147 01148 // remove request from the list 01149 pending.erase(pit--); 01150 } 01151 01152 delete packet; 01153 }
void LDP::processLABEL_RELEASE | ( | LDPLabelMapping * | packet | ) | [protected] |
01016 { 01017 FEC_TLV fec = packet->getFec(); 01018 int label = packet->getLabel(); 01019 IPAddress fromIP = packet->senderAddress(); 01020 01021 EV << "Mapping release received for label=" << label << " fec=" << fec << " from " << fromIP << endl; 01022 01023 ASSERT(label > 0); 01024 01025 // remove label from fecUp 01026 01027 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 01028 if (it == fecList.end()) 01029 { 01030 EV << "FEC no longer recognized here, ignoring" << endl; 01031 delete packet; 01032 return; 01033 } 01034 01035 FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, fromIP); 01036 if (uit == fecUp.end() || label != uit->label) 01037 { 01038 // this is ok and may happen; e.g. we removed the mapping because downstream 01039 // neighbour withdrew its mapping. we sent withdraw upstream as well and 01040 // this is upstream's response 01041 EV << "mapping not found among sent mappings, ignoring" << endl; 01042 delete packet; 01043 return; 01044 } 01045 01046 EV << "removing from LIB table label=" << uit->label << endl; 01047 lt->removeLibEntry(uit->label); 01048 01049 EV << "removing label from list of sent mappings" << endl; 01050 fecUp.erase(uit); 01051 01052 delete packet; 01053 }
void LDP::processLABEL_REQUEST | ( | LDPLabelRequest * | packet | ) | [protected] |
00920 { 00921 FEC_TLV fec = packet->getFec(); 00922 IPAddress srcAddr = packet->senderAddress(); 00923 00924 EV << "Label Request from LSR " << srcAddr << " for FEC " << fec << endl; 00925 00926 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 00927 if (it == fecList.end()) 00928 { 00929 EV << "FEC not recognized, sending back No route message" << endl; 00930 00931 sendNotify(NO_ROUTE, srcAddr, fec.addr, fec.length); 00932 00933 delete packet; 00934 return; 00935 } 00936 00937 // do we already have mapping for this fec from our downstream peer? 00938 00939 // 00940 // XXX this code duplicates rebuildFecList 00941 // 00942 00943 // does upstream have mapping from us? 00944 FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, srcAddr); 00945 00946 // shouldn't! 00947 ASSERT(uit == fecUp.end()); 00948 00949 // do we have mapping from downstream? 00950 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop); 00951 00952 // is next hop our LDP peer? 00953 bool ER = !peerSocketSoft(it->nextHop); 00954 00955 ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time 00956 00957 if (ER || dit != fecDown.end()) 00958 { 00959 fec_bind_t newItem; 00960 newItem.fecid = it->fecid; 00961 newItem.label = -1; 00962 newItem.peer = srcAddr; 00963 fecUp.push_back(newItem); 00964 uit = fecUp.end() - 1; 00965 } 00966 00967 std::string inInterface = findInterfaceFromPeerAddr(srcAddr); 00968 std::string outInterface = findInterfaceFromPeerAddr(it->nextHop); 00969 00970 if (ER) 00971 { 00972 // we are egress, that's easy: 00973 LabelOpVector outLabel = LIBTable::popLabel(); 00974 00975 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, 0); 00976 00977 EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00978 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00979 00980 // We are egress, let our upstream peer know 00981 // about it by sending back a Label Mapping message 00982 00983 sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length); 00984 00985 } 00986 else if (dit != fecDown.end()) 00987 { 00988 // we have mapping from DS, that's easy 00989 LabelOpVector outLabel = LIBTable::swapLabel(dit->label); 00990 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 00991 00992 EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00993 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00994 00995 // We already have a mapping for this FEC, let our upstream peer know 00996 // about it by sending back a Label Mapping message 00997 00998 sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length); 00999 } 01000 else 01001 { 01002 // no mapping from DS, mark as pending 01003 01004 EV << "no mapping for this FEC from the downstream router, marking as pending" << endl; 01005 01006 pending_req_t newItem; 01007 newItem.fecid = it->fecid; 01008 newItem.peer = srcAddr; 01009 pending.push_back(newItem); 01010 } 01011 01012 delete packet; 01013 }
void LDP::processLABEL_WITHDRAW | ( | LDPLabelMapping * | packet | ) | [protected] |
01056 { 01057 FEC_TLV fec = packet->getFec(); 01058 int label = packet->getLabel(); 01059 IPAddress fromIP = packet->senderAddress(); 01060 01061 EV << "Mapping withdraw received for label=" << label << " fec=" << fec << " from " << fromIP << endl; 01062 01063 ASSERT(label > 0); 01064 01065 // remove label from fecDown 01066 01067 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 01068 if (it == fecList.end()) 01069 { 01070 EV << "matching FEC not found, ignoring withdraw message" << endl; 01071 delete packet; 01072 return; 01073 } 01074 01075 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP); 01076 01077 if (dit == fecDown.end() || label != dit->label) 01078 { 01079 EV << "matching mapping not found, ignoring withdraw message" << endl; 01080 delete packet; 01081 return; 01082 } 01083 01084 ASSERT(dit != fecDown.end()); 01085 ASSERT(label == dit->label); 01086 01087 EV << "removing label from list of received mappings" << endl; 01088 fecDown.erase(dit); 01089 01090 EV << "sending back relase message" << endl; 01091 packet->setType(LABEL_RELEASE); 01092 01093 // send msg to peer over TCP 01094 sendToPeer(fromIP, packet); 01095 01096 updateFecListEntry(*it); 01097 }
void LDP::processLDPHello | ( | LDPHello * | msg | ) | [protected] |
00483 { 00484 UDPControlInfo *controlInfo = check_and_cast<UDPControlInfo *>(msg->controlInfo()); 00485 //IPAddress peerAddr = controlInfo->getSrcAddr().get4(); 00486 IPAddress peerAddr = msg->senderAddress(); 00487 int interfaceId = controlInfo->interfaceId(); 00488 delete msg; 00489 00490 EV << "Received LDP Hello from " << peerAddr << ", "; 00491 00492 if (peerAddr.isUnspecified() || peerAddr==rt->routerId()) 00493 { 00494 // must be ourselves (we're also in the all-routers multicast group), ignore 00495 EV << "that's myself, ignore\n"; 00496 return; 00497 } 00498 00499 // mark link as working if it was failed, and rebuild table 00500 unsigned int index = tedmod->linkIndex(rt->routerId(), peerAddr); 00501 if (!tedmod->ted[index].state) 00502 { 00503 tedmod->ted[index].state = true; 00504 tedmod->rebuildRoutingTable(); 00505 announceLinkChange(index); 00506 } 00507 00508 // peer already in table? 00509 int i = findPeer(peerAddr); 00510 if (i!=-1) 00511 { 00512 EV << "already in my peer table, rescheduling timeout" << endl; 00513 ASSERT(myPeers[i].timeout); 00514 cancelEvent(myPeers[i].timeout); 00515 scheduleAt(simTime() + holdTime, myPeers[i].timeout); 00516 return; 00517 } 00518 00519 // not in table, add it 00520 peer_info info; 00521 info.peerIP = peerAddr; 00522 info.linkInterface = ift->interfaceAt(interfaceId)->name(); 00523 info.activeRole = peerAddr.getInt() > rt->routerId().getInt(); 00524 info.socket = NULL; 00525 info.timeout = new cMessage("HelloTimeout"); 00526 scheduleAt(simTime() + holdTime, info.timeout); 00527 myPeers.push_back(info); 00528 int peerIndex = myPeers.size()-1; 00529 00530 EV << "added to peer table\n"; 00531 EV << "We'll be " << (info.activeRole ? "ACTIVE" : "PASSIVE") << " in this session\n"; 00532 00533 // introduce ourselves with a Hello, then connect if we're in ACTIVE role 00534 sendHelloTo(peerAddr); 00535 if (info.activeRole) 00536 { 00537 EV << "Establishing session with it\n"; 00538 openTCPConnectionToPeer(peerIndex); 00539 } 00540 }
void LDP::processLDPPacketFromTCP | ( | LDPPacket * | ldpPacket | ) | [protected] |
00646 { 00647 switch (ldpPacket->type()) 00648 { 00649 case HELLO: 00650 error("Received LDP HELLO over TCP (should arrive over UDP)"); 00651 00652 case ADDRESS: 00653 // processADDRESS(ldpPacket); 00654 error("Received LDP ADDRESS message, unsupported in this version"); 00655 break; 00656 00657 case ADDRESS_WITHDRAW: 00658 // processADDRESS_WITHDRAW(ldpPacket); 00659 error("LDP PROC DEBUG: Received LDP ADDRESS_WITHDRAW message, unsupported in this version"); 00660 break; 00661 00662 case LABEL_MAPPING: 00663 processLABEL_MAPPING(check_and_cast<LDPLabelMapping *>(ldpPacket)); 00664 break; 00665 00666 case LABEL_REQUEST: 00667 processLABEL_REQUEST(check_and_cast<LDPLabelRequest *>(ldpPacket)); 00668 break; 00669 00670 case LABEL_WITHDRAW: 00671 processLABEL_WITHDRAW(check_and_cast<LDPLabelMapping *>(ldpPacket)); 00672 break; 00673 00674 case LABEL_RELEASE: 00675 processLABEL_RELEASE(check_and_cast<LDPLabelMapping *>(ldpPacket)); 00676 break; 00677 00678 case NOTIFICATION: 00679 processNOTIFICATION(check_and_cast<LDPNotify*>(ldpPacket)); 00680 break; 00681 00682 default: 00683 error("LDP PROC DEBUG: Unrecognized LDP Message Type, type is %d", ldpPacket->type()); 00684 } 00685 }
void LDP::processMessageFromTCP | ( | cMessage * | msg | ) | [protected] |
00555 { 00556 TCPSocket *socket = socketMap.findSocketFor(msg); 00557 if (!socket) 00558 { 00559 // not yet in socketMap, must be new incoming connection. 00560 // find which peer it is and register connection 00561 socket = new TCPSocket(msg); 00562 socket->setOutputGate(gate("tcpOut")); 00563 00564 // FIXME there seems to be some confusion here. Is it sure that 00565 // routerIds we use as peerAddrs are the same as IP addresses 00566 // the routing is based on? --Andras 00567 IPAddress peerAddr = socket->remoteAddress().get4(); 00568 00569 int i = findPeer(peerAddr); 00570 if (i==-1 || myPeers[i].socket) 00571 { 00572 // nothing known about this guy, or already connected: refuse 00573 socket->close(); // reset()? 00574 delete socket; 00575 delete msg; 00576 return; 00577 } 00578 myPeers[i].socket = socket; 00579 socket->setCallbackObject(this, (void *)i); 00580 socketMap.addSocket(socket); 00581 } 00582 00583 // dispatch to socketEstablished(), socketDataArrived(), socketPeerClosed() 00584 // or socketFailure() 00585 socket->processMessage(msg); 00586 }
void LDP::processNOTIFICATION | ( | LDPNotify * | packet | ) | [protected] |
00859 { 00860 FEC_TLV fec = packet->getFec(); 00861 IPAddress srcAddr = packet->senderAddress(); 00862 int status = packet->getStatus(); 00863 00864 // XXX FIXME NO_ROUTE processing should probably be split into two functions, 00865 // this is not the cleanest thing I ever wrote :) --Vojta 00866 00867 if (packet->isSelfMessage()) 00868 { 00869 // re-scheduled by ourselves 00870 EV << "notification retry for peer=" << srcAddr << " fec=" << fec << " status=" << status << endl; 00871 } 00872 else 00873 { 00874 // received via network 00875 EV << "notification received from=" << srcAddr << " fec=" << fec << " status=" << status << endl; 00876 } 00877 00878 switch(status) 00879 { 00880 case NO_ROUTE: 00881 { 00882 EV << "route does not exit on that peer" << endl; 00883 00884 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 00885 if (it != fecList.end()) 00886 { 00887 if (it->nextHop == srcAddr) 00888 { 00889 if (!packet->isSelfMessage()) 00890 { 00891 EV << "we are still interesed in this mapping, we will retry later" << endl; 00892 00893 scheduleAt(simTime() + 1.0 /* XXX FIXME */, packet); 00894 return; 00895 } 00896 else 00897 { 00898 EV << "reissuing request" << endl; 00899 00900 sendMappingRequest(srcAddr, fec.addr, fec.length); 00901 } 00902 } 00903 else 00904 EV << "and we still recognize this FEC, but we use different next hop, forget it" << endl; 00905 } 00906 else 00907 EV << "and we do not recognize this any longer, forget it" << endl; 00908 00909 break; 00910 } 00911 00912 default: 00913 ASSERT(false); 00914 } 00915 00916 delete packet; 00917 }
void LDP::rebuildFecList | ( | ) | [private] |
00263 { 00264 EV << "make list of recognized FECs" << endl; 00265 00266 FecVector oldList = fecList; 00267 fecList.clear(); 00268 00269 for (int i = 0; i < rt->numRoutingEntries(); i++) 00270 { 00271 // every entry in the routing table 00272 00273 RoutingEntry *re = rt->routingEntry(i); 00274 00275 // ignore multicast routes 00276 if (re->host.isMulticast()) 00277 continue; 00278 00279 // find out current next hop according to routing table 00280 IPAddress nextHop = (re->type == RoutingEntry::DIRECT)? re->host: re->gateway; 00281 ASSERT(!nextHop.isUnspecified()); 00282 00283 EV << "nextHop <-- " << nextHop << endl; 00284 00285 FecVector::iterator it = findFecEntry(oldList, re->host, re->netmask.netmaskLength()); 00286 00287 if (it == oldList.end()) 00288 { 00289 // fec didn't exist, it was just created 00290 fec_t newItem; 00291 newItem.fecid = ++maxFecid; 00292 newItem.addr = re->host; 00293 newItem.length = re->netmask.netmaskLength(); 00294 newItem.nextHop = nextHop; 00295 updateFecListEntry(newItem); 00296 fecList.push_back(newItem); 00297 } 00298 else if (it->nextHop != nextHop) 00299 { 00300 // next hop for this FEC changed, 00301 it->nextHop = nextHop; 00302 updateFecListEntry(*it); 00303 fecList.push_back(*it); 00304 oldList.erase(it); 00305 } 00306 else 00307 { 00308 // FEC didn't change, reusing old values 00309 fecList.push_back(*it); 00310 oldList.erase(it); 00311 continue; 00312 } 00313 } 00314 00315 00316 // our own addresses (XXX is it needed?) 00317 00318 for (int i = 0; i< ift->numInterfaces(); ++i) 00319 { 00320 InterfaceEntry *ie = ift->interfaceAt(i); 00321 if (ie->networkLayerGateIndex() < 0) 00322 continue; 00323 00324 FecVector::iterator it = findFecEntry(oldList, ie->ipv4()->inetAddress(), 32); 00325 if (it == oldList.end()) 00326 { 00327 fec_t newItem; 00328 newItem.fecid = ++maxFecid; 00329 newItem.addr = ie->ipv4()->inetAddress(); 00330 newItem.length = 32; 00331 newItem.nextHop = ie->ipv4()->inetAddress(); 00332 fecList.push_back(newItem); 00333 } 00334 else 00335 { 00336 fecList.push_back(*it); 00337 oldList.erase(it); 00338 } 00339 } 00340 00341 if (oldList.size() > 0) 00342 { 00343 EV << "there are " << oldList.size() << " deprecated FECs, removing them" << endl; 00344 00345 FecVector::iterator it; 00346 for (it = oldList.begin(); it != oldList.end(); it++) 00347 { 00348 EV << "removing FEC= " << *it << endl; 00349 00350 FecBindVector::iterator dit; 00351 for (dit = fecDown.begin(); dit != fecDown.end(); dit++) 00352 { 00353 if (dit->fecid != it->fecid) 00354 continue; 00355 00356 EV << "sending release label=" << dit->label << " downstream to " << dit->peer << endl; 00357 00358 sendMapping(LABEL_RELEASE, dit->peer, dit->label, it->addr, it->length); 00359 } 00360 00361 FecBindVector::iterator uit; 00362 for (uit = fecUp.begin(); uit != fecUp.end(); uit++) 00363 { 00364 if (uit->fecid != it->fecid) 00365 continue; 00366 00367 EV << "sending withdraw label=" << uit->label << " upstream to " << uit->peer << endl; 00368 00369 sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, it->addr, it->length); 00370 00371 EV << "removing entry inLabel=" << uit->label << " from LIB" << endl; 00372 00373 lt->removeLibEntry(uit->label); 00374 } 00375 00376 } 00377 } 00378 00379 // we must keep this list sorted for matching to work correctly 00380 // this is probably slower than it must be 00381 00382 std::sort(fecList.begin(), fecList.end(), fecPrefixCompare); 00383 00384 }
void LDP::receiveChangeNotification | ( | int | category, | |
cPolymorphic * | details | |||
) | [protected, virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
01234 { 01235 Enter_Method_Silent(); 01236 printNotificationBanner(category, details); 01237 01238 ASSERT(category == NF_IPv4_ROUTINGTABLE_CHANGED); 01239 01240 EV << "routing table changed, rebuild list of known FEC" << endl; 01241 01242 rebuildFecList(); 01243 }
void LDP::sendHelloTo | ( | IPAddress | dest | ) | [protected] |
00399 { 00400 LDPHello *hello = new LDPHello("LDP-Hello"); 00401 hello->setByteLength(LDP_HEADER_BYTES); 00402 hello->setType(HELLO); 00403 hello->setSenderAddress(rt->routerId()); 00404 //hello->setReceiverAddress(...); 00405 hello->setHoldTime(holdTime); 00406 //hello->setRbit(...); 00407 //hello->setTbit(...); 00408 hello->addPar("color") = LDP_HELLO_TRAFFIC; 00409 00410 udpSocket.sendTo(hello, dest, LDP_PORT); 00411 }
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 }
void LDP::sendToPeer | ( | IPAddress | dest, | |
cMessage * | msg | |||
) | [private] |
void LDP::socketClosed | ( | int | connId, | |
void * | yourPtr | |||
) | [protected, virtual] |
Reimplemented from TCPSocket::CallbackInterface.
00626 { 00627 peer_info& peer = myPeers[(long)yourPtr]; 00628 EV << "TCP connection to peer " << peer.peerIP << " closed\n"; 00629 00630 ASSERT(false); 00631 00632 // FIXME what now? reconnect after a delay? 00633 }
void LDP::socketDataArrived | ( | int | connId, | |
void * | yourPtr, | |||
cMessage * | msg, | |||
bool | urgent | |||
) | [protected, virtual] |
Implements TCPSocket::CallbackInterface.
00600 { 00601 peer_info& peer = myPeers[(long)yourPtr]; 00602 EV << "Message arrived over TCP from peer " << peer.peerIP << "\n"; 00603 00604 delete msg->removeControlInfo(); 00605 processLDPPacketFromTCP(check_and_cast<LDPPacket *>(msg)); 00606 }
void LDP::socketEstablished | ( | int | connId, | |
void * | yourPtr | |||
) | [protected, virtual] |
Reimplemented from TCPSocket::CallbackInterface.
00589 { 00590 peer_info& peer = myPeers[(long)yourPtr]; 00591 EV << "TCP connection established with peer " << peer.peerIP << "\n"; 00592 00593 // we must update all entries with nextHop == peerIP 00594 updateFecList(peer.peerIP); 00595 00596 // FIXME start LDP session setup (if we're on the active side?) 00597 }
void LDP::socketFailure | ( | int | connId, | |
void * | yourPtr, | |||
int | code | |||
) | [protected, virtual] |
Reimplemented from TCPSocket::CallbackInterface.
00636 { 00637 peer_info& peer = myPeers[(long)yourPtr]; 00638 EV << "TCP connection to peer " << peer.peerIP << " broken\n"; 00639 00640 ASSERT(false); 00641 00642 // FIXME what now? reconnect after a delay? 00643 }
void LDP::socketPeerClosed | ( | int | connId, | |
void * | yourPtr | |||
) | [protected, virtual] |
Reimplemented from TCPSocket::CallbackInterface.
00609 { 00610 peer_info& peer = myPeers[(long)yourPtr]; 00611 EV << "Peer " << peer.peerIP << " closed TCP connection\n"; 00612 00613 ASSERT(false); 00614 00615 /* 00616 // close the connection (if not already closed) 00617 if (socket.state()==TCPSocket::PEER_CLOSED) 00618 { 00619 EV << "remote TCP closed, closing here as well\n"; 00620 close(); 00621 } 00622 */ 00623 }
virtual void LDP::socketStatusArrived | ( | int | connId, | |
void * | yourPtr, | |||
TCPStatusInfo * | status | |||
) | [inline, protected, virtual] |
void LDP::updateFecList | ( | IPAddress | nextHop | ) | [private] |
00387 { 00388 FecVector::iterator it; 00389 for (it = fecList.begin(); it != fecList.end(); it++) 00390 { 00391 if (it->nextHop != nextHop) 00392 continue; 00393 00394 updateFecListEntry(*it); 00395 } 00396 }
void LDP::updateFecListEntry | ( | fec_t | oldItem | ) | [private] |
00201 { 00202 // do we have mapping from downstream? 00203 FecBindVector::iterator dit = findFecEntry(fecDown, oldItem.fecid, oldItem.nextHop); 00204 00205 // is next hop our LDP peer? 00206 bool ER = !peerSocketSoft(oldItem.nextHop); 00207 00208 ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time 00209 00210 // adjust upstream mappings 00211 FecBindVector::iterator uit; 00212 for (uit = fecUp.begin(); uit != fecUp.end(); uit++) 00213 { 00214 if (uit->fecid != oldItem.fecid) 00215 continue; 00216 00217 std::string inInterface = findInterfaceFromPeerAddr(uit->peer); 00218 std::string outInterface = findInterfaceFromPeerAddr(oldItem.nextHop); 00219 if (ER) 00220 { 00221 // we are egress, that's easy: 00222 LabelOpVector outLabel = LIBTable::popLabel(); 00223 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 00224 00225 EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00226 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00227 } 00228 else if (dit != fecDown.end()) 00229 { 00230 // we have mapping from DS, that's easy 00231 LabelOpVector outLabel = LIBTable::swapLabel(dit->label); 00232 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 00233 00234 EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00235 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00236 00237 } 00238 else 00239 { 00240 // no mapping from DS, withdraw mapping US 00241 00242 EV << "sending withdraw message upstream" << endl; 00243 00244 sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, oldItem.addr, oldItem.length); 00245 00246 // remove from US mappings 00247 00248 fecUp.erase(uit--); 00249 } 00250 } 00251 00252 if (!ER && dit == fecDown.end()) 00253 { 00254 // and ask DS for mapping 00255 00256 EV << "sending request message downstream" << endl; 00257 00258 sendMappingRequest(oldItem.nextHop, oldItem.addr, oldItem.length); 00259 } 00260 }
FecBindVector LDP::fecDown [private] |
FecVector LDP::fecList [private] |
FecBindVector LDP::fecUp [private] |
double LDP::helloInterval [private] |
double LDP::holdTime [private] |
InterfaceTable* LDP::ift [private] |
int LDP::maxFecid [private] |
PeerVector LDP::myPeers [private] |
NotificationBoard* LDP::nb [private] |
PendingVector LDP::pending [private] |
RoutingTable* LDP::rt [private] |
cMessage* LDP::sendHelloMsg [private] |
TCPSocket LDP::serverSocket [private] |
TCPSocketMap LDP::socketMap [private] |
TED* LDP::tedmod [private] |
UDPSocket LDP::udpSocket [private] |