User Manual, Developers Guide and API Documentation

VirtualPathSelection.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  * WiFiMac                                                                    *
00003  * This file is part of openWNS (open Wireless Network Simulator)
00004  * _____________________________________________________________________________
00005  *
00006  * Copyright (C) 2004-2007
00007  * Chair of Communication Networks (ComNets)
00008  * Kopernikusstr. 16, D-52074 Aachen, Germany
00009  * phone: ++49-241-80-27910,
00010  * fax: ++49-241-80-22242
00011  * email: info@openwns.org
00012  * www: http://www.openwns.org
00013  * _____________________________________________________________________________
00014  *
00015  * openWNS is free software; you can redistribute it and/or modify it under the
00016  * terms of the GNU Lesser General Public License version 2 as published by the
00017  * Free Software Foundation;
00018  *
00019  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00020  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00021  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00022  * details.
00023  *
00024  * You should have received a copy of the GNU Lesser General Public License
00025  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00026  *
00027  ******************************************************************************/
00028 
00029 #include <WIFIMAC/pathselection/VirtualPathSelection.hpp>
00030 
00031 #include <DLL/RANG.hpp>
00032 
00033 #include <WNS/module/Base.hpp>
00034 #include <WNS/Exception.hpp>
00035 #include <WNS/pyconfig/Sequence.hpp>
00036 #include <WNS/Ttos.hpp>
00037 
00038 using namespace wifimac::pathselection;
00039 
00040 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00041     wifimac::pathselection::VirtualPathSelection,
00042     wns::node::component::Interface,
00043     "wifimac.pathselection.VirtualPathSelection",
00044     wns::node::component::ConfigCreator);
00045 
00046 
00047 VirtualPathSelectionService::VirtualPathSelectionService():
00048     logger("WIFIMAC", "VPS", wns::simulator::getMasterLogger()),
00049     vps(NULL)
00050 {
00051     MESSAGE_SINGLE(NORMAL, logger, "Starting VPS Service.");
00052 }
00053 
00054 void
00055 VirtualPathSelectionService::setVPS(VirtualPathSelection* _vps)
00056 {
00057     assure(vps == NULL, "setVPS already called, cannot call twice");
00058     vps = _vps;
00059 }
00060 
00061 VirtualPathSelection*
00062 VirtualPathSelectionService::getVPS()
00063 {
00064     assureNotNull(vps);
00065     return(vps);
00066 }
00067 
00068 VirtualPathSelection::VirtualPathSelection(wns::node::Interface* _node, const wns::pyconfig::View& _config) :
00069     wns::node::component::Component(_node, _config),
00070     logger(_config.get("logger")),
00071     numNodes(_config.get<int>("numNodes")),
00072     useStaticPS(_config.get<bool>("useStaticPS")),
00073     pathMatrixIsConsistent(true)
00074 {
00075     if (useStaticPS)
00076     {
00077         staticPSsnapshotTimeout = _config.get<wns::simulator::Time>("staticPSsnapshotTimeout");
00078     }
00079     TheVPSService::Instance().setVPS(this);
00080     MESSAGE_SINGLE(NORMAL, logger, "Starting VPS.");
00081 
00082     // Initialize path and cost matrices
00083     assure(numNodes > 0, "numNodes is below or equal to zero");
00084     const addressMatrix::SizeType sizesAM[2] = {numNodes, numNodes};
00085     paths = addressMatrix(sizesAM, 0);
00086 
00087     const metricMatrix::SizeType sizesMM[2] = {numNodes, numNodes};
00088     linkCosts = metricMatrix(sizesMM, Metric());
00089     pathCosts = metricMatrix(sizesMM, Metric());
00090 
00091     if(_config.knows("preKnowledge"))
00092     {
00093         preKnowledgeAlpha = _config.get<double>("preKnowledge.alpha");
00094         assure((preKnowledgeAlpha >= 0.0) and (preKnowledgeAlpha <= 1.0), "preKnowledgeAlpha must be between 0.0 and 1.0");
00095         MESSAGE_SINGLE(NORMAL, logger, "Existing preKnowledge with alpha " << preKnowledgeAlpha << ", " << _config.get<int>("preKnowledge.size()") << " entries:");
00096 
00097         preKnowledgeCosts = metricMatrix(sizesMM, Metric());
00098 
00099         for (int i=0; i < _config.get<int>("preKnowledge.size()"); ++i)
00100         {
00101             std::string s = "preKnowledge.get(" + wns::Ttos(i) + ")";
00102             wns::pyconfig::Sequence entry = _config.getSequence(s);
00103             assure(entry.size() == 3, "Entry has wrong size");
00104 
00105             wns::service::dll::UnicastAddress tx = entry.at<wns::service::dll::UnicastAddress>(0);
00106             int txId = mapper.map(tx);
00107             wns::service::dll::UnicastAddress rx = entry.at<wns::service::dll::UnicastAddress>(1);
00108             int rxId = mapper.map(rx);
00109             double cost = entry.at<double>(2);
00110 
00111             preKnowledgeCosts[txId][rxId] = Metric(cost);
00112             MESSAGE_SINGLE(NORMAL, logger, i << ":  Added preKnowledge " << tx << "->" << rx << " with cost " << preKnowledgeCosts[txId][rxId]);
00113         }
00114     }
00115 }
00116 
00117 
00118 void
00119 VirtualPathSelection::registerMP(const wns::service::dll::UnicastAddress mpAddress)
00120 {
00121     if(useStaticPS)
00122     {
00123         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00124         {
00125             return;
00126         }
00127     }
00128     assure(!isPortal(mpAddress), "Node with address " << mpAddress << " is already registered as portal and thus automatically as MP");
00129     assure(!isMeshPoint(mpAddress), "MP with address " << mpAddress << " already registered");
00130     assure(mapper.getMaxId() < numNodes, "numNodes (" << numNodes << ") is too small for another MP");
00131 
00132     int id = mapper.map(mpAddress);
00133     // store mp address
00134     mps.push_back(id);
00135 
00136     // set path to itself
00137     linkCosts[id][id] = 0;
00138 
00139     MESSAGE_SINGLE(NORMAL, logger, "Added MP " << mpAddress << " to list of MPs, now " << mps.size());
00140 }
00141 
00142 void
00143 VirtualPathSelection::registerPortal(const wns::service::dll::UnicastAddress portalAddress, dll::APUpperConvergence* apUC)
00144 {
00145     if(useStaticPS)
00146     {
00147         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00148         {
00149             return;
00150         }
00151     }
00152     assure(!isMeshPoint(portalAddress), "Node with address " << portalAddress << " is already registered as MP, cannot register also as portal");
00153     assure(!isPortal(portalAddress), "Portal with address " << portalAddress << " already registered");
00154     assure(mapper.getMaxId() < numNodes, "numNodes (" << numNodes << ") is too small for another Portal");
00155 
00156     int id = mapper.map(portalAddress);
00157 
00158     // first: every portal is also a mp
00159     mps.push_back(id);
00160 
00161     // set link costs from/to any other portal to zero
00162     for(adr2ucMap::const_iterator itr = portals.begin(); itr != portals.end(); ++itr)
00163     {
00164         linkCosts[itr->first][id] = 0;
00165         linkCosts[id][itr->first] = 0;
00166     }
00167 
00168     // set path to itself
00169     linkCosts[id][id] = 0;
00170 
00171     // store portal address
00172     portals[id] = apUC;
00173 
00174     MESSAGE_SINGLE(NORMAL, logger, "Added Portal " << portalAddress << " to list of Portals, now " << portals.size());
00175 }
00176 
00177 wns::service::dll::UnicastAddress
00178 VirtualPathSelection::getNextHop(const wns::service::dll::UnicastAddress current,
00179                                  const wns::service::dll::UnicastAddress finalDestination)
00180 {
00181     MESSAGE_SINGLE(VERBOSE, logger, "getNextHop query from " << current << " to " << finalDestination);
00182 
00183     if(!pathMatrixIsConsistent)
00184     {
00185         this->onNewPathSelectionEntry();
00186     }
00187 
00188     assure(current.isValid(), "current is not valid");
00189     assure(finalDestination.isValid(), "finalDestination is not valid");
00190     assure(isMeshPoint(current), "getNextHop: unknown MP " << current);
00191     assure(current != finalDestination, "Already reached finalDestination");
00192 
00193     wns::service::dll::UnicastAddress fD;
00194     if (isMeshPoint(finalDestination))
00195     {
00196         fD = finalDestination;
00197     }
00198     else
00199     {
00200         assure(isMeshPoint(getProxyFor(finalDestination)), finalDestination << " is neither known MP nor proxied by a known MP");
00201         fD = getProxyFor(finalDestination);
00202         MESSAGE_SINGLE(NORMAL, logger, "getNextHop: finalDestination " << finalDestination << " is proxied by " << fD);
00203     }
00204 
00205     if(pathCosts[mapper.get(current)][mapper.get(fD)].isInf())
00206     {
00207         MESSAGE_SINGLE(NORMAL, logger, "getNextHop query from " << current << " to " << fD << " is unknown");
00208         //this->printPathSelectionTable();
00209         return wns::service::dll::UnicastAddress();
00210     }
00211     else
00212     {
00213         MESSAGE_BEGIN(VERBOSE, logger, m, "getNextHop query from ");
00214         m << current << " to "<< fD;
00215         m << " --> " << mapper.get(paths[mapper.get(current)][mapper.get(fD)]) << " with total pathcost " << pathCosts[mapper.get(current)][mapper.get(fD)];
00216         MESSAGE_END();
00217 
00218         return(mapper.get(paths[mapper.get(current)][mapper.get(fD)]));
00219     }
00220 }
00221 
00222 bool
00223 VirtualPathSelection::isMeshPoint(const wns::service::dll::UnicastAddress address) const
00224 {
00225     assure(address.isValid(), "address is not valid");
00226 
00227     int id;
00228     if(!mapper.knows(address))
00229     {
00230         return false;
00231     }
00232     id = mapper.get(address);
00233 
00234     addressList::const_iterator itr;
00235     for (itr = mps.begin(); itr != mps.end(); ++itr)
00236     {
00237         if(*itr == id)
00238         {
00239             return true;
00240         }
00241     }
00242     return false;
00243 }
00244 
00245 bool
00246 VirtualPathSelection::isPortal(const wns::service::dll::UnicastAddress address) const
00247 {
00248     assure(address.isValid(), "address is not valid");
00249 
00250     int id;
00251     if(!mapper.knows(address))
00252     {
00253         return false;
00254     }
00255     id = mapper.get(address);
00256 
00257     adr2ucMap::const_iterator itr;
00258     for (itr = portals.begin(); itr != portals.end(); ++itr)
00259     {
00260         if(itr->first == id)
00261         {
00262             return true;
00263         }
00264     }
00265     return false;
00266 }
00267 
00268 wns::service::dll::UnicastAddress
00269 VirtualPathSelection::getPortalFor(const wns::service::dll::UnicastAddress clientAddress)
00270 {
00271     assure(clientAddress.isValid(), "clientAddress is not valid");
00272 
00273     MESSAGE_SINGLE(NORMAL, logger, "getPortalFor: " << clientAddress);
00274 
00275     if(!pathMatrixIsConsistent)
00276     {
00277         this->onNewPathSelectionEntry();
00278     }
00279 
00280 
00281     int id;
00282     if(!mapper.knows(clientAddress))
00283     {
00284         // unknown id
00285         return wns::service::dll::UnicastAddress();
00286     }
00287     id = mapper.get(clientAddress);
00288 
00289     addressMap::const_iterator itr = clients2portals.find(id);
00290     if(itr == clients2portals.end())
00291     {
00292         // not found in list
00293         return wns::service::dll::UnicastAddress();
00294     }
00295 
00296     assure(isMeshPoint(mapper.get(itr->second)), mapper.get(itr->second) << " is not a known MP");
00297     assure(isPortal(mapper.get(itr->second)), mapper.get(itr->second) << " is not a known Portal");
00298 
00299     MESSAGE_SINGLE(NORMAL, logger, "getPortalFor: portal for " << clientAddress << " is known to be " << mapper.get(itr->second));
00300 
00301     return(mapper.get(itr->second));
00302 }
00303 
00304 wns::service::dll::UnicastAddress
00305 VirtualPathSelection::getProxyFor(const wns::service::dll::UnicastAddress clientAddress)
00306 {
00307     assure(clientAddress.isValid(), "clientAddress is not valid");
00308     MESSAGE_SINGLE(NORMAL, logger, "getProxyFor: proxy for " << clientAddress);
00309 
00310     if(!pathMatrixIsConsistent)
00311     {
00312         this->onNewPathSelectionEntry();
00313     }
00314 
00315     int id;
00316     if(!mapper.knows(clientAddress))
00317     {
00318         // unknown id
00319         return wns::service::dll::UnicastAddress();
00320     }
00321     id = mapper.get(clientAddress);
00322 
00323     addressMap::const_iterator itr = clients2proxies.find(id);
00324     if(itr == clients2proxies.end())
00325     {
00326         // not found in list
00327         return wns::service::dll::UnicastAddress();
00328     }
00329 
00330     assure(isMeshPoint(mapper.get(itr->second)), mapper.get(itr->second) << " is not a known MP");
00331 
00332     MESSAGE_SINGLE(NORMAL, logger, "getProxyFor: proxy for " << clientAddress << " is known to be " << mapper.get(itr->second));
00333 
00334     return(mapper.get(itr->second));
00335 }
00336 
00337 
00338 void
00339 VirtualPathSelection::registerProxy(const wns::service::dll::UnicastAddress proxy,
00340                                     const wns::service::dll::UnicastAddress client)
00341 {
00342     if(useStaticPS)
00343     {
00344         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00345         {
00346             return;
00347         }
00348     }
00349 
00350     
00351     if(!pathMatrixIsConsistent)
00352     {
00353         this->onNewPathSelectionEntry();
00354     }
00355 
00356     assure(client.isValid(), "client address is invalid");
00357     assure(proxy.isValid(), "proxy address is invalid");
00358     assure(mapper.knows(proxy), "proxy with address " << proxy << " is not known");
00359     assure(getProxyFor(client) == wns::service::dll::UnicastAddress(),
00360            "client " << client << " is already proxied by " << getProxyFor(client) << ", second proxy by " << proxy << " is not allowed");
00361 
00362     int clientId = mapper.map(client);
00363     int proxyId = mapper.get(proxy);
00364 
00365     clients2proxies[clientId] = proxyId;
00366     MESSAGE_SINGLE(NORMAL, logger, "registered " << proxy << " as proxy for " << client);
00367 
00368     if(isPortal(proxy))
00369     {
00370         // The best portal is always the proxy itself
00371         // tell it to the RANG
00372         portals.find(proxyId)->second->getRANG()->updateAPLookUp(client, portals.find(proxyId)->second);
00373         clients2portals[clientId] = proxyId;
00374         MESSAGE_SINGLE(NORMAL, logger, "set portal for " << client << " to " << proxy);
00375         return;
00376     }
00377 
00378     // search the best portal for the new client
00379     // Attention: As the cost for portal->portal is zero, all portals have the same (minimum) cost
00380     // Hence, we search for the first portal from which the first hop to the proxy is not another portal
00381     for(adr2ucMap::iterator itr = portals.begin(); itr != portals.end(); ++itr)
00382     {
00383         if(getNextHop(mapper.get(itr->first), proxy).isValid() and !isPortal(getNextHop(mapper.get(itr->first), proxy)))
00384         {
00385             assure(pathCosts[proxyId][itr->first].isNotInf(), "Path cost from proxy to portal is inf -> network is not connected");
00386             assure(pathCosts[itr->first][proxyId].isNotInf(), "Path cost from portal to proxy is inf -> network is not connected");
00387 
00388             // tell it to the RANG
00389             portals.find(itr->first)->second->getRANG()->updateAPLookUp(client, portals.find(itr->first)->second);
00390             clients2portals[clientId] = itr->first;
00391             MESSAGE_SINGLE(NORMAL, logger, "set portal for " << client << " to " << mapper.get(itr->first));
00392             return;
00393         }
00394     }
00395     MESSAGE_SINGLE(NORMAL, logger, "no portal for client " << client << " available at this moment");
00396 }
00397 
00398 void
00399 VirtualPathSelection::deRegisterProxy(const wns::service::dll::UnicastAddress
00400 #if !defined(WNS_NO_LOGGING) || !defined(NDEBUG)
00401                                       proxy
00402 #endif
00403                                       , const wns::service::dll::UnicastAddress client)
00404 {
00405     if(useStaticPS)
00406     {
00407         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00408         {
00409             return;
00410         }
00411     }
00412 
00413     assure(mapper.knows(client), "client address is not known");
00414     assure(mapper.knows(proxy), "proxy address is not known");
00415     assure(getProxyFor(client) == proxy, "MP " << proxy << " is not a proxy for " << client << " --> cannot deRegisterProxy");
00416 
00417     addressMap::iterator itr = clients2proxies.find(mapper.get(client));
00418     if(itr == clients2proxies.end())
00419     {
00420         // not found in list
00421         assure(false, "trying to deRegister " << client << " but it has no proxy");
00422     }
00423 
00424     clients2proxies.erase(itr);
00425     MESSAGE_SINGLE(NORMAL, logger, "DEregistered " << proxy << " as proxy for " << client);
00426 
00427 }
00428 
00429 void
00430 VirtualPathSelection::createPeerLink(const wns::service::dll::UnicastAddress myself,
00431                                      const wns::service::dll::UnicastAddress peer,
00432                                      const Metric linkMetric)
00433 {
00434     if(useStaticPS)
00435     {
00436         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00437         {
00438             return;
00439         }
00440     }
00441     assure(mapper.knows(myself), "myself (" << myself << ") is not a known address");
00442     assure(mapper.knows(peer), "peer (" << peer << ") is not a known address");
00443     assure(isMeshPoint(myself) , "myself (" << myself << ") is not a known MP");
00444     assure(isMeshPoint(peer), "peer (" << peer << ") is not a known MP");
00445     assure(linkMetric.isNotInf(), "createPeerLink with metric == inf");
00446 
00447     if(isPortal(myself) && isPortal(peer))
00448     {
00449         MESSAGE_SINGLE(NORMAL, logger, "createPeerLink: Ignore wireless link between " << myself << " and " << peer << ", both are portals");
00450     }
00451     else
00452     {
00453         int myselfId = mapper.get(myself);
00454         int peerId = mapper.get(peer);
00455 
00456         assure(linkCosts[myselfId][peerId].isInf(), "createPeerLink with already known linkCosts");
00457 
00458         Metric newLinkMetric = linkMetric;
00459         if(preKnowledgeCosts[myselfId][peerId].isNotInf())
00460         {
00461             newLinkMetric = newLinkMetric * (1.0-preKnowledgeAlpha) + preKnowledgeCosts[myselfId][peerId] * preKnowledgeAlpha;
00462             MESSAGE_SINGLE(NORMAL, logger, "createPeerLink: " << myself << "->" << peer << " has preKnowledge of " << preKnowledgeCosts[myselfId][peerId] << ", " << linkMetric << "->" << newLinkMetric);
00463         }
00464 
00465         linkCosts[myselfId][peerId] = newLinkMetric;
00466 
00467 
00468         MESSAGE_SINGLE(NORMAL, logger, "createPeerLink: " << myself << " --> " << peer << " costs " << linkCosts[myselfId][peerId]);
00469         pathMatrixIsConsistent = false;
00470         onNewPathSelectionEntry();
00471     }
00472 }
00473 
00474 
00475 void
00476 VirtualPathSelection::updatePeerLink(const wns::service::dll::UnicastAddress myself,
00477                                      const wns::service::dll::UnicastAddress peer,
00478                                      const Metric linkMetric)
00479 {
00480     if(useStaticPS)
00481     {
00482         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00483         {
00484             return;
00485         }
00486     }
00487     assure(mapper.knows(myself), "myself (" << myself << ") is not a known address");
00488     assure(mapper.knows(peer), "peer (" << peer << ") is not a known address");
00489     assure(isMeshPoint(myself) , "myself (" << myself << ") is not a known MP");
00490     assure(isMeshPoint(peer), "peer (" << peer << ") is not a known MP");
00491     int myselfId = mapper.get(myself);
00492     int peerId = mapper.get(peer);
00493 
00494     if(linkCosts[myselfId][peerId].isInf())
00495     {
00496         throw wns::Exception("cannot update a link which has costs inf --> must be created first!");
00497     }
00498 
00499     if(isPortal(myself) && isPortal(peer))
00500     {
00501         // ignore wired link
00502         return;
00503     }
00504 
00505     Metric newLinkMetric = linkMetric;
00506     if(preKnowledgeCosts[myselfId][peerId].isNotInf())
00507     {
00508     newLinkMetric = linkMetric * (1.0-preKnowledgeAlpha) + preKnowledgeCosts[myselfId][peerId] * preKnowledgeAlpha;
00509         MESSAGE_SINGLE(NORMAL, logger, "updatePeerLink: " << myself << "->" << peer << " has preKnowledge of " << preKnowledgeCosts[myselfId][peerId] << ", " << linkMetric << "->" << newLinkMetric);
00510     }
00511 
00512     if(linkCosts[myselfId][peerId] == newLinkMetric)
00513     {
00514         // same values, no update required
00515         return;
00516     }
00517 
00518     MESSAGE_BEGIN(NORMAL, logger, m, "updatePeerLink: ");
00519     m << myself << " --> " << peer;
00520     m << " from costs " << linkCosts[myselfId][peerId];
00521     m << " to " << newLinkMetric;
00522     MESSAGE_END();
00523 
00524     linkCosts[myselfId][peerId] = newLinkMetric;
00525 
00526     pathMatrixIsConsistent = false;
00527     onNewPathSelectionEntry();
00528 }
00529 
00530 void
00531 VirtualPathSelection::closePeerLink(const wns::service::dll::UnicastAddress myself,
00532                                     const wns::service::dll::UnicastAddress peer)
00533 {
00534     if(useStaticPS)
00535     {
00536         if (wns::simulator::getEventScheduler()->getTime() > staticPSsnapshotTimeout)
00537         {
00538             return;
00539         }
00540     }
00541     assure(mapper.knows(myself), "myself (" << myself << ") is not a known address");
00542     assure(mapper.knows(peer), "peer (" << peer << ") is not a known address");
00543     assure(isMeshPoint(myself) , "myself (" << myself << ") is not a known MP");
00544     assure(isMeshPoint(peer), "peer (" << peer << ") is not a known MP");
00545 
00546     int myselfId = mapper.get(myself);
00547     int peerId = mapper.get(peer);
00548 
00549     if(linkCosts[myselfId][peerId].isInf())
00550     {
00551         throw wns::Exception("cannot close a link which has costs inf --> must be created first!");
00552     }
00553 
00554     if(isPortal(myself) && isPortal(peer))
00555     {
00556         // link between two portals cannot be closed
00557         return;
00558     }
00559 
00560     linkCosts[myselfId][peerId] = Metric();
00561 
00562     pathMatrixIsConsistent = false;
00563     onNewPathSelectionEntry();
00564 }
00565 
00566 void
00567 VirtualPathSelection::onNewPathSelectionEntry()
00568 {
00569     const addressMatrix::SizeType sizesMM[2] = {numNodes, numNodes};
00570     addressMatrix pred = addressMatrix(sizesMM, 0);
00571 
00572     // initialize predecessor and pathCost matrix:
00573     //   * predecessor: If direct link exists, predecessor is source itself
00574     //   * pathCost: Same as linkCost if the link is bidirectional, inf
00575     //     otherwise
00576     pathCosts = linkCosts;
00577     for (addressList::const_iterator i = mps.begin(); i != mps.end(); ++i)
00578     {
00579         MESSAGE_BEGIN(VERBOSE, logger, m, "lc " << *i << ":");
00580         for (addressList::const_iterator j = mps.begin(); j != mps.end(); ++j)
00581         {
00582             m << " " << *j << ":" << linkCosts[*i][*j];
00583         }
00584         MESSAGE_END();
00585     }
00586 
00587     for (addressList::const_iterator i = mps.begin(); i != mps.end(); ++i)
00588     {
00589         for (addressList::const_iterator j = mps.begin(); j != mps.end(); ++j)
00590         {
00591             if((*i != *j) and (linkCosts[*i][*j].isNotInf()))
00592             {
00593                 pred[*i][*j] = *i;
00594             }
00595             if((*i != *j) and (linkCosts[*i][*j].isNotInf()) and (linkCosts[*j][*i].isInf()))
00596             {
00597                 pathCosts[*i][*j] = Metric();
00598             }
00599         }
00600     }
00601 
00602     // Floyd-Warshall Algorithm to compute all-pairs shortest-path inclusive
00603     // predecessor matrix in O(nodes^3)
00604     for (addressList::const_iterator k = mps.begin(); k != mps.end(); ++k)
00605     {
00606         for (addressList::const_iterator i = mps.begin(); i != mps.end(); ++i)
00607         {
00608             for (addressList::const_iterator j = mps.begin(); j != mps.end(); ++j)
00609             {
00610                 if(pathCosts[*i][*k].isNotInf() and pathCosts[*k][*j].isNotInf())
00611                 {
00612                     if(pathCosts[*i][*k] + pathCosts[*k][*j] < pathCosts[*i][*j])
00613                     {
00614                         pathCosts[*i][*j] = pathCosts[*i][*k] + pathCosts[*k][*j];
00615                         assure(pathCosts[*i][*j] >= 0, "found negative cycle in graph");
00616 
00617                         pred[*i][*j] = pred[*k][*j];
00618                     }
00619                 }
00620             }
00621         }
00622     }
00623 
00624     // convert the predecessor matrix into successor matrix paths
00625     for (addressList::const_iterator i = mps.begin(); i != mps.end(); ++i)
00626     {
00627         for (addressList::const_iterator j = mps.begin(); j != mps.end(); ++j)
00628         {
00629             if((*i != *j) && (pathCosts[*i][*j].isNotInf()))
00630             {
00631                 int firstHopOut = *j;
00632 
00633                 while(pred[*i][firstHopOut] != *i)
00634                 {
00635                     firstHopOut = pred[*i][firstHopOut];
00636                 }
00637                 paths[*i][*j] = firstHopOut;
00638             }
00639         }
00640     }
00641 
00642     pathMatrixIsConsistent = true;
00643 
00644     // update portal settings for the clients
00645     // iterate over all clients
00646     for (addressMap::const_iterator clientsItr = clients2proxies.begin(); clientsItr != clients2proxies.end(); ++clientsItr)
00647     {
00648         // if the proxy is the portal, it remains the portal
00649         if(isPortal(mapper.get(clientsItr->second)))
00650         {
00651             assure(clients2portals[clientsItr->first] == clientsItr->second,
00652                    "Client " << mapper.get(clientsItr->first) <<
00653                    " has proxy " << mapper.get(clientsItr->second) <<
00654                    ", which is a portal but the client is assigned to the portal " << mapper.get(clients2portals[clientsItr->first]));
00655 
00656             MESSAGE_SINGLE(NORMAL, logger, "portal for " << mapper.get(clientsItr->first) << " remains " << mapper.get(clientsItr->second) << " beause it is also its proxy");
00657             continue;
00658         }
00659 
00660         // search the best (= lowest DL path cost) portal for the new client (clientsItr->first)
00661         // Attention: As the cost for portal->portal is zero, all portals have the same (minimum) cost
00662         // Hence, we search for the one portal from which the first hop to the proxy is not another portal
00663         for(adr2ucMap::iterator portalsItr = portals.begin(); portalsItr != portals.end(); ++portalsItr)
00664         {
00665             if(getNextHop(mapper.get(portalsItr->first), mapper.get(clientsItr->second)).isValid() and !isPortal(getNextHop(mapper.get(portalsItr->first), mapper.get(clientsItr->second))))
00666             {
00667                 assure(pathCosts[clientsItr->second][portalsItr->first].isNotInf(),
00668                        "Path cost from proxy to portal is inf -> network is not connected");
00669                 assure(pathCosts[portalsItr->first][clientsItr->second].isNotInf(),
00670                        "Path cost from portal to proxy is inf -> network is not connected");
00671 
00672                 if(portalsItr->first != clients2portals.find(clientsItr->first)->second)
00673                 {
00674                     portalsItr->second->getRANG()->updateAPLookUp(mapper.get(clientsItr->first), portalsItr->second);
00675                     clients2portals[clientsItr->first] = portalsItr->first;
00676                     MESSAGE_SINGLE(NORMAL, logger, "change portal for " << mapper.get(clientsItr->first) << " to " << mapper.get(portalsItr->first));
00677                 }
00678                 break;
00679             }
00680         }
00681     }
00682 
00683 #ifndef WNS_NO_LOGGING
00684     printPathSelectionTable();
00685 #endif
00686 }
00687 
00688 void
00689 VirtualPathSelection::printPathSelectionTable() const
00690 {
00691     assure(pathMatrixIsConsistent, "Called printPathSelectionTable for inconsistent pathMatrix");
00692 
00693     MESSAGE_SINGLE(VERBOSE, logger, "PathSelectionTable:");
00694     for(addressList::const_iterator itr = mps.begin(); itr != mps.end(); ++itr)
00695     {
00696         if(isPortal(mapper.get(*itr)))
00697         {
00698             MESSAGE_SINGLE(VERBOSE, logger, "AP" << mapper.get(*itr) );
00699             printPortalInformation(mapper.get(*itr));
00700         }
00701         else
00702         {
00703             MESSAGE_SINGLE(VERBOSE, logger, "MP" << mapper.get(*itr) );
00704         }
00705         printProxyInformation(mapper.get(*itr));
00706         printPathSelectionLine(mapper.get(*itr));
00707     }
00708 }
00709 
00710 void VirtualPathSelection::printPathSelectionLine(const wns::service::dll::UnicastAddress source) const
00711 {
00712     MESSAGE_BEGIN(VERBOSE, logger, m, "routing: ");
00713     for(addressList::const_iterator itr = mps.begin(); itr != mps.end(); ++itr)
00714     {
00715         if(pathCosts[mapper.get(source)][*itr].isInf())
00716         {
00717             m << mapper.get(*itr) << " (Inf/-1)\t";
00718         }
00719         else
00720         {
00721             if(*itr == mapper.get(source))
00722             {
00723                 m << mapper.get(*itr) << " (0/-1)\t";
00724             }
00725             else
00726             {
00727                 m << mapper.get(*itr) << " (" << pathCosts[mapper.get(source)][*itr].toDouble() << "/" << mapper.get(paths[mapper.get(source)][*itr]) << ")\t";
00728             }
00729         }
00730     }
00731     MESSAGE_END();
00732 }
00733 
00734 void VirtualPathSelection::printProxyInformation(const wns::service::dll::UnicastAddress proxy) const
00735 {
00736     MESSAGE_BEGIN(VERBOSE, logger, m, "proxied clients: ");
00737     for(addressMap::const_iterator itr = clients2proxies.begin(); itr != clients2proxies.end(); ++itr)
00738     {
00739         if(itr->second == mapper.get(proxy))
00740         {
00741             m << mapper.get(itr->first) << " ";
00742         }
00743     }
00744     MESSAGE_END();
00745 }
00746 
00747 void VirtualPathSelection::printPortalInformation(const wns::service::dll::UnicastAddress portal) const
00748 {
00749     MESSAGE_BEGIN(VERBOSE, logger, m, "portal for: ");
00750     for(addressMap::const_iterator itr = clients2portals.begin(); itr != clients2portals.end(); ++itr)
00751     {
00752         if(itr->second == mapper.get(portal))
00753         {
00754             m << mapper.get(itr->first) << " ";
00755         }
00756     }
00757     MESSAGE_END();
00758 }
00759 
00760 VirtualPathSelection::AddressStorage::AddressStorage() :
00761     nextId(1),
00762     adr2id(),
00763     id2adr()
00764 {
00765 
00766 }
00767 
00768 int
00769 VirtualPathSelection::AddressStorage::map(const wns::service::dll::UnicastAddress adr)
00770 {
00771     if(!adr2id.knows(adr))
00772     {
00773         assure(! id2adr.knows(nextId), "NextId already used?");
00774         adr2id.insert(adr, nextId);
00775         id2adr.insert(nextId, adr);
00776         ++nextId;
00777         return(nextId-1);
00778     }
00779 
00780     return(adr2id.find(adr));
00781 }
00782 
00783 int
00784 VirtualPathSelection::AddressStorage::get(const wns::service::dll::UnicastAddress adr) const
00785 {
00786     return(adr2id.find(adr));
00787 }
00788 
00789 wns::service::dll::UnicastAddress
00790 VirtualPathSelection::AddressStorage::get(const int id) const
00791 {
00792     return(id2adr.find(id));
00793 }
00794 
00795 bool
00796 VirtualPathSelection::AddressStorage::knows(const wns::service::dll::UnicastAddress adr) const
00797 {
00798     return(adr2id.knows(adr));
00799 }
00800 
00801 bool
00802 VirtualPathSelection::AddressStorage::knows(const int id) const
00803 {
00804        return(id2adr.knows(id));
00805 }
00806 
00807 int
00808 VirtualPathSelection::AddressStorage::getMaxId() const
00809 {
00810     return(nextId-1);
00811 }

Generated on Sat May 26 03:32:10 2012 for openWNS by  doxygen 1.5.5