User Manual, Developers Guide and API Documentation

TXOP.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/lowerMAC/TXOP.hpp>
00030 #include <WIFIMAC/FrameType.hpp>
00031 
00032 #include <WNS/probe/bus/utils.hpp>
00033 
00034 #include <algorithm>
00035 
00036 using namespace wifimac::lowerMAC;
00037 
00038 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00039     TXOP,
00040     wns::ldk::FunctionalUnit,
00041     "wifimac.lowerMAC.TXOP",
00042     wns::ldk::FUNConfigCreator);
00043 
00044 TXOP::TXOP(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) :
00045     wns::ldk::fu::Plain<TXOP, wns::ldk::EmptyCommand>(fun),
00046     managerName(config_.get<std::string>("managerName")),
00047     protocolCalculatorName(config_.get<std::string>("protocolCalculatorName")),
00048     txopWindowName(config_.get<std::string>("txopWindowName")),
00049     raName(config_.get<std::string>("raName")),
00050     sifsDuration(config_.get<wns::simulator::Time>("myConfig.sifsDuration")),
00051     maximumACKDuration(config_.get<wns::simulator::Time>("myConfig.maximumACKDuration")),
00052     txopLimit(config_.get<wns::simulator::Time>("myConfig.txopLimit")),
00053     singleReceiver(config_.get<bool>("myConfig.singleReceiver")),
00054     maxOutTXOP(config_.get<bool>("myConfig.maxOutTXOP")),
00055    remainingTXOPDuration(0),
00056     txopReceiver(),
00057     logger(config_.get("logger"))
00058 {
00059     // either no TXOP (==0) or TXOP limit long enough to contain SIFS duration and ACK response
00060 /*    if (txopLimit > 0)
00061     {
00062         assure (txopLimit > sifsDuration + maximumACKDuration,
00063                 "TXOP limit too small (must be greater than SIFS duration + maximum ACK Duration or 0 for no TXOP)");
00064     }
00065 */    MESSAGE_SINGLE(NORMAL, this->logger, "created");
00066 
00067     friends.manager = NULL;
00068     protocolCalculator = NULL;
00069     friends.txopWindow = NULL;
00070     friends.ra = NULL;
00071 
00072     // read the localIDs from the config
00073     wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection());
00074     for (int ii = 0; ii<config_.len("localIDs.keys()"); ++ii)
00075     {
00076         std::string key = config_.get<std::string>("localIDs.keys()",ii);
00077         unsigned int value  = config_.get<unsigned int>("localIDs.values()",ii);
00078         localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value));
00079         MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value);
00080     }
00081     TXOPDurationProbe = wns::probe::bus::collector(localContext, config_, "TXOPDurationProbeName");
00082 }
00083 
00084 
00085 TXOP::~TXOP()
00086 {
00087 }
00088 
00089 void TXOP::onFUNCreated()
00090 {
00091     MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started");
00092 
00093     friends.manager = getFUN()->findFriend<Manager*>(managerName);
00094     friends.txopWindow = getFUN()->findFriend<ITXOPWindow*>(txopWindowName);
00095     friends.ra = getFUN()->findFriend<RateAdaptation*>(raName);
00096     protocolCalculator = getFUN()->getLayer<dll::ILayer2*>()->getManagementService<wifimac::management::ProtocolCalculator>(protocolCalculatorName);
00097 }
00098 
00099 void
00100 TXOP::processIncoming(const wns::ldk::CompoundPtr& compound)
00101 {
00102     // reset frame type if necessary
00103     if(friends.manager->getFrameType(compound->getCommandPool()) == DATA_TXOP)
00104     {
00105         friends.manager->setFrameType(compound->getCommandPool(), DATA);
00106     }
00107 }
00108 
00109 
00110 
00111 
00112 void
00113 TXOP::processOutgoing(const wns::ldk::CompoundPtr& compound)
00114 {
00115     switch(friends.manager->getFrameType(compound->getCommandPool()))
00116     {
00117     case DATA:
00118     {
00119         if(this->remainingTXOPDuration == 0)
00120         {
00121             // start of the TXOP
00122             this->remainingTXOPDuration = this->txopLimit;
00123             if(singleReceiver)
00124             {
00125                 this->txopReceiver = friends.manager->getReceiverAddress(compound->getCommandPool());
00126             }
00127             MESSAGE_BEGIN(NORMAL, this->logger, m, "Outgoing data compound to ");
00128             m << friends.manager->getReceiverAddress(compound->getCommandPool());
00129             m << ", starting TXOP with duration " << this->remainingTXOPDuration;
00130             MESSAGE_END();
00131         }
00132         else
00133         {
00134             // we have an ongoing TXOP
00135 
00136             // no need check if frame fits into current TXOP:
00137             // Either, this frame is the expected frame and fits perfectly, or
00138             // the frame is a retransmission which is allowed to be send without
00139             // looking at the txop limit
00140             friends.manager->setFrameType(compound->getCommandPool(), DATA_TXOP);
00141             MESSAGE_BEGIN(NORMAL, this->logger, m, "Outgoing data compound to ");
00142             m << friends.manager->getReceiverAddress(compound->getCommandPool());
00143             m << ", continue TXOP with duration " << this->remainingTXOPDuration;
00144             MESSAGE_END();
00145         }
00146 
00147      // cut TXOP duration by current frame
00148         wifimac::convergence::PhyMode phyMode = friends.manager->getPhyMode(compound->getCommandPool());
00149         wns::simulator::Time duration = protocolCalculator->getDuration()->MPDU_PPDU(compound->getLengthInBits(),
00150                                                                                      phyMode);
00151 
00152         wns::simulator::Time cutTXOPDuration = this->remainingTXOPDuration
00153                                         - duration
00154                                         - this->sifsDuration
00155                                         - this->maximumACKDuration;
00156 
00157     if (friends.manager->getFrameType(compound->getCommandPool()) == DATA_TXOP)
00158                 cutTXOPDuration -= this->sifsDuration;
00159                     
00160         MESSAGE_SINGLE(NORMAL, this->logger, "Current compound cuts TXOP to " << cutTXOPDuration);
00161 
00162         if(cutTXOPDuration <= 0)
00163         {
00164             // no time for additional frames -> no (more) TXOP
00165             MESSAGE_SINGLE(NORMAL, this->logger, "Current compound fills complete TXOP");
00166             closeTXOP();
00167         return;
00168         }
00169     this->remainingTXOPDuration  = cutTXOPDuration;
00170 
00171     // check if next frame would fit into TXOP
00172         wns::simulator::Time nextDuration = friends.txopWindow->getNextTransmissionDuration();
00173 
00174         if(nextDuration == wns::simulator::Time())
00175         {
00176             // no next compound, no (more) TXOP
00177             MESSAGE_SINGLE(NORMAL, this->logger, "No next compound, no (more) TXOP");
00178         closeTXOP();
00179             return;
00180         }
00181 
00182         if(singleReceiver and (this->txopReceiver != friends.txopWindow->getNextReceiver()))
00183         {
00184             MESSAGE_BEGIN(NORMAL, this->logger, m, "TXOP is restricted to receiver ");
00185             m << this->txopReceiver << " and next compound is addressed to ";
00186             m << friends.txopWindow->getNextReceiver();
00187             m << "no (more) TXOP";
00188             MESSAGE_END();
00189         closeTXOP();
00190             return;
00191         }
00192 
00193         wns::simulator::Time nextFrameExchangeDuration;
00194 
00195         if (not maxOutTXOP)
00196         {
00197             nextFrameExchangeDuration =  this->sifsDuration
00198                 + nextDuration
00199                 + this->sifsDuration
00200                 + this->maximumACKDuration;
00201         }
00202         else
00203         {
00204             nextFrameExchangeDuration = this->remainingTXOPDuration;
00205         }
00206 
00207         if (this->remainingTXOPDuration < nextFrameExchangeDuration)
00208         {
00209             // next frame does not fit -> no (more) TXOP
00210             MESSAGE_SINGLE(NORMAL, this->logger, "Next frame has duration " << nextFrameExchangeDuration << ", does not fit");
00211         closeTXOP();
00212             return;
00213         }
00214 
00215         // next frame fits -> extend frame exchange duration by complete
00216         // next frame exchange
00217         friends.manager->setFrameExchangeDuration(compound->getCommandPool(),
00218                                                   friends.manager->getFrameExchangeDuration(compound->getCommandPool()) + nextFrameExchangeDuration);
00219 
00220         MESSAGE_BEGIN(NORMAL, this->logger, m,  "Next frame has duration ");
00221         m << nextFrameExchangeDuration;
00222         m << ", fit into TXOP, set NAV to ";
00223         m << friends.manager->getFrameExchangeDuration(compound->getCommandPool()) + nextFrameExchangeDuration;
00224         MESSAGE_END();
00225 
00226         break;
00227     }
00228 
00229     case ACK:
00230     {
00231         // do not change the ACK in any way before transmission
00232         break;
00233     }
00234     default:
00235     {
00236         throw wns::Exception("Unknown frame type");
00237         break;
00238     }
00239     }
00240 
00241 
00242 }
00243 
00244 bool TXOP::doIsAccepting(const wns::ldk::CompoundPtr& compound) const
00245 {
00246     if((friends.manager->getFrameType(compound->getCommandPool()) == DATA) and
00247        (this->remainingTXOPDuration > 0))
00248     {
00249         // we have an ongoing TXOP
00250 
00251         // no need check if frame fits into current TXOP:
00252         // Either, this frame is the expected frame and fits perfectly, or
00253         // the frame is a retransmission which is allowed to be send without
00254         // looking at the txop limit
00255 
00256         // copy the compound and change type so that the right path in the FUN
00257         // is taken
00258         wns::ldk::CompoundPtr txopCompound = compound->copy();
00259         friends.manager->setFrameType(txopCompound->getCommandPool(), DATA_TXOP);
00260 
00261         return wns::ldk::Processor<TXOP>::doIsAccepting(txopCompound);
00262     }
00263     else
00264     {
00265         // no special handling
00266         return wns::ldk::Processor<TXOP>::doIsAccepting(compound);
00267     }
00268 }
00269 
00270 
00271 void TXOP::closeTXOP() 
00272 {
00273     TXOPDurationProbe->put(this->txopLimit - this->remainingTXOPDuration);
00274     this->remainingTXOPDuration = 0;
00275     for(int i=0; i < observers.size();i++)
00276     {
00277     observers[i]->onTXOPClosed();
00278     }
00279 }
00280 
00281 
00282 void TXOP::setTXOPLimit(wns::simulator::Time limit)
00283 {
00284 /*    if (limit > 0)
00285     {
00286         assure (txopLimit > sifsDuration + maximumACKDuration,
00287                 "TXOP limit too small (must be greater than SIFS duration + maximum ACK Duration or 0 for no TXOP)");
00288     }
00289 */    this->txopLimit = limit;
00290     this->remainingTXOPDuration = 0;
00291 }

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