![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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 }
1.5.5