User Manual, Developers Guide and API Documentation

BeaconLinkQualityMeasurement.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/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 }

Generated on Mon May 21 03:32:16 2012 for openWNS by  doxygen 1.5.5