![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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 }
1.5.5