User Manual, Developers Guide and API Documentation

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

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