User Manual, Developers Guide and API Documentation

CumulativeACK.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/CumulativeACK.hpp>
00029 #include <WNS/pyconfig/View.hpp>
00030 #include <WNS/Assure.hpp>
00031 
00032 #include <algorithm>
00033 
00034 using namespace wns::ldk;
00035 using namespace wns::ldk::arq;
00036 
00037 
00038 STATIC_FACTORY_REGISTER_WITH_CREATOR(CumulativeACK, ARQ, "wns.arq.CumulativeACK", FUNConfigCreator);
00039 STATIC_FACTORY_REGISTER_WITH_CREATOR(CumulativeACK, FunctionalUnit, "wns.arq.CumulativeACK", FUNConfigCreator);
00040 
00041 CumulativeACK::CumulativeACK(fun::FUN* fuNet, const wns::pyconfig::View& config) :
00042     ARQ(config),
00043     wns::ldk::fu::Plain<CumulativeACK, CumulativeACKCommand>(fuNet),
00044     Delayed<CumulativeACK>(),
00045     SuspendSupport(fuNet, config),
00046     CanTimeout(),
00047     ackCompound(CompoundPtr()),
00048     wS(config.get<unsigned long int>("windowSize")),
00049     NS(0),
00050     NSack(0),
00051     NR(0),
00052     sequenceNumberSize(config.get<int>("sequenceNumberSize")),
00053     receivingCompounds(),
00054     sendingCompounds(),
00055     resendTimeout(config.get<double>("resendTimeout")),
00056     delayingDelivery(false),
00057     delayedDeliveryNR(0),
00058     logger(config.get("logger"))
00059 {
00060     assure((wS % 2) == 0, " Invalid windowSize, it has to be even.");
00061     assure(wS >= 4, " Invalid windowSize, it is to small.");
00062     CAElement foo(this);
00063     fill_n(back_inserter(sendingCompounds),wS,foo);
00064     fill_n(back_inserter(receivingCompounds),wS,foo);
00065 } // CumulativeACK
00066 
00067 CumulativeACK::~CumulativeACK()
00068 {
00069     receivingCompounds.clear();
00070     sendingCompounds.clear();
00071 } // ~CumulativeACK
00072 
00073 
00074 bool
00075 CumulativeACK::hasCapacity() const
00076 {
00077     //avoid warning
00078     int foo = wS / 2;
00079     int ret = NS - NSack;
00080     if (NS < NSack)
00081         ret = NS + wS - NSack;
00082     assure(ret <= foo, " Error :  Negative Capacity !");
00083     return (ret < foo);
00084 } // hasCapacity
00085 
00086 
00087 void CumulativeACK::processOutgoing(const wns::ldk::CompoundPtr& _compound)
00088 {
00089     assure(hasCapacity(), "processOutgoing called although not accepting.");
00090     assure(_compound != CompoundPtr(), "given compound is null");
00091 
00092     sendingCompounds[NS].compound = _compound;
00093     CumulativeACKCommand *command = activateCommand(_compound->getCommandPool());
00094     command->peer.type = CumulativeACKCommand::I;
00095     command->peer.NS = NS;
00096     sendingCompounds[NS].sendNow = true;
00097 
00098     MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00099     m << " processOutgoing NS -> " << command->peer.NS;
00100     MESSAGE_END();
00101 
00102     NS = (NS + 1) % wS;
00103 } // processOutgoing
00104 
00105 
00106 const wns::ldk::CompoundPtr
00107 CumulativeACK::hasACK() const
00108 {
00109     return this->ackCompound;
00110 } // hasACK
00111 
00112 
00113 const wns::ldk::CompoundPtr
00114 CumulativeACK::hasData() const
00115 {
00116     unsigned int tmpNS = NS;
00117     int diff = NS - NSack ;
00118     if(diff < 0)
00119         tmpNS = NS + wS;
00120     for(unsigned int i = NSack; i < tmpNS; i++) {
00121         if(sendingCompounds[i % wS].compound != CompoundPtr() && sendingCompounds[i % wS].sendNow)
00122             return sendingCompounds[(i % wS)].compound;
00123     }
00124 
00125     return CompoundPtr();
00126 } // hasData
00127 
00128 
00129 wns::ldk::CompoundPtr
00130 CumulativeACK::getACK()
00131 {
00132     wns::ldk::CompoundPtr it = this->ackCompound;
00133     MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00134     m << " Send ACK        NR -> " << getCommand(this->ackCompound->getCommandPool())->peer.NR;
00135     MESSAGE_END();
00136     this->ackCompound = CompoundPtr();
00137     return it;
00138 } // getACK
00139 
00140 
00141 wns::ldk::CompoundPtr
00142 CumulativeACK::getData()
00143 {
00144     unsigned int tmpNS = NS;
00145     int diff = NS-NSack;
00146     if (diff < 0)
00147         tmpNS = NS + wS;
00148     for (unsigned int i = NSack ; i <= tmpNS; i++ ) {
00149         if( sendingCompounds[(i % wS)].compound != CompoundPtr() && sendingCompounds[(i % wS)].sendNow) {
00150             sendingCompounds[(i % wS)].sendNow = false;
00151             sendingCompounds[(i % wS)].setTimeout(resendTimeout);
00152             MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00153             m << " Send IFrame     NS -> " << getCommand(sendingCompounds[i % wS].getCompound()->getCommandPool())->peer.NS;
00154             MESSAGE_END();
00155             //sending a copy
00156             return sendingCompounds[(i % wS)].getCompound()->copy();
00157         }
00158     }
00159 
00160     assure(false, "oops!");
00161     return CompoundPtr();
00162 } // getData
00163 
00164 
00165 void CumulativeACK::processIncoming(const wns::ldk::CompoundPtr& _compound)
00166 {
00167     wns::ldk::CompoundPtr compound = _compound;
00168     CumulativeACKCommand* command = getCommand(compound->getCommandPool());
00169     switch(command->peer.type)
00170     {
00171     case CumulativeACKCommand::I:
00172         MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00173         m << " Received IFrame NS -> " << command->peer.NS <<" expected NR -> " << NR;
00174         MESSAGE_END();
00175 
00176         if (delayingDelivery)
00177         {
00178             if ((command->peer.NS - delayedDeliveryNR + wS) % wS < wS/2)
00179             {
00180                 receivingCompounds[command->peer.NS].compound = compound;
00181 
00182                 if(command->peer.NS == NR) {
00183                     unsigned int tmpNR = NR;
00184                     NR = (NR + 1) % wS;
00185                     for(; receivingCompounds[NR].compound != CompoundPtr(); NR = (NR + 1) % wS) {
00186                         tmpNR = NR;
00187                     }
00188 
00189                     //send an ACK
00190                     assure(receivingCompounds[tmpNR].compound != CompoundPtr(), " error ACK can not be sent ");
00191                     CommandPool* ackPCI = createReply(receivingCompounds[tmpNR].compound->getCommandPool());
00192                     this->ackCompound = CompoundPtr(new wns::ldk::Compound(ackPCI));
00193                     CumulativeACKCommand* ackCommand = activateCommand(ackPCI);
00194                     ackCommand->peer.type = CumulativeACKCommand::RR;
00195                     ackCommand->peer.NR = NR;
00196                     ackCommand->peer.NS = NR;
00197                 }
00198             }
00199         }
00200         else
00201         {
00202             // this is the I Frame we waited for.
00203             if(command->peer.NS == NR) {
00204                 receivingCompounds[NR].compound = compound;
00205                 //Loop assures that RR-message refers to a not received PDU.
00206                 unsigned int tmpNR = NR;
00207                 NR = (NR + 1) % wS;
00208                 for(; receivingCompounds[NR].compound != CompoundPtr(); NR = (NR + 1) % wS) {
00209                     CompoundPtr tmpCompound = receivingCompounds[tmpNR].compound;
00210                     getDeliverer()->getAcceptor(tmpCompound)->onData(tmpCompound);
00211                     receivingCompounds[tmpNR].compound = CompoundPtr();
00212                     tmpNR = NR;
00213                 }
00214 
00215                 //send an ACK
00216                 assure(receivingCompounds[tmpNR].compound != CompoundPtr(), " error ACK can not be sent ");
00217                 CommandPool* ackPCI = getFUN()->getProxy()->createReply(receivingCompounds[tmpNR].compound->getCommandPool(), this);
00218                 this->ackCompound = CompoundPtr(new wns::ldk::Compound(ackPCI));
00219                 CumulativeACKCommand* ackCommand = activateCommand(ackPCI);
00220                 ackCommand->peer.type = CumulativeACKCommand::RR;
00221                 ackCommand->peer.NR = NR;
00222                 ackCommand->peer.NS = NR;
00223 
00224                 getDeliverer()->getAcceptor(receivingCompounds[tmpNR].compound)->onData(receivingCompounds[tmpNR].compound);
00225                 receivingCompounds[tmpNR].compound = CompoundPtr();
00226             }
00227             // in wS but after NR -> no ACK is send as there is at least a missing PDU before
00228             else if(((command->peer.NS > NR) && (command->peer.NS < (NR + wS / 2))) // NR and NS are not divided by a frame-boundary
00229                     || ((command->peer.NS + wS) < (NR + wS / 2))) { // divided by a frame-boundary
00230                 receivingCompounds[command->peer.NS].compound = compound;
00231             }
00232             //earlier compound is received again -> send RR-message with current NR
00233             else {
00234                 if (this->ackCompound == CompoundPtr()){
00235                     CommandPool* ackPCI = getFUN()->getProxy()->createReply(compound->getCommandPool(), this);
00236                     compound = CompoundPtr();
00237                     this->ackCompound = CompoundPtr(new wns::ldk::Compound(ackPCI));
00238                     CumulativeACKCommand* ackCommand = activateCommand(ackPCI);
00239                     ackCommand->peer.type = CumulativeACKCommand::RR;
00240                     ackCommand->peer.NS = NR;
00241                     ackCommand->peer.NR = NR;
00242                 }
00243             }
00244         }
00245         break;
00246     case CumulativeACKCommand::RR:
00247     {
00248         // ACK received although unacknowledged packet does not exist
00249         if (NSack == NS)
00250             return;
00251         if ((command->peer.NR - NSack + wS - 1) % wS >= wS/2)
00252             return;
00253         //2.index helping to cope with indexHop
00254         unsigned int tmpNS = NS;
00255         //prevent warning
00256         int dif = NS - NSack;
00257         if (  dif < 0)
00258             tmpNS = NS + wS;
00259         //lower index by one
00260         unsigned int tmpI = NSack;
00261         unsigned int i;
00262 
00263         for ( i = (NSack + 1) % wS ; i <= tmpNS; ++i ) {
00264             //assumes that no wrong command->peer.NS is received
00265             this->statusCollector->onSuccessfullTransmission(sendingCompounds[tmpI % wS].compound);
00266             sendingCompounds[tmpI % wS].sendNow = false;
00267             sendingCompounds[tmpI % wS].compound = CompoundPtr();
00268             if (sendingCompounds[tmpI % wS].hasTimeoutSet())
00269                 sendingCompounds[tmpI % wS].cancelTimeout();
00270             if( (i % wS) == command->peer.NR ) {
00271                 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00272                 m << " Received RRFrame NR-> " << command->peer.NR;
00273                 MESSAGE_END();
00274                 NSack = i % wS;
00275                 compound = CompoundPtr();
00276                 break;
00277             }
00278             tmpI = i;
00279         }
00280 //      assure(compound==CompoundPtr(),"ACK compound has been received and processed but it is still referred to");
00281     }
00282     break;
00283     default: assure(0," Unexpected PDU received!");
00284     }
00285     trySuspend();
00286 } // processOutgoing
00287 
00288 void
00289 CumulativeACK::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const
00290 {
00291     //What are the sizes in the upper Layers
00292     getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this);
00293 
00294     //Calculate PCI size
00295     commandPoolSize += static_cast<int>(ceil(log(sequenceNumberSize) / log(2)));
00296     commandPoolSize += 2; // 3 Frametypes can be represented with 2 Bits
00297 
00298 } // calculateSizes
00299 
00300 bool
00301 CumulativeACK::onSuspend() const
00302 {
00303     return NS == NSack;
00304 } // onSuspend
00305 
00306 void
00307 CumulativeACK::doDelayDelivery()
00308 {
00309     delayingDelivery = true;
00310     delayedDeliveryNR = NR;
00311 } // doDelayDelivery
00312 
00313 void
00314 CumulativeACK::doDeliver()
00315 {
00316     delayingDelivery = false;
00317 
00318     for(; receivingCompounds[delayedDeliveryNR].compound != CompoundPtr(); delayedDeliveryNR = (delayedDeliveryNR + 1) % wS) {
00319         CompoundPtr tmpCompound = receivingCompounds[delayedDeliveryNR].compound;
00320         getDeliverer()->getAcceptor(tmpCompound)->onData(tmpCompound);
00321         receivingCompounds[delayedDeliveryNR].compound = CompoundPtr();
00322     }
00323 } // doDeliver
00324 
00325 

Generated on Sun May 27 03:31:40 2012 for openWNS by  doxygen 1.5.5