User Manual, Developers Guide and API Documentation

LinkQualityMeasurement.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/LinkQualityMeasurement.hpp>
00030 #include <WIFIMAC/Layer2.hpp>
00031 
00032 #include <WNS/container/UntypedRegistry.hpp>
00033 
00034 using namespace wifimac::pathselection;
00035 
00036 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00037     wifimac::pathselection::LinkQualityMeasurement,
00038     wns::ldk::FunctionalUnit,
00039     "wifimac.pathselection.LinkQualityMeasurement",
00040     wns::ldk::FUNConfigCreator);
00041 
00042 LinkQuality::LinkQuality(wns::service::dll::UnicastAddress _rx,
00043              wns::simulator::Time _referenceFlightTime,
00044              wns::simulator::Time _periodicity,
00045              LinkQualityMeasurement* _parent):
00046         rx(_rx),
00047         referenceFlightTime(_referenceFlightTime),
00048         periodicity(_periodicity),
00049         parent(_parent),
00050         rxLastFrame(true),
00051         lastRxFrameFlightTime(_referenceFlightTime),
00052         linkCostTx(_periodicity, true),
00053         oldLinkCostTxAvg(1.0),
00054         uniform(0.0, 1.0, wns::simulator::getRNG())
00055 {
00056     this->startPeriodicTimeout(periodicity, periodicity);
00057     assure(referenceFlightTime > 0, "referenceFlighttime must be greater than 0");
00058 }
00059 
00060 void LinkQuality::receivedLinkQualityIndicator(const LinkQualityMeasurementCommand* lqm)
00061 {
00062     assure(lqm->peer.srcMACAddress == rx, "Wrong lqm for this LinkQuality object");
00063 
00064     rxLastFrame = true;
00065 
00066     assure(lqm->peer.lastFrameFlightTime > 0, "received lqm with lqm->peer.lastFrameFlightTime " << lqm->peer.lastFrameFlightTime);
00067     linkCostTx.put(lqm->peer.lastFrameFlightTime/referenceFlightTime);
00068     Metric newLinkCostTxAvg = linkCostTx.getAbsolute()/linkCostTx.getNumSamples();
00069     //Metric newLinkCostTx = lqm->peer.lastFrameFlightTime/referenceFlightTime;
00070 
00071     if(!oldLinkCostTxAvg.isNear(newLinkCostTxAvg))
00072     {
00073         oldLinkCostTxAvg = newLinkCostTxAvg;
00074         parent->newLinkCost(rx, newLinkCostTxAvg);
00075     }
00076 
00077     lastRxFrameFlightTime = wns::simulator::getEventScheduler()->getTime() - lqm->peer.txTime;
00078 }
00079 
00080 void LinkQuality::periodically()
00081 {
00082     assure(!hasTimeoutSet(), "new period over, but still timeout set");
00083     if(!rxLastFrame)
00084     {
00085         // no reply since the last transmission, link may be broken
00086         linkCostTx.put(oldLinkCostTxAvg.toDouble() * 100);
00087         oldLinkCostTxAvg = linkCostTx.getAbsolute()/linkCostTx.getNumSamples();
00088         parent->newLinkCost(rx, oldLinkCostTxAvg);
00089     }
00090 
00091     this->setTimeout(uniform.get() * periodicity/2);
00092     rxLastFrame = false; 
00093 }
00094 
00095 void LinkQuality::onTimeout()
00096 {
00097     parent->sendLinkMeasurement(rx, lastRxFrameFlightTime);
00098 }
00099 
00100 wns::simulator::Time LinkQuality::getLastRxFrameFlightTime() const
00101 {
00102     return(lastRxFrameFlightTime);
00103 }
00104 
00105 void LinkQuality::hasSendPiggybackedLQM()
00106 {
00107     // delay the next periodically transmission
00108     if(hasTimeoutSet())
00109     {
00110         cancelTimeout();
00111     }
00112     cancelPeriodicTimeout();
00113     startPeriodicTimeout(periodicity, periodicity);
00114 }
00115 
00116 LinkQualityMeasurement::LinkQualityMeasurement(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& _config):
00117     wns::ldk::fu::Plain<LinkQualityMeasurement, LinkQualityMeasurementCommand>(fun),
00118     config(_config),
00119     frameSize(config.get<Bit>("frameSize")),
00120     referenceFlightTime(config.get<wns::simulator::Time>("referenceFlightTime")),
00121     period(config.get<wns::simulator::Time>("period")),
00122     logger(config.get("logger")),
00123     ucName(config.get<std::string>("upperConvergenceName")),
00124     doPiggybacking(config.get<bool>("doPiggybacking"))
00125 {
00126     if(doPiggybacking)
00127     {
00128         piggybackingPeriod = config.get<int>("piggybackingPeriod");
00129         numPiggybacked = 0;
00130     }
00131     friends.uc = NULL;
00132 }
00133 
00134 LinkQualityMeasurement::~LinkQualityMeasurement()
00135 {
00136     linkQualities.clear();
00137 }
00138 
00139 void LinkQualityMeasurement::onFUNCreated()
00140 {
00141     // todo: actually, this should not be neccessary, as only the correct stationTypes will have this in
00142     // their FUN --> make an assure, not an if()
00143     if(getFUN()->getLayer<wifimac::Layer2*>()->getStationType() != dll::StationTypes::UT())
00144     {
00145         ps = getFUN()->getLayer<wifimac::Layer2*>()->getManagementService<wifimac::pathselection::PathSelectionInterface>
00146                 (config.get<std::string>("pathSelectionServiceName"));
00147         assure(ps, "Could not get PathSelection Management Service");
00148 
00149         // Observer for new links
00150         wifimac::management::LinkNotificator* linkNotificator =
00151                 getFUN()->findFriend<wifimac::management::LinkNotificator*>(
00152                 config.get<std::string>("linkNotificationName"));
00153         this->wns::Observer<LinkNotificationInterface>::startObserving(linkNotificator);
00154 
00155         friends.uc = getFUN()->findFriend<dll::UpperConvergence*>(ucName);
00156         assure(friends.uc, "Could not get " << ucName << " from my FUN");
00157     }
00158     
00159     myMACAddress = getFUN()->getLayer<wifimac::Layer2*>()->getDLLAddress();
00160 }
00161 
00162 bool LinkQualityMeasurement::doIsAccepting(const wns::ldk::CompoundPtr& _compound) const
00163 {
00164     return getConnector()->hasAcceptor(_compound);
00165 } //doIsAccepting
00166 
00167 void LinkQualityMeasurement::doSendData(const wns::ldk::CompoundPtr& compound)
00168 {
00169     assure(compound, "doSendData called with an invalid compound.");
00170 
00171     // see todo in onFUNCreated()
00172     if((getFUN()->getLayer<wifimac::Layer2*>()->getStationType() != dll::StationTypes::UT()) && (doPiggybacking))
00173     {
00174         assure(friends.uc != NULL, "friends.uc not set");
00175         assure(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), friends.uc),
00176             "upper convergence command is not activated");
00177     
00178         dll::UpperCommand* uc = friends.uc->getCommand(compound->getCommandPool());
00179         assure(uc->peer.targetMACAddress.isValid(), "uc->peer.targetMACAddress is not valid");
00180         
00181         if(linkQualities.knows(uc->peer.targetMACAddress))
00182         {
00183             numPiggybacked = (numPiggybacked+1) % piggybackingPeriod;
00184             if (numPiggybacked == piggybackingPeriod-1)
00185             {
00186                 LinkQualityMeasurementCommand* lqm = activateCommand(compound->getCommandPool());
00187             
00188                 lqm->peer.srcMACAddress = myMACAddress;
00189                 lqm->peer.dstMACAddress = uc->peer.targetMACAddress;
00190                 lqm->peer.txTime = wns::simulator::getEventScheduler()->getTime();
00191                 lqm->peer.lastFrameFlightTime = linkQualities.find(uc->peer.targetMACAddress)->getLastRxFrameFlightTime();
00192                 lqm->magic.isPiggybacked = true;
00193             
00194                 MESSAGE_BEGIN(NORMAL, this->logger, m, "");
00195                 m << ": piggyback linkMeasurement with dst " << uc->peer.targetMACAddress;
00196                 m << ", lastRxFrameFlightTime " << linkQualities.find(uc->peer.targetMACAddress)->getLastRxFrameFlightTime();
00197                 MESSAGE_END();
00198                 
00199                 linkQualities.find(uc->peer.targetMACAddress)->hasSendPiggybackedLQM();
00200             }
00201         }
00202     }
00203     
00204     getConnector()->getAcceptor(compound)->sendData(compound);
00205 } // doSendData
00206 
00207 void LinkQualityMeasurement::doWakeup()
00208 {
00209     // simply forward the wakeup call
00210     getReceptor()->wakeup();
00211 } // doWakeup
00212 
00213 void LinkQualityMeasurement::doOnData(const wns::ldk::CompoundPtr& compound)
00214 {
00215     assure(compound, "doOnData called with an invalid compound.");
00216 
00217     if(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this))
00218     {
00219         // this link-measurement frame is consumed here
00220         LinkQualityMeasurementCommand* lqm = getCommand(compound->getCommandPool());
00221         if(!linkQualities.knows(lqm->peer.srcMACAddress))
00222         {
00223             // this is a lqi from a very fresh link, we haven't even received at beacon by that one, but
00224             // the peer has received a beacon from myself. We do not hurry and wait for the beacon before doing
00225             // anything
00226         }
00227         else
00228         {
00229             MESSAGE_BEGIN(NORMAL, this->logger, m, "");
00230             m << ": received LinkMeasurement from " << lqm->peer.srcMACAddress;
00231             m << ", lastFrameFlightTime " << lqm->peer.lastFrameFlightTime;
00232             MESSAGE_END();  
00233             linkQualities.find(lqm->peer.srcMACAddress)->receivedLinkQualityIndicator(lqm);
00234         }
00235         
00236         if(lqm->magic.isPiggybacked)
00237         {
00238             assure(doPiggybacking, "received lqm-command, but piggybacking is deactivated");
00239             // forward frame upwards
00240             getDeliverer()->getAcceptor(compound)->onData(compound);
00241         }
00242     }
00243     else
00244     {
00245         // forward frame upwards
00246         getDeliverer()->getAcceptor(compound)->onData(compound);
00247     }
00248 }
00249 
00250 void LinkQualityMeasurement::sendLinkMeasurement(wns::service::dll::UnicastAddress rx, wns::simulator::Time last)
00251 {
00252     wns::ldk::CompoundPtr compound(new wns::ldk::Compound(getFUN()->getProxy()->createCommandPool()));
00253     LinkQualityMeasurementCommand* lqm = activateCommand(compound->getCommandPool());
00254     
00255     lqm->peer.srcMACAddress = myMACAddress;
00256     lqm->peer.dstMACAddress = rx;
00257     lqm->peer.txTime = wns::simulator::getEventScheduler()->getTime();
00258     lqm->peer.lastFrameFlightTime = last;
00259     lqm->magic.isPiggybacked = false;
00260     
00261     // also activate upperCommand
00262     dll::UpperCommand* uc = friends.uc->activateCommand(compound->getCommandPool());
00263     uc->peer.sourceMACAddress = myMACAddress;
00264     uc->peer.targetMACAddress = rx;
00265     
00266     MESSAGE_BEGIN(NORMAL, this->logger, m, "");
00267     m << ": sendLinkMeasurement with dst " << rx;
00268     m << ", lastFrameFlightTime " << last;
00269     MESSAGE_END();  
00270     
00271     getConnector()->getAcceptor(compound)->sendData(compound);
00272 }
00273 
00274 void LinkQualityMeasurement::newLinkCost(wns::service::dll::UnicastAddress rx, Metric cost)
00275 {
00276     // signal link-cost to path selection
00277     ps->updatePeerLink(myMACAddress, rx, cost);
00278 }
00279 
00280 void LinkQualityMeasurement::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const
00281 {
00282     if(getFUN()->getProxy()->commandIsActivated(commandPool, this))
00283     {
00284         if(getCommand(commandPool)->magic.isPiggybacked)
00285         {
00286             Bit magicIEsize = 8*8*3; // 8bits for IE-Hdr, Length, timestamp
00287             getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this);
00288             commandPoolSize += magicIEsize;
00289         }
00290         else
00291         {
00292             // todo: shift values to PyConfig
00293             Bit managementMACHdrSize = 24*8;
00294             Bit timestampSize = 8*8;
00295         
00296             dataSize = frameSize;
00297             commandPoolSize = managementMACHdrSize + timestampSize;
00298         }
00299     }
00300     else
00301     {
00302         // get sizes from upper layers
00303         getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this);
00304     }
00305 }
00306     
00307 void LinkQualityMeasurement::onLinkIndication(const wns::service::dll::UnicastAddress myself,
00308               const wns::service::dll::UnicastAddress peer)
00309 {
00310     if(!linkQualities.knows(peer))
00311     {
00312         // new, unknown link -> signal to path selection
00313         ps->createPeerLink(myself, peer, Metric(1));
00314     
00315         // create entry in map
00316         linkQualities.insert(peer, new LinkQuality(peer, referenceFlightTime, period, this));
00317     }   
00318 }
00319 

Generated on Thu May 24 03:32:11 2012 for openWNS by  doxygen 1.5.5