![]() |
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/BeaconLinkQualityMeasurement.hpp> 00030 #include <WIFIMAC/convergence/PhyUser.hpp> 00031 #include <WIFIMAC/FrameType.hpp> 00032 00033 #include <DLL/Layer2.hpp> 00034 #include <WNS/service/dll/StationTypes.hpp> 00035 #include <WNS/probe/bus/utils.hpp> 00036 00037 #include <math.h> 00038 00039 using namespace wifimac::pathselection; 00040 00041 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00042 wifimac::pathselection::BeaconLinkQualityMeasurement, 00043 wns::ldk::FunctionalUnit, 00044 "wifimac.pathselection.BeaconLinkQualityMeasurement", 00045 wns::ldk::FUNConfigCreator); 00046 00047 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00048 wifimac::pathselection::BeaconLinkQualityMeasurement, 00049 wns::ldk::probe::Probe, 00050 "wifimac.pathselection.BeaconLinkQualityMeasurement", 00051 wns::ldk::FUNConfigCreator); 00052 00053 BroadcastLinkQuality::BroadcastLinkQuality(const wns::pyconfig::View& config_, 00054 BeaconLinkQualityMeasurement* parent_, 00055 wns::service::dll::UnicastAddress peerAddress_, 00056 wns::service::dll::UnicastAddress myAddress_, 00057 wns::simulator::Time interval_): 00058 config(config_), 00059 parent(parent_), 00060 peerAddress(peerAddress_), 00061 myAddress(myAddress_), 00062 successRate(interval_*config.get<int>("myConfig.windowLength"), true), 00063 missedBeaconsInRow(10), 00064 linkCreated(false), 00065 meanFrameSize(config.get<Bit>("myConfig.meanFrameSize")), 00066 maximumACKDuration(config.get<wns::simulator::Time>("myConfig.maximumACKDuration")), 00067 slotDuration(config.get<wns::simulator::Time>("myConfig.slotDuration")), 00068 sifsDuration(config.get<wns::simulator::Time>("myConfig.sifsDuration")), 00069 preambleDuration(config.get<wns::simulator::Time>("myConfig.preambleDuration")), 00070 scalingFactor(config.get<double>("myConfig.scalingFactor")), 00071 maxMissedBeacons(config.get<int>("myConfig.maxMissedBeacons")) 00072 { 00073 ps = parent->getFUN()->getLayer<dll::Layer2*>()->getManagementService<wifimac::pathselection::IPathSelection> 00074 (config.get<std::string>("pathSelectionServiceName")); 00075 sinrMIB = parent->getFUN()->getLayer<dll::Layer2*>()->getManagementService<wifimac::management::SINRInformationBase> 00076 (config.get<std::string>("sinrMIBServiceName")); 00077 MESSAGE_SINGLE(VERBOSE, parent->logger, "BroadcastLinkQuality for "<< peerAddress << " created."); 00078 } 00079 00080 double 00081 BroadcastLinkQuality::getSuccessRate() 00082 { 00083 MESSAGE_SINGLE(NORMAL, parent->logger, "BroadcastLinkQuality for " << peerAddress << ": getSuccessRate with "<< successRate.getNumSamples() << " numSamples."); 00084 00085 if((successRate.getNumSamples() > 0) && (this->isActive())) 00086 { 00087 return(successRate.getAbsolute() / successRate.getNumSamples()); 00088 } 00089 else 00090 { 00091 return(0.0); 00092 } 00093 } 00094 00095 wns::Ratio 00096 BroadcastLinkQuality::getAverageSINR() 00097 { 00098 if(sinrMIB->knowsMeasuredSINR(peerAddress)) 00099 { 00100 return(sinrMIB->getMeasuredSINR(peerAddress)); 00101 } 00102 else 00103 { 00104 return(wns::Ratio::from_dB(0.0)); 00105 } 00106 } 00107 00108 void 00109 BroadcastLinkQuality::newBeacon(wns::simulator::Time interval) 00110 { 00111 // we give 1.5 x interval for the upcomming beacon 00112 this->curInterval = interval; 00113 setNewTimeout(curInterval*1.5); 00114 00115 successRate.put(1.0); 00116 00117 this->missedBeaconsInRow = 0; 00118 } 00119 00120 Metric 00121 BroadcastLinkQuality::newPeerMeasurement(double peerSuccessRate, wns::Ratio peerSINR) 00122 { 00123 sinrMIB->putPeerSINR(peerAddress, peerSINR); 00124 00125 // compute and send new metric for link me->peer to ps 00126 00127 // Convert optSINR to frametime + PLCP preamble + ACK + SIFS 00128 // TODO: This should be a function provided by the protocol calculator 00129 double frameTxTime = (this->meanFrameSize)/this->getBestRate(peerSINR) + this->preambleDuration + this->sifsDuration + this->maximumACKDuration; 00130 00131 // Convert rate to expected transmission time 00132 double ett = (1.0/peerSuccessRate) * frameTxTime + (pow(2,3+1.0/peerSuccessRate) - 1)/2*this->slotDuration; 00133 00134 // scale metric with usual BPSK1/2 transmission time 00135 Metric m = ett/this->scalingFactor; 00136 00137 MESSAGE_SINGLE(NORMAL, parent->logger, "BroadcastLinkQuality for " << peerAddress << ": new PeerMeasurement with " << peerSuccessRate << "/" << peerSINR << " --> " << m); 00138 00139 if(linkCreated) 00140 { 00141 ps->updatePeerLink(myAddress, peerAddress, m); 00142 } 00143 else 00144 { 00145 ps->createPeerLink(myAddress, peerAddress, m); 00146 linkCreated = true; 00147 } 00148 00149 if (ps->getProxyFor(parent->getFUN()->getLayer<dll::Layer2*>()->getDLLAddress()) == wns::service::dll::UnicastAddress()) 00150 { 00151 00152 MESSAGE_SINGLE(NORMAL, parent->logger,"Registering mesh point as proxy for itself at VPS"); 00153 ps->registerProxy(parent->getFUN()->getLayer<dll::Layer2*>()->getDLLAddress(),parent->getFUN()->getLayer<dll::Layer2*>()->getDLLAddress()); 00154 } 00155 return(m); 00156 } 00157 00158 double 00159 BroadcastLinkQuality::getBestRate(wns::Ratio sinr) 00160 { 00161 if(sinr >= wns::Ratio::from_dB(24.8)) 00162 { 00163 return (54e6); 00164 } 00165 if(sinr >= wns::Ratio::from_dB(23.5)) 00166 { 00167 return(48e6); 00168 } 00169 if(sinr >= wns::Ratio::from_dB(18.8)) 00170 { 00171 return(36e6); 00172 } 00173 if(sinr >= wns::Ratio::from_dB(15.4)) 00174 { 00175 return(24e6); 00176 } 00177 if(sinr >= wns::Ratio::from_dB(12.0)) 00178 { 00179 return(18e6); 00180 } 00181 if(sinr >= wns::Ratio::from_dB(8.8)) 00182 { 00183 return(12e6); 00184 } 00185 if(sinr >= wns::Ratio::from_dB(6.0)) 00186 { 00187 return(6e6); 00188 } 00189 00190 return(1); 00191 } 00192 00193 00194 void 00195 BroadcastLinkQuality::deadPeerMeasurement() 00196 { 00197 // my beacon was not received by peer for several times or I did not receive 00198 // a beacon for several times -> either way, the link seems to be closed 00199 MESSAGE_SINGLE(NORMAL, parent->logger, "BroadcastLinkQuality for " << peerAddress << ": dead PeerMeasurement"); 00200 ++missedBeaconsInRow; 00201 00202 if(linkCreated && (!this->isActive())) 00203 { 00204 ps->closePeerLink(myAddress, peerAddress); 00205 linkCreated = false; 00206 } 00207 } 00208 00209 void 00210 BroadcastLinkQuality::onTimeout() 00211 { 00212 this->deadPeerMeasurement(); 00213 00214 if(this->isActive()) 00215 { 00216 // failed beacon reception -> unstable link! 00217 setTimeout(curInterval); 00218 00219 successRate.put(0.0); 00220 // the averagePower only counts for successfull receptions 00221 00222 ++missedBeaconsInRow; 00223 } 00224 00225 MESSAGE_SINGLE(NORMAL, parent->logger, "BroadcastLinkQuality for " << peerAddress << ": timeout for new beacon, now " << missedBeaconsInRow << " missed"); 00226 } 00227 00228 bool 00229 BroadcastLinkQuality::isActive() const 00230 { 00231 return(missedBeaconsInRow <= this->maxMissedBeacons); 00232 } 00233 00234 BeaconLinkQualityMeasurement::BeaconLinkQualityMeasurement(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& _config): 00235 wns::ldk::fu::Plain<BeaconLinkQualityMeasurement, BeaconLinkQualityMeasurementCommand>(fun), 00236 logger(_config.get("logger")), 00237 config(_config), 00238 beaconInterval(config.get<wns::simulator::Time>("beaconInterval")), 00239 phyUserCommandName(config.get<std::string>("phyUserCommandName")) 00240 { 00241 friends.manager = NULL; 00242 00243 // read the local IDs from the config 00244 wns::probe::bus::ContextProviderCollection registry(&fun->getLayer()->getContextProviderCollection()); 00245 for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii) 00246 { 00247 std::string key = config.get<std::string>("localIDs.keys()",ii); 00248 unsigned long int value = config.get<unsigned long int>("localIDs.values()",ii); 00249 registry.addProvider(wns::probe::bus::contextprovider::Constant(key, value)); 00250 MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value); 00251 } 00252 00253 receivedPower = wns::probe::bus::collector(registry, config, "receivedPowerProbeName"); 00254 peerMeasurement = wns::probe::bus::collector(registry, config, "peerMeasurementProbeName"); 00255 linkCost = wns::probe::bus::collector(registry, config, "linkCostProbeName"); 00256 } 00257 00258 BeaconLinkQualityMeasurement::~BeaconLinkQualityMeasurement() 00259 { 00260 linkQualities.clear(); 00261 } 00262 00263 void 00264 BeaconLinkQualityMeasurement::onFUNCreated() 00265 { 00266 friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(config.get<std::string>("managerName")); 00267 assure(friends.manager, "Management entity not found"); 00268 00269 if(friends.manager->getStationType() != wns::service::dll::StationTypes::UT()) 00270 { 00271 ps = getFUN()->getLayer<dll::Layer2*>()->getManagementService<wifimac::pathselection::IPathSelection> 00272 (config.get<std::string>("pathSelectionServiceName")); 00273 assure(ps, "Could not get PathSelection Management Service"); 00274 } 00275 00276 myMACAddress = friends.manager->getMACAddress(); 00277 } 00278 00279 bool 00280 BeaconLinkQualityMeasurement::doIsAccepting(const wns::ldk::CompoundPtr& _compound) const 00281 { 00282 return getConnector()->hasAcceptor(_compound); 00283 } //doIsAccepting 00284 00285 void 00286 BeaconLinkQualityMeasurement::doSendData(const wns::ldk::CompoundPtr& compound) 00287 { 00288 assure(compound, "doSendData called with an invalid compound."); 00289 assure(friends.manager->getStationType() != wns::service::dll::StationTypes::UT(), "Only non-UT are allowed to send beacons"); 00290 assure(friends.manager->getFrameType(compound->getCommandPool()) == BEACON, 00291 "Frame type is no beacon, but " << friends.manager->getFrameType(compound->getCommandPool())); 00292 00293 BeaconLinkQualityMeasurementCommand* blqm = activateCommand(compound->getCommandPool()); 00294 blqm->peer.interval = beaconInterval; 00295 blqm->peer.rxBeaconSuccessRates = Address2SuccessRateMap(); 00296 blqm->peer.rxBeaconSINRs = Address2RatioMap(); 00297 00298 // add the results for each linkQuality to the compound 00299 for(adr2qualityMap::const_iterator itr = linkQualities.begin(); itr != linkQualities.end(); ++itr) 00300 { 00301 if(itr->second->isActive()) 00302 { 00303 blqm->peer.rxBeaconSuccessRates.insert(itr->first, itr->second->getSuccessRate()); 00304 blqm->peer.rxBeaconSINRs.insert(itr->first, itr->second->getAverageSINR()); 00305 MESSAGE_BEGIN(NORMAL, this->logger, m, ""); 00306 m << "Added linkQualityInformation for " << itr->first; 00307 m << " with rate " << itr->second->getSuccessRate(); 00308 m << " and sinr " << itr->second->getAverageSINR(); 00309 MESSAGE_END(); 00310 } 00311 else 00312 { 00313 MESSAGE_SINGLE(NORMAL, this->logger, "No lq for " << itr->first << ", because link is currently not active"); 00314 } 00315 } 00316 00317 getConnector()->getAcceptor(compound)->sendData(compound); 00318 } // doSendData 00319 00320 void 00321 BeaconLinkQualityMeasurement::doWakeup() 00322 { 00323 // simply forward the wakeup call 00324 getReceptor()->wakeup(); 00325 } // doWakeup 00326 00327 void 00328 BeaconLinkQualityMeasurement::doOnData(const wns::ldk::CompoundPtr& compound) 00329 { 00330 assure(compound, "doOnData called with an invalid compound."); 00331 00332 if(friends.manager->getStationType() == wns::service::dll::StationTypes::UT()) 00333 { 00334 // UT->nothing to do 00335 getDeliverer()->getAcceptor(compound)->onData(compound); 00336 return; 00337 } 00338 00339 if(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this)) 00340 { 00341 // this link-measurement frame is consumed here 00342 BeaconLinkQualityMeasurementCommand* blqm = getCommand(compound->getCommandPool()); 00343 wifimac::convergence::PhyUserCommand* puc = 00344 getFUN()->getCommandReader(phyUserCommandName)->readCommand<wifimac::convergence::PhyUserCommand>(compound->getCommandPool()); 00345 00346 if(!linkQualities.knows(friends.manager->getTransmitterAddress(compound->getCommandPool()))) 00347 { 00348 // received a beacon from a peer which was never seen before 00349 // create entry in map 00350 MESSAGE_BEGIN(NORMAL, this->logger, m, "Received first beacon from "); 00351 m << friends.manager->getTransmitterAddress(compound->getCommandPool()); 00352 m << ", creating lq with interval " << blqm->peer.interval; 00353 MESSAGE_END(); 00354 linkQualities.insert(friends.manager->getTransmitterAddress(compound->getCommandPool()), 00355 new BroadcastLinkQuality(config, this, 00356 friends.manager->getTransmitterAddress(compound->getCommandPool()), 00357 friends.manager->getMACAddress(), 00358 blqm->peer.interval)); 00359 } 00360 00361 BroadcastLinkQuality* currentLQ = linkQualities.find(friends.manager->getTransmitterAddress(compound->getCommandPool())); 00362 currentLQ->newBeacon(blqm->peer.interval); 00363 00364 // store the probe for received power 00365 receivedPower->put(compound, puc->local.rxPower.get_dBm()); 00366 00367 if(blqm->peer.rxBeaconSuccessRates.knows(myMACAddress)) 00368 { 00369 assure(blqm->peer.rxBeaconSINRs.knows(myMACAddress), 00370 "Beacon from " << friends.manager->getTransmitterAddress(compound->getCommandPool()) << " knows me in successRates, but not SINR"); 00371 MESSAGE_SINGLE(NORMAL, this->logger, "Received beacon from "<< friends.manager->getTransmitterAddress(compound->getCommandPool()) << ", which contains new lq information"); 00372 00373 Metric m; 00374 m = currentLQ->newPeerMeasurement(blqm->peer.rxBeaconSuccessRates.find(myMACAddress), 00375 blqm->peer.rxBeaconSINRs.find(myMACAddress)); 00376 00377 // put new link cost in probe 00378 linkCost->put(compound, m.toDouble()); 00379 // put positive measurement in probe 00380 peerMeasurement->put(compound, 1); 00381 } 00382 else 00383 { 00384 MESSAGE_SINGLE(NORMAL, this->logger, "Received beacon from "<< friends.manager->getTransmitterAddress(compound->getCommandPool()) << ", but no lq information for me"); 00385 currentLQ->deadPeerMeasurement(); 00386 00387 // put negative measurement in probe 00388 peerMeasurement->put(compound, 0); 00389 } 00390 } 00391 00392 // forward frame upwards 00393 getDeliverer()->getAcceptor(compound)->onData(compound); 00394 } 00395 00396 void BeaconLinkQualityMeasurement::newLinkCost(wns::service::dll::UnicastAddress rx, Metric cost) 00397 { 00398 // signal link-cost to path selection 00399 ps->updatePeerLink(myMACAddress, rx, cost); 00400 } 00401 00402 void BeaconLinkQualityMeasurement::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const 00403 { 00404 // get sizes from upper layers 00405 getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this); 00406 00407 if(getFUN()->getProxy()->commandIsActivated(commandPool, this)) 00408 { 00409 Bit ieHeaderSize = 8*3; // 8bits for IE-Hdr, Length, timestamp 00410 Bit nextPlannedTxSize = 8*4; 00411 00412 size_t numAddr = getCommand(commandPool)->peer.rxBeaconSuccessRates.size(); 00413 assure(numAddr == getCommand(commandPool)->peer.rxBeaconSINRs.size(), "successRates and powers have different size"); 00414 Bit lqInformationSize = (8*4 + 8 + 8) * numAddr; 00415 00416 commandPoolSize = commandPoolSize + ieHeaderSize + nextPlannedTxSize + lqInformationSize; 00417 } 00418 }
1.5.5