User Manual, Developers Guide and API Documentation

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

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