User Manual, Developers Guide and API Documentation

SelectiveRepeat.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 
00029 #include <WNS/ldk/arq/SelectiveRepeat.hpp>
00030 #include <WNS/ldk/Layer.hpp>
00031 #include <WNS/pyconfig/View.hpp>
00032 #include <WNS/Assure.hpp>
00033 
00034 using namespace wns::ldk;
00035 using namespace wns::ldk::arq;
00036 
00037 
00038 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00039     SelectiveRepeat,
00040     ARQ,
00041     "wns.arq.SelectiveRepeat",
00042     FUNConfigCreator);
00043 
00044 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00045     SelectiveRepeat,
00046     FunctionalUnit,
00047     "wns.arq.SelectiveRepeat",
00048     FUNConfigCreator);
00049 
00050 SelectiveRepeat::SelectiveRepeat(fun::FUN* fuNet, const wns::pyconfig::View& config) :
00051     ARQ(config),
00052 
00053     wns::ldk::fu::Plain<SelectiveRepeat, SelectiveRepeatCommand>(fuNet),
00054     Delayed<SelectiveRepeat>(),
00055     SuspendSupport(fuNet, config),
00056     CanTimeout(),
00057 
00058     windowSize(config.get<int>("windowSize")),
00059     sequenceNumberSize(config.get<int>("sequenceNumberSize")),
00060     commandSize(config.get<int>("commandSize")),
00061     NS(0),
00062     NR(0),
00063     LA(0),
00064     activeCompound(CompoundPtr()),
00065     sentPDUs(),
00066     toRetransmit(),
00067     ackPDUs(),
00068     receivedPDUs(),
00069     receivedACKs(),
00070     sendNow(false),
00071     resendTimeout(config.get<double>("resendTimeout")),
00072     retransmissionInterval(resendTimeout),
00073     transmissionAttemptsProbeBus( new wns::probe::bus::ContextCollector(
00074         wns::probe::bus::ContextProviderCollection(&fuNet->getLayer()->getContextProviderCollection()),
00075         config.get<std::string>("probeName"))),
00076     ackDelayProbeBus( new wns::probe::bus::ContextCollector(
00077         wns::probe::bus::ContextProviderCollection(&fuNet->getLayer()->getContextProviderCollection()),
00078         config.get<std::string>("ackDelayProbeName"))),
00079     roundTripTimeProbeBus( new wns::probe::bus::ContextCollector(
00080         wns::probe::bus::ContextProviderCollection(&fuNet->getLayer()->getContextProviderCollection()),
00081         config.get<std::string>("RTTProbeName"))),
00082     delayingDelivery(false),
00083     logger(config.get("logger"))
00084 {
00085     assure(windowSize >= 2, "Invalid windowSize.");
00086     assure(sequenceNumberSize >= 2*windowSize, "Maximum sequence number is to small for chosen windowSize");
00087 }
00088 
00089 
00090 SelectiveRepeat::~SelectiveRepeat()
00091 {
00092     // empty internal buffers
00093     ackPDUs.clear();
00094     sentPDUs.clear();
00095     toRetransmit.clear();
00096     receivedPDUs.clear();
00097     receivedACKs.clear();
00098 }
00099 
00100 
00101 bool
00102 SelectiveRepeat::hasCapacity() const
00103 {
00104     /* Make sure we
00105        1. don't have an active PDU we are processing
00106        2. aren't occupied with retransmissions
00107        3. don't exceed the sending window
00108     */
00109     return (this->activeCompound == CompoundPtr()
00110         && this->retransmissionState() == false
00111         && this->NS - this->LA < this->windowSize);
00112 }
00113 
00114 
00115 void
00116 SelectiveRepeat::processOutgoing(const CompoundPtr& compound)
00117 {
00118     assure(hasCapacity(), "processOutgoing called although not accepting.");
00119     activeCompound = compound;
00120 
00121     SelectiveRepeatCommand* command = activateCommand(compound->getCommandPool());
00122     this->commitSizes(compound->getCommandPool());
00123 
00124     command->peer.type = SelectiveRepeatCommand::I;
00125     command->setNS(NS);
00126 
00127     MESSAGE_BEGIN(NORMAL, logger, m,  "processOutgoing NS -> ");
00128     m << command->getNS();
00129     MESSAGE_END();
00130 
00131     ++NS;
00132 
00133     sendNow = true;
00134 }
00135 
00136 
00137 const wns::ldk::CompoundPtr
00138 SelectiveRepeat::hasACK() const
00139 {
00140     if(ackPDUs.empty() == false)
00141     {
00142         return ackPDUs.front();
00143     }
00144 
00145     return CompoundPtr();
00146 }
00147 
00148 
00149 const wns::ldk::CompoundPtr
00150 SelectiveRepeat::hasData() const
00151 {
00152     if(retransmissionState() == true)
00153     {
00154         return toRetransmit.front();
00155     }
00156 
00157     if(activeCompound != CompoundPtr() && sendNow == true)
00158     {
00159         return activeCompound;
00160     }
00161 
00162     return CompoundPtr();
00163 } // hasData
00164 
00165 
00166 wns::ldk::CompoundPtr
00167 SelectiveRepeat::getACK()
00168 {
00169     assure(hasACK(), getFUN()->getName() + " hasSomethingToSend has not been called to check whether there is something to send.");
00170 
00171     CompoundPtr nextACKToBeSent = ackPDUs.front();
00172     ackPDUs.pop_front();
00173 
00174     MESSAGE_BEGIN(NORMAL, logger, m, "Sent ACK frame ");
00175     m << getCommand(nextACKToBeSent->getCommandPool())->getNS();
00176     MESSAGE_END();
00177 
00178     return nextACKToBeSent;
00179 } // getACK
00180 
00181 
00182 wns::ldk::CompoundPtr
00183 SelectiveRepeat::getData()
00184 {
00185     if(retransmissionState() == true)
00186     {
00187         assure(
00188             toRetransmit.empty() == false,
00189             getFUN()->getName() + " is in retransmission state without anything to retransmit.");
00190 
00191         MESSAGE_BEGIN(NORMAL, logger, m, "Number of Frames to retransmit: ");
00192         m << toRetransmit.size();
00193         MESSAGE_END();
00194 
00195         // get first segment to retransmit
00196         CompoundPtr nextPDUToBeRetransmit = toRetransmit.front();
00197         // keep track of the number of retransmissions
00198         SelectiveRepeatCommand* command = this->getCommand(nextPDUToBeRetransmit);
00199         command->localTransmissionCounter++;
00200         // record the simTime when we made the last attempt to send this compound
00201         command->local.lastSentTime = wns::simulator::getEventScheduler()->getTime();
00202 
00203         // delete from beginning of retransmission buffer and store it
00204         // to the end of the sent buffer
00205         toRetransmit.pop_front();
00206         sentPDUs.push_back(nextPDUToBeRetransmit);
00207 
00208         MESSAGE_BEGIN(NORMAL, logger, m, "Re-Sent I frame ");
00209         m << getCommand(nextPDUToBeRetransmit->getCommandPool())->getNS();
00210         MESSAGE_END();
00211 
00212         // print out whether we leave retransmission state
00213         if(retransmissionState() == false)
00214         {
00215             MESSAGE_SINGLE(NORMAL, logger, "Leaving retransmission state");
00216         }
00217 
00218         // set the Timer
00219         this->setNewTimeout(resendTimeout);
00220         // and send a copy
00221         return nextPDUToBeRetransmit->copy();
00222     }
00223 
00224 
00225     // send a copy
00226     sendNow = false;
00227     setNewTimeout(resendTimeout);
00228     SelectiveRepeatCommand* myCommand = this->getCommand(activeCompound);
00229     // record the simTime when we made the first and the last attempt to send this compound
00230     myCommand->local.firstSentTime = wns::simulator::getEventScheduler()->getTime();
00231     myCommand->local.lastSentTime = wns::simulator::getEventScheduler()->getTime();
00232     // keep track of the number of retransmissions
00233     myCommand->localTransmissionCounter++;
00234     CompoundPtr it = activeCompound->copy();
00235     // store the PDU we now send in the Retransmission FIFO Buffer
00236     sentPDUs.push_back(activeCompound);
00237     // empty the space for new outgoing compounds
00238     activeCompound = CompoundPtr();
00239 
00240     MESSAGE_BEGIN(NORMAL, logger, m, "Sent I frame ");
00241     m << getCommand(it->getCommandPool())->getNS();
00242     MESSAGE_END();
00243 
00244     return it;
00245 }
00246 
00247 
00248 void
00249 SelectiveRepeat::onTimeout()
00250 {
00251     assure(sentPDUs.empty() == false, "No timeout without any sent frames possible");
00252 
00253     MESSAGE_SINGLE(NORMAL, logger, "Entering retransmission state on timeout");
00254 
00255     this->prepareRetransmission();
00256 
00257     // initiate retransmissions
00258     this->tryToSend();
00259 }
00260 
00261 
00262 void
00263 SelectiveRepeat::processIncoming(const CompoundPtr& compound)
00264 {
00265     SelectiveRepeatCommand *command = this->getCommand(compound);
00266 
00267     switch(command->peer.type)
00268     {
00269     case SelectiveRepeatCommand::I:
00270     {
00271         this->onIFrame(compound);
00272         break;
00273     }
00274 
00275     case SelectiveRepeatCommand::ACK:
00276     {
00277         this->onACKFrame(compound);
00278         break;
00279     }
00280     }
00281 }
00282 
00283 void
00284 SelectiveRepeat::onIFrame(const CompoundPtr& compound)
00285 {
00286     SelectiveRepeatCommand* command = this->getCommand(compound);
00287 
00288     MESSAGE_BEGIN(NORMAL, logger, m, "Received I frame.");
00289     m << " expected " << NR
00290       << " received " << command->getNS();
00291     MESSAGE_END();
00292 
00293     if(command->getNS() == NR && delayingDelivery == false)
00294     {
00295         // this is the I frame we waited for.
00296         MESSAGE_BEGIN(NORMAL, logger, m, "Delivering I frame ");
00297         m << NR;
00298         MESSAGE_END();
00299 
00300         this->getDeliverer()->getAcceptor(compound)->onData(compound);
00301         ++NR;
00302 
00303         // check if there are subsequent frames we have already received
00304         while (receivedPDUs.empty() == false)
00305         {
00306             ARQCommand::SequenceNumber toDeliver =  getCommand(receivedPDUs.front())->getNS();
00307 
00308             if(toDeliver != NR)
00309             {
00310                 break;
00311             }
00312 
00313             assure(toDeliver == NR,
00314                    "NS must be equal to NR since the loop will not be entered if it's greater zero and it cannot be smaller!!");
00315             // if so, deliver them
00316             MESSAGE_BEGIN(NORMAL, logger, m, "Delivering I frame ");
00317             m << NR;
00318             MESSAGE_END();
00319 
00320             getDeliverer()->getAcceptor(receivedPDUs.front())->onData(receivedPDUs.front());
00321 
00322             // and remove them from the receivedPDUs list.
00323             receivedPDUs.pop_front();
00324             MESSAGE_BEGIN(NORMAL, logger, m, "Removing from receivedPDUs: I-Frame ");
00325             m << NR;
00326             MESSAGE_END();
00327 
00328             // adjust received PDU counter
00329             ++NR;
00330         }
00331     } else {
00332         // we received an out-of-sequence frame
00333         if(command->getNS() > NR) {
00334             MESSAGE_BEGIN(NORMAL, logger, m,"Buffering out-of-sequence I frame ");
00335             m << command->getNS();
00336             MESSAGE_END();
00337 
00338             // store the received frame for later
00339             keepSorted(compound, receivedPDUs);
00340         } else {
00341             /* we received an old frame (ACK got lost)
00342                re-send the ACK and discard the frame */
00343         }
00344     }
00345 
00346     if (delayingDelivery == false || command->getNS() > NR)
00347     {
00348         // acknowledge the received I-Frame
00349         CommandPool* ackPCI = getFUN()->getProxy()->createReply(compound->getCommandPool(), this);
00350         CompoundPtr ack = CompoundPtr(new Compound(ackPCI));
00351         ackPDUs.push_back(ack);
00352         SelectiveRepeatCommand* ackCommand = activateCommand(ackPCI);
00353         this->commitSizes(ack->getCommandPool());
00354 
00355         ackCommand->peer.type = SelectiveRepeatCommand::ACK;
00356         ackCommand->setNS(  getCommand(compound)->getNS() );
00357         ackCommand->magic.ackSentTime = wns::simulator::getEventScheduler()->getTime();
00358 
00359         MESSAGE_BEGIN(NORMAL, logger, m, "Number of ACKs pending: ");
00360         m << ackPDUs.size();
00361         MESSAGE_END();
00362     }
00363 
00364 } // onIFrame
00365 
00366 void
00367 SelectiveRepeat::onACKFrame(const CompoundPtr& compound)
00368 {
00369     SelectiveRepeatCommand* command = this->getCommand(compound);
00370 
00371     // Delete ACKed frame from one of the retransmission buffers
00372     // it may happen, that due to duplicate ACKs the PDU is neither in sentPDUs
00373     // nor in toRetransmit
00374     this->removeACKed(compound, this->sentPDUs);
00375     this->removeACKed(compound, this->toRetransmit);
00376 
00377     if(command->getNS() == this->LA )
00378     {
00379         // received the expected ACK
00380         MESSAGE_BEGIN(NORMAL, this->logger, m, "Received ACK frame.");
00381         m << " expected " << this->LA << " received " << command->getNS();
00382         MESSAGE_END();
00383         // adjust counter (advance sending window)
00384         this->LA++;
00385         // probe the time this ACK took to travel back to me
00386         this->ackDelayProbeBus->put( compound, wns::simulator::getEventScheduler()->getTime() - command->magic.ackSentTime );
00387 
00388         // Now check if subsequent ACKs have been received before
00389         while(this->receivedACKs.empty() == false)
00390         {
00391             if(this->getCommand(this->receivedACKs.front())->getNS() == this->LA)
00392             {
00393                 this->LA++;
00394                 this->receivedACKs.front() = CompoundPtr();
00395                 this->receivedACKs.pop_front();
00396             }
00397             else
00398             {
00399                 break;
00400             }
00401         }
00402         this->trySuspend();
00403     }
00404     else
00405     {
00406         //received out-of-sequence ACK
00407         MESSAGE_BEGIN(NORMAL, logger, m, "Received Out-of-sequence ACK frame");
00408         m << " expected " << this->LA << " received " << command->getNS();
00409         MESSAGE_END();
00410 
00411         // probe the time this ACK took to travel back to me
00412         this->ackDelayProbeBus->put( compound, wns::simulator::getEventScheduler()->getTime() - command->magic.ackSentTime );
00413 
00414         if (command->getNS() > this->LA)
00415         {
00416             // Enter Retransmission State
00417             MESSAGE_SINGLE(NORMAL, logger,"Entering retransmission state on out-of-sequence ACK");
00418             // push current ACK to the list of received ones
00419             this->keepSorted(compound, this->receivedACKs);
00420             // prepare PDU List for Retransmission
00421             this->prepareRetransmission();
00422             if (this->retransmissionState() == false)
00423             {
00424                 MESSAGE_SINGLE(NORMAL, logger,"Leaving retransmission state, no Retransmissions pending.");
00425             }
00426         }
00427         else
00428         {
00429             MESSAGE_SINGLE(NORMAL, logger, "ACK is a duplicate, discarding ...");
00430         }
00431     }
00432 
00433     if (this->sentPDUs.empty() == true && this->hasTimeoutSet() == true)
00434     {
00435         this->cancelTimeout();
00436     }
00437     // Take care of pending retransmissions, if any
00438     if (this->retransmissionState())
00439     {
00440         this->tryToSend();
00441     }
00442 } // onACKFrame
00443 
00444 
00445 void
00446 SelectiveRepeat::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const
00447 {
00448     //What are the sizes in the upper Layers
00449     getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this);
00450 
00451 
00452     MESSAGE_SINGLE(VERBOSE, logger, "Size calc - Command: "<<commandPoolSize<<" Payload: "<<sduSize);
00453 
00454     MESSAGE_SINGLE(VERBOSE, logger, "Size of SR-ARQ Command: "<<commandSize<<" Bit");
00455 
00456     commandPoolSize += commandSize;
00457 
00458     MESSAGE_SINGLE(VERBOSE, logger, "Size calc - Command: "<<commandPoolSize<<" Payload: "<<sduSize);
00459 } // calculateSizes
00460 
00461 
00462 void
00463 SelectiveRepeat::prepareRetransmission()
00464 {
00465     bool retransmitAll = false;
00466     ARQCommand::SequenceNumber lastACK(0);
00467     if (receivedACKs.empty() == true)
00468     {
00469         // no ACKs received so far
00470         retransmitAll = true;
00471     }
00472     else
00473     {
00474         // remember the last ACK
00475         lastACK = this->getCommand(receivedACKs.back())->getNS();
00476     }
00477 
00478     for (CompoundContainer::iterator it = sentPDUs.begin(); it != sentPDUs.end();   )
00479     {
00480         SelectiveRepeatCommand* command = this->getCommand(*it);
00481         ARQCommand::SequenceNumber lookingAt = command->getNS();
00482         if ( lookingAt < lastACK || retransmitAll )
00483         {
00484             if (command->local.lastSentTime+retransmissionInterval <= wns::simulator::getEventScheduler()->getTime()
00485                 ||
00486                 command->local.lastSentTime==command->local.firstSentTime)
00487             {
00488                 MESSAGE_BEGIN(NORMAL, logger, m,  "Chosing I-Frame ");
00489                 m << lookingAt << " for retransmission:";
00490                 MESSAGE_END();
00491 
00492                 CompoundContainer::iterator copyOfIt = it++;
00493                 toRetransmit.push_back((*copyOfIt));
00494 
00495                 // collect statistics available for other FUs
00496                 this->statusCollector->onFailedTransmission((*copyOfIt));
00497 
00498                 sentPDUs.erase(copyOfIt);
00499                 continue;
00500             }
00501         }
00502         ++it;
00503     }
00504 } // prepareRetransmission
00505 
00506 
00507 void
00508 SelectiveRepeat::keepSorted(const CompoundPtr& compound, CompoundContainer& container)
00509 {
00510     SelectiveRepeatCommand* command = this->getCommand(compound);
00511 
00512     ARQCommand::SequenceNumber toInsert = command->getNS();
00513     CompoundContainer::iterator it;
00514     CompoundContainer::iterator itEnd = container.end();
00515 
00516     for(it = container.begin(); it != itEnd; ++it)
00517     {
00518         ARQCommand::SequenceNumber lookingAt = getCommand(*it)->getNS();
00519 
00520         if(lookingAt == toInsert)
00521         {
00522             MESSAGE_SINGLE(NORMAL, logger, "Don't need to insert, already in list");
00523             return;
00524         }
00525 
00526         if(lookingAt > toInsert)
00527         {
00528             break;
00529         }
00530     }
00531     container.insert(it, compound);
00532 } // keepSorted
00533 
00534 
00535 // remove ACKed PDU from list
00536 void
00537 SelectiveRepeat::removeACKed(const CompoundPtr& ackCompound, CompoundContainer& container)
00538 {
00539     SelectiveRepeatCommand* command = getCommand(ackCompound->getCommandPool());
00540     int NS = command->getNS();
00541     for(CompoundContainer::iterator iter = container.begin();  iter != container.end(); ++iter )
00542     {
00543         if(getCommand((*iter)->getCommandPool())->getNS() == NS)
00544         {
00545             // a probe counting the number of transmissions needed
00546             transmissionAttemptsProbeBus->put( ackCompound, getCommand(*iter)->localTransmissionCounter);
00547             // a probe counting the RoundTripTime needed
00548             simTimeType rtt = wns::simulator::getEventScheduler()->getTime() - getCommand((*iter)->getCommandPool())->local.firstSentTime;
00549             roundTripTimeProbeBus->put(ackCompound, rtt);
00550             // adjust min time between retransmissions to two times the RTT
00551             retransmissionInterval = std::min<simTimeType>(2*rtt, retransmissionInterval);
00552 
00553             // collect statistics available for other FUs
00554             this->statusCollector->onSuccessfullTransmission((*iter));
00555 
00556             MESSAGE_BEGIN(NORMAL, logger, m, "ACK frame received after ");
00557             m << rtt << " s and " << getCommand(*iter)->localTransmissionCounter << " transmission attempts. RTI is now " << retransmissionInterval;
00558             MESSAGE_END();
00559             container.erase(iter);
00560             break;
00561         }
00562     }
00563 }
00564 
00565 // return whether we are in retransmission mode
00566 bool
00567 SelectiveRepeat::retransmissionState() const
00568 {
00569     return !toRetransmit.empty();
00570 }
00571 
00572 bool
00573 SelectiveRepeat::onSuspend() const
00574 {
00575     return NS == LA;
00576 } // onSuspend
00577 
00578 void
00579 SelectiveRepeat::doDelayDelivery()
00580 {
00581     delayingDelivery = true;
00582 } // doDelayDelivery
00583 
00584 void
00585 SelectiveRepeat::doDeliver()
00586 {
00587     delayingDelivery = false;
00588 
00589     // check if there are subsequent frames we have already received
00590     while (!receivedPDUs.empty()) {
00591         ARQCommand::SequenceNumber toDeliver =  getCommand(receivedPDUs.front())->getNS();
00592 
00593         if(toDeliver != NR)
00594         {
00595             break;
00596         }
00597 
00598         assure(toDeliver == NR,
00599                "NS must be equal to NR since the loop will not be entered if it's greater zero and it cannot be smaller!!");
00600         // if so, deliver them
00601         MESSAGE_BEGIN(NORMAL, logger, m, "Delivering I frame ");
00602         m << NR;
00603         MESSAGE_END();
00604 
00605         getDeliverer()->getAcceptor(receivedPDUs.front())->onData(receivedPDUs.front());
00606 
00607         // and remove them from the receivedPDUs list.
00608         receivedPDUs.pop_front();
00609         MESSAGE_BEGIN(NORMAL, logger, m, "Removing from receivedPDUs: I-Frame ");
00610         m << NR;
00611         MESSAGE_END();
00612 
00613         // adjust received PDU counter
00614         ++NR;
00615     }
00616 
00617 } // doDeliver
00618 
00619 

Generated on Fri May 25 03:31:40 2012 for openWNS by  doxygen 1.5.5