![]() |
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/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
1.5.5