User Manual, Developers Guide and API Documentation

BlockACK.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/BlockACK.hpp>
00030 #include <WIFIMAC/convergence/PhyMode.hpp>
00031 
00032 #include <WNS/probe/bus/utils.hpp>
00033 
00034 using namespace wifimac::draftn;
00035 
00036 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00037     wifimac::draftn::BlockACK,
00038     wns::ldk::FunctionalUnit,
00039     "wifimac.draftn.BlockACK",
00040     wns::ldk::FUNConfigCreator);
00041 
00042 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00043     wifimac::draftn::BlockACK,
00044     wns::ldk::probe::Probe,
00045     "wifimac.draftn.BlockACK",
00046     wns::ldk::FUNConfigCreator);
00047 
00048 BlockACK::BlockACK(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) :
00049     wns::ldk::arq::ARQ(config_),
00050     wns::ldk::fu::Plain<BlockACK, BlockACKCommand>(fun),
00051 
00052     managerName(config_.get<std::string>("managerName")),
00053     rxStartEndName(config_.get<std::string>("rxStartEndName")),
00054     txStartEndName(config_.get<std::string>("txStartEndName")),
00055     sendBufferName(config_.get<std::string>("sendBufferName")),
00056     perMIBServiceName(config_.get<std::string>("perMIBServiceName")),
00057     sifsDuration(config_.get<wns::simulator::Time>("myConfig.sifsDuration")),
00058     maximumACKDuration(config_.get<wns::simulator::Time>("myConfig.maximumACKDuration")),
00059     ackTimeout(config_.get<wns::simulator::Time>("myConfig.ackTimeout")),
00060     blockACKPhyMode(config_.getView("myConfig.blockACKPhyMode")),
00061     capacity(config_.get<Bit>("myConfig.capacity")),
00062     maxOnAir(config_.get<size_t>("myConfig.maxOnAir")),
00063     baBits(config_.get<Bit>("myConfig.blockACKBits")),
00064     baReqBits(config_.get<Bit>("myConfig.blockACKRequestBits")),
00065     maximumTransmissions(config_.get<size_t>("myConfig.maximumTransmissions")),
00066     impatientBAreqTransmission(config_.get<bool>("myConfig.impatient")),
00067     currentTxQueue(NULL),
00068     rxQueues(),
00069     hasACKfor(),
00070     nextTransmissionSN(),
00071     baState(idle),
00072 
00073     logger(config_.get("logger"))
00074 {
00075     MESSAGE_SINGLE(NORMAL, this->logger, "created");
00076 
00077     // read the localIDs from the config
00078     wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection());
00079     for (int ii = 0; ii<config_.len("localIDs.keys()"); ++ii)
00080     {
00081         std::string key = config_.get<std::string>("localIDs.keys()",ii);
00082         unsigned int value  = config_.get<unsigned int>("localIDs.values()",ii);
00083         localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value));
00084         MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value);
00085     }
00086     numTxAttemptsProbe = wns::probe::bus::collector(localContext, config_, "numTxAttemptsProbeName");
00087     friends.manager = NULL;
00088 
00089     std::string pluginName = config_.get<std::string>("myConfig.sizeUnit");
00090     sizeCalculator = std::auto_ptr<wns::ldk::buffer::SizeCalculator>(wns::ldk::buffer::SizeCalculator::Factory::creator(pluginName)->create());
00091 }
00092 
00093 BlockACK::BlockACK(const BlockACK& other) :
00094     //CompoundHandlerInterface(other),
00095     CommandTypeSpecifierInterface(other),
00096     HasReceptorInterface(other),
00097     HasConnectorInterface(other),
00098     HasDelivererInterface(other),
00099     CloneableInterface(other),
00100     IOutputStreamable(other),
00101     PythonicOutput(other),
00102     FunctionalUnit(other),
00103     DelayedInterface(other),
00104     wns::ldk::arq::ARQ(other),
00105     wns::ldk::fu::Plain<BlockACK, BlockACKCommand>(other),
00106     wns::ldk::Delayed<BlockACK>(other),
00107     managerName(other.managerName),
00108     rxStartEndName(other.rxStartEndName),
00109     txStartEndName(other.txStartEndName),
00110     sendBufferName(other.sendBufferName),
00111     perMIBServiceName(other.perMIBServiceName),
00112     sifsDuration(other.sifsDuration),
00113     maximumACKDuration(other.maximumACKDuration),
00114     ackTimeout(other.ackTimeout),
00115     capacity(other.capacity),
00116     maxOnAir(other.maxOnAir),
00117     baBits(other.baBits),
00118     baReqBits(other.baReqBits),
00119     maximumTransmissions(other.maximumTransmissions),
00120     impatientBAreqTransmission(other.impatientBAreqTransmission),
00121     sizeCalculator(wns::clone(other.sizeCalculator))
00122 {
00123 }
00124 
00125 BlockACK::~BlockACK()
00126 {
00127     // clear queues
00128     rxQueues.clear();
00129     if (currentTxQueue != NULL)
00130     {
00131        delete currentTxQueue;
00132        currentTxQueue = NULL;
00133     }
00134 }
00135 
00136 void BlockACK::onFUNCreated()
00137 {
00138     MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started");
00139 
00140     friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName);
00141 
00142     // Observe rxStart
00143     this->wns::Observer<wifimac::convergence::IRxStartEnd>::startObserving
00144         (getFUN()->findFriend<wifimac::convergence::RxStartEndNotification*>(rxStartEndName));
00145 
00146     // Observe txStartEnd
00147     this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving
00148         (getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName));
00149 
00150     // signal packet success/errors to MIB
00151     perMIB = getFUN()->getLayer<dll::Layer2*>()->getManagementService<wifimac::management::PERInformationBase>(perMIBServiceName);
00152     friends.sendBuffer = getFUN()->findFriend<wns::ldk::DelayedInterface*>(sendBufferName);
00153 } // BlockACK::onFUNCreated
00154 
00155 unsigned int
00156 BlockACK::storageSize() const
00157 {
00158     unsigned int size = 0;
00159 
00160     if (currentTxQueue != NULL)
00161     {
00162         size = currentTxQueue->storageSize();
00163     }
00164 
00165     for(wns::container::Registry<wns::service::dll::UnicastAddress, ReceptionQueue*>::const_iterator it = rxQueues.begin();
00166         it != rxQueues.end();
00167         it++)
00168     {
00169         size += (*it).second->storageSize();
00170     }
00171 
00172     return(size);
00173 } // BlockACK::size()
00174 
00175 
00176 bool
00177 BlockACK::doIsAccepting(const wns::ldk::CompoundPtr& compound) const
00178 {
00179     return (((currentTxQueue == NULL) or
00180              (currentTxQueue->getReceiver() == friends.manager->getReceiverAddress(compound->getCommandPool())))
00181             and hasCapacity());
00182 }
00183 
00184 
00185 bool
00186 BlockACK::hasCapacity() const
00187 {
00188     return((this->storageSize() < this->capacity) and 
00189            ((currentTxQueue == NULL) or
00190             (not currentTxQueue->waitsForACK())) and
00191            ((currentTxQueue == NULL) or
00192             (currentTxQueue->storageSize() < this->maxOnAir)));
00193 }
00194 
00195 void
00196 BlockACK::processOutgoing(const wns::ldk::CompoundPtr& compound)
00197 {
00198     assure(this->hasCapacity(), "processOutgoing although no capacity");
00199 
00200     if(friends.manager->lifetimeExpired(compound->getCommandPool()))
00201     {
00202         MESSAGE_SINGLE(NORMAL, logger, "outgoing compound has expired lifetime -> drop");
00203         return;
00204     }
00205     wns::service::dll::UnicastAddress receiver = friends.manager->getReceiverAddress(compound->getCommandPool());
00206     if (currentTxQueue != NULL and receiver == currentTxQueue->getReceiver())
00207     {
00208         // processed compound has the current receiver as destination, added to
00209         // compound block for next round
00210         MESSAGE_SINGLE(NORMAL, this->logger,"Next frame in a row  processed for receiver: " << currentTxQueue->getReceiver() << " with SN: " << currentTxQueue->getNextSN());
00211         currentTxQueue->processOutgoing(compound);
00212     }
00213     if (currentTxQueue == NULL)
00214     {
00215         if (not nextTransmissionSN.knows(receiver))
00216         {
00217             nextTransmissionSN.insert(receiver,0);
00218         }
00219         currentTxQueue = new TransmissionQueue(this,
00220                                                maxOnAir,
00221                                                0.0,
00222                                                receiver,
00223                                                nextTransmissionSN.find(receiver),
00224                                                perMIB,
00225                                                &sizeCalculator);
00226 
00227         MESSAGE_BEGIN(NORMAL, this->logger, m, "First frame in a row");
00228         m << " processed for receiver: " << currentTxQueue->getReceiver();
00229         m << " with SN: " << nextTransmissionSN.find(receiver);
00230         MESSAGE_END();
00231         currentTxQueue->processOutgoing(compound);
00232     }
00233     MESSAGE_SINGLE(NORMAL, this->logger, "Stored outgoing frame, remaining capacity " << this->capacity - this->storageSize());
00234 }
00235 
00236 void
00237 BlockACK::processIncoming(const wns::ldk::CompoundPtr& compound)
00238 {
00239     wns::service::dll::UnicastAddress transmitter = friends.manager->getTransmitterAddress(compound->getCommandPool());
00240 
00241     if(getCommand(compound->getCommandPool())->isACK())
00242     {
00243         assure(currentTxQueue != NULL, "got ACK though no transmission queue");
00244         assure(transmitter == currentTxQueue->getReceiver(), "got ACK from wrong Station");
00245         assure(this->baState == receptionFinished or this->baState == receiving,
00246                "Received ACK but not waiting for one");
00247 
00248 
00249         //perMIB->onSuccessfullTransmission(currentTxQueue->getReceiver());
00250         this->processIncomingACKSNs(getCommand(compound->getCommandPool())->peer.ackSNs);
00251         return;
00252 
00253     } // if compound is ACK
00254     else
00255     {
00256         if(getCommand(compound->getCommandPool())->isACKreq())
00257         {
00258             if(not rxQueues.knows(transmitter))
00259             {
00260                 MESSAGE_BEGIN(NORMAL, this->logger, m, "Received BA-REQ from unknown transmitter ");
00261                 m << transmitter << " (this would not happen with correct BA-init)";
00262                 m << " -> new rxQueue";
00263                 MESSAGE_END();
00264 
00265                 assure(not hasACKfor.isValid(), "Received BA-REQ from " << transmitter << ", but already existing BA for " << hasACKfor);
00266 
00267                 rxQueues.insert(transmitter, new ReceptionQueue(this, getCommand(compound->getCommandPool())->peer.sn, transmitter));
00268             }
00269             rxQueues.find(transmitter)->processIncomingACKreq(compound);
00270             hasACKfor = transmitter;
00271             return;
00272         } // compound is ACK req
00273         else
00274         {
00275             if(not rxQueues.knows(transmitter))
00276             {
00277                 MESSAGE_SINGLE(NORMAL, this->logger, "First frame from " << transmitter << " -> new rxQueue");
00278                 rxQueues.insert(transmitter, new ReceptionQueue(this, getCommand(compound->getCommandPool())->peer.sn, transmitter));
00279             }
00280             rxQueues.find(transmitter)->processIncomingData(compound, (*sizeCalculator)(compound));
00281         } // is not ACK req
00282     } // is not ACK
00283 } // BlockACK::processIncoming
00284 
00285 void
00286 BlockACK::processIncomingACKSNs(std::set<BlockACKCommand::SequenceNumber> ackSNs)
00287 {
00288     if(hasTimeoutSet())
00289     {
00290         cancelTimeout();
00291     }
00292 
00293     // Reset the baState: Noting is send, not waiting for anything -> idle!
00294     this->baState = idle;
00295 
00296     // forward SNs to currentTxQueue
00297     currentTxQueue->processIncomingACK(ackSNs);
00298 
00299     if ((currentTxQueue->getNumWaitingPDUs()+currentTxQueue->getNumOnAirPDUs()) != 0)
00300     {
00301         // either not all compounds of the current send block have been
00302         // transmitted successfully or compounds for the same receiver
00303         // arrived while the current send block retransmitted unsuccessfully
00304         // sent compounds
00305         return;
00306     }
00307 
00308     // currentTxQueue is empty -> store SN and delete it
00309     nextTransmissionSN.update(currentTxQueue->getReceiver(),currentTxQueue->getNextSN());
00310     MESSAGE_SINGLE(NORMAL, this->logger, "No more waiting frames -> deleted currentTxQueue");
00311     delete currentTxQueue;
00312     currentTxQueue = NULL;
00313     return;
00314 }
00315 
00316 
00317 const wns::ldk::CompoundPtr
00318 BlockACK::hasACK() const
00319 {
00320     if(hasACKfor.isValid())
00321     {
00322         return(rxQueues.find(hasACKfor)->hasACK());
00323     }
00324     else
00325     {
00326         return wns::ldk::CompoundPtr();
00327     }
00328 } // hasACK
00329 
00330 wns::ldk::CompoundPtr
00331 BlockACK::getACK()
00332 {
00333     wns::service::dll::UnicastAddress adr = hasACKfor;
00334     hasACKfor = wns::service::dll::UnicastAddress();
00335     return(rxQueues.find(adr)->getACK());
00336 } // getACK
00337 
00338 const wns::ldk::CompoundPtr
00339 BlockACK::hasData() const
00340 {
00341     wns::ldk::CompoundPtr compound = friends.sendBuffer->hasSomethingToSend();
00342     if((hasCapacity()) and
00343        (compound != wns::ldk::CompoundPtr()) and
00344        (currentTxQueue != NULL) and
00345        (friends.manager->getReceiverAddress(compound->getCommandPool()) == currentTxQueue->getReceiver()))
00346     {
00347         // There are more compounds in the buffer and we still have capacity -> delay transmission
00348         return wns::ldk::CompoundPtr();
00349     }
00350 
00351     if (currentTxQueue != NULL)
00352     {
00353         return(currentTxQueue->hasData());
00354     }
00355     else
00356     {
00357         return wns::ldk::CompoundPtr();
00358     }
00359 } // hasData
00360 
00361 wns::ldk::CompoundPtr
00362 BlockACK::getData()
00363 {
00364     assure(hasData(), "trying to get data though there aren't any waiting");
00365 
00366     // get the next waiting compound
00367     wns::ldk::CompoundPtr it = currentTxQueue->getData();
00368 
00369     return(it);
00370 } // getData
00371 
00372 
00373 void
00374 BlockACK::onTxStart(const wns::ldk::CompoundPtr& /*compound*/)
00375 {
00376     baState = idle;
00377 }
00378 
00379 void
00380 BlockACK::onTxEnd(const wns::ldk::CompoundPtr& compound)
00381 {
00382     // we await the tx end of the blockACKreq
00383     if((getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this)) and
00384        (getCommand(compound->getCommandPool())->isACKreq()) and 
00385        (currentTxQueue->getReceiver() == friends.manager->getReceiverAddress(compound->getCommandPool())))
00386     {
00387         assure(currentTxQueue != NULL, "TxEnd from BA-REQ, but no transmission queue");
00388         assure(currentTxQueue->waitsForACK(),
00389                "TxEnd from BA-REQ for current receiver " << currentTxQueue->getReceiver() << ", but queue is not waiting for ACK");
00390 
00391         // we give ackTimeout until the baState must be "receiving"
00392         setNewTimeout(ackTimeout);
00393         baState = waitForACK;
00394         MESSAGE_SINGLE(NORMAL, this->logger, "onTxEnd() of BAreq, wait on BA for " << ackTimeout);
00395     }
00396 }
00397 
00398 void
00399 BlockACK::onTimeout()
00400 {
00401     if(this->baState == receiving)
00402     {
00403         MESSAGE_SINGLE(NORMAL, this->logger, "Started reception during wait for BA -> wait for delivery");
00404         return;
00405     }
00406 
00407     // we did not receive anything after the blockACKreq transmission
00408     assure(currentTxQueue != NULL, "Timeout, but no transmission queue");
00409     assure(currentTxQueue->waitsForACK(), "Timeout, but currentTxQueue is not waiting for ACK");
00410 
00411     MESSAGE_SINGLE(NORMAL, this->logger, "Timeout -> failed transmission to " << currentTxQueue->getReceiver());
00412     //perMIB->onFailedTransmission(currentTxQueue->getReceiver());
00413 
00414     // no ACK'ed SNs have arrived, use pseudo-vector
00415     std::set<BlockACKCommand::SequenceNumber> none;
00416     none.clear();
00417     this->processIncomingACKSNs(none);
00418 
00419     this->tryToSend();
00420 }
00421 
00422 void
00423 BlockACK::onTransmissionHasFailed(const wns::ldk::CompoundPtr& compound)
00424 {
00425     assure(currentTxQueue != NULL, "transsmissionHasFailed, but there is no transmission queue");
00426     assure(currentTxQueue->waitsForACK(), "transmissionHasFailed, but currentTxQueue is not waiting for ACK");
00427     assure(friends.manager->getReceiverAddress(compound->getCommandPool()) == currentTxQueue->getReceiver(),
00428            "transmissionHasFailed has different rx address than current receiver");
00429 
00430     MESSAGE_SINGLE(NORMAL, this->logger, "Indication of failed transmission to " << friends.manager->getReceiverAddress(compound->getCommandPool()));
00431     // RTS/CTS -> no signalling to perMIB
00432     //this->printTxQueueStatus();
00433 
00434 
00435     // no ACK'ed SNs have arrived, use pseudo-vector
00436     std::set<BlockACKCommand::SequenceNumber> none;
00437     none.clear();
00438     this->processIncomingACKSNs(none);
00439 
00440     this->tryToSend();
00441 }
00442 
00443 void
00444 BlockACK::onRxStart(wns::simulator::Time /*expRxTime*/)
00445 {
00446     if(this->baState == waitForACK)
00447     {
00448         assure(hasTimeoutSet(), "ackState is waiting but no timeout set?");
00449         this->baState = receiving;
00450         MESSAGE_SINGLE(NORMAL, this->logger, "onRxStart() during wait for BA");
00451     }
00452 }
00453 
00454 void
00455 BlockACK::onRxEnd()
00456 {
00457     if(this->baState == receiving)
00458     {
00459         this->baState = receptionFinished;
00460         if(not hasTimeoutSet())
00461         {
00462             setTimeout(10e-9);
00463             MESSAGE_SINGLE(NORMAL, this->logger, "onRxEnd() during wait for BA -> short wait for delivery of BA");
00464         }
00465     }
00466 }
00467 
00468 void
00469 BlockACK::onRxError()
00470 {
00471     if(this->baState == receiving)
00472     {
00473         MESSAGE_SINGLE(NORMAL, logger, "onRxError and waiting for ACK -> failure");
00474         this->baState = waitForACK;
00475 
00476         if(not hasTimeoutSet())
00477         {
00478             this->onTimeout();
00479         }
00480     }
00481 }
00482 
00483 void
00484 BlockACK::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const
00485 {
00486     if(getCommand(commandPool)->isACK())
00487     {
00488         commandPoolSize = this->baBits;
00489         dataSize = 0;
00490         return;
00491     }
00492 
00493     if(getCommand(commandPool)->isACKreq())
00494     {
00495         commandPoolSize = this->baReqBits;
00496         dataSize = 0;
00497         return;
00498     }
00499 
00500     getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this);
00501 }
00502 
00503 void BlockACK::printTxQueueStatus() const
00504 {
00505     if (currentTxQueue != NULL)
00506     {
00507         MESSAGE_SINGLE(NORMAL, this->logger, "TxQueue to " << currentTxQueue->getReceiver() << " waits for ACK: " << currentTxQueue->waitsForACK());
00508     }
00509     else
00510     {
00511         MESSAGE_SINGLE(NORMAL, this->logger, "no transmission queue allocated yet");
00512     }
00513 }
00514 
00515 unsigned int
00516 BlockACK::getTransmissionCounter(const wns::ldk::CompoundPtr& compound) const
00517 {
00518     if(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this))
00519     {
00520         return(this->getCommand(compound)->localTransmissionCounter);
00521     }
00522     else
00523     {
00524         return 1;
00525     }
00526 }
00527 
00528 void
00529 BlockACK::copyTransmissionCounter(const wns::ldk::CompoundPtr& src, const wns::ldk::CompoundPtr& dst)
00530 {
00531     this->activateCommand(dst->getCommandPool())->localTransmissionCounter = this->getCommand(src)->localTransmissionCounter;
00532 }
00533 

Generated on Mon May 21 03:32:11 2012 for openWNS by  doxygen 1.5.5