User Manual, Developers Guide and API Documentation

TempSendBuffer.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  * WiMeMac                                                                    *
00003  * This file is part of openWNS (open Wireless Network Simulator)
00004  * _____________________________________________________________________________
00005  *
00006  * Copyright (C) 2004-2011
00007  * Chair of Communication Networks (ComNets)
00008  * Kopernikusstr. 5, 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 #include <WIMEMAC/drp/TempSendBuffer.hpp>
00030 #include <WIMEMAC/drp/DRPScheduler.hpp>
00031 using namespace wimemac::drp;
00032 
00033 
00034 TempSendBuffer::TempSendBuffer(helper::Queues* _DRPQueues, wns::service::dll::UnicastAddress _target, DRPScheduler* _drpscheduler, wns::logger::Logger _logger):
00035     logger(_logger),
00036     DRPQueues(_DRPQueues),
00037 
00038     TxAckDuration(13.125E-6),
00039     SIFS(10E-6),
00040     GuardDuration(12E-6)
00041 {
00042     drpscheduler = _drpscheduler;
00043     tempBuffer.bits = 0;
00044     tempBuffer.target = _target;
00045     tempBuffer.timeleft = 0;
00046     isWaitingSIFS = false;
00047     isTransmissionStarted = false;
00048 
00049     numOfRetransmissions = 0;
00050     numTotalRetransmissions = 0;
00051     sentCompoundsInLastTxOP = 0;
00052     successfullCompoundsInLastTxOP = 0;
00053     sentCompoundsInLastBufferAction = 0;
00054     successfullCompoundsInLastBufferAction = 0;
00055 }
00056 
00057 void
00058 TempSendBuffer::SetTxopDuration(wns::simulator::Time _duration)
00059 {
00060 
00061     txOPStartTime = wns::simulator::getEventScheduler()->getTime();
00062     txOPTime = _duration - GuardDuration;
00063     firstMASOfTxOP = drpscheduler->getManager()->getMASNumber(txOPStartTime);
00064 
00065     if(!IsBufferEmpty())
00066     {
00067         MESSAGE_SINGLE(NORMAL, logger, "Buffer is not empty, there are still " << numCompounds() << " compounds with total size of " << tempBuffer.bits << " bits in the buffer.");
00068 
00069     }
00070     tempBuffer.timeleft = txOPTime - txBufferTime();
00071     assure(txOPTime > 0, "No valid TxOP");
00072 
00073     MESSAGE_SINGLE(NORMAL, logger, "SetTxOP : Sent compounds during the last TXOP : " << sentCompoundsInLastTxOP << " | Successfull compounds : " << successfullCompoundsInLastTxOP);
00074 
00075     if(sentCompoundsInLastBufferAction > 0)
00076     {
00077         sentCompoundsInLastTxOP = sentCompoundsInLastBufferAction;
00078         successfullCompoundsInLastTxOP = successfullCompoundsInLastBufferAction;
00079 
00080         sentCompoundsInLastBufferAction = 0;
00081         successfullCompoundsInLastBufferAction = 0;
00082     }
00083 }
00084 
00085 int
00086 TempSendBuffer::GetNumOfTotalRetransmissions()
00087 {
00088     return numTotalRetransmissions;
00089 }
00090 
00091 int
00092 TempSendBuffer::GetNumOfRetransmissions(const wns::ldk::CompoundPtr& compound)
00093 {
00094     assure(tempBuffer.pduQueue.front()->getData() == compound->getData(),"The compound that was asked for does not equal the first compound in the tempBuffer");
00095     return numOfRetransmissions;
00096 }
00097 
00098 int
00099 TempSendBuffer::GetNumOfRetransmissions()
00100 {
00101     return numOfRetransmissions;
00102 }
00103 
00104 wns::service::dll::UnicastAddress
00105 TempSendBuffer::GetTarget()
00106 {
00107     return tempBuffer.target;
00108 }
00109 
00110 bool
00111 TempSendBuffer::StartBuffering()
00112 {
00113     if(!hasTimeoutSet() && FillBuffer() == false)
00114     {
00115         MESSAGE_SINGLE(NORMAL, logger, "Buffer : Cannot fill the buffer!" );
00116         return false;
00117     }
00118     while(FillBuffer() == true);
00119     MESSAGE_SINGLE(NORMAL, logger, "Buffer is filled size: " << tempBuffer.pduQueue.size() << " Start sending !" );
00120     if(!hasTimeoutSet())
00121         SendCompounds();
00122     else MESSAGE_SINGLE(NORMAL, logger, "Buffer : TimeOut already set -> wait until timeout!");
00123     return true;
00124 }
00125 void
00126 TempSendBuffer::StopBuffering()
00127 {
00128     isTransmissionStarted = false;
00129 
00130     if(hasTimeoutSet())
00131     {
00132         cancelTimeout();
00133         onTimeout();
00134     }
00135 
00136     // Remove compounds from TempBuffer after the TxOP is over
00137     while(IsBufferEmpty() == false)
00138     {
00139         DRPQueues->putFront(tempBuffer.pduQueue.back() , tempBuffer.target);
00140 
00141         wns::simulator::Time duration_ = CalculateTxTime(tempBuffer.pduQueue.back()->getLengthInBits());
00142         tempBuffer.timeleft += duration_;
00143         tempBuffer.bits -= tempBuffer.pduQueue.back()->getLengthInBits();
00144         tempBuffer.pduQueue.pop_back();
00145     }
00146 
00147     txOPTime = wns::simulator::getEventScheduler()->getTime() - txOPStartTime;
00148 }
00149 
00150 bool
00151 TempSendBuffer::FillBuffer()
00152 {
00153     wns::simulator::Time duration_ = 0;
00154 
00155     if(txBufferTime() <= txOPTime)
00156     {
00157         // The current fill level of the buffer is below the TX opportunity -> fill the buffer
00158         int size = GetCompoundSize();
00159 
00160         if(size > 0)
00161         {
00162             if(CalculateTxTime(size, duration_))
00163             {
00164                 MESSAGE_SINGLE(NORMAL, logger, "Buffer calculates duration: " << duration_);
00165 
00166                 if(DRPQueues->hasQueue(tempBuffer.target) && DRPQueues->queueHasPDUs(tempBuffer.target))
00167                 {
00168                     wns::ldk::CompoundPtr compound = DRPQueues->getHeadOfLinePDU(tempBuffer.target);
00169                     tempBuffer.pduQueue.push_back(compound);
00170                     tempBuffer.timeleft -= duration_;
00171                     tempBuffer.bits += compound->getLengthInBits();
00172                     assure(tempBuffer.timeleft >= 0, "Buffer error, time < 0");
00173                     MESSAGE_SINGLE(NORMAL, logger, "Buffer calculates time: " << tempBuffer.timeleft);
00174 
00175                     return true;
00176                 }
00177 
00178             }
00179             MESSAGE_SINGLE(NORMAL, logger, "Intermediate Buffer: compound doesn't fit");
00180         }
00181         else if(size == 0)
00182             MESSAGE_SINGLE(NORMAL, logger, "Intermediate Buffer: no more compounds");
00183 
00184         return false;
00185     }
00186 
00187     else
00188     {
00189         // The current fill level of the buffer is above the TX OP -> put compounds back into the Queue
00190         DRPQueues->putFront(tempBuffer.pduQueue.back() , tempBuffer.target);
00191 
00192         wns::simulator::Time duration_ = CalculateTxTime(tempBuffer.pduQueue.back()->getLengthInBits());
00193         tempBuffer.timeleft += duration_;
00194         tempBuffer.bits -= tempBuffer.pduQueue.back()->getLengthInBits();
00195         tempBuffer.pduQueue.pop_back();
00196 
00197         MESSAGE_SINGLE(NORMAL, logger, "The buffer fill level is " << txBufferTime() << " and therefore above the TXopTime of " << txOPTime << ". Removing last compound from the intermediate buffer!");
00198 
00199         return true;
00200     }
00201 
00202 }
00203 
00204 int
00205 TempSendBuffer::CalculateMaxSize()
00206 {
00207 
00208 }
00209 
00210 int
00211 TempSendBuffer::GetCompoundSize()
00212 {
00213     int size = 0;
00214 
00215     if(DRPQueues->hasQueue(tempBuffer.target) && DRPQueues->queueHasPDUs(tempBuffer.target) )
00216         size = DRPQueues->getHeadOfLinePDUbits(tempBuffer.target);
00217 
00218     MESSAGE_SINGLE(NORMAL, logger, "Buffer asked for compound size: " << size);
00219     return size;
00220 }
00221 
00222 Bit
00223 TempSendBuffer::getNextCompoundSize()
00224 {
00225     if(!(numCompounds() > 1)) return 0;
00226     else
00227     {
00228         return tempBuffer.pduQueue[1]->getLengthInBits();
00229     }
00230 }
00231 
00232 Bit
00233 TempSendBuffer::getCurrentCompoundSize()
00234 {
00235     if(!(numCompounds() > 0)) return 0;
00236     else
00237     {
00238         return tempBuffer.pduQueue[0]->getLengthInBits();
00239     }
00240 }
00241 
00242 bool
00243 TempSendBuffer::CalculateTxTime(int size, wns::simulator::Time &duration_)
00244 {
00245     wns::simulator::Time TxDuration = drpscheduler->getManager()->getProtocolCalculator()->getDuration()->MSDU_PPDU((Bit)size, drpscheduler->getPhyMode(tempBuffer.target, firstMASOfTxOP));
00246 
00247     MESSAGE_SINGLE(NORMAL, logger, "Intermediate Buffer compound time: " << TxDuration);
00248 
00249     TxDuration += TxAckDuration + 2*SIFS;
00250     MESSAGE_SINGLE(NORMAL, logger, "Intermediate Buffer FT time: " << TxDuration);
00251     if(TxDuration > tempBuffer.timeleft)
00252     {
00253         MESSAGE_SINGLE(NORMAL, logger, "Intermediate Buffer compound doesn't fit: " << TxDuration);
00254         return false;
00255     }
00256 
00257     duration_ = TxDuration;
00258 
00259     return true;
00260 }
00261 
00262 
00263 wns::simulator::Time
00264 TempSendBuffer::CalculateTxTime(int size)
00265 {
00266     wns::simulator::Time TxDuration = drpscheduler->getManager()->getProtocolCalculator()->getDuration()->MSDU_PPDU((Bit)size, drpscheduler->getPhyMode(tempBuffer.target, firstMASOfTxOP)); // TODO manager->getMASNumber(now) for PCA transmissions that happen in MASs of different set PhyMode
00267     TxDuration += TxAckDuration + 2*SIFS;
00268     return TxDuration;
00269 }
00270 
00271 
00272 bool
00273 TempSendBuffer::IsBufferEmpty() const
00274 {
00275     return (tempBuffer.pduQueue.empty());
00276 }
00277 
00278 void
00279 TempSendBuffer::SendCompounds()
00280 {
00281 
00282     if (!IsBufferEmpty())
00283     {
00284         wns::simulator::Time FTDuration =
00285         CalculateTxTime(tempBuffer.pduQueue.front()->getLengthInBits());
00286         if( (wns::simulator::getEventScheduler()->getTime() + FTDuration) > (txOPStartTime + txOPTime) )
00287         {
00288             MESSAGE_SINGLE(NORMAL, logger, "There is not enough time left to send the next packet");
00289             drpscheduler->stopPCAtransmission();
00290         }
00291         else
00292         {
00293             MESSAGE_SINGLE(NORMAL, logger, "Buffer is filled or not empty, start sending compounds: ");
00294             drpscheduler->SendCompounds(tempBuffer.target);
00295         }
00296     }
00297 
00298     else
00299     {
00300         MESSAGE_SINGLE(NORMAL, logger, "The temporary Buffer is empty");
00301         drpscheduler->stopPCAtransmission();
00302     }
00303 }
00304 
00305 wns::ldk::CompoundPtr
00306 TempSendBuffer::GetCompound()
00307 {
00308     return (tempBuffer.pduQueue.front());
00309 }
00310 
00311 void
00312 TempSendBuffer::TransmitCompound(const wns::ldk::CompoundPtr& compound)
00313 {
00314     assure(compound == tempBuffer.pduQueue.front(), "Transmitted compound does not equal the first compound in queue");
00315 
00316     wns::simulator::Time FTDuration =
00317     CalculateTxTime(tempBuffer.pduQueue.front()->getLengthInBits());
00318     setTimeout(FTDuration);
00319 
00320     sentCompoundsInLastBufferAction += 1; //DEBUG
00321     isTransmissionStarted = true;
00322 }
00323 
00324 void
00325 TempSendBuffer::onTimeout()
00326 {
00327     if (isWaitingSIFS)
00328     {
00329         isWaitingSIFS = false;
00330         MESSAGE_SINGLE(NORMAL, logger, "Buffer: waited SIFS after ACK. Proceed with next transmission! ");
00331         // The acknowledged compound is already deleted from the queue
00332     }
00333     else
00334     {
00335         // Inform drpscheduler about failed frame for FER evaluation
00336         drpscheduler->failedAck(tempBuffer.target);
00337 
00338         if(drpscheduler->getIsDroppingAfterRetr() == -1)
00339         {
00340             // Infinite retransmissions
00341             MESSAGE_SINGLE(NORMAL, logger, "Buffer: compound was not acknowledged after " << numOfRetransmissions +1 << " transmissions, retransmit! ");
00342             numTotalRetransmissions++;
00343             numOfRetransmissions++;
00344         }
00345         else if(drpscheduler->getIsDroppingAfterRetr() == 0)
00346         {
00347             // No retransmissions allowed -> drop compound from head of queue
00348             MESSAGE_SINGLE(NORMAL, logger, "Buffer: compound was not acknowledged, compound lost! ");
00349             tempBuffer.bits -= tempBuffer.pduQueue.front()->getLengthInBits();
00350             tempBuffer.pduQueue.pop_front();
00351             numOfRetransmissions = 0;
00352         }
00353         else
00354         {
00355             // x retransmissions allowed;
00356             if (numOfRetransmissions >= drpscheduler->getIsDroppingAfterRetr())
00357             {
00358                 // Maximum number of retransmissions exceeded -> drop
00359                 MESSAGE_SINGLE(NORMAL, logger, "Buffer: compound was not acknowledged and maximum number of retransmissions of " << drpscheduler->getIsDroppingAfterRetr() << " are used! Dropping compound! ");
00360                 tempBuffer.bits -= tempBuffer.pduQueue.front()->getLengthInBits();
00361                 tempBuffer.pduQueue.pop_front();
00362                 numOfRetransmissions = 0;
00363             }
00364             else
00365             {
00366                 // The unacknowledged compound is still on top of the queue
00367                 numTotalRetransmissions++;
00368                 numOfRetransmissions++;
00369                 MESSAGE_SINGLE(NORMAL, logger, "Buffer: compound was not acknowledged, retransmit " << numOfRetransmissions << " of " << drpscheduler->getIsDroppingAfterRetr());
00370             }
00371         }
00372     }
00373 
00374     if(isTransmissionStarted) SendCompounds();
00375     else
00376     {
00377         MESSAGE_SINGLE(NORMAL, logger, "Buffer: Transmission was stopped! Proceed in next TxOP");
00378     }
00379 }
00380 
00381 void
00382 TempSendBuffer::ImmAck()
00383 {
00384     MESSAGE_SINGLE(NORMAL, logger, "Buffer: ARQ informs about an ImmAck! ");
00385 
00386     if(hasTimeoutSet())
00387         cancelTimeout();
00388     else assure(false, "Buffer: Received ACK, but no TimeOut is set. Transmission already stopped?");
00389     tempBuffer.bits -= tempBuffer.pduQueue.front()->getLengthInBits();
00390     tempBuffer.pduQueue.pop_front();
00391     // wait another SIFS
00392 
00393     successfullCompoundsInLastBufferAction += 1; //DEBUG
00394     numOfRetransmissions = 0;
00395 
00396     isWaitingSIFS = true;
00397     setTimeout(SIFS);
00398 }
00399 
00400 void
00401 TempSendBuffer::NewArrival()
00402 {
00403     MESSAGE_SINGLE(NORMAL, logger, "Refill Buffer");
00404     if(StartBuffering());
00405 }
00406 
00407 int
00408 TempSendBuffer::numCompounds()
00409 {
00410     return(tempBuffer.pduQueue.size());
00411 }
00412 
00413 wns::simulator::Time
00414 TempSendBuffer::txBufferTime()
00415 {
00416     if (!IsBufferEmpty())
00417     {
00418         // If Imm-Ack is on
00419         wns::simulator::Time totalTime_ = 0;
00420         for (int i = 0; i < tempBuffer.pduQueue.size(); i++)
00421             totalTime_ += CalculateTxTime(tempBuffer.pduQueue[i]->getLengthInBits());
00422 
00423         return totalTime_;
00424     }
00425     else return 0;
00426 }

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