![]() |
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/convergence/ChannelState.hpp> 00030 #include <WIFIMAC/lowerMAC/RTSCTS.hpp> 00031 00032 #include <WNS/probe/bus/utils.hpp> 00033 00034 using namespace wifimac::convergence; 00035 00036 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00037 wifimac::convergence::ChannelState, 00038 wns::ldk::FunctionalUnit, 00039 "wifimac.convergence.ChannelState", 00040 wns::ldk::FUNConfigCreator); 00041 00042 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00043 wifimac::convergence::ChannelState, 00044 wns::ldk::probe::Probe, 00045 "wifimac.convergence.ChannelState", 00046 wns::ldk::FUNConfigCreator); 00047 00048 ChannelState::ChannelState(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) : 00049 wns::ldk::fu::Plain<ChannelState, ChannelStateCommand>(fun), 00050 wns::ldk::probe::Probe(), 00051 wns::events::PeriodicTimeout(), 00052 00053 config(config_), 00054 logger(config.get("logger")), 00055 00056 // thresholds 00057 rawEnergyThreshold(config.get<wns::Power>("myConfig.rawEnergyThreshold")), 00058 phyCarrierSenseThreshold(config.get<wns::Power>("myConfig.phyCarrierSenseThreshold")), 00059 00060 // rememberinf lastCS 00061 lastCS(idle), 00062 latestNAV(0), 00063 waitForReply(false), 00064 00065 // FU and command names, durations 00066 managerName(config.get<std::string>("managerName")), 00067 phyUserCommandName(config.get<std::string>("phyUserCommandName")), 00068 rtsctsCommandName(config.get<std::string>("rtsctsCommandName")), 00069 txStartEndName(config.get<std::string>("txStartEndName")), 00070 rxStartEndName(config.get<std::string>("rxStartEndName")), 00071 00072 sifsDuration(config_.get<wns::simulator::Time>("myConfig.sifsDuration")), 00073 00074 // probing the channel busy fraction 00075 channelBusyFractionProbe(), 00076 channelBusyFractionMeasurementPeriod(config.get<wns::simulator::Time>("myConfig.channelBusyFractionMeasurementPeriod")), 00077 channelBusyTime(0), 00078 channelBusySlotStart(0), 00079 channelBusyLastChangeToBusy(0) 00080 { 00081 // configure the active indicators 00082 activeIndicators.rawEnergyDetection = config.get<bool>("myConfig.useRawEnergyDetection"); 00083 activeIndicators.phyCarrierSense = config.get<bool>("myConfig.usePhyCarrierSense"); 00084 activeIndicators.ownRx = config.get<bool>("myConfig.useOwnRx"); 00085 activeIndicators.nav = config.get<bool>("myConfig.useNAV"); 00086 activeIndicators.ownTx = config.get<bool>("myConfig.useOwnTx"); 00087 00088 // reset all indicator values to zero 00089 indicators.rawEnergy = wns::Power::from_mW(0); 00090 indicators.phyCarrierSense = wns::Power::from_mW(0); 00091 indicators.ownTx = false; 00092 indicators.ownRx = false; 00093 00094 assure(!activeIndicators.rawEnergyDetection, "ChannelState based on rawEnergyDetection not yet implemented!"); 00095 00096 MESSAGE_BEGIN(NORMAL, logger, m, "Created, indicators: "); 00097 if (activeIndicators.rawEnergyDetection) m << "rawEnergyDetection(" << rawEnergyThreshold << ") "; 00098 if (activeIndicators.phyCarrierSense) m << "phyCarrierSense(" << phyCarrierSenseThreshold << ") "; 00099 if (activeIndicators.nav) m << "NAV "; 00100 if (activeIndicators.ownTx) m << "ownTx "; 00101 if (activeIndicators.ownRx) m << "ownRx"; 00102 MESSAGE_END(); 00103 00104 // Probe-Stuff 00105 // read the localContext from the config 00106 wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection()); 00107 for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii) 00108 { 00109 std::string key = config.get<std::string>("localIDs.keys()",ii); 00110 unsigned long int value = config.get<unsigned long int>("localIDs.values()",ii); 00111 localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value)); 00112 MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value); 00113 } 00114 this->channelBusyFractionProbe = wns::probe::bus::collector(localContext, config, "busyFractionProbeName"); 00115 this->startPeriodicTimeout(this->channelBusyFractionMeasurementPeriod); 00116 00117 friends.manager = NULL; 00118 } 00119 00120 ChannelState::~ChannelState() 00121 { 00122 } 00123 00124 void ChannelState::onFUNCreated() 00125 { 00126 MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started"); 00127 00128 friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName); 00129 00130 // Observe txStartEnd 00131 if(activeIndicators.ownTx) 00132 { 00133 this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving(getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName)); 00134 } 00135 00136 // Observe rxStartEnd 00137 if(activeIndicators.ownRx) 00138 { 00139 this->wns::Observer<wifimac::convergence::IRxStartEnd>::startObserving(getFUN()->findFriend<wifimac::convergence::RxStartEndNotification*>(rxStartEndName)); 00140 } 00141 } 00142 00143 void ChannelState::setCarrierSensingService(wns::service::Service* cs) 00144 { 00145 assure(cs, "must be non-NULL"); 00146 assureType(cs, wns::service::phy::ofdma::Notification*); 00147 this->myCS = dynamic_cast<wns::service::phy::ofdma::Notification*>(cs); 00148 this->myCS->registerRSSHandler(this); 00149 00150 } // setNotificationService 00151 00152 void 00153 ChannelState::onTxStart(const wns::ldk::CompoundPtr& /*compound*/) 00154 { 00155 this->indicators.ownTx = true; 00156 MESSAGE_SINGLE(NORMAL, logger, "Start of own transmission --> busy"); 00157 checkNewCS(); 00158 } 00159 00160 void 00161 ChannelState::onTxEnd(const wns::ldk::CompoundPtr& compound) 00162 { 00163 this->indicators.ownTx = false; 00164 00165 if((friends.manager->getFrameExchangeDuration(compound->getCommandPool()) > this->sifsDuration) or 00166 (friends.manager->getReplyTimeout(compound->getCommandPool()) > 0.0)) 00167 { 00168 MESSAGE_SINGLE(NORMAL, logger, "End of own transmission, awaiting reply --> set NAV"); 00169 // something expected after the frame (either own tx or reply) --> set 00170 // short NAV 00171 00172 wns::simulator::Time duration = friends.manager->getReplyTimeout(compound->getCommandPool()); 00173 if(wns::simulator::getEventScheduler()->getTime() + duration > this->latestNAV) 00174 { 00175 latestNAV = wns::simulator::getEventScheduler()->getTime() + duration; 00176 this->setNewTimeout(duration); 00177 this->waitForReply = true; 00178 } 00179 } 00180 else 00181 { 00182 MESSAGE_SINGLE(NORMAL, logger, "End of own transmission --> idle"); 00183 } 00184 checkNewCS(); 00185 } 00186 00187 void 00188 ChannelState::onRxStart(const wns::simulator::Time /*expRxDuration*/) 00189 { 00190 this->indicators.ownRx = true; 00191 checkNewCS(); 00192 } 00193 00194 void 00195 ChannelState::onRxEnd() 00196 { 00197 this->indicators.ownRx = false; 00198 checkNewCS(); 00199 } 00200 00201 void 00202 ChannelState::onRxError() 00203 { 00204 this->onRxEnd(); 00205 } 00206 00207 void 00208 ChannelState::processOutgoing(const wns::ldk::CompoundPtr& compound) 00209 { 00210 // The onTxStart/onTxEnd is not issued for preambles! 00211 if(friends.manager->getFrameType(compound->getCommandPool()) == PREAMBLE) 00212 { 00213 this->onTxStart(compound); 00214 } 00215 } 00216 00217 void 00218 ChannelState::processIncoming(const wns::ldk::CompoundPtr& compound) 00219 { 00220 assure(compound, "doOnData called with an invalid compound."); 00221 // Derive channel state from NAV information send in the MAC header 00222 if(friends.manager->getFrameType(compound->getCommandPool()) != PREAMBLE) 00223 { 00224 if(friends.manager->isForMe(compound->getCommandPool())) 00225 { 00226 00227 if(this->waitForReply) 00228 { 00229 // abort own NAV 00230 this->latestNAV = wns::simulator::getEventScheduler()->getTime(); 00231 cancelTimeout(); 00232 this->waitForReply = false; 00233 checkNewCS(); 00234 } 00235 // NAV is only set for frames NOT for me 00236 return; 00237 } 00238 00239 00240 wns::simulator::Time duration = 0; 00241 if(isRTS(compound)) 00242 { 00243 assure(friends.manager->getFrameExchangeDuration(compound->getCommandPool()) > 0, 00244 "Received RTS with FrameExchangeDuration <= 0"); 00245 00246 // special handling of RTS frames: set duration only until expected 00247 // reception start of the data frame: 00248 duration = friends.manager->getReplyTimeout(compound->getCommandPool()); 00249 } 00250 else 00251 { 00252 duration = friends.manager->getFrameExchangeDuration(compound->getCommandPool()); 00253 MESSAGE_SINGLE(NORMAL, logger, "Received valid compound with fExDur " << duration); 00254 00255 if(duration < this->sifsDuration) 00256 { 00257 return; 00258 } 00259 00260 } 00261 00262 if(wns::simulator::getEventScheduler()->getTime() + duration > this->latestNAV) 00263 { 00264 latestNAV = wns::simulator::getEventScheduler()->getTime() + duration; 00265 00266 // signal NAV 00267 this->wns::Subject<INetworkAllocationVector>::forEachObserver 00268 (OnChangedNAV(true, friends.manager->getTransmitterAddress(compound->getCommandPool()))); 00269 00270 this->setNewTimeout(duration); 00271 this->checkNewCS(); 00272 } 00273 00274 } 00275 else 00276 { 00277 wns::simulator::Time duration = friends.manager->getFrameExchangeDuration(compound->getCommandPool()); 00278 MESSAGE_SINGLE(NORMAL, logger, "Received valid preamble with fExDur " << duration); 00279 if(wns::simulator::getEventScheduler()->getTime() + duration > this->latestNAV) 00280 { 00281 latestNAV = wns::simulator::getEventScheduler()->getTime() + duration; 00282 this->setNewTimeout(duration); 00283 this->checkNewCS(); 00284 } 00285 } 00286 00287 } 00288 00289 bool ChannelState::isRTS(const wns::ldk::CompoundPtr& compound) const 00290 { 00291 return((getFUN()->getCommandReader(rtsctsCommandName)->commandIsActivated(compound->getCommandPool())) and 00292 (getFUN()->getCommandReader(rtsctsCommandName)->readCommand<wifimac::lowerMAC::RTSProviderCommand>(compound->getCommandPool())->isRTS())); 00293 } 00294 00295 void ChannelState::onTimeout() 00296 { 00297 // NAV has ended 00298 assure(latestNAV == wns::simulator::getEventScheduler()->getTime(), "indicators.nav has different time than now!"); 00299 MESSAGE_SINGLE(NORMAL, logger, "NAV has finished"); 00300 if(this->waitForReply) 00301 { 00302 // was own NAV 00303 this->waitForReply = false; 00304 } 00305 this->wns::Subject<INetworkAllocationVector>::forEachObserver 00306 (OnChangedNAV(false, wns::service::dll::UnicastAddress())); 00307 00308 myCS->updateRequest(); 00309 00310 this->checkNewCS(); 00311 } 00312 00313 void ChannelState::periodically() 00314 { 00315 // pre-tick: compute busy of the current slot 00316 if(this->getCurrentChannelState() == busy) 00317 { 00318 this->probeChannelIdle(); 00319 this->probeChannelBusy(); 00320 } 00321 double busyFraction = this->channelBusyTime / this->channelBusyFractionMeasurementPeriod; 00322 00323 // tick -> put probe 00324 this->channelBusyFractionProbe->put(busyFraction); 00325 00326 this->channelBusySlotStart = wns::simulator::getEventScheduler()->getTime(); 00327 this->channelBusyTime = 0.0; 00328 } 00329 00330 void ChannelState::onRSSChange(wns::Power newRSS) 00331 { 00332 MESSAGE_SINGLE(NORMAL, logger, "RSS changed to " << newRSS); 00333 00334 if (activeIndicators.phyCarrierSense) 00335 { 00336 indicators.phyCarrierSense = newRSS; 00337 checkNewCS(); 00338 } 00339 00340 for(int i=0; i < rssObservers.size(); i++) 00341 { 00342 rssObservers[i]->onRSSChange(newRSS); 00343 } 00344 } 00345 00346 CS ChannelState::getCurrentChannelState() const 00347 { 00348 // the channel state is a big OR over the active indicators 00349 00350 if ((activeIndicators.ownTx) and (indicators.ownTx)) 00351 { 00352 MESSAGE_SINGLE(VERBOSE, logger, "ownTx is active"); 00353 return(busy); 00354 } 00355 00356 if((activeIndicators.ownRx) and (indicators.ownRx)) 00357 { 00358 MESSAGE_SINGLE(VERBOSE, logger, "ownRx is active"); 00359 return(busy); 00360 } 00361 00362 if ((activeIndicators.rawEnergyDetection) and (indicators.rawEnergy > rawEnergyThreshold)) 00363 { 00364 MESSAGE_SINGLE(VERBOSE, logger, "rawEnergy " << indicators.rawEnergy << " > " << rawEnergyThreshold); 00365 return(busy); 00366 } 00367 00368 if ((activeIndicators.phyCarrierSense) and (indicators.phyCarrierSense > phyCarrierSenseThreshold)) 00369 { 00370 MESSAGE_SINGLE(VERBOSE, logger, "phyCS " << indicators.phyCarrierSense << " > " << phyCarrierSenseThreshold); 00371 return(busy); 00372 } 00373 00374 if((activeIndicators.nav) and (this->hasTimeoutSet())) 00375 { 00376 MESSAGE_SINGLE(VERBOSE, logger, "NAV is set until " << this->latestNAV); 00377 return(busy); 00378 } 00379 00380 return(idle); 00381 } 00382 00383 void ChannelState::checkNewCS() 00384 { 00385 CS newCS = getCurrentChannelState(); 00386 00387 if (newCS != lastCS) 00388 { 00389 // Channel has changed, inform observers 00390 MESSAGE_SINGLE(NORMAL, logger, "Channel changed to " << ((newCS == busy)? "busy":"idle")); 00391 this->wns::Subject<IChannelState>::forEachObserver(OnChangedCS(newCS)); 00392 lastCS = newCS; 00393 00394 if(newCS == busy) 00395 { 00396 this->probeChannelBusy(); 00397 } 00398 else 00399 { 00400 this->probeChannelIdle(); 00401 } 00402 } 00403 } 00404 00405 void ChannelState::probeChannelBusy() 00406 { 00407 this->channelBusyLastChangeToBusy = wns::simulator::getEventScheduler()->getTime(); 00408 } 00409 00410 void ChannelState::probeChannelIdle() 00411 { 00412 if(this->channelBusyLastChangeToBusy > this->channelBusySlotStart) 00413 { 00414 // latest change to channel busy occured during this slot 00415 this->channelBusyTime += wns::simulator::getEventScheduler()->getTime() 00416 - this->channelBusyLastChangeToBusy; 00417 } 00418 else 00419 { 00420 // lastest change to busy occured before this slot 00421 this->channelBusyTime += wns::simulator::getEventScheduler()->getTime() 00422 - this->channelBusySlotStart; 00423 } 00424 assure(this->channelBusyTime <= this->channelBusyFractionMeasurementPeriod+1e9, 00425 "busyTime must be leq than measurementPeriod"); 00426 }
1.5.5