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