User Manual, Developers Guide and API Documentation

StopAndWaitARQ.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 
00030 #include <WIFIMAC/lowerMAC/StopAndWaitARQ.hpp>
00031 #include <WIFIMAC/FrameType.hpp>
00032 
00033 #include <WNS/probe/bus/utils.hpp>
00034 
00035 using namespace wifimac::lowerMAC;
00036 
00037 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00038     wifimac::lowerMAC::StopAndWaitARQ,
00039     wns::ldk::FunctionalUnit,
00040     "wifimac.lowerMAC.StopAndWaitARQ",
00041     wns::ldk::FUNConfigCreator);
00042 
00043 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00044     wifimac::lowerMAC::StopAndWaitARQ,
00045     wns::ldk::probe::Probe,
00046     "wifimac.lowerMAC.StopAndWaitARQ",
00047     wns::ldk::FUNConfigCreator);
00048 
00049 StopAndWaitARQ::StopAndWaitARQ(wns::ldk::fun::FUN* fuNet, const wns::pyconfig::View& config) :
00050     wns::ldk::arq::StopAndWait(fuNet, config),
00051     rxsName(config.get<std::string>("rxStartName")),
00052     txStartEndName(config.get<std::string>("txStartEndName")),
00053     managerName(config.get<std::string>("managerName")),
00054     perMIBServiceName(config.get<std::string>("perMIBServiceName")),
00055     shortRetryLimit(config.get<int>("shortRetryLimit")),
00056     longRetryLimit(config.get<int>("longRetryLimit")),
00057     stationShortRetryCounter(0),
00058     stationLongRetryCounter(0),
00059     shortRetryCounter(0),
00060     longRetryCounter(0),
00061     rtsctsThreshold(config.get<Bit>("rtsctsThreshold")),
00062     sifsDuration(config.get<wns::simulator::Time>("sifsDuration")),
00063     maximumACKDuration(config.get<wns::simulator::Time>("maximumACKDuration")),
00064     ackTimeout(config.get<wns::simulator::Time>("ackTimeout")),
00065     ackPhyMode(config.getView("ackPhyMode")),
00066     bianchiRetryCounter(config.get<bool>("bianchiRetryCounter")),
00067     ackState(none)
00068 {
00069     friends.manager = NULL;
00070 
00071     // read the localIDs from the config
00072     wns::probe::bus::ContextProviderCollection localContext(&fuNet->getLayer()->getContextProviderCollection());
00073     for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii)
00074     {
00075         std::string key = config.get<std::string>("localIDs.keys()",ii);
00076         unsigned long int value  = config.get<unsigned long int>("localIDs.values()",ii);
00077         localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value));
00078         MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value);
00079     }
00080     numTxAttemptsProbe = wns::probe::bus::collector(localContext, config, "numTxAttemptsProbeName");
00081 }
00082 
00083 void StopAndWaitARQ::onFUNCreated()
00084 {
00085     // Observe rxStart
00086     this->wns::Observer<wifimac::convergence::IRxStartEnd>::startObserving
00087         (getFUN()->findFriend<wifimac::convergence::RxStartEndNotification*>(rxsName));
00088 
00089     // Observe txStartEnd
00090     this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving
00091         (getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName));
00092 
00093     // get manager
00094     friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName);
00095 
00096     // signal packet success/errors to MIB
00097     perMIB = getFUN()->getLayer<dll::ILayer2*>()->getManagementService<wifimac::management::PERInformationBase>(perMIBServiceName);
00098 }
00099 
00100 
00101 wns::ldk::CompoundPtr StopAndWaitARQ::getData()
00102 {
00103     sendNow = false;
00104 
00105     // send a copy
00106     return activeCompound->copy();
00107 }
00108 
00109 void StopAndWaitARQ::onRxStart(wns::simulator::Time /*expRxTime*/)
00110 {
00111     if (ackState == waitForACK)
00112     {
00113         assure(this->activeCompound, "state is waitForACK but no active compound");
00114         assure(hasTimeoutSet(), "ackState is waiting but no timeout set?");
00115 
00116         MESSAGE_SINGLE(NORMAL, logger, "got rxStartIndication, wait for ACK delivery");
00117         ackState = receiving;
00118     }
00119 }
00120 
00121 void StopAndWaitARQ::onRxEnd()
00122 {
00123     if (ackState == receiving)
00124     {
00125         assure(this->activeCompound, "state is receiving but no active compound");
00126         ackState = receptionFinished;
00127         if(not hasTimeoutSet())
00128         {
00129             setTimeout(10e-9);
00130             MESSAGE_SINGLE(NORMAL, logger, "onRxEnd and waiting for ACK -> set short timeout");
00131         }
00132 
00133     }
00134 }
00135 
00136 void StopAndWaitARQ::onRxError()
00137 {
00138     if(ackState == receiving)
00139     {
00140         assure(this->activeCompound, "state is waitForACK/receiving but no active compound");
00141         MESSAGE_SINGLE(NORMAL, logger, "onRxError and waiting for ACK -> failure");
00142 
00143         // return to waitForACK
00144         ackState = waitForACK;
00145 
00146         if(not hasTimeoutSet())
00147         {
00148             this->onTimeout();
00149         }
00150     }
00151 }
00152 
00153 void
00154 StopAndWaitARQ::onTxStart(const wns::ldk::CompoundPtr& compound)
00155 {
00156     // this is just for the resetting of the short retry counters in the case
00157     // that a long frame used RTS/CTS for its transmission. If the tx starts AND
00158     // the data is long, the CTS was received and hence the counters can be
00159     // reset
00160     if(this->activeCompound and
00161        ((friends.manager->getFrameType(compound->getCommandPool()) == DATA) or (friends.manager->getFrameType(compound->getCommandPool()) == DATA_TXOP)) and
00162        (compound->getBirthmark() == this->activeCompound->getBirthmark()))
00163     {
00164         Bit commandPoolSize;
00165         Bit dataSize;
00166         this->calculateSizes(compound->getCommandPool(), commandPoolSize, dataSize);
00167         Bit psduSize = commandPoolSize + dataSize;
00168 
00169         if(psduSize > rtsctsThreshold)
00170         {
00171             MESSAGE_SINGLE(NORMAL, logger, "Data is sent --> CTS received successfully --> reset short retry counters");
00172             shortRetryCounter = 0;
00173             stationShortRetryCounter = 0;
00174         }
00175     }
00176 
00177 }
00178 
00179 void
00180 StopAndWaitARQ::onTxEnd(const wns::ldk::CompoundPtr& compound)
00181 {
00182     if(this->activeCompound and
00183        ((friends.manager->getFrameType(compound->getCommandPool()) == DATA) or (friends.manager->getFrameType(compound->getCommandPool()) == DATA_TXOP)) and
00184        (compound->getBirthmark() == this->activeCompound->getBirthmark()))
00185     {
00186         ackState = waitForACK;
00187         setNewTimeout(ackTimeout);
00188         MESSAGE_SINGLE(NORMAL, logger, "Data is sent, waiting for ACK for " << ackTimeout);
00189     }
00190     else
00191     {
00192         if(this->ackState == sendingACK)
00193         {
00194             MESSAGE_SINGLE(NORMAL, logger, "done sending ack");
00195             this->ackState = none;
00196             this->tryToSend();
00197         }
00198     }
00199 }
00200 
00201 void StopAndWaitARQ::processOutgoing(const wns::ldk::CompoundPtr& compound)
00202 {
00203     if(friends.manager->lifetimeExpired(compound->getCommandPool()))
00204     {
00205         MESSAGE_SINGLE(NORMAL, logger, "outgoing compound has expired lifetime -> drop");
00206     }
00207     else
00208     {
00209         // TODO: Set the frame exchange duration here
00210         friends.manager->setReplyTimeout(compound->getCommandPool(), ackTimeout);
00211         wns::ldk::arq::StopAndWait::processOutgoing(compound);
00212 
00213         if(not this->bianchiRetryCounter)
00214         {
00215             // According to the standard, the retransmission counter is set by
00216             // the station (short|long) counters
00217             getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter =
00218                 stationShortRetryCounter + stationLongRetryCounter + 1;
00219         }
00220     }
00221 }
00222 
00223 void StopAndWaitARQ::processIncoming(const wns::ldk::CompoundPtr& compound)
00224 {
00225     wns::ldk::arq::StopAndWaitCommand* command = this->getCommand(compound->getCommandPool());
00226 
00227     if(command->isACK())
00228     {
00229         MESSAGE_SINGLE(NORMAL, this->logger, "Received ACK frame, consider current frame as done");
00230 
00231         assure(this->ackState == receptionFinished, "Received ACK but not waiting for ack");
00232         assure(this->activeCompound, "Received ACK but no active compound");
00233 
00234         this->statusCollector->onSuccessfullTransmission(this->activeCompound);
00235         this->perMIB->onSuccessfullTransmission(friends.manager->getReceiverAddress(this->activeCompound->getCommandPool()));
00236         numTxAttemptsProbe->put(this->activeCompound, shortRetryCounter + longRetryCounter + 1);
00237 
00238         // received acknowledgement frame for the current compound --> reset counters
00239         Bit commandPoolSize;
00240         Bit dataSize;
00241         this->calculateSizes(activeCompound->getCommandPool(), commandPoolSize, dataSize);
00242         Bit psduSize = commandPoolSize + dataSize;
00243 
00244         if(psduSize > rtsctsThreshold)
00245         {
00246             longRetryCounter = 0;
00247             stationLongRetryCounter = 0;
00248         }
00249         else
00250         {
00251             shortRetryCounter = 0;
00252             stationShortRetryCounter = 0;
00253         }
00254 
00255         this->activeCompound = wns::ldk::CompoundPtr();
00256         this->ackState = none;
00257 
00258         if(this->hasTimeoutSet())
00259         {
00260             this->cancelTimeout();
00261         }
00262     }
00263     else
00264     {
00265         MESSAGE_SINGLE(NORMAL, this->logger, "Received DATA frame, reply with ACK");
00266 
00267         // send ACK
00268         wns::ldk::CommandPool* ackPCI = this->getFUN()->getProxy()->createReply(compound->getCommandPool(), this);
00269         this->ackCompound = wns::ldk::CompoundPtr(new wns::ldk::Compound(ackPCI));
00270         friends.manager->setFrameType(ackPCI, ACK);
00271         friends.manager->setPhyMode(ackPCI, ackPhyMode);
00272         wns::simulator::Time fxDur = friends.manager->getFrameExchangeDuration(compound->getCommandPool()) - sifsDuration - maximumACKDuration;
00273         if (fxDur < sifsDuration)
00274         {
00275             fxDur = 0;
00276         }
00277 
00278         MESSAGE_SINGLE(NORMAL,logger,"create ACK with exchange duration : " << fxDur);
00279 
00280         friends.manager->setFrameExchangeDuration(ackPCI,
00281                                                   fxDur);
00282         wns::ldk::arq::StopAndWaitCommand* ackCommand = this->activateCommand(ackPCI);
00283         ackCommand->peer.type = wns::ldk::arq::StopAndWaitCommand::RR;
00284         this->ackState = sendingACK;
00285         assure(getConnector()->hasAcceptor(this->ackCompound), "No acceptor for ACK");
00286 
00287         // deliver frame
00288         getDeliverer()->getAcceptor(compound)->onData(compound);
00289     }
00290 }
00291 
00292 bool
00293 StopAndWaitARQ::hasCapacity() const
00294 {
00295     return (!this->activeCompound) and (!this->ackCompound) and (this->ackState != sendingACK);
00296 }
00297 
00298 void
00299 StopAndWaitARQ::onTransmissionHasFailed(const wns::ldk::CompoundPtr& compound)
00300 {
00301     // indication from RTS/CTS that the CTS was not received
00302     ++shortRetryCounter;
00303     ++stationShortRetryCounter;
00304 
00305     MESSAGE_BEGIN(NORMAL, logger, m, "Missing CTS, retry counters now:");
00306     m << " src " << shortRetryCounter;
00307     m << " ssrc " << stationShortRetryCounter;
00308     m << " (limit " << shortRetryLimit << ")";
00309     m << " lrc " << longRetryCounter;
00310     m << " slrc " << stationLongRetryCounter;
00311     m << " (limit " << longRetryLimit << ")";
00312     MESSAGE_END();
00313 
00314     this->transmissionHasFailed(compound);
00315 }
00316 
00317 void StopAndWaitARQ::onTimeout()
00318 {
00319     if(ackState == receiving)
00320     {
00321         MESSAGE_SINGLE(NORMAL, this->logger, "Started reception during wait for ACK -> wait for delivery");
00322         return;
00323     }
00324 
00325     // ACK was not received before timeout
00326     assure(this->activeCompound, "no active compound, no failed transmission");
00327 
00328     // get the PSDU size
00329     Bit commandPoolSize;
00330     Bit dataSize;
00331     this->calculateSizes(activeCompound->getCommandPool(), commandPoolSize, dataSize);
00332     Bit psduSize = commandPoolSize + dataSize;
00333 
00334     if(psduSize <= rtsctsThreshold)
00335     {
00336         ++shortRetryCounter;
00337         ++stationShortRetryCounter;
00338     }
00339     else
00340     {
00341         ++longRetryCounter;
00342         ++stationLongRetryCounter;
00343     }
00344 
00345     MESSAGE_BEGIN(NORMAL, logger, m, "Timeout of ACK, retry counters now:");
00346     m << " src " << shortRetryCounter;
00347     m << " ssrc " << stationShortRetryCounter;
00348     m << " (limit " << shortRetryLimit << ")";
00349     m << " lrc " << longRetryCounter;
00350     m << " slrc " << stationLongRetryCounter;
00351     m << " (limit " << longRetryLimit << ")";
00352     MESSAGE_END();
00353 
00354     this->perMIB->onFailedTransmission(friends.manager->getReceiverAddress(activeCompound->getCommandPool()));
00355     this->transmissionHasFailed(activeCompound);
00356 }
00357 
00358 void
00359 StopAndWaitARQ::transmissionHasFailed(const wns::ldk::CompoundPtr& compound)
00360 {
00361     assure(this->activeCompound, "no active compound, no failed transmission");
00362     assure(friends.manager->getFrameType(compound->getCommandPool()) == DATA, "compound must have type DATA");
00363     assure(compound->getBirthmark() == this->activeCompound->getBirthmark(), "compound has not same birthmark as active one");
00364 
00365     if(hasTimeoutSet())
00366     {
00367         cancelTimeout();
00368     }
00369 
00370     ackState = none;
00371 
00372     wns::ldk::arq::StopAndWaitCommand* command = this->getCommand(this->activeCompound);
00373 
00374     if((shortRetryCounter == shortRetryLimit) or
00375        (longRetryCounter == longRetryLimit) or
00376        (friends.manager->lifetimeExpired(compound->getCommandPool())))
00377     {
00378         MESSAGE_SINGLE(NORMAL, logger, "Failed transmission, txCounter has reached limit -> drop packet");
00379         this->statusCollector->onFailedTransmission(this->activeCompound);
00380         numTxAttemptsProbe->put(this->activeCompound, shortRetryCounter + longRetryCounter + 1);
00381         // reset retry counters, but NOT station retry counters!
00382         shortRetryCounter = 0;
00383         longRetryCounter = 0;
00384 
00385         this->sendNow = false;
00386         this->activeCompound = wns::ldk::CompoundPtr();
00387         this->tryToSend();
00388     }
00389     else
00390     {
00391         wns::ldk::arq::StopAndWait::onTimeout();
00392         // The backoff will select the size of the contention window (cw)
00393         // according to the number or retries. Hence, setting this correctly is
00394         // important.
00395 
00396         if(this->bianchiRetryCounter)
00397         {
00398             // This implements the retry counter as described in the Bianchi DCF
00399             // model: Every new compound resets the number of retries,
00400             // independently from the failure of the compound before. Hence, the
00401             // number of transmissions is the src+lrc+1.
00402 
00403             getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter =
00404                 shortRetryCounter + longRetryCounter + 1;
00405         }
00406         else
00407         {
00408             // This implements the standard (IEEE 802.11-2007): The cw size is
00409             // set according to the station (short|long) retry counter, which
00410             // are the same as the src/lrc as long as every compound is
00411             // transmitted successful eventually, i.e. before the retry limit.
00412             // If the retry limit is reached the first time, the cw is reset
00413             // (and the compound discarded). If even the second compound cannot
00414             // be transmitted and is discarded, the cw is NOT reset any more.
00415 
00416             if(stationShortRetryCounter < shortRetryLimit and stationLongRetryCounter < longRetryLimit)
00417             {
00418                 // no retry limit was reached so far
00419                 getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter =
00420                     stationShortRetryCounter + stationLongRetryCounter + 1;
00421             }
00422             else
00423             {
00424                 int newCounter = 0;
00425                 if(stationShortRetryCounter >= shortRetryLimit)
00426                 {
00427                     // the shortRetryLimit was reached (at least) once -> reduce
00428                     // the retry counter
00429                     newCounter += stationShortRetryCounter - shortRetryLimit;
00430                 }
00431                 else
00432                 {
00433                     newCounter += stationShortRetryCounter;
00434                 }
00435 
00436                 if(stationLongRetryCounter >= longRetryLimit)
00437                 {
00438                     // the longRetryLimit was reached (at least) once -> reduce
00439                     // the retry counter
00440                     newCounter += stationLongRetryCounter - longRetryLimit;
00441                 }
00442                 else
00443                 {
00444                     newCounter += stationLongRetryCounter;
00445                 }
00446 
00447                 // new transmission!
00448                 newCounter += 1;
00449 
00450                 assure(newCounter > 0, "Transmission counter must be greater than 0");
00451 
00452                 getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter = newCounter;
00453             }
00454         }
00455         MESSAGE_SINGLE(NORMAL, this->logger,
00456                        "Failed transmission, retransmit");
00457     }
00458 }
00459 
00460 unsigned int
00461 StopAndWaitARQ::getTransmissionCounter(const wns::ldk::CompoundPtr& compound) const
00462 {
00463     if(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this))
00464     {
00465         return(this->getCommand(compound)->localTransmissionCounter);
00466     }
00467     else
00468     {
00469         return 1;
00470     }
00471 }
00472 
00473 void
00474 StopAndWaitARQ::copyTransmissionCounter(const wns::ldk::CompoundPtr& src, const wns::ldk::CompoundPtr& dst)
00475 {
00476     wns::ldk::arq::StopAndWaitCommand* command = this->activateCommand(dst->getCommandPool());
00477     command->localTransmissionCounter = this->getCommand(src)->localTransmissionCounter;
00478 }

Generated on Sat May 26 03:32:09 2012 for openWNS by  doxygen 1.5.5