User Manual, Developers Guide and API Documentation

StopAndWait.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 #include <WNS/ldk/arq/StopAndWait.hpp>
00029 
00030 #include <WNS/pyconfig/View.hpp>
00031 #include <WNS/Assure.hpp>
00032 
00033 using namespace wns::ldk;
00034 using namespace wns::ldk::arq;
00035 
00036 
00037 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00038     StopAndWait,
00039     ARQ,
00040     "wns.arq.StopAndWait",
00041     FUNConfigCreator);
00042 
00043 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00044     StopAndWait,
00045     FunctionalUnit,
00046     "wns.arq.StopAndWait",
00047     FUNConfigCreator);
00048 
00049 StopAndWait::StopAndWait(fun::FUN* fuNet, const wns::pyconfig::View& config) :
00050     ARQ(config),
00051     wns::ldk::fu::Plain<StopAndWait, StopAndWaitCommand>(fuNet),
00052     Delayed<StopAndWait>(),
00053     SuspendSupport(fuNet, config),
00054     CanTimeout(),
00055 
00056     resendTimeout(config.get<double>("resendTimeout")),
00057     bitsPerIFrame(config.get<int>("bitsPerIFrame")),
00058     bitsPerRRFrame(config.get<int>("bitsPerRRFrame")),
00059 
00060     NS(0),
00061     NR(0),
00062     activeCompound(CompoundPtr()),
00063     ackCompound(CompoundPtr()),
00064     sendNow(false),
00065     logger(config.get("logger"))
00066 {
00067 } // StopAndWait
00068 
00069 
00070 StopAndWait::~StopAndWait()
00071 {
00072 } // ~StopAndWait
00073 
00074 
00075 bool
00076 StopAndWait::hasCapacity() const
00077 {
00078     return !this->activeCompound;
00079 } // hasCapacity
00080 
00081 
00082 void
00083 StopAndWait::processOutgoing(const CompoundPtr& compound)
00084 {
00085     assure(this->hasCapacity(), "processOutgoing called although not accepting.");
00086     this->activeCompound = compound;
00087 
00088     StopAndWaitCommand* command = this->activateCommand(compound->getCommandPool());
00089 
00090     command->peer.type = StopAndWaitCommand::I;
00091     command->peer.NS = this->NS;
00092     command->localTransmissionCounter = 1;
00093 
00094     MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName());
00095     m << " processOutgoing(compound),"
00096       << " sequence number (NS) of compound: " << command->peer.NS;
00097     MESSAGE_END();
00098 
00099     ++this->NS;
00100 
00101     this->sendNow = true;
00102 } // processOutgoing
00103 
00104 
00105 const wns::ldk::CompoundPtr
00106 StopAndWait::hasACK() const
00107 {
00108     return this->ackCompound;
00109 } // hasACK
00110 
00111 
00112 const wns::ldk::CompoundPtr
00113 StopAndWait::hasData() const
00114 {
00115     if(this->sendNow)
00116     {
00117         return this->activeCompound;
00118     }
00119     else
00120     {
00121         return CompoundPtr();
00122     }
00123 } // hasData
00124 
00125 
00126 wns::ldk::CompoundPtr
00127 StopAndWait::getACK()
00128 {
00129     CompoundPtr it = this->ackCompound;
00130     this->ackCompound = CompoundPtr();
00131 
00132     return it;
00133 } // getACK
00134 
00135 
00136 wns::ldk::CompoundPtr
00137 StopAndWait::getData()
00138 {
00139     this->sendNow = false;
00140     this->setTimeout(this->resendTimeout);
00141 
00142     // send a copy
00143     return this->activeCompound->copy();
00144 } // getData
00145 
00146 
00147 void
00148 StopAndWait::onTimeout()
00149 {
00150     assure(this->activeCompound, "Unexpected timeout.");
00151 
00152     this->statusCollector->onFailedTransmission(this->activeCompound);
00153 
00154     StopAndWaitCommand* command = this->getCommand(this->activeCompound);
00155     command->localTransmissionCounter++;
00156 
00157     MESSAGE_SINGLE(
00158         NORMAL,
00159         this->logger,
00160         "Timeout for compound with sequence number (NS) " << command->peer.NS <<
00161         ". Increased transmission counter to " << command->localTransmissionCounter);
00162 
00163     this->sendNow = true;
00164     this->tryToSend();
00165 } // onTimeout
00166 
00167 
00168 void
00169 StopAndWait::processIncoming(const CompoundPtr& compound)
00170 {
00171     StopAndWaitCommand *command = this->getCommand(compound->getCommandPool());
00172 
00173     switch(command->peer.type)
00174     {
00175     case StopAndWaitCommand::I:
00176     {
00177         MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName());
00178         m << " processIncoming(compound), Received I frame "
00179           << " expected (this->NR) " << this->NR
00180           << " received (command->peer.NS) " << command->peer.NS;
00181         MESSAGE_END();
00182 
00183         // The I-Frame must be either the one we're expecting (NR) or
00184         // the one before the one we're expecting (NR-1). If it is NR-1
00185         // it is a duplicate, that we've already acknowledged. May be
00186         // our ACK got lost. So we send it again.
00187         if(command->peer.NS == NR || command->peer.NS == NR-1)
00188         {
00189             if(command->peer.NS == NR)
00190             {
00191                 MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " This was the next expected I frame");
00192                 this->getDeliverer()->getAcceptor(compound)->onData(compound);
00193                 this->NR++;
00194             }
00195             else
00196             {
00197                 MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " Already received this I frame (duplicate)");
00198             }
00199 
00200             // As stated above ACK is sent in any case
00201             CommandPool* ackPCI = this->getFUN()->getProxy()->createReply(compound->getCommandPool(), this);
00202             ackCompound = CompoundPtr(new Compound(ackPCI));
00203             StopAndWaitCommand* ackCommand = this->activateCommand(ackPCI);
00204 
00205             ackCommand->peer.type = StopAndWaitCommand::RR;
00206             ackCommand->peer.NS = NR;
00207             MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " Prepared RR frame (ACK) with NS=" << ackCommand->peer.NS << " (the next I frame we're expexcting)");
00208         }
00209         else
00210         {
00211             // this can not happen.
00212             wns::Exception e;
00213             e << "StopAndWait-ARQ received an I frame that neither (NR) nor (NR-1). "
00214               << "This can not happen and is most probably an implementation error";
00215             throw e;
00216         }
00217 
00218         break;
00219     }
00220 
00221     case StopAndWaitCommand::RR:
00222     {
00223         MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName());
00224         m << " processIncoming(compound), Received RR frame "
00225           << " expected (this->NS) " << this->NS
00226           << " received (command->peer.NS) " << command->peer.NS;
00227         MESSAGE_END();
00228 
00229         if(!(command->peer.NS == NS || command->peer.NS == NS-1))
00230         {
00231             // this can not happen.
00232             wns::Exception e;
00233             e << "StopAndWait-ARQ received an ACK that with neither (NS) nor (NS-1). "
00234               << "This can not happen and is most probably an implementation error";
00235             // stop here
00236             throw e;
00237         }
00238 
00239         // only compounds with NS == NS or NS == NS-1 are left
00240         if(command->peer.NS == NS-1)
00241         {
00242             // duplicate ACK (must be due to duplicate I)
00243             MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName());
00244             m << " Unexpected RR frame (due to duplicate I frame).";
00245             m << "\nHINT: Check your resend timeout. This indicates it is too short.";
00246             MESSAGE_END();
00247             break;
00248         } else {
00249             // this is the ACK we've been waiting for -> we can stop
00250             // the timeout
00251             MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " This is the RR frame (ACK) for the last sent I frame (compound)");
00252             this->statusCollector->onSuccessfullTransmission(this->activeCompound);
00253 
00254             this->activeCompound = CompoundPtr();
00255             this->trySuspend();
00256 
00257             if (this->hasTimeoutSet() == true)
00258             {
00259                 MESSAGE_SINGLE(VERBOSE, this->logger, this->getFUN()->getName() << "Stopping timeout.");
00260                 this->cancelTimeout();
00261             }
00262             MESSAGE_SINGLE(VERBOSE, this->logger, this->getFUN()->getName() << " Ready for next compound from higher FU.");
00263         }
00264         break;
00265     }
00266 
00267     default:
00268     {
00269         wns::Exception e;
00270         e << this->getFUN()->getName()
00271           << " StopAndWait-ARQ: Unknown frame type received (" << command->peer.type << ").";
00272         // stop here
00273         throw e;
00274         break;
00275     }
00276     }
00277 }
00278 
00279 void
00280 StopAndWait::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const
00281 {
00282     //What are the sizes in the upper Layers
00283     this->getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this);
00284 
00285     StopAndWaitCommand* command = this->getCommand(commandPool);
00286 
00287     switch(command->peer.type)
00288     {
00289     case StopAndWaitCommand::I:
00290     {
00291         commandPoolSize += this->bitsPerIFrame;
00292         break;
00293     }
00294     case StopAndWaitCommand::RR:
00295     {
00296         commandPoolSize += this->bitsPerRRFrame;
00297         break;
00298     }
00299     default:
00300     {
00301         wns::Exception e;
00302         e << this->getFUN()->getName()
00303           << " StopAndWait-ARQ: Unknown frame type in size calculation (" << command->peer.type << ").";
00304         // stop here
00305         throw e;
00306         break;
00307     }
00308     }
00309 } // calculateSizes
00310 
00311 
00312 bool
00313 StopAndWait::onSuspend() const
00314 {
00315     return !activeCompound;
00316 } // onSuspend
00317 
00318 
00319 

Generated on Sat May 26 03:31:38 2012 for openWNS by  doxygen 1.5.5