User Manual, Developers Guide and API Documentation

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

Generated on Sun May 27 03:32:06 2012 for openWNS by  doxygen 1.5.5