![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * WiMeMac * 00003 * This file is part of openWNS (open Wireless Network Simulator) 00004 * _____________________________________________________________________________ 00005 * 00006 * Copyright (C) 2004-2011 00007 * Chair of Communication Networks (ComNets) 00008 * Kopernikusstr. 5, 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 <WIMEMAC/convergence/ChannelState.hpp> 00030 00031 #include <WNS/probe/bus/utils.hpp> 00032 00033 using namespace wimemac::convergence; 00034 00035 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00036 wimemac::convergence::ChannelState, 00037 wns::ldk::FunctionalUnit, 00038 "wimemac.convergence.ChannelState", 00039 wns::ldk::FUNConfigCreator); 00040 00041 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00042 wimemac::convergence::ChannelState, 00043 wns::ldk::probe::Probe, 00044 "wimemac.convergence.ChannelState", 00045 wns::ldk::FUNConfigCreator); 00046 00047 ChannelState::ChannelState(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) : 00048 wns::ldk::fu::Plain<ChannelState, ChannelStateCommand>(fun), 00049 wns::ldk::probe::Probe(), 00050 wns::events::PeriodicTimeout(), 00051 00052 config(config_), 00053 logger(config.get("logger")), 00054 00055 // thresholds 00056 rawEnergyThreshold(config.get<wns::Power>("myConfig.rawEnergyThreshold")), 00057 phyCarrierSenseThreshold(config.get<wns::Power>("myConfig.phyCarrierSenseThreshold")), 00058 00059 // rememberinf lastCS 00060 lastCS(idle), 00061 latestNAV(0), 00062 waitForReply(false), 00063 00064 // FU and command names, durations 00065 managerName(config.get<std::string>("managerName")), 00066 phyUserCommandName(config.get<std::string>("phyUserCommandName")), 00067 crcCommandName(config.get<std::string>("crcCommandName")), 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<wimemac::lowerMAC::IManagerServices*>(managerName); 00129 00130 // Observe txStartEnd 00131 if(activeIndicators.ownTx) 00132 { 00133 this->wns::Observer<wimemac::convergence::ITxStartEnd>::startObserving(getFUN()->findFriend<wimemac::convergence::TxStartEndNotification*>(txStartEndName)); 00134 } 00135 00136 // Observe rxStartEnd 00137 if(activeIndicators.ownRx) 00138 { 00139 this->wns::Observer<wimemac::convergence::IRxStartEnd>::startObserving(getFUN()->findFriend<wimemac::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) && 00166 (friends.manager->hasPayload(compound->getCommandPool()))) 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 wns::simulator::Time duration = friends.manager->getFrameExchangeDuration(compound->getCommandPool()); 00174 if(wns::simulator::getEventScheduler()->getTime() + duration > this->latestNAV) 00175 { 00176 latestNAV = wns::simulator::getEventScheduler()->getTime() + duration; 00177 this->setNewTimeout(duration); 00178 this->waitForReply = true; 00179 } 00180 } 00181 else 00182 { 00183 MESSAGE_SINGLE(NORMAL, logger, "End of own transmission --> idle"); 00184 } 00185 checkNewCS(); 00186 } 00187 00188 void 00189 ChannelState::onRxStart(const wns::simulator::Time /*expRxDuration*/) 00190 { 00191 this->indicators.ownRx = true; 00192 checkNewCS(); 00193 } 00194 00195 void 00196 ChannelState::onRxEnd() 00197 { 00198 this->indicators.ownRx = false; 00199 checkNewCS(); 00200 } 00201 00202 void 00203 ChannelState::onRxError() 00204 { 00205 this->onRxEnd(); 00206 } 00207 00208 void 00209 ChannelState::processOutgoing(const wns::ldk::CompoundPtr& compound) 00210 { 00211 // The onTxStart/onTxEnd is not issued for preambles! 00212 if(friends.manager->isPreamble(compound->getCommandPool() ) ) 00213 { 00214 this->onTxStart(compound); 00215 00216 // If no payload follows the preamble inform about Tx End by scheduled call 00217 if(!friends.manager->hasPayload(compound->getCommandPool())) 00218 { 00219 wns::simulator::Time frameTxDuration = getFUN()->getCommandReader("TxDurationCommand")-> 00220 readCommand<wimemac::convergence::TxDurationSetterCommand>(compound->getCommandPool())->getDuration(); 00221 00222 wns::simulator::getEventScheduler()->scheduleDelay( 00223 boost::bind(&ChannelState::onTxEnd, this, compound), 00224 frameTxDuration); 00225 00226 MESSAGE_SINGLE(NORMAL, logger, "Preamble w/o Payload -> set TxEnd to " << frameTxDuration); 00227 } 00228 } 00229 } 00230 00231 void 00232 ChannelState::processIncoming(const wns::ldk::CompoundPtr& compound) 00233 { 00234 assure(compound, "doOnData called with an invalid compound."); 00235 if((friends.manager->getCompoundType(compound->getCommandPool()) == ACK_PREAMBLE) && (friends.manager->isForMe(compound->getCommandPool()))) 00236 { 00237 if(this->waitForReply) 00238 { 00239 // abort own NAV 00240 this->latestNAV = wns::simulator::getEventScheduler()->getTime(); 00241 cancelTimeout(); 00242 this->waitForReply = false; 00243 checkNewCS(); 00244 } 00245 // NAV is only set for frames NOT for me 00246 return; 00247 } 00248 00249 wns::simulator::Time duration = friends.manager->getFrameExchangeDuration(compound->getCommandPool()); 00250 00251 if(duration < this->sifsDuration) 00252 { 00253 return; 00254 } 00255 00256 // Derive channel state from NAV information sent in the MAC header 00257 if(wns::simulator::getEventScheduler()->getTime() + duration > this->latestNAV) 00258 { 00259 latestNAV = wns::simulator::getEventScheduler()->getTime() + duration; 00260 00261 // signal NAV 00262 this->wns::Subject<INetworkAllocationVector>::forEachObserver 00263 (OnChangedNAV(true, friends.manager->getTransmitterAddress(compound->getCommandPool()))); 00264 00265 MESSAGE_SINGLE(NORMAL, logger, "Set new NAV to " << duration); 00266 this->setNewTimeout(duration); 00267 this->checkNewCS(); 00268 } 00269 } 00270 00271 // bool ChannelState::isRTS(const wns::ldk::CompoundPtr& compound) const 00272 // { 00273 // return((getFUN()->getCommandReader(rtsctsCommandName)->commandIsActivated(compound->getCommandPool())) and 00274 // (getFUN()->getCommandReader(rtsctsCommandName)->readCommand<wimemac::lowerMAC::RTSCTSCommand>(compound->getCommandPool())->peer.isRTS)); 00275 // } 00276 00277 void ChannelState::onTimeout() 00278 { 00279 // NAV has ended 00280 assure(latestNAV == wns::simulator::getEventScheduler()->getTime(), "indicators.nav has different time than now!"); 00281 MESSAGE_SINGLE(NORMAL, logger, "NAV has finished"); 00282 if(this->waitForReply) 00283 { 00284 // was own NAV 00285 this->waitForReply = false; 00286 } 00287 00288 this->wns::Subject<INetworkAllocationVector>::forEachObserver 00289 (OnChangedNAV(false, wns::service::dll::UnicastAddress())); 00290 00291 myCS->updateRequest(); 00292 00293 this->checkNewCS(); 00294 00295 } 00296 00297 void ChannelState::periodically() 00298 { 00299 // pre-tick: compute busy of the current slot 00300 if(this->getCurrentChannelState() == busy) 00301 { 00302 this->probeChannelIdle(); 00303 this->probeChannelBusy(); 00304 } 00305 double busyFraction = this->channelBusyTime / this->channelBusyFractionMeasurementPeriod; 00306 00307 // tick -> put probe 00308 this->channelBusyFractionProbe->put(busyFraction); 00309 00310 this->channelBusySlotStart = wns::simulator::getEventScheduler()->getTime(); 00311 this->channelBusyTime = 0.0; 00312 } 00313 00314 void ChannelState::onRSSChange(wns::Power newRSS) 00315 { 00316 // MESSAGE_SINGLE(NORMAL, logger, "RSS changed to " << newRSS); 00317 00318 if (activeIndicators.phyCarrierSense) 00319 { 00320 indicators.phyCarrierSense = newRSS; 00321 checkNewCS(); 00322 } 00323 00324 for(int i=0; i < rssObservers.size(); i++) 00325 { 00326 rssObservers[i]->onRSSChange(newRSS); 00327 } 00328 } 00329 00330 CS ChannelState::getCurrentChannelState() const 00331 { 00332 // the channel state is a big OR over the active indicators 00333 00334 if ((activeIndicators.ownTx) and (indicators.ownTx)) 00335 { 00336 MESSAGE_SINGLE(VERBOSE, logger, "ownTx is active"); 00337 return(busy); 00338 } 00339 00340 if((activeIndicators.ownRx) and (indicators.ownRx)) 00341 { 00342 MESSAGE_SINGLE(VERBOSE, logger, "ownRx is active"); 00343 return(busy); 00344 } 00345 00346 if ((activeIndicators.rawEnergyDetection) and (indicators.rawEnergy > rawEnergyThreshold)) 00347 { 00348 MESSAGE_SINGLE(VERBOSE, logger, "rawEnergy " << indicators.rawEnergy << " > " << rawEnergyThreshold); 00349 return(busy); 00350 } 00351 00352 if ((activeIndicators.phyCarrierSense) and (indicators.phyCarrierSense > phyCarrierSenseThreshold)) 00353 { 00354 MESSAGE_SINGLE(VERBOSE, logger, "phyCS " << indicators.phyCarrierSense << " > " << phyCarrierSenseThreshold); 00355 return(busy); 00356 } 00357 00358 if((activeIndicators.nav) and (this->hasTimeoutSet())) 00359 { 00360 MESSAGE_SINGLE(VERBOSE, logger, "NAV is set until " << this->latestNAV); 00361 return(busy); 00362 } 00363 00364 return(idle); 00365 } 00366 00367 void ChannelState::checkNewCS() 00368 { 00369 CS newCS = getCurrentChannelState(); 00370 00371 if (newCS != lastCS) 00372 { 00373 // Channel has changed, inform observers 00374 MESSAGE_SINGLE(NORMAL, logger, "Channel changed to " << ((newCS == busy)? "busy":"idle")); 00375 this->wns::Subject<IChannelState>::forEachObserver(OnChangedCS(newCS)); 00376 lastCS = newCS; 00377 00378 if(newCS == busy) 00379 { 00380 this->probeChannelBusy(); 00381 } 00382 else 00383 { 00384 this->probeChannelIdle(); 00385 } 00386 } 00387 } 00388 00389 void ChannelState::probeChannelBusy() 00390 { 00391 this->channelBusyLastChangeToBusy = wns::simulator::getEventScheduler()->getTime(); 00392 } 00393 00394 void ChannelState::probeChannelIdle() 00395 { 00396 if(this->channelBusyLastChangeToBusy > this->channelBusySlotStart) 00397 { 00398 // latest change to channel busy occured during this slot 00399 this->channelBusyTime += wns::simulator::getEventScheduler()->getTime() 00400 - this->channelBusyLastChangeToBusy; 00401 } 00402 else 00403 { 00404 // lastest change to busy occured before this slot 00405 this->channelBusyTime += wns::simulator::getEventScheduler()->getTime() 00406 - this->channelBusySlotStart; 00407 } 00408 assure(this->channelBusyTime <= this->channelBusyFractionMeasurementPeriod+1e9, 00409 "busyTime must be less than measurementPeriod"); 00410 }
1.5.5