User Manual, Developers Guide and API Documentation

DeAggregation.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/draftn/DeAggregation.hpp>
00030 
00031 #include <DLL/Layer2.hpp>
00032 
00033 #include <WNS/ldk/concatenation/Concatenation.hpp>
00034 
00035 
00036 using namespace wifimac::draftn;
00037 
00038 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00039     wifimac::draftn::DeAggregation,
00040     wns::ldk::FunctionalUnit,
00041     "wifimac.draftn.DeAggregation",
00042     wns::ldk::FUNConfigCreator);
00043 
00044 DeAggregation::DeAggregation(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) :
00045     wns::ldk::fu::Plain<DeAggregation, DeAggregationCommand>(fun),
00046 
00047     managerName(config_.get<std::string>("managerName")),
00048     protocolCalculatorName(config_.get<std::string>("protocolCalculatorName")),
00049     txStartEndName(config_.get<std::string>("phyUserName")),
00050     aggregationCommandName(config_.get<std::string>("aggregationCommandName")),
00051 
00052     txQueue(),
00053     currentTxCompound(),
00054     currentRxContainer(),
00055     doSignalTxStart(false),
00056     numEntries(0),
00057 
00058     logger(config_.get("logger"))
00059 {
00060     MESSAGE_SINGLE(NORMAL, this->logger, "created");
00061 
00062     protocolCalculator = NULL;
00063     friends.manager = NULL;
00064 }
00065 
00066 
00067 DeAggregation::~DeAggregation()
00068 {
00069 }
00070 
00071 void DeAggregation::onFUNCreated()
00072 {
00073     MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started");
00074     protocolCalculator = getFUN()->getLayer<dll::ILayer2*>()->getManagementService<wifimac::management::ProtocolCalculator>(protocolCalculatorName);
00075     friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName);
00076 
00077     // Observe txStartEnd
00078     this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving(getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName));
00079 }
00080 
00081 void
00082 DeAggregation::processIncoming(const wns::ldk::CompoundPtr& compound)
00083 {
00084     DeAggregationCommand* command = getCommand(compound->getCommandPool());
00085 
00086     if(command->peer.singleFragment)
00087     {
00088         // no aggregation at all
00089         MESSAGE_SINGLE(NORMAL, this->logger, "Single fragment -> deliver");
00090         getDeliverer()->getAcceptor(compound)->onData(compound);
00091         return;
00092     }
00093 
00094     MESSAGE_SINGLE(NORMAL, this->logger, "Process incoming aggregation fragment from " << friends.manager->getTransmitterAddress(compound->getCommandPool()));
00095 
00096     if(friends.manager->getFrameType(compound->getCommandPool()) == PREAMBLE)
00097     {
00098         // new aggregation
00099         if(this->currentRxContainer)
00100         {
00101             // capture effect: we receive a preamble of a different compound
00102             // before the current container is received completely.
00103             MESSAGE_SINGLE(NORMAL, this->logger, "Received aggregation preamble, during aggregation -> deliver old with " << this->numEntries << " entries");
00104             getDeliverer()->getAcceptor(this->currentRxContainer)->onData(this->currentRxContainer);
00105             this->currentRxContainer = wns::ldk::CompoundPtr();
00106             this->numEntries = 0;
00107             this->cancelTimeout();
00108         }
00109 
00110         // generate container from preamble
00111         this->currentRxContainer = compound->copy();
00112         friends.manager->setFrameType(this->currentRxContainer->getCommandPool(), DATA);
00113 
00114         // clear compound container
00115         getFUN()->getCommandReader(aggregationCommandName)->
00116             readCommand<wns::ldk::concatenation::ConcatenationCommand>(this->currentRxContainer->getCommandPool())->peer.compounds.clear();
00117 
00118         MESSAGE_SINGLE(NORMAL, this->logger, "Received aggregation preamble, create container");
00119 
00120         // set timeout for the delivery of the compounds
00121         this->setTimeout(friends.manager->getFrameExchangeDuration(compound->getCommandPool()) + 10e-9);
00122 
00123         // deliver preamble
00124         getDeliverer()->getAcceptor(compound)->onData(compound);
00125         return;
00126     }
00127 
00128     assure(not (this->currentRxContainer == wns::ldk::CompoundPtr()),
00129            "Received A-MPDU fragment, but rxContainer is empty!");
00130 
00131     // append current compound
00132     wns::ldk::concatenation::ConcatenationCommand* aggCommand = getFUN()->getCommandReader(aggregationCommandName)->
00133         readCommand<wns::ldk::concatenation::ConcatenationCommand>(this->currentRxContainer->getCommandPool());
00134     aggCommand->peer.compounds.push_back(compound);
00135 
00136     MESSAGE_SINGLE(NORMAL, this->logger, "Received aggregation fragment, append");
00137     this->numEntries++;
00138 
00139     if(command->peer.finalFragment)
00140     {
00141         MESSAGE_SINGLE(NORMAL, this->logger, "Received last aggregation fragment, deliver container with " << this->numEntries << " entries");
00142         // final fragment -> deliver complete aggregated compound
00143         wns::ldk::CompoundPtr it = this->currentRxContainer->copy();
00144         this->currentRxContainer = wns::ldk::CompoundPtr();
00145         this->numEntries = 0;
00146         this->cancelTimeout();
00147 
00148         getDeliverer()->getAcceptor(it)->onData(it);
00149     }
00150 }
00151 
00152 void DeAggregation::onTimeout()
00153 {
00154     if(this->numEntries > 0)
00155     {
00156         assure(this->currentRxContainer, "No current container");
00157         MESSAGE_SINGLE(NORMAL, this->logger, "Timeout for last aggregation fragment, deliver container with " << this->numEntries << " entries");
00158         getDeliverer()->getAcceptor(this->currentRxContainer)->onData(this->currentRxContainer);
00159         this->currentRxContainer = wns::ldk::CompoundPtr();
00160         this->numEntries = 0;
00161     }
00162     else
00163     {
00164         MESSAGE_SINGLE(NORMAL, this->logger, "Timeout for aggregation, no entries successfully received");
00165         this->currentRxContainer = wns::ldk::CompoundPtr();
00166     }
00167 }
00168 
00169 
00170 void
00171 DeAggregation::processOutgoing(const wns::ldk::CompoundPtr& compound)
00172 {
00173     assure(this->currentTxCompound == wns::ldk::CompoundPtr(), "processOutgoing, but currentTxCompound is not free");
00174     assure(this->txQueue.empty(), "processOutgoing, but txQueue is not empty");
00175 
00176     // calculate tx duration
00177     DeAggregationCommand* command = activateCommand(compound->getCommandPool());
00178     wifimac::convergence::PhyMode phyMode = friends.manager->getPhyMode(compound->getCommandPool());
00179     wns::simulator::Time preambleTxDuration = protocolCalculator->getDuration()->preamble(phyMode);
00180 
00181     if(friends.manager->getFrameType(compound->getCommandPool()) == PREAMBLE)
00182     {
00183         command->local.txDuration = preambleTxDuration;
00184         if(getFUN()->getCommandReader(aggregationCommandName)->commandIsActivated(compound->getCommandPool()))
00185         {
00186             // preamble of aggregation command
00187             command->peer.singleFragment = false;
00188             command->peer.finalFragment = false;
00189         }
00190         else
00191         {
00192             command->peer.singleFragment = true;
00193         }
00194         this->txQueue.push_back(compound);
00195         return;
00196     }
00197 
00198     this->currentTxCompound = compound;
00199     this->doSignalTxStart = true;
00200 
00201     wns::simulator::Time frameTxDuration = protocolCalculator->getDuration()->MPDU_PPDU(compound->getLengthInBits(), phyMode) - preambleTxDuration;
00202 
00203     if(not getFUN()->getCommandReader(aggregationCommandName)->commandIsActivated(compound->getCommandPool()))
00204     {
00205         // not an aggregation container command, schedule transmission for now
00206         command->local.txDuration = frameTxDuration;
00207         command->peer.singleFragment = true;
00208         this->txQueue.push_back(compound);
00209         return;
00210     }
00211 
00212     wns::simulator::Time nav = friends.manager->getFrameExchangeDuration(compound->getCommandPool());
00213     assure(frameTxDuration > 0, "Cannot transmit a frame with duration <= 0");
00214 
00215     MESSAGE_SINGLE(NORMAL, logger, "Outgoing aggregated compound with frame duration " << frameTxDuration);
00216 
00217     // split aggregation container into single compounds
00218     std::vector<Bit> sduSizes = std::vector<Bit>();
00219     Bit completeSize = 0;
00220 
00221     // iterate over the compounds to get the complete and single sizes
00222     // note that those sizes do NOT include any padding done by the Aggregation/Concatanation FU thus sizes differ from
00223     // those of the Aggregation FU. HOWEVER since the frameTxDuration is correct and sizes are only used to calculate
00224     // fractions of this duration, the mechanism still works (-:
00225 
00226     wns::ldk::concatenation::ConcatenationCommand* aggCommand = getFUN()->getCommandReader(aggregationCommandName)->
00227         readCommand<wns::ldk::concatenation::ConcatenationCommand>(compound->getCommandPool());
00228     for (std::vector<wns::ldk::CompoundPtr>::iterator it = aggCommand->peer.compounds.begin();
00229          it != aggCommand->peer.compounds.end();
00230          ++it)
00231     {
00232         completeSize += (*it)->getLengthInBits();
00233         sduSizes.push_back((*it)->getLengthInBits());
00234     }
00235 
00236     MESSAGE_SINGLE(NORMAL, logger, aggCommand->peer.compounds.size() << " entries in aggregation container, complete size " << completeSize);
00237 
00238     // iterate over the compounds and queue transmissions
00239     wns::simulator::Time nextStart = 0.0;
00240     std::vector<Bit>::iterator itS = sduSizes.begin();
00241 
00242     for (std::vector<wns::ldk::CompoundPtr>::iterator itC = aggCommand->peer.compounds.begin();
00243          itC != aggCommand->peer.compounds.end();
00244          ++itC, ++itS)
00245     {
00246         // set duration field to end of transmission + former nav
00247         wns::simulator::Time currentDuration = static_cast<double>(*itS)/static_cast<double>(completeSize) * frameTxDuration;
00248         friends.manager->setFrameExchangeDuration((*itC)->getCommandPool(), (frameTxDuration - nextStart - currentDuration) + nav);
00249 
00250         // all fragments must have the same phyMode
00251         friends.manager->setPhyMode((*itC)->getCommandPool(), friends.manager->getPhyMode(compound->getCommandPool()));
00252 
00253         // schedule fragment transmission
00254         DeAggregationCommand* currentCommand = activateCommand((*itC)->getCommandPool());
00255         currentCommand->local.txDuration = currentDuration;
00256 
00257         nextStart = nextStart + currentDuration;
00258 
00259         currentCommand->peer.singleFragment = false;
00260         // mark last compound
00261         currentCommand->peer.finalFragment = (itC+1 == aggCommand->peer.compounds.end());
00262 
00263         // next fragment, queue for transmission
00264         this->txQueue.push_back(*itC);
00265 
00266         MESSAGE_BEGIN(NORMAL, logger, m, " * size " << (*itS));
00267         m << ", fraction " << static_cast<double>(*itS)/static_cast<double>(completeSize);
00268         m << "-> delay " << nextStart - currentDuration;
00269         m << " duration " << currentDuration;
00270         m << " final " << currentCommand->peer.finalFragment;
00271         MESSAGE_END();
00272     }
00273 }
00274 
00275 const wns::ldk::CompoundPtr
00276 DeAggregation::hasSomethingToSend() const
00277 {
00278     if(txQueue.empty())
00279     {
00280         return(wns::ldk::CompoundPtr());
00281     }
00282     else
00283     {
00284         return(*(txQueue.begin()));
00285     }
00286 }
00287 
00288 wns::ldk::CompoundPtr
00289 DeAggregation::getSomethingToSend()
00290 {
00291     wns::ldk::CompoundPtr send = *(this->txQueue.begin());
00292     this->txQueue.pop_front();
00293     return(send);
00294 }
00295 
00296 bool
00297 DeAggregation::hasCapacity() const
00298 {
00299     return(this->currentTxCompound == wns::ldk::CompoundPtr());
00300 }
00301 
00302 void
00303 DeAggregation::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const
00304 {
00305 
00306     getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this);
00307 }
00308 
00309 void
00310 DeAggregation::onTxStart(const wns::ldk::CompoundPtr& /*compound*/)
00311 {
00312     if(this->doSignalTxStart)
00313     {
00314         this->doSignalTxStart = false;
00315         this->wns::Subject<ITxStartEnd>::forEachObserver(OnTxStartEnd(this->currentTxCompound, wifimac::convergence::start));
00316     }
00317 }
00318 
00319 void
00320 DeAggregation::onTxEnd(const wns::ldk::CompoundPtr& /*compound*/)
00321 {
00322     if((this->txQueue.empty()) and (this->currentTxCompound != wns::ldk::CompoundPtr()))
00323     {
00324         // signal tx end of complete frame
00325         this->wns::Subject<ITxStartEnd>::forEachObserver(OnTxStartEnd(this->currentTxCompound, wifimac::convergence::end));
00326         this->currentTxCompound = wns::ldk::CompoundPtr();
00327     }
00328 }

Generated on Wed May 23 03:32:03 2012 for openWNS by  doxygen 1.5.5