![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * WiFiMac * 00003 * This file is part of openWNS (open Wireless Network Simulator) 00004 * _____________________________________________________________________________ 00005 * 00006 * Copyright (C) 2004-2007 00007 * Chair of Communication Networks (ComNets) 00008 * Kopernikusstr. 16, 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 <WIFIMAC/draftn/BlockACK.hpp> 00030 #include <WIFIMAC/convergence/PhyMode.hpp> 00031 00032 #include <WNS/probe/bus/utils.hpp> 00033 00034 using namespace wifimac::draftn; 00035 00036 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00037 wifimac::draftn::BlockACK, 00038 wns::ldk::FunctionalUnit, 00039 "wifimac.draftn.BlockACK", 00040 wns::ldk::FUNConfigCreator); 00041 00042 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00043 wifimac::draftn::BlockACK, 00044 wns::ldk::probe::Probe, 00045 "wifimac.draftn.BlockACK", 00046 wns::ldk::FUNConfigCreator); 00047 00048 BlockACK::BlockACK(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) : 00049 wns::ldk::arq::ARQ(config_), 00050 wns::ldk::fu::Plain<BlockACK, BlockACKCommand>(fun), 00051 00052 managerName(config_.get<std::string>("managerName")), 00053 rxStartEndName(config_.get<std::string>("rxStartEndName")), 00054 txStartEndName(config_.get<std::string>("txStartEndName")), 00055 sendBufferName(config_.get<std::string>("sendBufferName")), 00056 perMIBServiceName(config_.get<std::string>("perMIBServiceName")), 00057 sifsDuration(config_.get<wns::simulator::Time>("myConfig.sifsDuration")), 00058 maximumACKDuration(config_.get<wns::simulator::Time>("myConfig.maximumACKDuration")), 00059 ackTimeout(config_.get<wns::simulator::Time>("myConfig.ackTimeout")), 00060 blockACKPhyMode(config_.getView("myConfig.blockACKPhyMode")), 00061 capacity(config_.get<Bit>("myConfig.capacity")), 00062 maxOnAir(config_.get<size_t>("myConfig.maxOnAir")), 00063 baBits(config_.get<Bit>("myConfig.blockACKBits")), 00064 baReqBits(config_.get<Bit>("myConfig.blockACKRequestBits")), 00065 maximumTransmissions(config_.get<size_t>("myConfig.maximumTransmissions")), 00066 impatientBAreqTransmission(config_.get<bool>("myConfig.impatient")), 00067 currentTxQueue(NULL), 00068 rxQueues(), 00069 hasACKfor(), 00070 nextTransmissionSN(), 00071 baState(idle), 00072 00073 logger(config_.get("logger")) 00074 { 00075 MESSAGE_SINGLE(NORMAL, this->logger, "created"); 00076 00077 // read the localIDs from the config 00078 wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection()); 00079 for (int ii = 0; ii<config_.len("localIDs.keys()"); ++ii) 00080 { 00081 std::string key = config_.get<std::string>("localIDs.keys()",ii); 00082 unsigned int value = config_.get<unsigned int>("localIDs.values()",ii); 00083 localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value)); 00084 MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value); 00085 } 00086 numTxAttemptsProbe = wns::probe::bus::collector(localContext, config_, "numTxAttemptsProbeName"); 00087 friends.manager = NULL; 00088 00089 std::string pluginName = config_.get<std::string>("myConfig.sizeUnit"); 00090 sizeCalculator = std::auto_ptr<wns::ldk::buffer::SizeCalculator>(wns::ldk::buffer::SizeCalculator::Factory::creator(pluginName)->create()); 00091 } 00092 00093 BlockACK::BlockACK(const BlockACK& other) : 00094 //CompoundHandlerInterface(other), 00095 CommandTypeSpecifierInterface(other), 00096 HasReceptorInterface(other), 00097 HasConnectorInterface(other), 00098 HasDelivererInterface(other), 00099 CloneableInterface(other), 00100 IOutputStreamable(other), 00101 PythonicOutput(other), 00102 FunctionalUnit(other), 00103 DelayedInterface(other), 00104 wns::ldk::arq::ARQ(other), 00105 wns::ldk::fu::Plain<BlockACK, BlockACKCommand>(other), 00106 wns::ldk::Delayed<BlockACK>(other), 00107 managerName(other.managerName), 00108 rxStartEndName(other.rxStartEndName), 00109 txStartEndName(other.txStartEndName), 00110 sendBufferName(other.sendBufferName), 00111 perMIBServiceName(other.perMIBServiceName), 00112 sifsDuration(other.sifsDuration), 00113 maximumACKDuration(other.maximumACKDuration), 00114 ackTimeout(other.ackTimeout), 00115 capacity(other.capacity), 00116 maxOnAir(other.maxOnAir), 00117 baBits(other.baBits), 00118 baReqBits(other.baReqBits), 00119 maximumTransmissions(other.maximumTransmissions), 00120 impatientBAreqTransmission(other.impatientBAreqTransmission), 00121 sizeCalculator(wns::clone(other.sizeCalculator)) 00122 { 00123 } 00124 00125 BlockACK::~BlockACK() 00126 { 00127 // clear queues 00128 rxQueues.clear(); 00129 if (currentTxQueue != NULL) 00130 { 00131 delete currentTxQueue; 00132 currentTxQueue = NULL; 00133 } 00134 } 00135 00136 void BlockACK::onFUNCreated() 00137 { 00138 MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started"); 00139 00140 friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName); 00141 00142 // Observe rxStart 00143 this->wns::Observer<wifimac::convergence::IRxStartEnd>::startObserving 00144 (getFUN()->findFriend<wifimac::convergence::RxStartEndNotification*>(rxStartEndName)); 00145 00146 // Observe txStartEnd 00147 this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving 00148 (getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName)); 00149 00150 // signal packet success/errors to MIB 00151 perMIB = getFUN()->getLayer<dll::Layer2*>()->getManagementService<wifimac::management::PERInformationBase>(perMIBServiceName); 00152 friends.sendBuffer = getFUN()->findFriend<wns::ldk::DelayedInterface*>(sendBufferName); 00153 } // BlockACK::onFUNCreated 00154 00155 unsigned int 00156 BlockACK::storageSize() const 00157 { 00158 unsigned int size = 0; 00159 00160 if (currentTxQueue != NULL) 00161 { 00162 size = currentTxQueue->storageSize(); 00163 } 00164 00165 for(wns::container::Registry<wns::service::dll::UnicastAddress, ReceptionQueue*>::const_iterator it = rxQueues.begin(); 00166 it != rxQueues.end(); 00167 it++) 00168 { 00169 size += (*it).second->storageSize(); 00170 } 00171 00172 return(size); 00173 } // BlockACK::size() 00174 00175 00176 bool 00177 BlockACK::doIsAccepting(const wns::ldk::CompoundPtr& compound) const 00178 { 00179 return (((currentTxQueue == NULL) or 00180 (currentTxQueue->getReceiver() == friends.manager->getReceiverAddress(compound->getCommandPool()))) 00181 and hasCapacity()); 00182 } 00183 00184 00185 bool 00186 BlockACK::hasCapacity() const 00187 { 00188 return((this->storageSize() < this->capacity) and 00189 ((currentTxQueue == NULL) or 00190 (not currentTxQueue->waitsForACK())) and 00191 ((currentTxQueue == NULL) or 00192 (currentTxQueue->storageSize() < this->maxOnAir))); 00193 } 00194 00195 void 00196 BlockACK::processOutgoing(const wns::ldk::CompoundPtr& compound) 00197 { 00198 assure(this->hasCapacity(), "processOutgoing although no capacity"); 00199 00200 if(friends.manager->lifetimeExpired(compound->getCommandPool())) 00201 { 00202 MESSAGE_SINGLE(NORMAL, logger, "outgoing compound has expired lifetime -> drop"); 00203 return; 00204 } 00205 wns::service::dll::UnicastAddress receiver = friends.manager->getReceiverAddress(compound->getCommandPool()); 00206 if (currentTxQueue != NULL and receiver == currentTxQueue->getReceiver()) 00207 { 00208 // processed compound has the current receiver as destination, added to 00209 // compound block for next round 00210 MESSAGE_SINGLE(NORMAL, this->logger,"Next frame in a row processed for receiver: " << currentTxQueue->getReceiver() << " with SN: " << currentTxQueue->getNextSN()); 00211 currentTxQueue->processOutgoing(compound); 00212 } 00213 if (currentTxQueue == NULL) 00214 { 00215 if (not nextTransmissionSN.knows(receiver)) 00216 { 00217 nextTransmissionSN.insert(receiver,0); 00218 } 00219 currentTxQueue = new TransmissionQueue(this, 00220 maxOnAir, 00221 0.0, 00222 receiver, 00223 nextTransmissionSN.find(receiver), 00224 perMIB, 00225 &sizeCalculator); 00226 00227 MESSAGE_BEGIN(NORMAL, this->logger, m, "First frame in a row"); 00228 m << " processed for receiver: " << currentTxQueue->getReceiver(); 00229 m << " with SN: " << nextTransmissionSN.find(receiver); 00230 MESSAGE_END(); 00231 currentTxQueue->processOutgoing(compound); 00232 } 00233 MESSAGE_SINGLE(NORMAL, this->logger, "Stored outgoing frame, remaining capacity " << this->capacity - this->storageSize()); 00234 } 00235 00236 void 00237 BlockACK::processIncoming(const wns::ldk::CompoundPtr& compound) 00238 { 00239 wns::service::dll::UnicastAddress transmitter = friends.manager->getTransmitterAddress(compound->getCommandPool()); 00240 00241 if(getCommand(compound->getCommandPool())->isACK()) 00242 { 00243 assure(currentTxQueue != NULL, "got ACK though no transmission queue"); 00244 assure(transmitter == currentTxQueue->getReceiver(), "got ACK from wrong Station"); 00245 assure(this->baState == receptionFinished or this->baState == receiving, 00246 "Received ACK but not waiting for one"); 00247 00248 00249 //perMIB->onSuccessfullTransmission(currentTxQueue->getReceiver()); 00250 this->processIncomingACKSNs(getCommand(compound->getCommandPool())->peer.ackSNs); 00251 return; 00252 00253 } // if compound is ACK 00254 else 00255 { 00256 if(getCommand(compound->getCommandPool())->isACKreq()) 00257 { 00258 if(not rxQueues.knows(transmitter)) 00259 { 00260 MESSAGE_BEGIN(NORMAL, this->logger, m, "Received BA-REQ from unknown transmitter "); 00261 m << transmitter << " (this would not happen with correct BA-init)"; 00262 m << " -> new rxQueue"; 00263 MESSAGE_END(); 00264 00265 assure(not hasACKfor.isValid(), "Received BA-REQ from " << transmitter << ", but already existing BA for " << hasACKfor); 00266 00267 rxQueues.insert(transmitter, new ReceptionQueue(this, getCommand(compound->getCommandPool())->peer.sn, transmitter)); 00268 } 00269 rxQueues.find(transmitter)->processIncomingACKreq(compound); 00270 hasACKfor = transmitter; 00271 return; 00272 } // compound is ACK req 00273 else 00274 { 00275 if(not rxQueues.knows(transmitter)) 00276 { 00277 MESSAGE_SINGLE(NORMAL, this->logger, "First frame from " << transmitter << " -> new rxQueue"); 00278 rxQueues.insert(transmitter, new ReceptionQueue(this, getCommand(compound->getCommandPool())->peer.sn, transmitter)); 00279 } 00280 rxQueues.find(transmitter)->processIncomingData(compound, (*sizeCalculator)(compound)); 00281 } // is not ACK req 00282 } // is not ACK 00283 } // BlockACK::processIncoming 00284 00285 void 00286 BlockACK::processIncomingACKSNs(std::set<BlockACKCommand::SequenceNumber> ackSNs) 00287 { 00288 if(hasTimeoutSet()) 00289 { 00290 cancelTimeout(); 00291 } 00292 00293 // Reset the baState: Noting is send, not waiting for anything -> idle! 00294 this->baState = idle; 00295 00296 // forward SNs to currentTxQueue 00297 currentTxQueue->processIncomingACK(ackSNs); 00298 00299 if ((currentTxQueue->getNumWaitingPDUs()+currentTxQueue->getNumOnAirPDUs()) != 0) 00300 { 00301 // either not all compounds of the current send block have been 00302 // transmitted successfully or compounds for the same receiver 00303 // arrived while the current send block retransmitted unsuccessfully 00304 // sent compounds 00305 return; 00306 } 00307 00308 // currentTxQueue is empty -> store SN and delete it 00309 nextTransmissionSN.update(currentTxQueue->getReceiver(),currentTxQueue->getNextSN()); 00310 MESSAGE_SINGLE(NORMAL, this->logger, "No more waiting frames -> deleted currentTxQueue"); 00311 delete currentTxQueue; 00312 currentTxQueue = NULL; 00313 return; 00314 } 00315 00316 00317 const wns::ldk::CompoundPtr 00318 BlockACK::hasACK() const 00319 { 00320 if(hasACKfor.isValid()) 00321 { 00322 return(rxQueues.find(hasACKfor)->hasACK()); 00323 } 00324 else 00325 { 00326 return wns::ldk::CompoundPtr(); 00327 } 00328 } // hasACK 00329 00330 wns::ldk::CompoundPtr 00331 BlockACK::getACK() 00332 { 00333 wns::service::dll::UnicastAddress adr = hasACKfor; 00334 hasACKfor = wns::service::dll::UnicastAddress(); 00335 return(rxQueues.find(adr)->getACK()); 00336 } // getACK 00337 00338 const wns::ldk::CompoundPtr 00339 BlockACK::hasData() const 00340 { 00341 wns::ldk::CompoundPtr compound = friends.sendBuffer->hasSomethingToSend(); 00342 if((hasCapacity()) and 00343 (compound != wns::ldk::CompoundPtr()) and 00344 (currentTxQueue != NULL) and 00345 (friends.manager->getReceiverAddress(compound->getCommandPool()) == currentTxQueue->getReceiver())) 00346 { 00347 // There are more compounds in the buffer and we still have capacity -> delay transmission 00348 return wns::ldk::CompoundPtr(); 00349 } 00350 00351 if (currentTxQueue != NULL) 00352 { 00353 return(currentTxQueue->hasData()); 00354 } 00355 else 00356 { 00357 return wns::ldk::CompoundPtr(); 00358 } 00359 } // hasData 00360 00361 wns::ldk::CompoundPtr 00362 BlockACK::getData() 00363 { 00364 assure(hasData(), "trying to get data though there aren't any waiting"); 00365 00366 // get the next waiting compound 00367 wns::ldk::CompoundPtr it = currentTxQueue->getData(); 00368 00369 return(it); 00370 } // getData 00371 00372 00373 void 00374 BlockACK::onTxStart(const wns::ldk::CompoundPtr& /*compound*/) 00375 { 00376 baState = idle; 00377 } 00378 00379 void 00380 BlockACK::onTxEnd(const wns::ldk::CompoundPtr& compound) 00381 { 00382 // we await the tx end of the blockACKreq 00383 if((getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this)) and 00384 (getCommand(compound->getCommandPool())->isACKreq()) and 00385 (currentTxQueue->getReceiver() == friends.manager->getReceiverAddress(compound->getCommandPool()))) 00386 { 00387 assure(currentTxQueue != NULL, "TxEnd from BA-REQ, but no transmission queue"); 00388 assure(currentTxQueue->waitsForACK(), 00389 "TxEnd from BA-REQ for current receiver " << currentTxQueue->getReceiver() << ", but queue is not waiting for ACK"); 00390 00391 // we give ackTimeout until the baState must be "receiving" 00392 setNewTimeout(ackTimeout); 00393 baState = waitForACK; 00394 MESSAGE_SINGLE(NORMAL, this->logger, "onTxEnd() of BAreq, wait on BA for " << ackTimeout); 00395 } 00396 } 00397 00398 void 00399 BlockACK::onTimeout() 00400 { 00401 if(this->baState == receiving) 00402 { 00403 MESSAGE_SINGLE(NORMAL, this->logger, "Started reception during wait for BA -> wait for delivery"); 00404 return; 00405 } 00406 00407 // we did not receive anything after the blockACKreq transmission 00408 assure(currentTxQueue != NULL, "Timeout, but no transmission queue"); 00409 assure(currentTxQueue->waitsForACK(), "Timeout, but currentTxQueue is not waiting for ACK"); 00410 00411 MESSAGE_SINGLE(NORMAL, this->logger, "Timeout -> failed transmission to " << currentTxQueue->getReceiver()); 00412 //perMIB->onFailedTransmission(currentTxQueue->getReceiver()); 00413 00414 // no ACK'ed SNs have arrived, use pseudo-vector 00415 std::set<BlockACKCommand::SequenceNumber> none; 00416 none.clear(); 00417 this->processIncomingACKSNs(none); 00418 00419 this->tryToSend(); 00420 } 00421 00422 void 00423 BlockACK::onTransmissionHasFailed(const wns::ldk::CompoundPtr& compound) 00424 { 00425 assure(currentTxQueue != NULL, "transsmissionHasFailed, but there is no transmission queue"); 00426 assure(currentTxQueue->waitsForACK(), "transmissionHasFailed, but currentTxQueue is not waiting for ACK"); 00427 assure(friends.manager->getReceiverAddress(compound->getCommandPool()) == currentTxQueue->getReceiver(), 00428 "transmissionHasFailed has different rx address than current receiver"); 00429 00430 MESSAGE_SINGLE(NORMAL, this->logger, "Indication of failed transmission to " << friends.manager->getReceiverAddress(compound->getCommandPool())); 00431 // RTS/CTS -> no signalling to perMIB 00432 //this->printTxQueueStatus(); 00433 00434 00435 // no ACK'ed SNs have arrived, use pseudo-vector 00436 std::set<BlockACKCommand::SequenceNumber> none; 00437 none.clear(); 00438 this->processIncomingACKSNs(none); 00439 00440 this->tryToSend(); 00441 } 00442 00443 void 00444 BlockACK::onRxStart(wns::simulator::Time /*expRxTime*/) 00445 { 00446 if(this->baState == waitForACK) 00447 { 00448 assure(hasTimeoutSet(), "ackState is waiting but no timeout set?"); 00449 this->baState = receiving; 00450 MESSAGE_SINGLE(NORMAL, this->logger, "onRxStart() during wait for BA"); 00451 } 00452 } 00453 00454 void 00455 BlockACK::onRxEnd() 00456 { 00457 if(this->baState == receiving) 00458 { 00459 this->baState = receptionFinished; 00460 if(not hasTimeoutSet()) 00461 { 00462 setTimeout(10e-9); 00463 MESSAGE_SINGLE(NORMAL, this->logger, "onRxEnd() during wait for BA -> short wait for delivery of BA"); 00464 } 00465 } 00466 } 00467 00468 void 00469 BlockACK::onRxError() 00470 { 00471 if(this->baState == receiving) 00472 { 00473 MESSAGE_SINGLE(NORMAL, logger, "onRxError and waiting for ACK -> failure"); 00474 this->baState = waitForACK; 00475 00476 if(not hasTimeoutSet()) 00477 { 00478 this->onTimeout(); 00479 } 00480 } 00481 } 00482 00483 void 00484 BlockACK::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const 00485 { 00486 if(getCommand(commandPool)->isACK()) 00487 { 00488 commandPoolSize = this->baBits; 00489 dataSize = 0; 00490 return; 00491 } 00492 00493 if(getCommand(commandPool)->isACKreq()) 00494 { 00495 commandPoolSize = this->baReqBits; 00496 dataSize = 0; 00497 return; 00498 } 00499 00500 getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this); 00501 } 00502 00503 void BlockACK::printTxQueueStatus() const 00504 { 00505 if (currentTxQueue != NULL) 00506 { 00507 MESSAGE_SINGLE(NORMAL, this->logger, "TxQueue to " << currentTxQueue->getReceiver() << " waits for ACK: " << currentTxQueue->waitsForACK()); 00508 } 00509 else 00510 { 00511 MESSAGE_SINGLE(NORMAL, this->logger, "no transmission queue allocated yet"); 00512 } 00513 } 00514 00515 unsigned int 00516 BlockACK::getTransmissionCounter(const wns::ldk::CompoundPtr& compound) const 00517 { 00518 if(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this)) 00519 { 00520 return(this->getCommand(compound)->localTransmissionCounter); 00521 } 00522 else 00523 { 00524 return 1; 00525 } 00526 } 00527 00528 void 00529 BlockACK::copyTransmissionCounter(const wns::ldk::CompoundPtr& src, const wns::ldk::CompoundPtr& dst) 00530 { 00531 this->activateCommand(dst->getCommandPool())->localTransmissionCounter = this->getCommand(src)->localTransmissionCounter; 00532 } 00533
1.5.5