RSVP.cc

Go to the documentation of this file.
00001 //
00002 // (C) 2005 Vojtech Janota
00003 //
00004 // This library is free software, you can redistribute it
00005 // and/or modify
00006 // it under  the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation;
00008 // either version 2 of the License, or any later version.
00009 // The library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00012 // See the GNU Lesser General Public License for more details.
00013 //
00014 
00015 #include "RSVP.h"
00016 #include "IPControlInfo.h"
00017 #include "IPAddressResolver.h"
00018 #include "common.h"
00019 #include "Utils.h"
00020 #include "XMLUtils.h"
00021 #include "IPv4InterfaceData.h"
00022 #include "TEDAccess.h"
00023 #include "RoutingTableAccess.h"
00024 #include "InterfaceTableAccess.h"
00025 #include "LIBTableAccess.h"
00026 #include "NotifierConsts.h"
00027 
00028 #define PSB_REFRESH_INTERVAL    5.0
00029 #define RSB_REFRESH_INTERVAL    6.0
00030 
00031 #define PSB_TIMEOUT_INTERVAL    16.0
00032 #define RSB_TIMEOUT_INTERVAL    19.0
00033 
00034 #define PATH_ERR_UNFEASIBLE     1
00035 #define PATH_ERR_PREEMPTED      2
00036 #define PATH_ERR_NEXTHOP_FAILED 3
00037 
00038 Define_Module(RSVP);
00039 
00040 
00041 RSVP::RSVP()
00042 {
00043 }
00044 
00045 RSVP::~RSVP()
00046 {
00047     // TODO cancelAndDelete timers in all data structures
00048 }
00049 
00050 void RSVP::initialize(int stage)
00051 {
00052     // we have to wait for stage 2 until interfaces get registered (stage 0)
00053     // and get their auto-assigned IP addresses (stage 2); routerId gets
00054     // assigned in state 3
00055     if (stage==4)
00056     {
00057         tedmod = TEDAccess().get();
00058         rt = RoutingTableAccess().get();
00059         ift = InterfaceTableAccess().get();
00060         routerId = rt->getRouterId();
00061         lt = LIBTableAccess().get();
00062         nb = NotificationBoardAccess().get();
00063 
00064         rpct = check_and_cast<IRSVPClassifier*>(getParentModule()->getSubmodule("classifier"));
00065 
00066         maxPsbId = 0;
00067         maxRsbId = 0;
00068         maxSrcInstance = 0;
00069 
00070         retryInterval = 1.0;
00071 
00072         // setup hello
00073         setupHello();
00074 
00075         // process traffic configuration
00076         readTrafficFromXML(par("traffic").xmlValue());
00077     }
00078 }
00079 
00080 int RSVP::getInLabel(const SessionObj_t& session, const SenderTemplateObj_t& sender)
00081 {
00082     unsigned int index;
00083     ResvStateBlock_t *rsb = findRSB(session, sender, index);
00084     if (!rsb)
00085         return -1;
00086 
00087     return rsb->inLabelVector[index];
00088 }
00089 
00090 void RSVP::createPath(const SessionObj_t& session, const SenderTemplateObj_t& sender)
00091 {
00092     if (findPSB(session, sender))
00093     {
00094         EV << "path (PSB) already exists, doing nothing" << endl;
00095         return;
00096     }
00097 
00098     // find entry in traffic database
00099 
00100     std::vector<traffic_session_t>::iterator sit;
00101     sit = findSession(session);
00102 
00103     if (sit == traffic.end())
00104     {
00105         EV << "session not found in traffic database, path won't be created" << endl;
00106         return;
00107     }
00108 
00109     std::vector<traffic_path_t>::iterator pit;
00110     pit = findPath(&(*sit), sender);
00111 
00112     if (pit == sit->paths.end())
00113     {
00114         EV << "path doesn't belong to this session according to our database, doing nothing" << endl;
00115         return;
00116     }
00117 
00118     PathStateBlock_t *psb = createIngressPSB(*sit, *pit);
00119     if (psb)
00120     {
00121         // PSB successfully created, send path message downstream
00122         scheduleRefreshTimer(psb, 0.0);
00123     }
00124     else
00125     {
00126         EV << "ingress PSB couln't be created" << endl;
00127 
00128         // inform the owner of this path
00129         sendPathNotify(pit->owner, sit->sobj, pit->sender, PATH_UNFEASIBLE, 0.0);
00130 
00131         // remove non-permanent path
00132         if (!pit->permanent)
00133         {
00134             EV << "removing path from traffic database" << endl;
00135 
00136             sit->paths.erase(pit--);
00137         }
00138         else
00139         {
00140             EV << "path is permanent, we will try again later" << endl;
00141 
00142             sendPathNotify(getId(), sit->sobj, pit->sender, PATH_RETRY, retryInterval);
00143         }
00144     }
00145 }
00146 
00147 void RSVP::readTrafficFromXML(const cXMLElement* traffic)
00148 {
00149     ASSERT(traffic);
00150     ASSERT(!strcmp(traffic->getTagName(), "sessions"));
00151     checkTags(traffic, "session");
00152     cXMLElementList list = traffic->getChildrenByTagName("session");
00153     for (cXMLElementList::iterator it=list.begin(); it != list.end(); it++)
00154         readTrafficSessionFromXML(*it);
00155 }
00156 
00157 EroVector RSVP::readTrafficRouteFromXML(const cXMLElement *route)
00158 {
00159     checkTags(route, "node lnode");
00160 
00161     EroVector ERO;
00162 
00163     for (cXMLElement *hop = route->getFirstChild(); hop; hop = hop->getNextSibling())
00164     {
00165         EroObj_t h;
00166         if (!strcmp(hop->getTagName(), "node"))
00167         {
00168             h.L = false;
00169             h.node = IPAddressResolver().resolve(hop->getNodeValue()).get4();
00170         }
00171         else if (!strcmp(hop->getTagName(), "lnode"))
00172         {
00173             h.L = true;
00174             h.node = IPAddressResolver().resolve(hop->getNodeValue()).get4();
00175         }
00176         else
00177         {
00178             ASSERT(false);
00179         }
00180         ERO.push_back(h);
00181     }
00182 
00183     return ERO;
00184 }
00185 
00186 void RSVP::readTrafficSessionFromXML(const cXMLElement *session)
00187 {
00188     checkTags(session, "tunnel_id endpoint setup_pri holding_pri paths");
00189 
00190     traffic_session_t newSession;
00191 
00192     newSession.sobj.Tunnel_Id = getParameterIntValue(session, "tunnel_id");
00193     newSession.sobj.Extended_Tunnel_Id = routerId.getInt();
00194     newSession.sobj.DestAddress = getParameterIPAddressValue(session, "endpoint");
00195 
00196     std::vector<traffic_session_t>::iterator sit = findSession(newSession.sobj);
00197 
00198     bool merge;
00199 
00200     if (sit != traffic.end())
00201     {
00202         // session already exits, add new paths
00203 
00204         merge = true;
00205 
00206         ASSERT(!getUniqueChildIfExists(session, "holding_pri") || getParameterIntValue(session, "holding_pri") == sit->sobj.holdingPri);
00207         ASSERT(!getUniqueChildIfExists(session, "setup_pri") || getParameterIntValue(session, "setup_pri") == sit->sobj.setupPri);
00208 
00209         newSession.sobj.setupPri = sit->sobj.setupPri;
00210         newSession.sobj.holdingPri = sit->sobj.holdingPri;
00211 
00212         sit->sobj = newSession.sobj;
00213     }
00214     else
00215     {
00216         // session not found, create new
00217 
00218         merge = false;
00219 
00220         newSession.sobj.setupPri = getParameterIntValue(session, "setup_pri", 7);
00221         newSession.sobj.holdingPri = getParameterIntValue(session, "holding_pri", 7);
00222     }
00223 
00224     const cXMLElement *paths = getUniqueChild(session, "paths");
00225     checkTags(paths, "path");
00226 
00227     cXMLElementList list = paths->getChildrenByTagName("path");
00228     for (cXMLElementList::iterator it=list.begin(); it != list.end(); it++)
00229     {
00230         cXMLElement *path = *it;
00231         checkTags(path, "sender lspid bandwidth max_delay route permanent owner color");
00232 
00233         int lspid = getParameterIntValue(path, "lspid");;
00234 
00235         std::vector<traffic_path_t>::iterator pit;
00236 
00237         traffic_path_t newPath;
00238 
00239         newPath.sender.SrcAddress = getParameterIPAddressValue(path, "sender", routerId);
00240         newPath.sender.Lsp_Id = lspid;
00241 
00242         // make sure path doesn't exist yet
00243 
00244         if (merge)
00245         {
00246             pit = findPath(&(*sit), newPath.sender);
00247             if (pit != sit->paths.end())
00248             {
00249                 EV << "path " << lspid << " already exists in this session, doing nothing" << endl;
00250                 continue;
00251             }
00252         }
00253         else
00254         {
00255             pit = findPath(&newSession, newPath.sender);
00256             if (pit != newSession.paths.end())
00257             {
00258                 EV << "path " << lspid << " already exists in this session, doing nothing" << endl;
00259                 continue;
00260             }
00261         }
00262 
00263         const char *str = getParameterStrValue(path, "owner", "");
00264         if (strlen(str))
00265         {
00266             cModule *mod = simulation.getModuleByPath(str);
00267             newPath.owner = mod->getId();
00268         }
00269         else
00270         {
00271             newPath.owner = getId();
00272         }
00273 
00274         newPath.permanent = getParameterBoolValue(path, "permanent", true);
00275         newPath.color = getParameterIntValue(path, "color", 0);
00276 
00277         newPath.tspec.req_bandwidth = getParameterDoubleValue(path, "bandwidth", 0.0);
00278         newPath.max_delay = getParameterDoubleValue(path, "max_delay", 0.0);
00279 
00280         const cXMLElement *route = getUniqueChildIfExists(path, "route");
00281         if (route)
00282             newPath.ERO = readTrafficRouteFromXML(route);
00283 
00284         if (merge)
00285         {
00286             EV << "adding new path into an existing session" << endl;
00287 
00288             sit->paths.push_back(newPath);
00289         }
00290         else
00291         {
00292             EV << "adding new path into new session" << endl;
00293 
00294             newSession.paths.push_back(newPath);
00295         }
00296 
00297         // schedule path creation
00298 
00299         sendPathNotify(getId(), newSession.sobj, newPath.sender, PATH_RETRY, 0.0);
00300     }
00301 
00302     if (!merge)
00303     {
00304         EV << "adding new session into database" << endl;
00305 
00306         traffic.push_back(newSession);
00307     }
00308 }
00309 
00310 std::vector<RSVP::traffic_path_t>::iterator RSVP::findPath(traffic_session_t *session, const SenderTemplateObj_t &sender)
00311 {
00312     std::vector<traffic_path_t>::iterator it;
00313     for (it = session->paths.begin(); it != session->paths.end(); it++)
00314     {
00315         if (it->sender != sender)
00316             continue;
00317 
00318         break;
00319     }
00320     return it;
00321 }
00322 
00323 void RSVP::setupHello()
00324 {
00325     helloInterval = par("helloInterval").doubleValue();
00326     helloTimeout = par("helloTimeout").doubleValue();
00327 
00328     cStringTokenizer tokenizer(par("peers"));
00329     const char *token;
00330     while ((token = tokenizer.nextToken())!=NULL)
00331     {
00332         ASSERT(ift->getInterfaceByName(token));
00333 
00334         IPAddress peer = tedmod->getPeerByLocalAddress(ift->getInterfaceByName(token)->ipv4Data()->getIPAddress());
00335 
00336         HelloState_t h;
00337 
00338         h.timer = new HelloTimerMsg("hello timer");
00339         h.timer->setPeer(peer);
00340 
00341         h.timeout = new HelloTimeoutMsg("hello timeout");
00342         h.timeout->setPeer(peer);
00343 
00344         h.peer = peer;
00345 
00346         if (helloInterval > 0.0)
00347         {
00348             // peer is down until we know he is ok
00349 
00350             h.ok = false;
00351         }
00352         else
00353         {
00354             // don't use HELLO at all, consider all peers running all the time
00355 
00356             h.ok = true;
00357         }
00358 
00359         HelloList.push_back(h);
00360 
00361         if (helloInterval > 0.0)
00362         {
00363             startHello(peer, exponential(helloInterval));
00364         }
00365     }
00366 }
00367 
00368 void RSVP::startHello(IPAddress peer, simtime_t delay)
00369 {
00370     EV << "scheduling hello start in " << delay << " seconds" << endl;
00371 
00372     HelloState_t *h = findHello(peer);
00373     ASSERT(h);
00374 
00375     ASSERT(!h->timer->isScheduled());
00376     ASSERT(!h->timeout->isScheduled());
00377     ASSERT(!h->ok);
00378 
00379     h->srcInstance = ++maxSrcInstance;
00380     h->dstInstance = 0;
00381     h->request = true;
00382     h->ack = false;
00383 
00384     scheduleAt(simTime() + delay, h->timer);
00385 }
00386 
00387 void RSVP::sendPathNotify(int handler, const SessionObj_t& session, const SenderTemplateObj_t& sender, int status, simtime_t delay)
00388 {
00389     if (handler < 0)
00390         return; // handler not specified
00391 
00392     cModule *mod = simulation.getModule(handler);
00393 
00394     if (!mod)
00395         return; // handler no longer exists
00396 
00397     PathNotifyMsg *msg = new PathNotifyMsg("path notify");
00398 
00399     msg->setSession(session);
00400     msg->setSender(sender);
00401     msg->setStatus(status);
00402 
00403     if (handler == getId())
00404         scheduleAt(simTime() + delay, msg);
00405     else
00406         sendDirect(msg, delay, 0, mod, "from_rsvp");
00407 }
00408 
00409 void RSVP::processHELLO_TIMEOUT(HelloTimeoutMsg* msg)
00410 {
00411     IPAddress peer = msg->getPeer();
00412 
00413     EV << "hello timeout, considering " << peer << " failed" << endl;
00414 
00415     // update hello state (set to failed and turn hello off)
00416 
00417     HelloState_t *hello = findHello(peer);
00418     ASSERT(hello);
00419     hello->ok = false;
00420     ASSERT(!hello->timeout->isScheduled());
00421     cancelEvent(hello->timer);
00422 
00423     // update TED and routing table
00424 
00425     unsigned int index = tedmod->linkIndex(routerId, peer);
00426     tedmod->ted[index].state = false;
00427     announceLinkChange(index);
00428     tedmod->rebuildRoutingTable();
00429 
00430     // send PATH_ERROR for existing paths
00431 
00432     for (PSBVector::iterator it = PSBList.begin(); it != PSBList.end(); it++)
00433     {
00434         if (it->OutInterface != tedmod->ted[index].local)
00435             continue;
00436 
00437         sendPathErrorMessage(&(*it), PATH_ERR_NEXTHOP_FAILED);
00438     }
00439 }
00440 
00441 void RSVP::processHELLO_TIMER(HelloTimerMsg* msg)
00442 {
00443     IPAddress peer = msg->getPeer();
00444 
00445     HelloState_t *h = findHello(peer);
00446     ASSERT(h);
00447 
00448     RSVPHelloMsg *hMsg = new RSVPHelloMsg("hello message");
00449 
00450     hMsg->setSrcInstance(h->srcInstance);
00451     hMsg->setDstInstance(h->dstInstance);
00452 
00453     hMsg->setRequest(h->request);
00454     hMsg->setAck(h->ack);
00455 
00456     int length = 10;
00457 
00458     // see comment elsewhere (in TED.cc)
00459     length /= 10;
00460 
00461     hMsg->setByteLength(length);
00462 
00463     sendToIP(hMsg, peer);
00464 
00465     h->ack = false;
00466 
00467     scheduleAt(simTime() + helloInterval, msg);
00468 }
00469 
00470 void RSVP::processPSB_TIMER(PsbTimerMsg *msg)
00471 {
00472     PathStateBlock_t *psb = findPsbById(msg->getId());
00473     ASSERT(psb);
00474 
00475     refreshPath(psb);
00476     scheduleRefreshTimer(psb, PSB_REFRESH_INTERVAL);
00477 }
00478 
00479 void RSVP::processPSB_TIMEOUT(PsbTimeoutMsg* msg)
00480 {
00481     PathStateBlock_t *psb = findPsbById(msg->getId());
00482     ASSERT(psb);
00483 
00484     if (tedmod->isLocalAddress(psb->OutInterface))
00485     {
00486         ASSERT(psb->OutInterface == tedmod->getInterfaceAddrByPeerAddress(psb->ERO[0].node));
00487 
00488         sendPathTearMessage(psb->ERO[0].node, psb->Session_Object,
00489             psb->Sender_Template_Object, psb->OutInterface, routerId, false);
00490     }
00491 
00492     removePSB(psb);
00493 }
00494 
00495 
00496 void RSVP::processRSB_REFRESH_TIMER(RsbRefreshTimerMsg *msg)
00497 {
00498     ResvStateBlock_t *rsb = findRsbById(msg->getId());
00499     if (rsb->commitTimerMsg->isScheduled())
00500     {
00501         // reschedule after commit
00502         scheduleRefreshTimer(rsb, 0.0);
00503     }
00504     else
00505     {
00506         refreshResv(rsb);
00507 
00508         scheduleRefreshTimer(rsb, RSB_REFRESH_INTERVAL);
00509     }
00510 }
00511 
00512 void RSVP::processRSB_COMMIT_TIMER(RsbCommitTimerMsg *msg)
00513 {
00514     ResvStateBlock_t *rsb = findRsbById(msg->getId());
00515     commitResv(rsb);
00516 }
00517 
00518 void RSVP::processRSB_TIMEOUT(RsbTimeoutMsg* msg)
00519 {
00520     EV << "RSB TIMEOUT RSB " << msg->getId() << endl;
00521 
00522     ResvStateBlock_t *rsb = findRsbById(msg->getId());
00523 
00524     ASSERT(rsb);
00525     ASSERT(tedmod->isLocalAddress(rsb->OI));
00526 
00527     for (unsigned int i = 0; i < rsb->FlowDescriptor.size(); i++)
00528     {
00529         removeRsbFilter(rsb, 0);
00530     }
00531     removeRSB(rsb);
00532 }
00533 
00534 bool RSVP::doCACCheck(const SessionObj_t& session, const SenderTspecObj_t& tspec, IPAddress OI)
00535 {
00536     ASSERT(tedmod->isLocalAddress(OI));
00537 
00538     int k = tedmod->linkIndex(OI);
00539 
00540     double sharedBW = 0.0;
00541 
00542     for (RSBVector::iterator it = RSBList.begin(); it != RSBList.end(); it++)
00543     {
00544         if (it->Session_Object != session)
00545             continue;
00546 
00547         if (it->Flowspec_Object.req_bandwidth <= sharedBW)
00548             continue;
00549 
00550         sharedBW = it->Flowspec_Object.req_bandwidth;
00551     }
00552 
00553     EV << "CACCheck: link=" << OI <<
00554         " requested=" << tspec.req_bandwidth <<
00555         " shared=" << sharedBW <<
00556         " available (immediately)=" << tedmod->ted[k].UnResvBandwidth[7] <<
00557         " available (preemptible)=" << tedmod->ted[k].UnResvBandwidth[session.setupPri] << endl;
00558 
00559     return (tedmod->ted[k].UnResvBandwidth[session.setupPri] + sharedBW >= tspec.req_bandwidth);
00560 }
00561 
00562 void RSVP::refreshPath(PathStateBlock_t *psbEle)
00563 {
00564     EV << "refresh path (PSB " << psbEle->id << ")" << endl;
00565 
00566     IPAddress& OI = psbEle->OutInterface;
00567     EroVector& ERO = psbEle->ERO;
00568 
00569     ASSERT(!OI.isUnspecified());
00570     ASSERT(tedmod->isLocalAddress(OI));
00571 
00572     RSVPPathMsg *pm = new RSVPPathMsg("Path");
00573 
00574     pm->setSession(psbEle->Session_Object);
00575     pm->setSenderTemplate(psbEle->Sender_Template_Object);
00576     pm->setSenderTspec(psbEle->Sender_Tspec_Object);
00577 
00578     RsvpHopObj_t hop;
00579     hop.Logical_Interface_Handle = OI;
00580     hop.Next_Hop_Address = routerId;
00581     pm->setHop(hop);
00582 
00583     pm->setERO(ERO);
00584     pm->setColor(psbEle->color);
00585 
00586     int length = 85 + (ERO.size() * 5);
00587 
00588     pm->setByteLength(length);
00589 
00590     IPAddress nextHop = tedmod->getPeerByLocalAddress(OI);
00591 
00592     ASSERT(ERO.size() == 0 ||ERO[0].node.equals(nextHop) || ERO[0].L);
00593 
00594     sendToIP(pm, nextHop);
00595 }
00596 
00597 void RSVP::refreshResv(ResvStateBlock_t *rsbEle)
00598 {
00599     EV << "refresh reservation (RSB " << rsbEle->id << ")" << endl;
00600 
00601     IPAddressVector phops;
00602 
00603     for (PSBVector::iterator it = PSBList.begin(); it != PSBList.end(); it++)
00604     {
00605         if (it->OutInterface != rsbEle->OI)
00606             continue;
00607 
00608         for (int i = 0; i < (int)rsbEle->FlowDescriptor.size(); i++)
00609         {
00610             if ((FilterSpecObj_t&)it->Sender_Template_Object != rsbEle->FlowDescriptor[i].Filter_Spec_Object)
00611                 continue;
00612 
00613             if (tedmod->isLocalAddress(it->Previous_Hop_Address))
00614                 continue; // IR nothing to refresh
00615 
00616             if (!find(phops, it->Previous_Hop_Address))
00617                 phops.push_back(it->Previous_Hop_Address);
00618         }
00619 
00620         for (IPAddressVector::iterator it = phops.begin(); it != phops.end(); it++)
00621             refreshResv(rsbEle, *it);
00622     }
00623 }
00624 
00625 void RSVP::refreshResv(ResvStateBlock_t *rsbEle, IPAddress PHOP)
00626 {
00627     EV << "refresh reservation (RSB " << rsbEle->id << ") PHOP " << PHOP << endl;
00628 
00629     RSVPResvMsg *msg = new RSVPResvMsg("    Resv");
00630 
00631     FlowDescriptorVector flows;
00632 
00633     msg->setSession(rsbEle->Session_Object);
00634 
00635     RsvpHopObj_t hop;
00636     hop.Logical_Interface_Handle = tedmod->peerRemoteInterface(PHOP);
00637     hop.Next_Hop_Address = PHOP;
00638     msg->setHop(hop);
00639 
00640     for (PSBVector::iterator it = PSBList.begin(); it != PSBList.end(); it++)
00641     {
00642         if (it->Previous_Hop_Address != PHOP)
00643             continue;
00644 
00645         //if (it->LIH != LIH)
00646         //  continue;
00647 
00648         if (it->Session_Object != rsbEle->Session_Object)
00649             continue;
00650 
00651         for (unsigned int c = 0; c < rsbEle->FlowDescriptor.size(); c++)
00652         {
00653             if ((FilterSpecObj_t&)it->Sender_Template_Object != rsbEle->FlowDescriptor[c].Filter_Spec_Object)
00654                 continue;
00655 
00656             ASSERT(rsbEle->inLabelVector.size() == rsbEle->FlowDescriptor.size());
00657 
00658             FlowDescriptor_t flow;
00659             flow.Filter_Spec_Object = (FilterSpecObj_t&)it->Sender_Template_Object;
00660             flow.Flowspec_Object = (FlowSpecObj_t&)it->Sender_Tspec_Object;
00661             flow.RRO = rsbEle->FlowDescriptor[c].RRO;
00662             flow.RRO.push_back(routerId);
00663             flow.label = rsbEle->inLabelVector[c];
00664             flows.push_back(flow);
00665 
00666             break;
00667         }
00668     }
00669 
00670     msg->setFlowDescriptor(flows);
00671 
00672     int fd_length = 0;
00673     for (unsigned int i = 0; i < flows.size(); i++)
00674         fd_length += 28 + (flows[i].RRO.size() * 4);
00675 
00676     int length = 34 + fd_length;
00677 
00678     // see comment elsewhere (in TED.cc)
00679     length /= 10;
00680 
00681     msg->setByteLength(length);
00682 
00683     sendToIP(msg, PHOP);
00684 }
00685 
00686 void RSVP::preempt(IPAddress OI, int priority, double bandwidth)
00687 {
00688     ASSERT(tedmod->isLocalAddress(OI));
00689 
00690     unsigned int index = tedmod->linkIndex(OI);
00691 
00692     for (RSBVector::iterator it = RSBList.begin(); it != RSBList.end(); it++)
00693     {
00694         if (it->OI != OI)
00695             continue;
00696 
00697         if (it->Session_Object.holdingPri != priority)
00698             continue;
00699 
00700         if (it->Flowspec_Object.req_bandwidth == 0.0)
00701             continue;
00702 
00703         // preempt RSB
00704 
00705         for (int i = priority; i < 8; i++)
00706             tedmod->ted[index].UnResvBandwidth[i] += it->Flowspec_Object.req_bandwidth;
00707 
00708         bandwidth -= it->Flowspec_Object.req_bandwidth;
00709         it->Flowspec_Object.req_bandwidth = 0.0;
00710 
00711         scheduleCommitTimer(&(*it));
00712 
00713         //
00714 
00715         if (bandwidth <= 0.0)
00716             break;
00717     }
00718 }
00719 
00720 bool RSVP::allocateResource(IPAddress OI, const SessionObj_t& session, double bandwidth)
00721 {
00722     if (OI.isUnspecified())
00723         return true;
00724 
00725     if (!tedmod->isLocalAddress(OI))
00726         return true;
00727 
00728     if (bandwidth == 0.0)
00729         return true;
00730 
00731     int setupPri = session.setupPri;
00732     int holdingPri = session.holdingPri;
00733 
00734     unsigned int index = tedmod->linkIndex(OI);
00735 
00736     // Note: UnRB[7] <= UnRW[setupPri] <= UnRW[holdingPri] <= BW[0]
00737     // UnRW[7] is the actual BW left on the link
00738 
00739     if (tedmod->ted[index].UnResvBandwidth[setupPri] < bandwidth)
00740         return false;
00741 
00742     for (int p = holdingPri; p < 8; p++)
00743     {
00744         tedmod->ted[index].UnResvBandwidth[p] -= bandwidth;
00745 
00746         if (tedmod->ted[index].UnResvBandwidth[p] < 0.0)
00747             preempt(OI, p, -tedmod->ted[index].UnResvBandwidth[p]);
00748     }
00749 
00750     // announce changes
00751 
00752     announceLinkChange(index);
00753 
00754     return true;
00755 }
00756 
00757 void RSVP::announceLinkChange(int tedlinkindex)
00758 {
00759     TEDChangeInfo d;
00760     d.setTedLinkIndicesArraySize(1);
00761     d.setTedLinkIndices(0, tedlinkindex);
00762     nb->fireChangeNotification(NF_TED_CHANGED, &d);
00763 }
00764 
00765 void RSVP::commitResv(ResvStateBlock_t *rsb)
00766 {
00767     EV << "commit reservation (RSB " << rsb->id << ")" << endl;
00768 
00769     // allocate bandwidth as needed
00770 
00771     EV << "currently allocated: " << rsb->Flowspec_Object << endl;
00772 
00773     while(true)
00774     {
00775         // remove RSB if empty
00776 
00777         if (rsb->FlowDescriptor.size() == 0)
00778         {
00779             removeRSB(rsb);
00780             return;
00781         }
00782 
00783         FlowSpecObj_t req;
00784         req.req_bandwidth = 0.0;
00785 
00786         unsigned int maxFlowIndex;
00787         for (unsigned int i = 0; i < rsb->FlowDescriptor.size(); i++)
00788         {
00789             if (rsb->FlowDescriptor[i].Flowspec_Object.req_bandwidth > req.req_bandwidth)
00790             {
00791                 req.req_bandwidth = rsb->FlowDescriptor[i].Flowspec_Object.req_bandwidth;
00792                 maxFlowIndex = i;
00793             }
00794         }
00795 
00796         EV << "currently required: " << req << endl;
00797 
00798         double needed = req.req_bandwidth - rsb->Flowspec_Object.req_bandwidth;
00799 
00800         if (needed != 0.0)
00801         {
00802             if (allocateResource(rsb->OI, rsb->Session_Object, needed))
00803             {
00804                 // allocated (deallocated) successfully
00805 
00806                 EV << "additional bandwidth of " << needed << " allocated sucessfully" << endl;
00807 
00808                 rsb->Flowspec_Object.req_bandwidth += needed;
00809             }
00810             else
00811             {
00812                 // bandwidth not available
00813 
00814                 ASSERT(rsb->inLabelVector.size() == rsb->FlowDescriptor.size());
00815 
00816                 EV << "not enough bandwidth to accommodate this RSB" << endl;
00817 
00818                 int lspid = rsb->FlowDescriptor[maxFlowIndex].Filter_Spec_Object.Lsp_Id;
00819                 int oldInLabel = rsb->inLabelVector[maxFlowIndex];
00820                 PathStateBlock_t *psb = findPSB(rsb->Session_Object, (SenderTemplateObj_t&)rsb->FlowDescriptor[maxFlowIndex].Filter_Spec_Object);
00821 
00822                 EV << "removing filter lspid=" << lspid << " (max. flow)" << endl;
00823 
00824                 rsb->FlowDescriptor.erase(rsb->FlowDescriptor.begin() + maxFlowIndex);
00825                 rsb->inLabelVector.erase(rsb->inLabelVector.begin() + maxFlowIndex);
00826 
00827                 if (oldInLabel != -1)
00828                 {
00829                     // path already existed, this must be preemption
00830 
00831                     sendPathErrorMessage(psb, PATH_ERR_PREEMPTED);
00832 
00833                     lt->removeLibEntry(oldInLabel);
00834                 }
00835                 else
00836                 {
00837                     // path not established yet, report as unfeasible
00838 
00839                     sendPathErrorMessage(psb, PATH_ERR_UNFEASIBLE);
00840                 }
00841 
00842                 continue;
00843             }
00844 
00845         }
00846 
00847         break;
00848     }
00849 
00850     // install labels into lib
00851 
00852     for (unsigned int i = 0; i < rsb->FlowDescriptor.size(); i++)
00853     {
00854         int lspid = rsb->FlowDescriptor[i].Filter_Spec_Object.Lsp_Id;
00855 
00856         EV << "processing lspid=" << lspid << endl;
00857 
00858         PathStateBlock_t *psb = findPSB(rsb->Session_Object, rsb->FlowDescriptor[i].Filter_Spec_Object);
00859 
00860         LabelOpVector outLabel;
00861         std::string inInterface, outInterface;
00862 
00863         bool IR = (psb->Previous_Hop_Address == routerId);
00864         //bool ER = psb->OutInterface.isUnspecified();
00865         if (!IR)
00866         {
00867             IPAddress localInf = tedmod->getInterfaceAddrByPeerAddress(psb->Previous_Hop_Address);
00868             inInterface = rt->getInterfaceByAddress(localInf)->getName();
00869         }
00870         else
00871             inInterface = "any";
00872 
00873         // outlabel and outgoing interface
00874 
00875         LabelOp lop;
00876 
00877         if (tedmod->isLocalAddress(psb->OutInterface))
00878         {
00879             // regular next hop
00880 
00881             lop.optcode = IR? PUSH_OPER: SWAP_OPER;
00882             lop.label = rsb->FlowDescriptor[i].label;
00883             outLabel.push_back(lop);
00884 
00885             outInterface = rt->getInterfaceByAddress(psb->OutInterface)->getName();
00886         }
00887         else
00888         {
00889             // egress router
00890 
00891             lop.label = 0;
00892             lop.optcode = POP_OPER;
00893             outLabel.push_back(lop);
00894 
00895             outInterface = "lo0";
00896 
00897             if (!tedmod->isLocalAddress(psb->Session_Object.DestAddress))
00898             {
00899                 InterfaceEntry *ie = rt->getInterfaceForDestAddr(psb->Session_Object.DestAddress);
00900                 if (ie)
00901                     outInterface = ie->getName(); // FIXME why use name to identify an interface?
00902             }
00903         }
00904 
00905         EV << "installing label for " << lspid << " outLabel=" << outLabel <<
00906             " outInterface=" << outInterface << endl;
00907 
00908         ASSERT(rsb->inLabelVector.size() == rsb->FlowDescriptor.size());
00909 
00910         int inLabel = lt->installLibEntry(rsb->inLabelVector[i], inInterface,
00911                 outLabel, outInterface, psb->color);
00912 
00913         ASSERT(inLabel >= 0);
00914 
00915         if (IR && rsb->inLabelVector[i] == -1)
00916         {
00917             // path established
00918             sendPathNotify(psb->handler, psb->Session_Object, psb->Sender_Template_Object, PATH_CREATED, 0.0);
00919         }
00920 
00921         if (rsb->inLabelVector[i] != inLabel)
00922         {
00923             // remember our current label
00924             rsb->inLabelVector[i] = inLabel;
00925 
00926             // bind fec
00927             rpct->bind(psb->Session_Object, psb->Sender_Template_Object, inLabel);
00928         }
00929 
00930         // schedule commit of merging backups too...
00931         for (unsigned int j = 0; j < RSBList.size(); j++)
00932         {
00933             if (RSBList[j].OI != lspid)
00934                 continue;
00935 
00936             scheduleCommitTimer(&RSBList[j]);
00937         }
00938     }
00939 }
00940 
00941 RSVP::ResvStateBlock_t* RSVP::createRSB(RSVPResvMsg *msg)
00942 {
00943     ResvStateBlock_t rsbEle;
00944 
00945     rsbEle.id = ++maxRsbId;
00946 
00947     rsbEle.timeoutMsg = new RsbTimeoutMsg("rsb timeout");
00948     rsbEle.timeoutMsg->setId(rsbEle.id);
00949 
00950     rsbEle.refreshTimerMsg = new RsbRefreshTimerMsg("rsb timer");
00951     rsbEle.refreshTimerMsg->setId(rsbEle.id);
00952 
00953     rsbEle.commitTimerMsg = new RsbCommitTimerMsg("rsb commit");
00954     rsbEle.commitTimerMsg->setId(rsbEle.id);
00955 
00956     rsbEle.Session_Object = msg->getSession();
00957     rsbEle.Next_Hop_Address = msg->getNHOP();
00958     rsbEle.OI = msg->getLIH();
00959 
00960     ASSERT(rsbEle.inLabelVector.size() == rsbEle.FlowDescriptor.size());
00961 
00962     for (unsigned int i = 0; i < msg->getFlowDescriptor().size(); i++)
00963     {
00964         FlowDescriptor_t flow = msg->getFlowDescriptor()[i];
00965         rsbEle.FlowDescriptor.push_back(flow);
00966         rsbEle.inLabelVector.push_back(-1);
00967     }
00968 
00969     RSBList.push_back(rsbEle);
00970     ResvStateBlock_t *rsb = &(*(RSBList.end() - 1));
00971 
00972     EV << "created new RSB " << rsb->id << endl;
00973 
00974     return rsb;
00975 }
00976 
00977 void RSVP::updateRSB(ResvStateBlock_t* rsb, RSVPResvMsg *msg)
00978 {
00979     ASSERT(rsb);
00980 
00981     for (unsigned int k = 0; k < msg->getFlowDescriptor().size(); k++)
00982     {
00983         FlowDescriptor_t flow = msg->getFlowDescriptor()[k];
00984 
00985         unsigned int m;
00986         for (m = 0; m < rsb->FlowDescriptor.size(); m++)
00987         {
00988             if (rsb->FlowDescriptor[m].Filter_Spec_Object == flow.Filter_Spec_Object)
00989             {
00990                 // sender found
00991                 EV << "sender (lspid=" << flow.Filter_Spec_Object.Lsp_Id << ") found in RSB" << endl;
00992 
00993                 if (rsb->FlowDescriptor[m].label != flow.label)
00994                 {
00995                     EV << "label modified (new label="  << flow.label << ")" << endl;
00996 
00997                     rsb->FlowDescriptor[m].label = flow.label;
00998 
00999                     // label must be updated in lib table
01000 
01001                     scheduleCommitTimer(rsb);
01002                 }
01003 
01004                 break;
01005             }
01006         }
01007         if (m == rsb->FlowDescriptor.size())
01008         {
01009             // sender not found
01010             EV << "sender (lspid=" << flow.Filter_Spec_Object.Lsp_Id << ") not found in RSB, adding..." << endl;
01011 
01012             rsb->FlowDescriptor.push_back(flow);
01013             rsb->inLabelVector.push_back(-1);
01014 
01015             // resv is new and must be forwarded
01016 
01017             scheduleCommitTimer(rsb);
01018             scheduleRefreshTimer(rsb, 0.0);
01019         }
01020     }
01021 }
01022 
01023 void RSVP::removeRsbFilter(ResvStateBlock_t *rsb, unsigned int index)
01024 {
01025     ASSERT(rsb);
01026     ASSERT(index < rsb->FlowDescriptor.size());
01027     ASSERT(rsb->inLabelVector.size() == rsb->FlowDescriptor.size());
01028 
01029     int lspid = rsb->FlowDescriptor[index].Filter_Spec_Object.Lsp_Id;
01030     int inLabel = rsb->inLabelVector[index];
01031 
01032     EV << "removing filter (lspid=" << lspid << ")" << endl;
01033 
01034     if (inLabel != -1)
01035         lt->removeLibEntry(inLabel);
01036 
01037     rsb->FlowDescriptor.erase(rsb->FlowDescriptor.begin() + index);
01038     rsb->inLabelVector.erase(rsb->inLabelVector.begin() + index);
01039 
01040     scheduleCommitTimer(rsb);
01041 }
01042 
01043 void RSVP::removeRSB(ResvStateBlock_t *rsb)
01044 {
01045     ASSERT(rsb);
01046     ASSERT(rsb->FlowDescriptor.size() == 0);
01047 
01048     EV << "removing empty RSB " << rsb->id << endl;
01049 
01050     cancelEvent(rsb->refreshTimerMsg);
01051     cancelEvent(rsb->commitTimerMsg);
01052     cancelEvent(rsb->timeoutMsg);
01053 
01054     delete rsb->refreshTimerMsg;
01055     delete rsb->commitTimerMsg;
01056     delete rsb->timeoutMsg;
01057 
01058     if (rsb->Flowspec_Object.req_bandwidth > 0)
01059     {
01060         // deallocate resources
01061         allocateResource(rsb->OI, rsb->Session_Object, -rsb->Flowspec_Object.req_bandwidth);
01062     }
01063 
01064     for (RSBVector::iterator it = RSBList.begin(); it != RSBList.end(); it++)
01065     {
01066         if (it->id != rsb->id)
01067             continue;
01068 
01069         RSBList.erase(it);
01070         return;
01071     }
01072     ASSERT(false);
01073 }
01074 
01075 void RSVP::removePSB(PathStateBlock_t *psb)
01076 {
01077     ASSERT(psb);
01078 
01079     int lspid = psb->Sender_Template_Object.Lsp_Id;
01080 
01081     EV << "removing PSB " << psb->id << " (lspid " << lspid << ")" << endl;
01082 
01083     // remove reservation state if exists **************************************
01084 
01085     unsigned int filterIndex;
01086     ResvStateBlock_t *rsb = findRSB(psb->Session_Object, psb->Sender_Template_Object, filterIndex);
01087     if (rsb)
01088     {
01089         EV << "reservation state present, will be removed too" << endl;
01090 
01091         removeRsbFilter(rsb, filterIndex);
01092     }
01093 
01094     // proceed with actual removal *********************************************
01095 
01096     cancelEvent(psb->timerMsg);
01097     cancelEvent(psb->timeoutMsg);
01098 
01099     delete psb->timerMsg;
01100     delete psb->timeoutMsg;
01101 
01102     for (PSBVector::iterator it = PSBList.begin(); it != PSBList.end(); it++)
01103     {
01104         if (it->id != psb->id)
01105             continue;
01106 
01107         PSBList.erase(it);
01108         return;
01109     }
01110     ASSERT(false);
01111 }
01112 
01113 bool RSVP::evalNextHopInterface(IPAddress destAddr, const EroVector& ERO, IPAddress& OI)
01114 {
01115     if (ERO.size() > 0)
01116     {
01117         // explicit routing
01118 
01119         if (ERO[0].L)
01120         {
01121             InterfaceEntry *ie = rt->getInterfaceForDestAddr(ERO[0].node);
01122 
01123             if (!ie)
01124             {
01125                 EV << "next (loose) hop address " << ERO[0].node << " is currently unroutable" << endl;
01126                 return false;
01127             }
01128 
01129             OI = ie->ipv4Data()->getIPAddress();
01130 
01131         }
01132         else
01133         {
01134             OI = tedmod->getInterfaceAddrByPeerAddress(ERO[0].node);
01135         }
01136 
01137         IPAddress peer = tedmod->getPeerByLocalAddress(OI);
01138         HelloState_t *h = findHello(peer);
01139         if (!h)
01140             error("Peer %s on interface %s is not an RSVP peer", peer.str().c_str(), OI.str().c_str());
01141 
01142         // ok, only if next hop is up and running
01143 
01144         return h->ok;
01145     }
01146     else
01147     {
01148         // hop-by-hop routing
01149 
01150         if (!tedmod->isLocalAddress(destAddr))
01151         {
01152             InterfaceEntry *ie = rt->getInterfaceForDestAddr(destAddr);
01153 
01154             if (!ie)
01155             {
01156                 EV << "destination address " << destAddr << " is currently unroutable" << endl;
01157                 return false;
01158             }
01159 
01160             OI = ie->ipv4Data()->getIPAddress();
01161 
01162             HelloState_t *h = findHello(tedmod->getPeerByLocalAddress(OI));
01163             if (!h)
01164             {
01165                 // outgoing interface is not LSR, we are egress router
01166 
01167                 OI = IPAddress();
01168 
01169                 return true;
01170             }
01171             else
01172             {
01173                 // outgoing interface is LSR
01174 
01175                 ASSERT(h->ok); // rt->getInterfaceForDestAddr() wouldn't choose this entry
01176 
01177                 return h->ok;
01178             }
01179         }
01180         else
01181         {
01182             // destAddress is ours, we're egress
01183 
01184             return true;
01185         }
01186     }
01187 }
01188 
01189 RSVP::PathStateBlock_t* RSVP::createPSB(RSVPPathMsg *msg)
01190 {
01191     const EroVector& ERO = msg->getERO();
01192     IPAddress destAddr = msg->getDestAddress();
01193 
01194     //
01195 
01196     IPAddress OI;
01197 
01198     if (!evalNextHopInterface(destAddr, ERO, OI))
01199         return NULL;
01200 
01201     if (tedmod->isLocalAddress(OI) && !doCACCheck(msg->getSession(), msg->getSenderTspec(), OI))
01202         return NULL; // not enough resources
01203 
01204     PathStateBlock_t psbEle;
01205 
01206     psbEle.id = ++maxPsbId;
01207 
01208     psbEle.timeoutMsg = new PsbTimeoutMsg("psb timeout");
01209     psbEle.timeoutMsg->setId(psbEle.id);
01210 
01211     psbEle.timerMsg = new PsbTimerMsg("psb timer");
01212     psbEle.timerMsg->setId(psbEle.id);
01213 
01214     psbEle.Session_Object = msg->getSession();
01215     psbEle.Sender_Template_Object = msg->getSenderTemplate();
01216     psbEle.Sender_Tspec_Object = msg->getSenderTspec();
01217 
01218     psbEle.Previous_Hop_Address = msg->getNHOP();
01219     //psbEle.LIH = msg->getLIH();
01220 
01221     psbEle.OutInterface = OI;
01222     psbEle.ERO = ERO;
01223 
01224     psbEle.color = msg->getColor();
01225     psbEle.handler = -1;
01226 
01227     PSBList.push_back(psbEle);
01228     PathStateBlock_t *cPSB = &(*(PSBList.end() - 1));
01229 
01230     EV << "created new PSB " << cPSB->id << endl;
01231 
01232     return cPSB;
01233 }
01234 
01235 RSVP::PathStateBlock_t* RSVP::createIngressPSB(const traffic_session_t& session, const traffic_path_t& path)
01236 {
01237     EroVector ERO = path.ERO;
01238 
01239     while(ERO.size() > 0 && ERO[0].node == routerId)
01240     {
01241         // remove ourselves from the beginning of the hop list
01242         ERO.erase(ERO.begin());
01243     }
01244 
01245     IPAddress OI;
01246 
01247     if (!evalNextHopInterface(session.sobj.DestAddress, ERO, OI))
01248         return NULL;
01249 
01250     if (!doCACCheck(session.sobj, path.tspec, OI))
01251         return NULL;
01252 
01253     EV << "CACCheck passed, creating PSB" << endl;
01254 
01255     PathStateBlock_t psbEle;
01256     psbEle.id = ++maxPsbId;
01257 
01258     psbEle.timeoutMsg = new PsbTimeoutMsg("psb timeout");
01259     psbEle.timeoutMsg->setId(psbEle.id);
01260 
01261     psbEle.timerMsg = new PsbTimerMsg("psb timer");
01262     psbEle.timerMsg->setId(psbEle.id);
01263 
01264     psbEle.Session_Object = session.sobj;
01265     psbEle.Sender_Template_Object = path.sender;
01266     psbEle.Sender_Tspec_Object = path.tspec;
01267 
01268     psbEle.Previous_Hop_Address = routerId;
01269 
01270     psbEle.OutInterface = OI;
01271     psbEle.ERO = ERO;
01272     psbEle.color = path.color;
01273 
01274     psbEle.handler = path.owner;
01275 
01276     PSBList.push_back(psbEle);
01277     PathStateBlock_t *cPSB = &(*(PSBList.end() - 1));
01278 
01279     return cPSB;
01280 }
01281 
01282 
01283 RSVP::ResvStateBlock_t* RSVP::createEgressRSB(PathStateBlock_t *psb)
01284 {
01285     ResvStateBlock_t rsbEle;
01286 
01287     rsbEle.id = ++maxRsbId;
01288 
01289     rsbEle.timeoutMsg = new RsbTimeoutMsg("rsb timeout");
01290     rsbEle.timeoutMsg->setId(rsbEle.id);
01291 
01292     rsbEle.refreshTimerMsg = new RsbRefreshTimerMsg("rsb timer");
01293     rsbEle.refreshTimerMsg->setId(rsbEle.id);
01294 
01295     rsbEle.commitTimerMsg = new RsbCommitTimerMsg("rsb commit");
01296     rsbEle.commitTimerMsg->setId(rsbEle.id);
01297 
01298     rsbEle.Session_Object = psb->Session_Object;
01299     rsbEle.Next_Hop_Address = psb->Previous_Hop_Address;
01300 
01301     rsbEle.OI = psb->OutInterface;
01302 
01303     FlowDescriptor_t flow;
01304     flow.Flowspec_Object = (FlowSpecObj_t&)psb->Sender_Tspec_Object;
01305     flow.Filter_Spec_Object = (FilterSpecObj_t&)psb->Sender_Template_Object;
01306     flow.label = -1;
01307 
01308     rsbEle.FlowDescriptor.push_back(flow);
01309     rsbEle.inLabelVector.push_back(-1);
01310 
01311     RSBList.push_back(rsbEle);
01312     ResvStateBlock_t *rsb = &(*(RSBList.end() - 1));
01313 
01314     EV << "created new (egress) RSB " << rsb->id << endl;
01315 
01316     return rsb;
01317 }
01318 
01319 void RSVP::handleMessage(cMessage *msg)
01320 {
01321     SignallingMsg *sMsg = dynamic_cast<SignallingMsg*>(msg);
01322     RSVPMessage *rMsg = dynamic_cast<RSVPMessage*>(msg);
01323 
01324     if (sMsg)
01325     {
01326         processSignallingMessage(sMsg);
01327         return;
01328     }
01329     else if (rMsg)
01330     {
01331         processRSVPMessage(rMsg);
01332         return;
01333     }
01334     else
01335         ASSERT(false);
01336 }
01337 
01338 void RSVP::processRSVPMessage(RSVPMessage *msg)
01339 {
01340     int kind = msg->getRsvpKind();
01341     switch(kind)
01342     {
01343         case PATH_MESSAGE:
01344             processPathMsg(check_and_cast<RSVPPathMsg*>(msg));
01345             break;
01346 
01347         case RESV_MESSAGE:
01348             processResvMsg(check_and_cast<RSVPResvMsg*>(msg));
01349             break;
01350 
01351         case PTEAR_MESSAGE:
01352             processPathTearMsg(check_and_cast<RSVPPathTear*>(msg));
01353             break;
01354 
01355         case HELLO_MESSAGE:
01356             processHelloMsg(check_and_cast<RSVPHelloMsg*>(msg));
01357             break;
01358 
01359         case PERROR_MESSAGE:
01360             processPathErrMsg(check_and_cast<RSVPPathError*>(msg));
01361             break;
01362 
01363         default:
01364             ASSERT(false);
01365     }
01366 }
01367 
01368 void RSVP::processHelloMsg(RSVPHelloMsg* msg)
01369 {
01370     EV << "Received RSVP_HELLO" << endl;
01371     //print(msg);
01372 
01373     IPControlInfo *controlInfo = check_and_cast<IPControlInfo*>(msg->getControlInfo());
01374     IPAddress sender = controlInfo->getSrcAddr();
01375     IPAddress peer = tedmod->primaryAddress(sender);
01376 
01377     bool request = msg->getRequest();
01378     bool ack = msg->getAck();
01379 
01380     EV << "hello sender " << peer;
01381     if (request) EV << " REQ";
01382     if (ack) EV << " ACK";
01383     EV << endl;
01384 
01385     int rcvSrcInstance = msg->getSrcInstance();
01386     int rcvDstInstance = msg->getDstInstance();
01387 
01388     delete msg;
01389 
01390     HelloState_t *h = findHello(peer);
01391     ASSERT(h);
01392 
01393     ASSERT(h->srcInstance);
01394     ASSERT(rcvSrcInstance);
01395 
01396     bool failure = false;
01397 
01398     if (h->srcInstance != rcvDstInstance)
01399     {
01400         if (rcvDstInstance != 0)
01401         {
01402             failure = true;
01403         }
01404         else
01405         {
01406             ASSERT(request);
01407         }
01408     }
01409 
01410     if (h->dstInstance != rcvSrcInstance)
01411     {
01412         if (h->dstInstance != 0)
01413         {
01414             failure = true;
01415         }
01416         h->dstInstance = rcvSrcInstance;
01417     }
01418 
01419     if (failure)
01420     {
01421         // mismatch encountered
01422         h->srcInstance = ++maxSrcInstance;
01423     }
01424 
01425     if (failure || !h->ok)
01426     {
01427         h->ok = true;
01428 
01429         EV << "local peer " << peer << " is now considered up and running" << endl;
01430 
01431         recoveryEvent(peer);
01432 
01433         // if peer was considered down, we have stopped sending hellos: resume now
01434         if (!h->timer->isScheduled())
01435             scheduleAt(simTime(), h->timer);
01436     }
01437 
01438     if (request)
01439     {
01440         // immediately respond to a request with an ack
01441         h->ack = true;
01442         h->request = false;
01443 
01444         cancelEvent(h->timer);
01445         scheduleAt(simTime(), h->timer);
01446     }
01447     else
01448     {
01449         // next message will be regular
01450 
01451         h->ack = false;
01452         h->request = false;
01453 
01454         ASSERT(h->timer->isScheduled());
01455     }
01456 
01457     cancelEvent(h->timeout);
01458     scheduleAt(simTime() + helloTimeout, h->timeout);
01459 }
01460 
01461 void RSVP::processPathErrMsg(RSVPPathError* msg)
01462 {
01463     EV << "Received PATH_ERROR" << endl;
01464     //print(msg);
01465 
01466     //int lspid = msg->getLspId();
01467     int errCode = msg->getErrorCode();
01468 
01469     PathStateBlock_t *psb = findPSB(msg->getSession(), msg->getSenderTemplate());
01470     if (!psb)
01471     {
01472         EV << "matching PSB not found, ignoring error message" << endl;
01473         delete msg;
01474         return;
01475     }
01476 
01477     if (psb->Previous_Hop_Address != routerId)
01478     {
01479         EV << "forwarding error message to PHOP (" << psb->Previous_Hop_Address << ")" << endl;
01480 
01481         msg->removeControlInfo();
01482         sendToIP(msg, psb->Previous_Hop_Address);
01483     }
01484     else
01485     {
01486         EV << "error reached ingress router" << endl;
01487 
01488         switch(errCode)
01489         {
01490             case PATH_ERR_PREEMPTED:
01491                 sendPathNotify(psb->handler, psb->Session_Object, psb->Sender_Template_Object, PATH_PREEMPTED, 0.0);
01492                 break;
01493 
01494             case PATH_ERR_UNFEASIBLE:
01495                 sendPathNotify(psb->handler, psb->Session_Object, psb->Sender_Template_Object, PATH_UNFEASIBLE, 0.0);
01496                 break;
01497 
01498             case PATH_ERR_NEXTHOP_FAILED:
01499                 sendPathNotify(psb->handler, psb->Session_Object, psb->Sender_Template_Object, PATH_FAILED, 0.0);
01500                 break;
01501 
01502             default:
01503                 ASSERT(false);
01504         }
01505 
01506         delete msg;
01507     }
01508 }
01509 
01510 void RSVP::processPathTearMsg(RSVPPathTear *msg)
01511 {
01512     EV << "Received PATH_TEAR" << endl;
01513     //print(msg);
01514 
01515     int lspid = msg->getLspId();
01516 
01517     PathStateBlock_t *psb = findPSB(msg->getSession(), msg->getSenderTemplate());
01518     if (!psb)
01519     {
01520         EV << "received PATH_TEAR for nonexisting lspid=" << lspid << endl;
01521         delete msg;
01522         return;
01523     }
01524 
01525     // ignore message if backup exists and force flag is not set
01526 
01527     bool modified = false;
01528 
01529     for (PSBVector::iterator it = PSBList.begin(); it != PSBList.end(); it++)
01530     {
01531         if (it->OutInterface.getInt() != lspid)
01532             continue;
01533 
01534         // merging backup exists
01535 
01536         if (!msg->getForce())
01537         {
01538             EV << "merging backup tunnel exists and force flag is not set, ignoring teardown" << endl;
01539             delete msg;
01540             return;
01541         }
01542 
01543         EV << "merging backup must be removed too" << endl;
01544 
01545         removePSB(&(*it));
01546         --it;
01547 
01548         modified = true;
01549     }
01550 
01551     if (modified)
01552         psb = findPSB(msg->getSession(), msg->getSenderTemplate());
01553 
01554     // forward path teardown downstream
01555 
01556     if (psb->ERO.size() > 0)
01557     {
01558         EV << "forward teardown downstream" << endl;
01559 
01560         sendPathTearMessage(psb->ERO[0].node, psb->Session_Object, psb->Sender_Template_Object,
01561             tedmod->getInterfaceAddrByPeerAddress(psb->ERO[0].node), routerId, msg->getForce());
01562     }
01563 
01564     // remove path state block
01565 
01566     removePSB(psb);
01567 
01568     delete msg;
01569 }
01570 
01571 void RSVP::processPathMsg(RSVPPathMsg *msg)
01572 {
01573     EV << "Received PATH_MESSAGE" << endl;
01574     print(msg);
01575 
01576     // process ERO *************************************************************
01577 
01578     EroVector ERO = msg->getERO();
01579 
01580     while(ERO.size() > 0 && ERO[0].node == routerId)
01581     {
01582         ERO.erase(ERO.begin());
01583     }
01584 
01585     msg->setERO(ERO);
01586 
01587     // create PSB if doesn't exist yet *****************************************
01588 
01589     PathStateBlock_t *psb = findPSB(msg->getSession(), msg->getSenderTemplate());
01590 
01591     if (!psb)
01592     {
01593         psb = createPSB(msg);
01594         if (!psb)
01595         {
01596             sendPathErrorMessage(msg->getSession(), msg->getSenderTemplate(),
01597                 msg->getSenderTspec(), msg->getNHOP(), PATH_ERR_UNFEASIBLE);
01598             delete msg;
01599             return;
01600         }
01601         scheduleRefreshTimer(psb, 0.0);
01602 
01603         if (tedmod->isLocalAddress(psb->OutInterface))
01604         {
01605             unsigned int index = tedmod->linkIndex(psb->OutInterface);
01606             if (!tedmod->ted[index].state)
01607             {
01608                 sendPathErrorMessage(psb, PATH_ERR_NEXTHOP_FAILED);
01609             }
01610         }
01611     }
01612 
01613     // schedule timer&timeout **************************************************
01614 
01615     scheduleTimeout(psb);
01616 
01617     // create RSB if we're egress and doesn't exist yet ************************
01618 
01619     unsigned int index;
01620     ResvStateBlock_t *rsb = findRSB(msg->getSession(), msg->getSenderTemplate(), index);
01621 
01622     if (!rsb && psb->OutInterface.isUnspecified())
01623     {
01624         ASSERT(ERO.size() == 0);
01625         rsb = createEgressRSB(psb);
01626         ASSERT(rsb);
01627         scheduleCommitTimer(rsb);
01628     }
01629 
01630     if (rsb)
01631         scheduleRefreshTimer(rsb, 0.0);
01632 
01633     delete msg;
01634 }
01635 
01636 void RSVP::processResvMsg(RSVPResvMsg *msg)
01637 {
01638     EV << "Received RESV_MESSAGE" << endl;
01639     print(msg);
01640 
01641     IPAddress OI = msg->getLIH();
01642 
01643     // find matching PSB for every flow ****************************************
01644 
01645     for (unsigned int m = 0; m < msg->getFlowDescriptor().size(); m++)
01646     {
01647 
01648         PathStateBlock_t *psb = findPSB(msg->getSession(), (SenderTemplateObj_t&)msg->getFlowDescriptor()[m].Filter_Spec_Object);
01649         if (!psb)
01650         {
01651             EV << "matching PSB not found for lspid=" << msg->getFlowDescriptor()[m].Filter_Spec_Object.Lsp_Id << endl;
01652 
01653             // remove descriptor from message
01654             msg->getFlowDescriptor().erase(msg->getFlowDescriptor().begin() + m);
01655             --m;
01656         }
01657     }
01658 
01659     if (msg->getFlowDescriptor().size() == 0)
01660     {
01661         EV << "no matching PSB found" << endl;
01662         delete msg;
01663         return;
01664     }
01665 
01666     // find matching RSB *******************************************************
01667 
01668     ResvStateBlock_t *rsb = NULL;
01669     for (RSBVector::iterator it = RSBList.begin(); it != RSBList.end(); it++)
01670     {
01671         if (!(msg->isInSession(&it->Session_Object)))
01672             continue;
01673 
01674         if (it->Next_Hop_Address != msg->getNHOP())
01675             continue;
01676 
01677         if (it->OI != msg->getLIH())
01678             continue;
01679 
01680         rsb = &(*it);
01681         break;
01682     }
01683 
01684     if (!rsb)
01685     {
01686         rsb = createRSB(msg);
01687 
01688         scheduleCommitTimer(rsb);
01689 
01690         // reservation is new, propagate upstream immediately
01691         scheduleRefreshTimer(rsb, 0.0);
01692     }
01693     else
01694         updateRSB(rsb, msg);
01695 
01696     scheduleTimeout(rsb);
01697 
01698     delete msg;
01699 }
01700 
01701 void RSVP::recoveryEvent(IPAddress peer)
01702 {
01703     // called when peer's operation is restored
01704 
01705     unsigned int index = tedmod->linkIndex(routerId, peer);
01706     bool rtmodified = !tedmod->ted[index].state;
01707     tedmod->ted[index].state = true;
01708     announceLinkChange(index);
01709 
01710     // rebuild routing table if link state changed
01711     if (rtmodified)
01712         tedmod->rebuildRoutingTable();
01713 
01714     // refresh all paths towards this neighbour
01715     for (PSBVector::iterator it = PSBList.begin(); it != PSBList.end(); it++)
01716     {
01717         if (it->OutInterface != tedmod->ted[index].local)
01718             continue;
01719 
01720         scheduleRefreshTimer(&(*it), 0.0);
01721     }
01722 }
01723 
01724 void RSVP::processSignallingMessage(SignallingMsg *msg)
01725 {
01726     int command = msg->getCommand();
01727     switch(command)
01728     {
01729         case MSG_PSB_TIMER:
01730             processPSB_TIMER(check_and_cast<PsbTimerMsg*>(msg));
01731             break;
01732 
01733         case MSG_PSB_TIMEOUT:
01734             processPSB_TIMEOUT(check_and_cast<PsbTimeoutMsg*>(msg));
01735             break;
01736 
01737         case MSG_RSB_REFRESH_TIMER:
01738             processRSB_REFRESH_TIMER(check_and_cast<RsbRefreshTimerMsg*>(msg));
01739             break;
01740 
01741         case MSG_RSB_COMMIT_TIMER:
01742             processRSB_COMMIT_TIMER(check_and_cast<RsbCommitTimerMsg*>(msg));
01743             break;
01744 
01745         case MSG_RSB_TIMEOUT:
01746             processRSB_TIMEOUT(check_and_cast<RsbTimeoutMsg*>(msg));
01747             break;
01748 
01749         case MSG_HELLO_TIMER:
01750             processHELLO_TIMER(check_and_cast<HelloTimerMsg*>(msg));
01751             break;
01752 
01753         case MSG_HELLO_TIMEOUT:
01754             processHELLO_TIMEOUT(check_and_cast<HelloTimeoutMsg*>(msg));
01755             break;
01756 
01757         case MSG_PATH_NOTIFY:
01758             processPATH_NOTIFY(check_and_cast<PathNotifyMsg*>(msg));
01759             break;
01760 
01761         default:
01762             ASSERT(false);
01763     }
01764 }
01765 
01766 void RSVP::pathProblem(PathStateBlock_t *psb)
01767 {
01768     ASSERT(psb);
01769     ASSERT(!psb->OutInterface.isUnspecified());
01770 
01771     IPAddress nextHop = tedmod->getPeerByLocalAddress(psb->OutInterface);
01772 
01773     EV << "sending PathTear to " << nextHop << endl;
01774 
01775     sendPathTearMessage(nextHop, psb->Session_Object, psb->Sender_Template_Object,
01776                         tedmod->getInterfaceAddrByPeerAddress(nextHop), routerId, true);
01777 
01778     // schedule re-creation if path is permanent
01779 
01780     std::vector<traffic_session_t>::iterator sit = findSession(psb->Session_Object);
01781     ASSERT(sit != traffic.end());
01782     traffic_session_t *s = &(*sit);
01783 
01784     std::vector<traffic_path_t>::iterator pit = findPath(s, psb->Sender_Template_Object);
01785     ASSERT(pit != s->paths.end());
01786     traffic_path_t *p = &(*pit);
01787 
01788     if (p->permanent)
01789     {
01790         EV << "this path is permanent, we will try to re-create it later" << endl;
01791 
01792         sendPathNotify(getId(), psb->Session_Object, psb->Sender_Template_Object, PATH_RETRY, retryInterval);
01793 
01794     }
01795     else
01796     {
01797         EV << "removing path from traffic database" << endl;
01798 
01799         sit->paths.erase(pit);
01800     }
01801 
01802     // remove path
01803 
01804     EV << "removing PSB" << endl;
01805 
01806     removePSB(psb);
01807 }
01808 
01809 void RSVP::processPATH_NOTIFY(PathNotifyMsg* msg)
01810 {
01811     PathStateBlock_t *psb;
01812 
01813     switch(msg->getStatus())
01814     {
01815         case PATH_RETRY:
01816             createPath(msg->getSession(), msg->getSender());
01817             break;
01818 
01819         case PATH_UNFEASIBLE:
01820         case PATH_PREEMPTED:
01821         case PATH_FAILED:
01822             psb = findPSB(msg->getSession(), msg->getSender());
01823             if (psb)
01824                 pathProblem(psb);
01825             break;
01826 
01827         case PATH_CREATED:
01828             EV << "Path successfully established" << endl;
01829             break;
01830 
01831 
01832         default:
01833             ASSERT(false);
01834     }
01835 
01836     delete msg;
01837 }
01838 
01839 
01840 std::vector<RSVP::traffic_session_t>::iterator RSVP::findSession(const SessionObj_t& session)
01841 {
01842     std::vector<traffic_session_t>::iterator it;
01843     for (it = traffic.begin(); it != traffic.end(); it++)
01844     {
01845         if (it->sobj != session)
01846             continue;
01847 
01848         break;
01849     }
01850 
01851     return it;
01852 }
01853 
01854 void RSVP::addSession(const cXMLElement& node)
01855 {
01856     Enter_Method_Silent();
01857 
01858     readTrafficSessionFromXML(&node);
01859 }
01860 
01861 void RSVP::delSession(const cXMLElement& node)
01862 {
01863     Enter_Method_Silent();
01864 
01865     checkTags(&node, "tunnel_id extended_tunnel_id endpoint paths");
01866 
01867     SessionObj_t sobj;
01868 
01869     sobj.Tunnel_Id = getParameterIntValue(&node, "tunnel_id");
01870     sobj.Extended_Tunnel_Id = getParameterIPAddressValue(&node, "extended_tunnel_id", routerId).getInt();
01871     sobj.DestAddress = getParameterIPAddressValue(&node, "endpoint");
01872 
01873     std::vector<traffic_session_t>::iterator sit = findSession(sobj);
01874     ASSERT(sit != traffic.end());
01875     traffic_session_t *session = &(*sit);
01876 
01877     const cXMLElement *paths = getUniqueChildIfExists(&node, "paths");
01878     cXMLElementList pathList;
01879     if (paths)
01880     {
01881         // only specified paths will be removed, session remains
01882 
01883         checkTags(paths, "path");
01884         pathList = paths->getChildrenByTagName("path");
01885     }
01886 
01887     std::vector<traffic_path_t>::iterator it;
01888     for (it = session->paths.begin(); it != session->paths.end(); it++)
01889     {
01890         bool remove;
01891 
01892         if (paths)
01893         {
01894             remove = false;
01895 
01896             for (cXMLElementList::iterator p=pathList.begin(); p != pathList.end(); p++)
01897             {
01898                 if (it->sender.Lsp_Id != getParameterIntValue(*p, "lspid"))
01899                     continue;
01900 
01901                 // remove path from session
01902 
01903                 remove = true;
01904                 break;
01905             }
01906         }
01907         else
01908         {
01909             // remove all paths
01910 
01911             remove = true;
01912         }
01913 
01914         if (remove)
01915         {
01916             PathStateBlock_t *psb = findPSB(session->sobj, it->sender);
01917             if (psb)
01918             {
01919                 ASSERT(psb->ERO.size() > 0);
01920 
01921                 sendPathTearMessage(psb->ERO[0].node, psb->Session_Object, psb->Sender_Template_Object,
01922                         tedmod->getInterfaceAddrByPeerAddress(psb->ERO[0].node), routerId, true);
01923 
01924                 removePSB(psb);
01925             }
01926 
01927             session->paths.erase(it--);
01928         }
01929     }
01930 
01931     if (!paths)
01932     {
01933         traffic.erase(sit);
01934     }
01935 }
01936 
01937 void RSVP::processCommand(const cXMLElement& node)
01938 {
01939     if (!strcmp(node.getTagName(), "add-session"))
01940     {
01941         addSession(node);
01942     }
01943     else if (!strcmp(node.getTagName(), "del-session"))
01944     {
01945         delSession(node);
01946     }
01947     else
01948         ASSERT(false);
01949 }
01950 
01951 void RSVP::sendPathTearMessage(IPAddress peerIP, const SessionObj_t& session, const SenderTemplateObj_t& sender, IPAddress LIH, IPAddress NHOP, bool force)
01952 {
01953     RSVPPathTear *msg = new RSVPPathTear("PathTear");
01954     msg->setSenderTemplate(sender);
01955     msg->setSession(session);
01956     RsvpHopObj_t hop;
01957     hop.Logical_Interface_Handle = LIH;
01958     hop.Next_Hop_Address = NHOP;
01959     msg->setHop(hop);
01960     msg->setForce(force);
01961 
01962     int length = 44;
01963 
01964     msg->setByteLength(length);
01965 
01966     sendToIP(msg, peerIP);
01967 }
01968 
01969 void RSVP::sendPathErrorMessage(PathStateBlock_t *psb, int errCode)
01970 {
01971     sendPathErrorMessage(psb->Session_Object, psb->Sender_Template_Object, psb->Sender_Tspec_Object, psb->Previous_Hop_Address, errCode);
01972 }
01973 
01974 void RSVP::sendPathErrorMessage(SessionObj_t session, SenderTemplateObj_t sender, SenderTspecObj_t tspec, IPAddress nextHop, int errCode)
01975 {
01976     RSVPPathError *msg = new RSVPPathError("PathErr");
01977     msg->setErrorCode(errCode);
01978     msg->setErrorNode(routerId);
01979     msg->setSession(session);
01980     msg->setSenderTemplate(sender);
01981     msg->setSenderTspec(tspec);
01982 
01983     int length = 52;
01984 
01985     // see comment elsewhere (in TED.cc)
01986     length /= 10;
01987 
01988     msg->setByteLength(length);
01989 
01990     sendToIP(msg, nextHop);
01991 }
01992 
01993 
01994 void RSVP::sendToIP(cMessage *msg, IPAddress destAddr)
01995 {
01996     IPControlInfo *controlInfo = new IPControlInfo();
01997     controlInfo->setDestAddr(destAddr);
01998     controlInfo->setProtocol(IP_PROT_RSVP);
01999     msg->setControlInfo(controlInfo);
02000 
02001     msg->addPar("color") = RSVP_TRAFFIC;
02002 
02003     send(msg, "ipOut");
02004 }
02005 
02006 void RSVP::scheduleTimeout(PathStateBlock_t *psbEle)
02007 {
02008     ASSERT(psbEle);
02009 
02010     if (psbEle->timeoutMsg->isScheduled())
02011         cancelEvent(psbEle->timeoutMsg);
02012 
02013     scheduleAt(simTime() + PSB_TIMEOUT_INTERVAL, psbEle->timeoutMsg);
02014 }
02015 
02016 void RSVP::scheduleRefreshTimer(PathStateBlock_t *psbEle, simtime_t delay)
02017 {
02018     ASSERT(psbEle);
02019 
02020     if (psbEle->OutInterface.isUnspecified())
02021         return;
02022 
02023     if (!tedmod->isLocalAddress(psbEle->OutInterface))
02024         return;
02025 
02026     if (psbEle->timerMsg->isScheduled())
02027         cancelEvent(psbEle->timerMsg);
02028 
02029     EV << "scheduling PSB " << psbEle->id << " refresh " << (simTime() + delay) << endl;
02030 
02031     scheduleAt(simTime() + delay, psbEle->timerMsg);
02032 }
02033 
02034 void RSVP::scheduleTimeout(ResvStateBlock_t *rsbEle)
02035 {
02036     ASSERT(rsbEle);
02037 
02038     if (rsbEle->timeoutMsg->isScheduled())
02039         cancelEvent(rsbEle->timeoutMsg);
02040 
02041     scheduleAt(simTime() + RSB_TIMEOUT_INTERVAL, rsbEle->timeoutMsg);
02042 }
02043 
02044 void RSVP::scheduleRefreshTimer(ResvStateBlock_t *rsbEle, simtime_t delay)
02045 {
02046     ASSERT(rsbEle);
02047 
02048     if (rsbEle->refreshTimerMsg->isScheduled())
02049         cancelEvent(rsbEle->refreshTimerMsg);
02050 
02051     scheduleAt(simTime() + delay, rsbEle->refreshTimerMsg);
02052 }
02053 
02054 void RSVP::scheduleCommitTimer(ResvStateBlock_t *rsbEle)
02055 {
02056     ASSERT(rsbEle);
02057 
02058     if (rsbEle->commitTimerMsg->isScheduled())
02059         cancelEvent(rsbEle->commitTimerMsg);
02060 
02061     scheduleAt(simTime(), rsbEle->commitTimerMsg);
02062 }
02063 
02064 RSVP::ResvStateBlock_t* RSVP::findRSB(const SessionObj_t& session, const SenderTemplateObj_t& sender, unsigned int& index)
02065 {
02066     RSBVector::iterator it;
02067 
02068     for (it = RSBList.begin(); it != RSBList.end(); it++)
02069     {
02070         if (it->Session_Object != session)
02071             continue;
02072 
02073         FlowDescriptorVector::iterator fit;
02074         index = 0;
02075         for (fit = it->FlowDescriptor.begin(); fit != it->FlowDescriptor.end(); fit++)
02076         {
02077             if ((SenderTemplateObj_t&)fit->Filter_Spec_Object != sender)
02078             {
02079                 ++index;
02080                 continue;
02081             }
02082 
02083             return &(*it);
02084         }
02085 
02086         // don't break here, may be in different (if outInterface is different)
02087     }
02088     return NULL;
02089 }
02090 
02091 RSVP::PathStateBlock_t* RSVP::findPSB(const SessionObj_t& session, const SenderTemplateObj_t& sender)
02092 {
02093     PSBVector::iterator it;
02094     for (it = PSBList.begin(); it != PSBList.end(); it++)
02095     {
02096         if (it->Session_Object != session)
02097             continue;
02098 
02099         if (it->Sender_Template_Object != sender)
02100             continue;
02101 
02102         return &(*it);
02103     }
02104 
02105     return NULL;
02106 }
02107 
02108 RSVP::PathStateBlock_t* RSVP::findPsbById(int id)
02109 {
02110     for (unsigned int i = 0; i < PSBList.size(); i++)
02111     {
02112         if (PSBList[i].id != id)
02113             continue;
02114 
02115         return &PSBList[i];
02116     }
02117     ASSERT(false);
02118     return NULL; // prevent warning
02119 }
02120 
02121 
02122 RSVP::ResvStateBlock_t* RSVP::findRsbById(int id)
02123 {
02124     for (unsigned int i = 0; i < RSBList.size(); i++)
02125     {
02126         if (RSBList[i].id != id)
02127             continue;
02128 
02129         return &RSBList[i];
02130     }
02131     ASSERT(false);
02132     return NULL; // prevent warning
02133 }
02134 
02135 RSVP::HelloState_t* RSVP::findHello(IPAddress peer)
02136 {
02137     for (HelloVector::iterator it = HelloList.begin(); it != HelloList.end(); it++)
02138     {
02139         if (it->peer != peer)
02140             continue;
02141 
02142         return &(*it);
02143     }
02144     return NULL;
02145 }
02146 
02147 bool operator==(const SessionObj_t& a, const SessionObj_t& b)
02148 {
02149     return (a.DestAddress == b.DestAddress &&
02150         a.Tunnel_Id == b.Tunnel_Id &&
02151         a.Extended_Tunnel_Id == b.Extended_Tunnel_Id);
02152     // NOTE: don't compare holdingPri and setupPri; their placement
02153     // into Session_Object is only for our convenience
02154 }
02155 
02156 bool operator!=(const SessionObj_t& a, const SessionObj_t& b)
02157 {
02158     return !operator==(a, b);
02159 }
02160 
02161 bool operator==(const FilterSpecObj_t& a, const FilterSpecObj_t& b)
02162 {
02163     return a.SrcAddress==b.SrcAddress && a.Lsp_Id==b.Lsp_Id;
02164 }
02165 
02166 bool operator!=(const FilterSpecObj_t& a, const FilterSpecObj_t& b)
02167 {
02168     return !operator==(a, b);
02169 }
02170 
02171 bool operator==(const SenderTemplateObj_t& a, const SenderTemplateObj_t& b)
02172 {
02173     return a.SrcAddress == b.SrcAddress && a.Lsp_Id == b.Lsp_Id;
02174 }
02175 
02176 bool operator!=(const SenderTemplateObj_t& a, const SenderTemplateObj_t& b)
02177 {
02178     return !operator==(a, b);
02179 }
02180 
02181 std::ostream& operator<<(std::ostream& os, const FlowSpecObj_t& a)
02182 {
02183     os << "{bandwidth:" << a.req_bandwidth << "}";
02184     return os;
02185 }
02186 
02187 std::ostream& operator<<(std::ostream& os, const SessionObj_t& a)
02188 {
02189     os << "{tunnelId:" << a.Tunnel_Id << "  exTunnelId:" << a.Extended_Tunnel_Id <<
02190             "  destAddr:" << a.DestAddress << "}";
02191     return os;
02192 }
02193 
02194 std::ostream& operator<<(std::ostream& os, const SenderTemplateObj_t& a)
02195 {
02196     os << "{lspid:" << a.Lsp_Id << "  sender:" << a.SrcAddress << "}";
02197     return os;
02198 }
02199 
02200 void RSVP::print(RSVPPathMsg *p)
02201 {
02202     EV << "PATH_MESSAGE: lspid " << p->getLspId() << " ERO " << vectorToString(p->getERO()) << endl;
02203 }
02204 
02205 void RSVP::print(RSVPResvMsg *r)
02206 {
02207     EV << "RESV_MESSAGE: " << endl;
02208     for (unsigned int i = 0; i < r->getFlowDescriptor().size(); i++)
02209     {
02210         EV << " lspid " << r->getFlowDescriptor()[i].Filter_Spec_Object.Lsp_Id <<
02211             " label " << r->getFlowDescriptor()[i].label << endl;
02212     }
02213 }
02214