|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // (C) 2005 Vojtech Janota 00003 // (C) 2004 Andras Varga 00004 // 00005 // This library is free software, you can redistribute it 00006 // and/or modify 00007 // it under the terms of the GNU Lesser General Public License 00008 // as published by the Free Software Foundation; 00009 // either version 2 of the License, or any later version. 00010 // The library is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00013 // See the GNU Lesser General Public License for more details. 00014 // 00015 00016 #include <omnetpp.h> 00017 #include <iostream> 00018 #include <fstream> 00019 #include <algorithm> 00020 #include "ConstType.h" 00021 #include "LDP.h" 00022 #include "LIBTable.h" 00023 #include "InterfaceTableAccess.h" 00024 #include "IPv4InterfaceData.h" 00025 #include "RoutingTableAccess.h" 00026 #include "LIBTableAccess.h" 00027 #include "TEDAccess.h" 00028 #include "NotifierConsts.h" 00029 #include "UDPPacket.h" 00030 #include "TCPSegment.h" 00031 00032 00033 Define_Module(LDP); 00034 00035 00036 std::ostream& operator<<(std::ostream& os, const LDP::fec_bind_t& f) 00037 { 00038 os << "fecid=" << f.fecid << " peer=" << f.peer << " label=" << f.label; 00039 return os; 00040 } 00041 00042 bool fecPrefixCompare(const LDP::fec_t& a, const LDP::fec_t& b) 00043 { 00044 return a.length > b.length; 00045 } 00046 00047 std::ostream& operator<<(std::ostream& os, const LDP::fec_t& f) 00048 { 00049 os << "fecid=" << f.fecid << " addr=" << f.addr << " length=" << f.length << " nextHop=" << f.nextHop; 00050 return os; 00051 } 00052 00053 std::ostream& operator<<(std::ostream& os, const LDP::pending_req_t& r) 00054 { 00055 os << "fecid=" << r.fecid << " peer=" << r.peer; 00056 return os; 00057 } 00058 00059 std::ostream& operator<<(std::ostream& os, const LDP::peer_info& p) 00060 { 00061 os << "peerIP=" << p.peerIP << " interface=" << p.linkInterface << 00062 " activeRole=" << (p.activeRole ? "true" : "false") << 00063 " socket=" << (p.socket ? TCPSocket::stateName(p.socket->getState()) : "NULL"); 00064 return os; 00065 } 00066 00067 bool operator==(const FEC_TLV& a, const FEC_TLV& b) 00068 { 00069 return a.length == b.length && a.addr == b.addr; 00070 } 00071 00072 bool operator!=(const FEC_TLV& a, const FEC_TLV& b) 00073 { 00074 return !operator==(a, b); 00075 } 00076 00077 std::ostream& operator<<(std::ostream& os, const FEC_TLV& a) 00078 { 00079 os << "addr=" << a.addr << " length=" << a.length; 00080 return os; 00081 } 00082 00083 00084 LDP::LDP() 00085 { 00086 sendHelloMsg = NULL; 00087 } 00088 00089 LDP::~LDP() 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 } 00098 00099 void LDP::initialize(int stage) 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_ROUTE_ADDED); 00140 nb->subscribe(this, NF_IPv4_ROUTE_DELETED); 00141 } 00142 00143 void LDP::handleMessage(cMessage *msg) 00144 { 00145 EV << "Received: (" << msg->getClassName() << ")" << msg->getName() << "\n"; 00146 if (msg==sendHelloMsg) 00147 { 00148 // every LDP capable router periodically sends HELLO messages to the 00149 // "all routers in the sub-network" multicast address 00150 EV << "Multicasting LDP Hello to neighboring routers\n"; 00151 sendHelloTo(IPAddress::ALL_ROUTERS_MCAST); 00152 00153 // schedule next hello 00154 scheduleAt(simTime() + helloInterval, sendHelloMsg); 00155 } 00156 else if (msg->isSelfMessage()) 00157 { 00158 EV << "Timer " << msg->getName() << " expired\n"; 00159 if (!strcmp(msg->getName(), "HelloTimeout")) 00160 { 00161 processHelloTimeout(msg); 00162 } 00163 else 00164 { 00165 processNOTIFICATION(check_and_cast<LDPNotify*>(msg)); 00166 } 00167 } 00168 else if (!strcmp(msg->getArrivalGate()->getName(), "udpIn")) 00169 { 00170 // we can only receive LDP Hello from UDP (everything else goes over TCP) 00171 processLDPHello(check_and_cast<LDPHello *>(msg)); 00172 } 00173 else if (!strcmp(msg->getArrivalGate()->getName(), "tcpIn")) 00174 { 00175 processMessageFromTCP(msg); 00176 } 00177 } 00178 00179 void LDP::sendToPeer(IPAddress dest, cMessage *msg) 00180 { 00181 getPeerSocket(dest)->send(msg); 00182 } 00183 00184 void LDP::sendMappingRequest(IPAddress dest, IPAddress addr, int length) 00185 { 00186 LDPLabelRequest *requestMsg = new LDPLabelRequest("Lb-Req"); 00187 requestMsg->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length 00188 requestMsg->setType(LABEL_REQUEST); 00189 00190 FEC_TLV fec; 00191 fec.addr = addr; 00192 fec.length = length; 00193 requestMsg->setFec(fec); 00194 00195 requestMsg->setReceiverAddress(dest); 00196 requestMsg->setSenderAddress(rt->getRouterId()); 00197 00198 sendToPeer(dest, requestMsg); 00199 } 00200 00201 void LDP::updateFecListEntry(LDP::fec_t oldItem) 00202 { 00203 // do we have mapping from downstream? 00204 FecBindVector::iterator dit = findFecEntry(fecDown, oldItem.fecid, oldItem.nextHop); 00205 00206 // is next hop our LDP peer? 00207 bool ER = findPeerSocket(oldItem.nextHop)==NULL; 00208 00209 ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time 00210 00211 // adjust upstream mappings 00212 FecBindVector::iterator uit; 00213 for (uit = fecUp.begin(); uit != fecUp.end();) 00214 { 00215 if (uit->fecid != oldItem.fecid) 00216 { 00217 uit++; 00218 continue; 00219 } 00220 00221 std::string inInterface = findInterfaceFromPeerAddr(uit->peer); 00222 std::string outInterface = findInterfaceFromPeerAddr(oldItem.nextHop); 00223 if (ER) 00224 { 00225 // we are egress, that's easy: 00226 LabelOpVector outLabel = LIBTable::popLabel(); 00227 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 00228 00229 EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00230 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00231 uit++; 00232 } 00233 else if (dit != fecDown.end()) 00234 { 00235 // we have mapping from DS, that's easy 00236 LabelOpVector outLabel = LIBTable::swapLabel(dit->label); 00237 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 00238 00239 EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00240 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00241 uit++; 00242 } 00243 else 00244 { 00245 // no mapping from DS, withdraw mapping US 00246 EV << "sending withdraw message upstream" << endl; 00247 sendMapping(LABEL_WITHDRAW, uit->peer, uit->label, oldItem.addr, oldItem.length); 00248 00249 // remove from US mappings 00250 uit = fecUp.erase(uit); 00251 } 00252 } 00253 00254 if (!ER && dit == fecDown.end()) 00255 { 00256 // and ask DS for mapping 00257 EV << "sending request message downstream" << endl; 00258 sendMappingRequest(oldItem.nextHop, oldItem.addr, oldItem.length); 00259 } 00260 } 00261 00262 void LDP::rebuildFecList() 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->getNumRoutes(); i++) 00270 { 00271 // every entry in the routing table 00272 00273 const IPRoute *re = rt->getRoute(i); 00274 00275 // ignore multicast routes 00276 if (re->getHost().isMulticast()) 00277 continue; 00278 00279 // find out current next hop according to routing table 00280 IPAddress nextHop = (re->getType() == IPRoute::DIRECT) ? re->getHost() : re->getGateway(); 00281 ASSERT(!nextHop.isUnspecified()); 00282 00283 EV << "nextHop <-- " << nextHop << endl; 00284 00285 FecVector::iterator it = findFecEntry(oldList, re->getHost(), re->getNetmask().getNetmaskLength()); 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->getHost(); 00293 newItem.length = re->getNetmask().getNetmaskLength(); 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->getNumInterfaces(); ++i) 00319 { 00320 InterfaceEntry *ie = ift->getInterface(i); 00321 if (ie->getNetworkLayerGateIndex() < 0) 00322 continue; 00323 00324 FecVector::iterator it = findFecEntry(oldList, ie->ipv4Data()->getIPAddress(), 32); 00325 if (it == oldList.end()) 00326 { 00327 fec_t newItem; 00328 newItem.fecid = ++maxFecid; 00329 newItem.addr = ie->ipv4Data()->getIPAddress(); 00330 newItem.length = 32; 00331 newItem.nextHop = ie->ipv4Data()->getIPAddress(); 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 std::sort(fecList.begin(), fecList.end(), fecPrefixCompare); 00382 } 00383 00384 void LDP::updateFecList(IPAddress nextHop) 00385 { 00386 FecVector::iterator it; 00387 for (it = fecList.begin(); it != fecList.end(); it++) 00388 { 00389 if (it->nextHop != nextHop) 00390 continue; 00391 00392 updateFecListEntry(*it); 00393 } 00394 } 00395 00396 void LDP::sendHelloTo(IPAddress dest) 00397 { 00398 LDPHello *hello = new LDPHello("LDP-Hello"); 00399 hello->setByteLength(LDP_HEADER_BYTES); 00400 hello->setType(HELLO); 00401 hello->setSenderAddress(rt->getRouterId()); 00402 //hello->setReceiverAddress(...); 00403 hello->setHoldTime(SIMTIME_DBL(holdTime)); 00404 //hello->setRbit(...); 00405 //hello->setTbit(...); 00406 hello->addPar("color") = LDP_HELLO_TRAFFIC; 00407 00408 udpSocket.sendTo(hello, dest, LDP_PORT); 00409 } 00410 00411 void LDP::processHelloTimeout(cMessage *msg) 00412 { 00413 // peer is gone 00414 00415 unsigned int i; 00416 for (i = 0; i < myPeers.size(); i++) 00417 if (myPeers[i].timeout == msg) 00418 break; 00419 ASSERT(i < myPeers.size()); 00420 00421 IPAddress peerIP = myPeers[i].peerIP; 00422 00423 EV << "peer=" << peerIP << " is gone, removing adjacency" << endl; 00424 00425 ASSERT(!myPeers[i].timeout->isScheduled()); 00426 delete myPeers[i].timeout; 00427 ASSERT(myPeers[i].socket); 00428 myPeers[i].socket->abort(); // should we only close? 00429 delete myPeers[i].socket; 00430 myPeers.erase(myPeers.begin() + i); 00431 00432 EV << "removing (stale) bindings from fecDown for peer=" << peerIP << endl; 00433 00434 FecBindVector::iterator dit; 00435 for (dit = fecDown.begin(); dit != fecDown.end();) 00436 { 00437 if (dit->peer != peerIP) 00438 { 00439 dit++; 00440 continue; 00441 } 00442 00443 EV << "label=" << dit->label << endl; 00444 00445 // send release message just in case (?) 00446 // what happens if peer is not really down and 00447 // hello messages just disappeared? 00448 // does the protocol recover on its own (XXX check this) 00449 00450 dit = fecDown.erase(dit); 00451 } 00452 00453 EV << "removing bindings from sent to peer=" << peerIP << " from fecUp" << endl; 00454 00455 FecBindVector::iterator uit; 00456 for (uit = fecUp.begin(); uit != fecUp.end();) 00457 { 00458 if (uit->peer != peerIP) 00459 { 00460 uit++; 00461 continue; 00462 } 00463 00464 EV << "label=" << uit->label << endl; 00465 00466 // send withdraw message just in case (?) 00467 // see comment above... 00468 00469 uit = fecUp.erase(uit); 00470 } 00471 00472 EV << "updating fecList" << endl; 00473 00474 updateFecList(peerIP); 00475 00476 // update TED and routing table 00477 00478 unsigned int index = tedmod->linkIndex(rt->getRouterId(), peerIP); 00479 tedmod->ted[index].state = false; 00480 announceLinkChange(index); 00481 tedmod->rebuildRoutingTable(); 00482 } 00483 00484 void LDP::processLDPHello(LDPHello *msg) 00485 { 00486 UDPControlInfo *controlInfo = check_and_cast<UDPControlInfo *>(msg->getControlInfo()); 00487 //IPAddress peerAddr = controlInfo->getSrcAddr().get4(); 00488 IPAddress peerAddr = msg->getSenderAddress(); 00489 int interfaceId = controlInfo->getInterfaceId(); 00490 delete msg; 00491 00492 EV << "Received LDP Hello from " << peerAddr << ", "; 00493 00494 if (peerAddr.isUnspecified() || peerAddr==rt->getRouterId()) 00495 { 00496 // must be ourselves (we're also in the all-routers multicast group), ignore 00497 EV << "that's myself, ignore\n"; 00498 return; 00499 } 00500 00501 // mark link as working if it was failed, and rebuild table 00502 unsigned int index = tedmod->linkIndex(rt->getRouterId(), peerAddr); 00503 if (!tedmod->ted[index].state) 00504 { 00505 tedmod->ted[index].state = true; 00506 tedmod->rebuildRoutingTable(); 00507 announceLinkChange(index); 00508 } 00509 00510 // peer already in table? 00511 int i = findPeer(peerAddr); 00512 if (i!=-1) 00513 { 00514 EV << "already in my peer table, rescheduling timeout" << endl; 00515 ASSERT(myPeers[i].timeout); 00516 cancelEvent(myPeers[i].timeout); 00517 scheduleAt(simTime() + holdTime, myPeers[i].timeout); 00518 return; 00519 } 00520 00521 // not in table, add it 00522 peer_info info; 00523 info.peerIP = peerAddr; 00524 info.linkInterface = ift->getInterfaceById(interfaceId)->getName(); 00525 info.activeRole = peerAddr.getInt() > rt->getRouterId().getInt(); 00526 info.socket = NULL; 00527 info.timeout = new cMessage("HelloTimeout"); 00528 scheduleAt(simTime() + holdTime, info.timeout); 00529 myPeers.push_back(info); 00530 int peerIndex = myPeers.size()-1; 00531 00532 EV << "added to peer table\n"; 00533 EV << "We'll be " << (info.activeRole ? "ACTIVE" : "PASSIVE") << " in this session\n"; 00534 00535 // introduce ourselves with a Hello, then connect if we're in ACTIVE role 00536 sendHelloTo(peerAddr); 00537 if (info.activeRole) 00538 { 00539 EV << "Establishing session with it\n"; 00540 openTCPConnectionToPeer(peerIndex); 00541 } 00542 } 00543 00544 void LDP::openTCPConnectionToPeer(int peerIndex) 00545 { 00546 TCPSocket *socket = new TCPSocket(); 00547 socket->setOutputGate(gate("tcpOut")); 00548 socket->setCallbackObject(this, (void*)peerIndex); 00549 socket->bind(rt->getRouterId(), 0); 00550 socketMap.addSocket(socket); 00551 myPeers[peerIndex].socket = socket; 00552 00553 socket->connect(myPeers[peerIndex].peerIP, LDP_PORT); 00554 } 00555 00556 void LDP::processMessageFromTCP(cMessage *msg) 00557 { 00558 TCPSocket *socket = socketMap.findSocketFor(msg); 00559 if (!socket) 00560 { 00561 // not yet in socketMap, must be new incoming connection. 00562 // find which peer it is and register connection 00563 socket = new TCPSocket(msg); 00564 socket->setOutputGate(gate("tcpOut")); 00565 00566 // FIXME there seems to be some confusion here. Is it sure that 00567 // routerIds we use as peerAddrs are the same as IP addresses 00568 // the routing is based on? --Andras 00569 IPAddress peerAddr = socket->getRemoteAddress().get4(); 00570 00571 int i = findPeer(peerAddr); 00572 if (i==-1 || myPeers[i].socket) 00573 { 00574 // nothing known about this guy, or already connected: refuse 00575 socket->close(); // reset()? 00576 delete socket; 00577 delete msg; 00578 return; 00579 } 00580 myPeers[i].socket = socket; 00581 socket->setCallbackObject(this, (void *)i); 00582 socketMap.addSocket(socket); 00583 } 00584 00585 // dispatch to socketEstablished(), socketDataArrived(), socketPeerClosed() 00586 // or socketFailure() 00587 socket->processMessage(msg); 00588 } 00589 00590 void LDP::socketEstablished(int, void *yourPtr) 00591 { 00592 peer_info& peer = myPeers[(long)yourPtr]; 00593 EV << "TCP connection established with peer " << peer.peerIP << "\n"; 00594 00595 // we must update all entries with nextHop == peerIP 00596 updateFecList(peer.peerIP); 00597 00598 // FIXME start LDP session setup (if we're on the active side?) 00599 } 00600 00601 void LDP::socketDataArrived(int, void *yourPtr, cPacket *msg, bool) 00602 { 00603 peer_info& peer = myPeers[(long)yourPtr]; 00604 EV << "Message arrived over TCP from peer " << peer.peerIP << "\n"; 00605 00606 delete msg->removeControlInfo(); 00607 processLDPPacketFromTCP(check_and_cast<LDPPacket *>(msg)); 00608 } 00609 00610 void LDP::socketPeerClosed(int, void *yourPtr) 00611 { 00612 peer_info& peer = myPeers[(long)yourPtr]; 00613 EV << "Peer " << peer.peerIP << " closed TCP connection\n"; 00614 00615 ASSERT(false); 00616 00617 /* 00618 // close the connection (if not already closed) 00619 if (socket.getState()==TCPSocket::PEER_CLOSED) 00620 { 00621 EV << "remote TCP closed, closing here as well\n"; 00622 close(); 00623 } 00624 */ 00625 } 00626 00627 void LDP::socketClosed(int, void *yourPtr) 00628 { 00629 peer_info& peer = myPeers[(long)yourPtr]; 00630 EV << "TCP connection to peer " << peer.peerIP << " closed\n"; 00631 00632 ASSERT(false); 00633 00634 // FIXME what now? reconnect after a delay? 00635 } 00636 00637 void LDP::socketFailure(int, void *yourPtr, int code) 00638 { 00639 peer_info& peer = myPeers[(long)yourPtr]; 00640 EV << "TCP connection to peer " << peer.peerIP << " broken\n"; 00641 00642 ASSERT(false); 00643 00644 // FIXME what now? reconnect after a delay? 00645 } 00646 00647 void LDP::processLDPPacketFromTCP(LDPPacket *ldpPacket) 00648 { 00649 switch (ldpPacket->getType()) 00650 { 00651 case HELLO: 00652 error("Received LDP HELLO over TCP (should arrive over UDP)"); 00653 00654 case ADDRESS: 00655 // processADDRESS(ldpPacket); 00656 error("Received LDP ADDRESS message, unsupported in this version"); 00657 break; 00658 00659 case ADDRESS_WITHDRAW: 00660 // processADDRESS_WITHDRAW(ldpPacket); 00661 error("LDP PROC DEBUG: Received LDP ADDRESS_WITHDRAW message, unsupported in this version"); 00662 break; 00663 00664 case LABEL_MAPPING: 00665 processLABEL_MAPPING(check_and_cast<LDPLabelMapping *>(ldpPacket)); 00666 break; 00667 00668 case LABEL_REQUEST: 00669 processLABEL_REQUEST(check_and_cast<LDPLabelRequest *>(ldpPacket)); 00670 break; 00671 00672 case LABEL_WITHDRAW: 00673 processLABEL_WITHDRAW(check_and_cast<LDPLabelMapping *>(ldpPacket)); 00674 break; 00675 00676 case LABEL_RELEASE: 00677 processLABEL_RELEASE(check_and_cast<LDPLabelMapping *>(ldpPacket)); 00678 break; 00679 00680 case NOTIFICATION: 00681 processNOTIFICATION(check_and_cast<LDPNotify*>(ldpPacket)); 00682 break; 00683 00684 default: 00685 error("LDP PROC DEBUG: Unrecognized LDP Message Type, type is %d", ldpPacket->getType()); 00686 } 00687 } 00688 00689 IPAddress LDP::locateNextHop(IPAddress dest) 00690 { 00691 // Mapping L3 IP-host of next hop to L2 peer address. 00692 00693 // Lookup the routing table, rfc3036 00694 // "When the FEC for which a label is requested is a Prefix FEC Element or 00695 // a Host Address FEC Element, the receiving LSR uses its routing table to determine 00696 // its response. Unless its routing table includes an entry that exactly matches 00697 // the requested Prefix or Host Address, the LSR must respond with a 00698 // No Route Notification message." 00699 // 00700 // FIXME the code below (though seems like that's what the RFC refers to) doesn't work 00701 // -- we can't reasonably expect the destination host to be exaplicitly in an 00702 // LSR's routing table!!! Use simple IP routing instead. --Andras 00703 // 00704 // Wrong code: 00705 //int i; 00706 //for (i=0; i < rt->getNumRoutes(); i++) 00707 // if (rt->getRoute(i)->host == dest) 00708 // break; 00709 // 00710 //if (i == rt->getNumRoutes()) 00711 // return IPAddress(); // Signal an NOTIFICATION of NO ROUTE 00712 // 00713 InterfaceEntry *ie = rt->getInterfaceForDestAddr(dest); 00714 if (!ie) 00715 return IPAddress(); // no route 00716 00717 std::string iName = ie->getName(); // FIXME why use name for lookup? 00718 return findPeerAddrFromInterface(iName); 00719 } 00720 00721 // FIXME To allow this to work, make sure there are entries of hosts for all peers 00722 00723 IPAddress LDP::findPeerAddrFromInterface(std::string interfaceName) 00724 { 00725 int i = 0; 00726 int k = 0; 00727 InterfaceEntry *ie = ift->getInterfaceByName(interfaceName.c_str()); 00728 00729 const IPRoute *anEntry; 00730 00731 for (i = 0; i < rt->getNumRoutes(); i++) 00732 { 00733 for (k = 0; k < (int)myPeers.size(); k++) 00734 { 00735 anEntry = rt->getRoute(i); 00736 if (anEntry->getHost()==myPeers[k].peerIP && anEntry->getInterface()==ie) 00737 { 00738 return myPeers[k].peerIP; 00739 } 00740 // addresses->push_back(peerIP[k]); 00741 } 00742 } 00743 00744 // Return any IP which has default route - not in routing table entries 00745 for (i = 0; i < (int)myPeers.size(); i++) 00746 { 00747 for (k = 0; k < rt->getNumRoutes(); k++) 00748 { 00749 anEntry = rt->getRoute(i); 00750 if (anEntry->getHost() == myPeers[i].peerIP) 00751 break; 00752 } 00753 if (k == rt->getNumRoutes()) 00754 break; 00755 } 00756 00757 // return the peer's address if found, unspecified address otherwise 00758 return i==(int)myPeers.size() ? IPAddress() : myPeers[i].peerIP; 00759 } 00760 00761 // Pre-condition: myPeers vector is finalized 00762 std::string LDP::findInterfaceFromPeerAddr(IPAddress peerIP) 00763 { 00764 /* 00765 int i; 00766 for (unsigned int i=0;i<myPeers.size();i++) 00767 { 00768 if (myPeers[i].peerIP == peerIP) 00769 return string(myPeers[i].linkInterface); 00770 } 00771 return string("X"); 00772 */ 00773 // Rely on port index to find the interface name 00774 00775 // this function is a misnomer, we must recognize our own address too 00776 if (rt->isLocalAddress(peerIP)) 00777 return "lo0"; 00778 00779 InterfaceEntry *ie = rt->getInterfaceForDestAddr(peerIP); 00780 if (!ie) 00781 error("findInterfaceFromPeerAddr(): %s is not routable", peerIP.str().c_str()); 00782 return ie->getName(); 00783 } 00784 00785 //bool LDP::matches(const FEC_TLV& a, const FEC_TLV& b) 00786 //{ 00787 // return b.addr.prefixMatches(a, b.length); 00788 //} 00789 00790 LDP::FecBindVector::iterator LDP::findFecEntry(FecBindVector& fecs, int fecid, IPAddress peer) 00791 { 00792 FecBindVector::iterator it; 00793 for (it = fecs.begin(); it != fecs.end(); it++) 00794 { 00795 if (it->fecid != fecid) 00796 continue; 00797 00798 if (it->peer != peer) 00799 continue; 00800 00801 break; 00802 } 00803 return it; 00804 } 00805 00806 LDP::FecVector::iterator LDP::findFecEntry(FecVector& fecs, IPAddress addr, int length) 00807 { 00808 FecVector::iterator it; 00809 for (it = fecs.begin(); it != fecs.end(); it++) 00810 { 00811 if (it->length != length) 00812 continue; 00813 00814 if (it->addr != addr) // XXX compare only relevant part (?) 00815 continue; 00816 00817 break; 00818 } 00819 return it; 00820 } 00821 00822 void LDP::sendNotify(int status, IPAddress dest, IPAddress addr, int length) 00823 { 00824 // Send NOTIFY message 00825 LDPNotify *lnMessage = new LDPNotify("Lb-Notify"); 00826 lnMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length 00827 lnMessage->setType(NOTIFICATION); 00828 lnMessage->setStatus(NO_ROUTE); 00829 lnMessage->setReceiverAddress(dest); 00830 lnMessage->setSenderAddress(rt->getRouterId()); 00831 00832 FEC_TLV fec; 00833 fec.addr = addr; 00834 fec.length = length; 00835 00836 lnMessage->setFec(fec); 00837 00838 sendToPeer(dest, lnMessage); 00839 } 00840 00841 void LDP::sendMapping(int type, IPAddress dest, int label, IPAddress addr, int length) 00842 { 00843 // Send LABEL MAPPING downstream 00844 LDPLabelMapping *lmMessage = new LDPLabelMapping("Lb-Mapping"); 00845 lmMessage->setByteLength(LDP_HEADER_BYTES); // FIXME find out actual length 00846 lmMessage->setType(type); 00847 lmMessage->setReceiverAddress(dest); 00848 lmMessage->setSenderAddress(rt->getRouterId()); 00849 lmMessage->setLabel(label); 00850 00851 FEC_TLV fec; 00852 fec.addr = addr; 00853 fec.length = length; 00854 00855 lmMessage->setFec(fec); 00856 00857 sendToPeer(dest, lmMessage); 00858 } 00859 00860 void LDP::processNOTIFICATION(LDPNotify *packet) 00861 { 00862 FEC_TLV fec = packet->getFec(); 00863 IPAddress srcAddr = packet->getSenderAddress(); 00864 int status = packet->getStatus(); 00865 00866 // XXX FIXME NO_ROUTE processing should probably be split into two functions, 00867 // this is not the cleanest thing I ever wrote :) --Vojta 00868 00869 if (packet->isSelfMessage()) 00870 { 00871 // re-scheduled by ourselves 00872 EV << "notification retry for peer=" << srcAddr << " fec=" << fec << " status=" << status << endl; 00873 } 00874 else 00875 { 00876 // received via network 00877 EV << "notification received from=" << srcAddr << " fec=" << fec << " status=" << status << endl; 00878 } 00879 00880 switch(status) 00881 { 00882 case NO_ROUTE: 00883 { 00884 EV << "route does not exit on that peer" << endl; 00885 00886 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 00887 if (it != fecList.end()) 00888 { 00889 if (it->nextHop == srcAddr) 00890 { 00891 if (!packet->isSelfMessage()) 00892 { 00893 EV << "we are still interesed in this mapping, we will retry later" << endl; 00894 00895 scheduleAt(simTime() + 1.0 /* XXX FIXME */, packet); 00896 return; 00897 } 00898 else 00899 { 00900 EV << "reissuing request" << endl; 00901 00902 sendMappingRequest(srcAddr, fec.addr, fec.length); 00903 } 00904 } 00905 else 00906 EV << "and we still recognize this FEC, but we use different next hop, forget it" << endl; 00907 } 00908 else 00909 EV << "and we do not recognize this any longer, forget it" << endl; 00910 00911 break; 00912 } 00913 00914 default: 00915 ASSERT(false); 00916 } 00917 00918 delete packet; 00919 } 00920 00921 void LDP::processLABEL_REQUEST(LDPLabelRequest *packet) 00922 { 00923 FEC_TLV fec = packet->getFec(); 00924 IPAddress srcAddr = packet->getSenderAddress(); 00925 00926 EV << "Label Request from LSR " << srcAddr << " for FEC " << fec << endl; 00927 00928 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 00929 if (it == fecList.end()) 00930 { 00931 EV << "FEC not recognized, sending back No route message" << endl; 00932 00933 sendNotify(NO_ROUTE, srcAddr, fec.addr, fec.length); 00934 00935 delete packet; 00936 return; 00937 } 00938 00939 // do we already have mapping for this fec from our downstream peer? 00940 00941 // 00942 // XXX this code duplicates rebuildFecList 00943 // 00944 00945 // does upstream have mapping from us? 00946 FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, srcAddr); 00947 00948 // shouldn't! 00949 ASSERT(uit == fecUp.end()); 00950 00951 // do we have mapping from downstream? 00952 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop); 00953 00954 // is next hop our LDP peer? 00955 bool ER = !findPeerSocket(it->nextHop); 00956 00957 ASSERT(!(ER && dit != fecDown.end())); // can't be egress and have mapping at the same time 00958 00959 if (ER || dit != fecDown.end()) 00960 { 00961 fec_bind_t newItem; 00962 newItem.fecid = it->fecid; 00963 newItem.label = -1; 00964 newItem.peer = srcAddr; 00965 fecUp.push_back(newItem); 00966 uit = fecUp.end() - 1; 00967 } 00968 00969 std::string inInterface = findInterfaceFromPeerAddr(srcAddr); 00970 std::string outInterface = findInterfaceFromPeerAddr(it->nextHop); 00971 00972 if (ER) 00973 { 00974 // we are egress, that's easy: 00975 LabelOpVector outLabel = LIBTable::popLabel(); 00976 00977 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, 0); 00978 00979 EV << "installed (egress) LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00980 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00981 00982 // We are egress, let our upstream peer know 00983 // about it by sending back a Label Mapping message 00984 00985 sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length); 00986 00987 } 00988 else if (dit != fecDown.end()) 00989 { 00990 // we have mapping from DS, that's easy 00991 LabelOpVector outLabel = LIBTable::swapLabel(dit->label); 00992 uit->label = lt->installLibEntry(uit->label, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 00993 00994 EV << "installed LIB entry inLabel=" << uit->label << " inInterface=" << inInterface << 00995 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 00996 00997 // We already have a mapping for this FEC, let our upstream peer know 00998 // about it by sending back a Label Mapping message 00999 01000 sendMapping(LABEL_MAPPING, srcAddr, uit->label, fec.addr, fec.length); 01001 } 01002 else 01003 { 01004 // no mapping from DS, mark as pending 01005 01006 EV << "no mapping for this FEC from the downstream router, marking as pending" << endl; 01007 01008 pending_req_t newItem; 01009 newItem.fecid = it->fecid; 01010 newItem.peer = srcAddr; 01011 pending.push_back(newItem); 01012 } 01013 01014 delete packet; 01015 } 01016 01017 void LDP::processLABEL_RELEASE(LDPLabelMapping *packet) 01018 { 01019 FEC_TLV fec = packet->getFec(); 01020 int label = packet->getLabel(); 01021 IPAddress fromIP = packet->getSenderAddress(); 01022 01023 EV << "Mapping release received for label=" << label << " fec=" << fec << " from " << fromIP << endl; 01024 01025 ASSERT(label > 0); 01026 01027 // remove label from fecUp 01028 01029 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 01030 if (it == fecList.end()) 01031 { 01032 EV << "FEC no longer recognized here, ignoring" << endl; 01033 delete packet; 01034 return; 01035 } 01036 01037 FecBindVector::iterator uit = findFecEntry(fecUp, it->fecid, fromIP); 01038 if (uit == fecUp.end() || label != uit->label) 01039 { 01040 // this is ok and may happen; e.g. we removed the mapping because downstream 01041 // neighbour withdrew its mapping. we sent withdraw upstream as well and 01042 // this is upstream's response 01043 EV << "mapping not found among sent mappings, ignoring" << endl; 01044 delete packet; 01045 return; 01046 } 01047 01048 EV << "removing from LIB table label=" << uit->label << endl; 01049 lt->removeLibEntry(uit->label); 01050 01051 EV << "removing label from list of sent mappings" << endl; 01052 fecUp.erase(uit); 01053 01054 delete packet; 01055 } 01056 01057 void LDP::processLABEL_WITHDRAW(LDPLabelMapping *packet) 01058 { 01059 FEC_TLV fec = packet->getFec(); 01060 int label = packet->getLabel(); 01061 IPAddress fromIP = packet->getSenderAddress(); 01062 01063 EV << "Mapping withdraw received for label=" << label << " fec=" << fec << " from " << fromIP << endl; 01064 01065 ASSERT(label > 0); 01066 01067 // remove label from fecDown 01068 01069 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 01070 if (it == fecList.end()) 01071 { 01072 EV << "matching FEC not found, ignoring withdraw message" << endl; 01073 delete packet; 01074 return; 01075 } 01076 01077 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP); 01078 01079 if (dit == fecDown.end() || label != dit->label) 01080 { 01081 EV << "matching mapping not found, ignoring withdraw message" << endl; 01082 delete packet; 01083 return; 01084 } 01085 01086 ASSERT(dit != fecDown.end()); 01087 ASSERT(label == dit->label); 01088 01089 EV << "removing label from list of received mappings" << endl; 01090 fecDown.erase(dit); 01091 01092 EV << "sending back relase message" << endl; 01093 packet->setType(LABEL_RELEASE); 01094 01095 // send msg to peer over TCP 01096 sendToPeer(fromIP, packet); 01097 01098 updateFecListEntry(*it); 01099 } 01100 01101 void LDP::processLABEL_MAPPING(LDPLabelMapping *packet) 01102 { 01103 FEC_TLV fec = packet->getFec(); 01104 int label = packet->getLabel(); 01105 IPAddress fromIP = packet->getSenderAddress(); 01106 01107 EV << "Label mapping label=" << label << " received for fec=" << fec << " from " << fromIP << endl; 01108 01109 ASSERT(label > 0); 01110 01111 FecVector::iterator it = findFecEntry(fecList, fec.addr, fec.length); 01112 ASSERT(it != fecList.end()); 01113 01114 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, fromIP); 01115 ASSERT(dit == fecDown.end()); 01116 01117 // insert among received mappings 01118 01119 fec_bind_t newItem; 01120 newItem.fecid = it->fecid; 01121 newItem.peer = fromIP; 01122 newItem.label = label; 01123 fecDown.push_back(newItem); 01124 01125 // respond to pending requests 01126 01127 PendingVector::iterator pit; 01128 for (pit = pending.begin(); pit != pending.end();) 01129 { 01130 if (pit->fecid != it->fecid) 01131 { 01132 pit++; 01133 continue; 01134 } 01135 01136 EV << "there's pending request for this FEC from " << pit->peer << ", sending mapping" << endl; 01137 01138 std::string inInterface = findInterfaceFromPeerAddr(pit->peer); 01139 std::string outInterface = findInterfaceFromPeerAddr(fromIP); 01140 LabelOpVector outLabel = LIBTable::swapLabel(label); 01141 01142 fec_bind_t newItem; 01143 newItem.fecid = it->fecid; 01144 newItem.peer = pit->peer; 01145 newItem.label = lt->installLibEntry(-1, inInterface, outLabel, outInterface, LDP_USER_TRAFFIC); 01146 fecUp.push_back(newItem); 01147 01148 EV << "installed LIB entry inLabel=" << newItem.label << " inInterface=" << inInterface << 01149 " outLabel=" << outLabel << " outInterface=" << outInterface << endl; 01150 01151 sendMapping(LABEL_MAPPING, pit->peer, newItem.label, it->addr, it->length); 01152 01153 // remove request from the list 01154 pit = pending.erase(pit); 01155 } 01156 01157 delete packet; 01158 } 01159 01160 int LDP::findPeer(IPAddress peerAddr) 01161 { 01162 for (PeerVector::iterator i=myPeers.begin(); i!=myPeers.end(); ++i) 01163 if (i->peerIP==peerAddr) 01164 return i-myPeers.begin(); 01165 return -1; 01166 } 01167 01168 TCPSocket *LDP::findPeerSocket(IPAddress peerAddr) 01169 { 01170 // find peer in table and return its socket 01171 int i = findPeer(peerAddr); 01172 if (i==-1 || !(myPeers[i].socket) || myPeers[i].socket->getState()!=TCPSocket::CONNECTED) 01173 return NULL; // we don't have an LDP session to this peer 01174 return myPeers[i].socket; 01175 } 01176 01177 TCPSocket *LDP::getPeerSocket(IPAddress peerAddr) 01178 { 01179 TCPSocket *sock = findPeerSocket(peerAddr); 01180 ASSERT(sock); 01181 if (!sock) 01182 error("No LDP session to peer %s yet", peerAddr.str().c_str()); 01183 return sock; 01184 } 01185 01186 bool LDP::lookupLabel(IPDatagram *ipdatagram, LabelOpVector& outLabel, std::string& outInterface, int& color) 01187 { 01188 IPAddress destAddr = ipdatagram->getDestAddress(); 01189 int protocol = ipdatagram->getTransportProtocol(); 01190 01191 // never match and always route via L3 if: 01192 01193 // OSPF traffic (TED) 01194 if (protocol == IP_PROT_OSPF) 01195 return false; 01196 01197 // LDP traffic (both discovery... 01198 if (protocol == IP_PROT_UDP && check_and_cast<UDPPacket*>(ipdatagram->getEncapsulatedPacket())->getDestinationPort() == LDP_PORT) 01199 return false; 01200 01201 // ...and session) 01202 if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedPacket())->getDestPort() == LDP_PORT) 01203 return false; 01204 if (protocol == IP_PROT_TCP && check_and_cast<TCPSegment*>(ipdatagram->getEncapsulatedPacket())->getSrcPort() == LDP_PORT) 01205 return false; 01206 01207 // regular traffic, classify, label etc. 01208 01209 FecVector::iterator it; 01210 for (it = fecList.begin(); it != fecList.end(); it++) 01211 { 01212 if (!destAddr.prefixMatches(it->addr, it->length)) 01213 continue; 01214 01215 EV << "FEC matched: " << *it << endl; 01216 01217 FecBindVector::iterator dit = findFecEntry(fecDown, it->fecid, it->nextHop); 01218 if (dit != fecDown.end()) 01219 { 01220 outLabel = LIBTable::pushLabel(dit->label); 01221 outInterface = findInterfaceFromPeerAddr(it->nextHop); 01222 color = LDP_USER_TRAFFIC; 01223 EV << "mapping found, outLabel=" << outLabel << ", outInterface=" << outInterface << endl; 01224 return true; 01225 } 01226 else 01227 { 01228 EV << "no mapping for this FEC exists" << endl; 01229 return false; 01230 } 01231 } 01232 return false; 01233 } 01234 01235 void LDP::receiveChangeNotification(int category, const cPolymorphic *details) 01236 { 01237 Enter_Method_Silent(); 01238 printNotificationBanner(category, details); 01239 01240 ASSERT(category==NF_IPv4_ROUTE_ADDED || category==NF_IPv4_ROUTE_DELETED); 01241 01242 EV << "routing table changed, rebuild list of known FEC" << endl; 01243 01244 rebuildFecList(); 01245 } 01246 01247 void LDP::announceLinkChange(int tedlinkindex) 01248 { 01249 TEDChangeInfo d; 01250 d.setTedLinkIndicesArraySize(1); 01251 d.setTedLinkIndices(0, tedlinkindex); 01252 nb->fireChangeNotification(NF_TED_CHANGED, &d); 01253 } 01254 01255