User Manual, Developers Guide and API Documentation

StopAndWaitRC.cpp

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

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