User Manual, Developers Guide and API Documentation

ChannelState.cpp

Go to the documentation of this file.
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 }

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