![]() |
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 00030 #include <WIFIMAC/lowerMAC/StopAndWaitARQ.hpp> 00031 #include <WIFIMAC/FrameType.hpp> 00032 00033 #include <WNS/probe/bus/utils.hpp> 00034 00035 using namespace wifimac::lowerMAC; 00036 00037 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00038 wifimac::lowerMAC::StopAndWaitARQ, 00039 wns::ldk::FunctionalUnit, 00040 "wifimac.lowerMAC.StopAndWaitARQ", 00041 wns::ldk::FUNConfigCreator); 00042 00043 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00044 wifimac::lowerMAC::StopAndWaitARQ, 00045 wns::ldk::probe::Probe, 00046 "wifimac.lowerMAC.StopAndWaitARQ", 00047 wns::ldk::FUNConfigCreator); 00048 00049 StopAndWaitARQ::StopAndWaitARQ(wns::ldk::fun::FUN* fuNet, const wns::pyconfig::View& config) : 00050 wns::ldk::arq::StopAndWait(fuNet, config), 00051 rxsName(config.get<std::string>("rxStartName")), 00052 txStartEndName(config.get<std::string>("txStartEndName")), 00053 managerName(config.get<std::string>("managerName")), 00054 perMIBServiceName(config.get<std::string>("perMIBServiceName")), 00055 shortRetryLimit(config.get<int>("shortRetryLimit")), 00056 longRetryLimit(config.get<int>("longRetryLimit")), 00057 stationShortRetryCounter(0), 00058 stationLongRetryCounter(0), 00059 shortRetryCounter(0), 00060 longRetryCounter(0), 00061 rtsctsThreshold(config.get<Bit>("rtsctsThreshold")), 00062 sifsDuration(config.get<wns::simulator::Time>("sifsDuration")), 00063 maximumACKDuration(config.get<wns::simulator::Time>("maximumACKDuration")), 00064 ackTimeout(config.get<wns::simulator::Time>("ackTimeout")), 00065 ackPhyMode(config.getView("ackPhyMode")), 00066 bianchiRetryCounter(config.get<bool>("bianchiRetryCounter")), 00067 ackState(none) 00068 { 00069 friends.manager = NULL; 00070 00071 // read the localIDs from the config 00072 wns::probe::bus::ContextProviderCollection localContext(&fuNet->getLayer()->getContextProviderCollection()); 00073 for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii) 00074 { 00075 std::string key = config.get<std::string>("localIDs.keys()",ii); 00076 unsigned long int value = config.get<unsigned long int>("localIDs.values()",ii); 00077 localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value)); 00078 MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value); 00079 } 00080 numTxAttemptsProbe = wns::probe::bus::collector(localContext, config, "numTxAttemptsProbeName"); 00081 } 00082 00083 void StopAndWaitARQ::onFUNCreated() 00084 { 00085 // Observe rxStart 00086 this->wns::Observer<wifimac::convergence::IRxStartEnd>::startObserving 00087 (getFUN()->findFriend<wifimac::convergence::RxStartEndNotification*>(rxsName)); 00088 00089 // Observe txStartEnd 00090 this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving 00091 (getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName)); 00092 00093 // get manager 00094 friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName); 00095 00096 // signal packet success/errors to MIB 00097 perMIB = getFUN()->getLayer<dll::ILayer2*>()->getManagementService<wifimac::management::PERInformationBase>(perMIBServiceName); 00098 } 00099 00100 00101 wns::ldk::CompoundPtr StopAndWaitARQ::getData() 00102 { 00103 sendNow = false; 00104 00105 // send a copy 00106 return activeCompound->copy(); 00107 } 00108 00109 void StopAndWaitARQ::onRxStart(wns::simulator::Time /*expRxTime*/) 00110 { 00111 if (ackState == waitForACK) 00112 { 00113 assure(this->activeCompound, "state is waitForACK but no active compound"); 00114 assure(hasTimeoutSet(), "ackState is waiting but no timeout set?"); 00115 00116 MESSAGE_SINGLE(NORMAL, logger, "got rxStartIndication, wait for ACK delivery"); 00117 ackState = receiving; 00118 } 00119 } 00120 00121 void StopAndWaitARQ::onRxEnd() 00122 { 00123 if (ackState == receiving) 00124 { 00125 assure(this->activeCompound, "state is receiving but no active compound"); 00126 ackState = receptionFinished; 00127 if(not hasTimeoutSet()) 00128 { 00129 setTimeout(10e-9); 00130 MESSAGE_SINGLE(NORMAL, logger, "onRxEnd and waiting for ACK -> set short timeout"); 00131 } 00132 00133 } 00134 } 00135 00136 void StopAndWaitARQ::onRxError() 00137 { 00138 if(ackState == receiving) 00139 { 00140 assure(this->activeCompound, "state is waitForACK/receiving but no active compound"); 00141 MESSAGE_SINGLE(NORMAL, logger, "onRxError and waiting for ACK -> failure"); 00142 00143 // return to waitForACK 00144 ackState = waitForACK; 00145 00146 if(not hasTimeoutSet()) 00147 { 00148 this->onTimeout(); 00149 } 00150 } 00151 } 00152 00153 void 00154 StopAndWaitARQ::onTxStart(const wns::ldk::CompoundPtr& compound) 00155 { 00156 // this is just for the resetting of the short retry counters in the case 00157 // that a long frame used RTS/CTS for its transmission. If the tx starts AND 00158 // the data is long, the CTS was received and hence the counters can be 00159 // reset 00160 if(this->activeCompound and 00161 ((friends.manager->getFrameType(compound->getCommandPool()) == DATA) or (friends.manager->getFrameType(compound->getCommandPool()) == DATA_TXOP)) and 00162 (compound->getBirthmark() == this->activeCompound->getBirthmark())) 00163 { 00164 Bit commandPoolSize; 00165 Bit dataSize; 00166 this->calculateSizes(compound->getCommandPool(), commandPoolSize, dataSize); 00167 Bit psduSize = commandPoolSize + dataSize; 00168 00169 if(psduSize > rtsctsThreshold) 00170 { 00171 MESSAGE_SINGLE(NORMAL, logger, "Data is sent --> CTS received successfully --> reset short retry counters"); 00172 shortRetryCounter = 0; 00173 stationShortRetryCounter = 0; 00174 } 00175 } 00176 00177 } 00178 00179 void 00180 StopAndWaitARQ::onTxEnd(const wns::ldk::CompoundPtr& compound) 00181 { 00182 if(this->activeCompound and 00183 ((friends.manager->getFrameType(compound->getCommandPool()) == DATA) or (friends.manager->getFrameType(compound->getCommandPool()) == DATA_TXOP)) and 00184 (compound->getBirthmark() == this->activeCompound->getBirthmark())) 00185 { 00186 ackState = waitForACK; 00187 setNewTimeout(ackTimeout); 00188 MESSAGE_SINGLE(NORMAL, logger, "Data is sent, waiting for ACK for " << ackTimeout); 00189 } 00190 else 00191 { 00192 if(this->ackState == sendingACK) 00193 { 00194 MESSAGE_SINGLE(NORMAL, logger, "done sending ack"); 00195 this->ackState = none; 00196 this->tryToSend(); 00197 } 00198 } 00199 } 00200 00201 void StopAndWaitARQ::processOutgoing(const wns::ldk::CompoundPtr& compound) 00202 { 00203 if(friends.manager->lifetimeExpired(compound->getCommandPool())) 00204 { 00205 MESSAGE_SINGLE(NORMAL, logger, "outgoing compound has expired lifetime -> drop"); 00206 } 00207 else 00208 { 00209 // TODO: Set the frame exchange duration here 00210 friends.manager->setReplyTimeout(compound->getCommandPool(), ackTimeout); 00211 wns::ldk::arq::StopAndWait::processOutgoing(compound); 00212 00213 if(not this->bianchiRetryCounter) 00214 { 00215 // According to the standard, the retransmission counter is set by 00216 // the station (short|long) counters 00217 getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter = 00218 stationShortRetryCounter + stationLongRetryCounter + 1; 00219 } 00220 } 00221 } 00222 00223 void StopAndWaitARQ::processIncoming(const wns::ldk::CompoundPtr& compound) 00224 { 00225 wns::ldk::arq::StopAndWaitCommand* command = this->getCommand(compound->getCommandPool()); 00226 00227 if(command->isACK()) 00228 { 00229 MESSAGE_SINGLE(NORMAL, this->logger, "Received ACK frame, consider current frame as done"); 00230 00231 assure(this->ackState == receptionFinished, "Received ACK but not waiting for ack"); 00232 assure(this->activeCompound, "Received ACK but no active compound"); 00233 00234 this->statusCollector->onSuccessfullTransmission(this->activeCompound); 00235 this->perMIB->onSuccessfullTransmission(friends.manager->getReceiverAddress(this->activeCompound->getCommandPool())); 00236 numTxAttemptsProbe->put(this->activeCompound, shortRetryCounter + longRetryCounter + 1); 00237 00238 // received acknowledgement frame for the current compound --> reset counters 00239 Bit commandPoolSize; 00240 Bit dataSize; 00241 this->calculateSizes(activeCompound->getCommandPool(), commandPoolSize, dataSize); 00242 Bit psduSize = commandPoolSize + dataSize; 00243 00244 if(psduSize > rtsctsThreshold) 00245 { 00246 longRetryCounter = 0; 00247 stationLongRetryCounter = 0; 00248 } 00249 else 00250 { 00251 shortRetryCounter = 0; 00252 stationShortRetryCounter = 0; 00253 } 00254 00255 this->activeCompound = wns::ldk::CompoundPtr(); 00256 this->ackState = none; 00257 00258 if(this->hasTimeoutSet()) 00259 { 00260 this->cancelTimeout(); 00261 } 00262 } 00263 else 00264 { 00265 MESSAGE_SINGLE(NORMAL, this->logger, "Received DATA frame, reply with ACK"); 00266 00267 // send ACK 00268 wns::ldk::CommandPool* ackPCI = this->getFUN()->getProxy()->createReply(compound->getCommandPool(), this); 00269 this->ackCompound = wns::ldk::CompoundPtr(new wns::ldk::Compound(ackPCI)); 00270 friends.manager->setFrameType(ackPCI, ACK); 00271 friends.manager->setPhyMode(ackPCI, ackPhyMode); 00272 wns::simulator::Time fxDur = friends.manager->getFrameExchangeDuration(compound->getCommandPool()) - sifsDuration - maximumACKDuration; 00273 if (fxDur < sifsDuration) 00274 { 00275 fxDur = 0; 00276 } 00277 00278 MESSAGE_SINGLE(NORMAL,logger,"create ACK with exchange duration : " << fxDur); 00279 00280 friends.manager->setFrameExchangeDuration(ackPCI, 00281 fxDur); 00282 wns::ldk::arq::StopAndWaitCommand* ackCommand = this->activateCommand(ackPCI); 00283 ackCommand->peer.type = wns::ldk::arq::StopAndWaitCommand::RR; 00284 this->ackState = sendingACK; 00285 assure(getConnector()->hasAcceptor(this->ackCompound), "No acceptor for ACK"); 00286 00287 // deliver frame 00288 getDeliverer()->getAcceptor(compound)->onData(compound); 00289 } 00290 } 00291 00292 bool 00293 StopAndWaitARQ::hasCapacity() const 00294 { 00295 return (!this->activeCompound) and (!this->ackCompound) and (this->ackState != sendingACK); 00296 } 00297 00298 void 00299 StopAndWaitARQ::onTransmissionHasFailed(const wns::ldk::CompoundPtr& compound) 00300 { 00301 // indication from RTS/CTS that the CTS was not received 00302 ++shortRetryCounter; 00303 ++stationShortRetryCounter; 00304 00305 MESSAGE_BEGIN(NORMAL, logger, m, "Missing CTS, retry counters now:"); 00306 m << " src " << shortRetryCounter; 00307 m << " ssrc " << stationShortRetryCounter; 00308 m << " (limit " << shortRetryLimit << ")"; 00309 m << " lrc " << longRetryCounter; 00310 m << " slrc " << stationLongRetryCounter; 00311 m << " (limit " << longRetryLimit << ")"; 00312 MESSAGE_END(); 00313 00314 this->transmissionHasFailed(compound); 00315 } 00316 00317 void StopAndWaitARQ::onTimeout() 00318 { 00319 if(ackState == receiving) 00320 { 00321 MESSAGE_SINGLE(NORMAL, this->logger, "Started reception during wait for ACK -> wait for delivery"); 00322 return; 00323 } 00324 00325 // ACK was not received before timeout 00326 assure(this->activeCompound, "no active compound, no failed transmission"); 00327 00328 // get the PSDU size 00329 Bit commandPoolSize; 00330 Bit dataSize; 00331 this->calculateSizes(activeCompound->getCommandPool(), commandPoolSize, dataSize); 00332 Bit psduSize = commandPoolSize + dataSize; 00333 00334 if(psduSize <= rtsctsThreshold) 00335 { 00336 ++shortRetryCounter; 00337 ++stationShortRetryCounter; 00338 } 00339 else 00340 { 00341 ++longRetryCounter; 00342 ++stationLongRetryCounter; 00343 } 00344 00345 MESSAGE_BEGIN(NORMAL, logger, m, "Timeout of ACK, retry counters now:"); 00346 m << " src " << shortRetryCounter; 00347 m << " ssrc " << stationShortRetryCounter; 00348 m << " (limit " << shortRetryLimit << ")"; 00349 m << " lrc " << longRetryCounter; 00350 m << " slrc " << stationLongRetryCounter; 00351 m << " (limit " << longRetryLimit << ")"; 00352 MESSAGE_END(); 00353 00354 this->perMIB->onFailedTransmission(friends.manager->getReceiverAddress(activeCompound->getCommandPool())); 00355 this->transmissionHasFailed(activeCompound); 00356 } 00357 00358 void 00359 StopAndWaitARQ::transmissionHasFailed(const wns::ldk::CompoundPtr& compound) 00360 { 00361 assure(this->activeCompound, "no active compound, no failed transmission"); 00362 assure(friends.manager->getFrameType(compound->getCommandPool()) == DATA, "compound must have type DATA"); 00363 assure(compound->getBirthmark() == this->activeCompound->getBirthmark(), "compound has not same birthmark as active one"); 00364 00365 if(hasTimeoutSet()) 00366 { 00367 cancelTimeout(); 00368 } 00369 00370 ackState = none; 00371 00372 wns::ldk::arq::StopAndWaitCommand* command = this->getCommand(this->activeCompound); 00373 00374 if((shortRetryCounter == shortRetryLimit) or 00375 (longRetryCounter == longRetryLimit) or 00376 (friends.manager->lifetimeExpired(compound->getCommandPool()))) 00377 { 00378 MESSAGE_SINGLE(NORMAL, logger, "Failed transmission, txCounter has reached limit -> drop packet"); 00379 this->statusCollector->onFailedTransmission(this->activeCompound); 00380 numTxAttemptsProbe->put(this->activeCompound, shortRetryCounter + longRetryCounter + 1); 00381 // reset retry counters, but NOT station retry counters! 00382 shortRetryCounter = 0; 00383 longRetryCounter = 0; 00384 00385 this->sendNow = false; 00386 this->activeCompound = wns::ldk::CompoundPtr(); 00387 this->tryToSend(); 00388 } 00389 else 00390 { 00391 wns::ldk::arq::StopAndWait::onTimeout(); 00392 // The backoff will select the size of the contention window (cw) 00393 // according to the number or retries. Hence, setting this correctly is 00394 // important. 00395 00396 if(this->bianchiRetryCounter) 00397 { 00398 // This implements the retry counter as described in the Bianchi DCF 00399 // model: Every new compound resets the number of retries, 00400 // independently from the failure of the compound before. Hence, the 00401 // number of transmissions is the src+lrc+1. 00402 00403 getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter = 00404 shortRetryCounter + longRetryCounter + 1; 00405 } 00406 else 00407 { 00408 // This implements the standard (IEEE 802.11-2007): The cw size is 00409 // set according to the station (short|long) retry counter, which 00410 // are the same as the src/lrc as long as every compound is 00411 // transmitted successful eventually, i.e. before the retry limit. 00412 // If the retry limit is reached the first time, the cw is reset 00413 // (and the compound discarded). If even the second compound cannot 00414 // be transmitted and is discarded, the cw is NOT reset any more. 00415 00416 if(stationShortRetryCounter < shortRetryLimit and stationLongRetryCounter < longRetryLimit) 00417 { 00418 // no retry limit was reached so far 00419 getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter = 00420 stationShortRetryCounter + stationLongRetryCounter + 1; 00421 } 00422 else 00423 { 00424 int newCounter = 0; 00425 if(stationShortRetryCounter >= shortRetryLimit) 00426 { 00427 // the shortRetryLimit was reached (at least) once -> reduce 00428 // the retry counter 00429 newCounter += stationShortRetryCounter - shortRetryLimit; 00430 } 00431 else 00432 { 00433 newCounter += stationShortRetryCounter; 00434 } 00435 00436 if(stationLongRetryCounter >= longRetryLimit) 00437 { 00438 // the longRetryLimit was reached (at least) once -> reduce 00439 // the retry counter 00440 newCounter += stationLongRetryCounter - longRetryLimit; 00441 } 00442 else 00443 { 00444 newCounter += stationLongRetryCounter; 00445 } 00446 00447 // new transmission! 00448 newCounter += 1; 00449 00450 assure(newCounter > 0, "Transmission counter must be greater than 0"); 00451 00452 getCommand(this->activeCompound->getCommandPool())->localTransmissionCounter = newCounter; 00453 } 00454 } 00455 MESSAGE_SINGLE(NORMAL, this->logger, 00456 "Failed transmission, retransmit"); 00457 } 00458 } 00459 00460 unsigned int 00461 StopAndWaitARQ::getTransmissionCounter(const wns::ldk::CompoundPtr& compound) const 00462 { 00463 if(getFUN()->getProxy()->commandIsActivated(compound->getCommandPool(), this)) 00464 { 00465 return(this->getCommand(compound)->localTransmissionCounter); 00466 } 00467 else 00468 { 00469 return 1; 00470 } 00471 } 00472 00473 void 00474 StopAndWaitARQ::copyTransmissionCounter(const wns::ldk::CompoundPtr& src, const wns::ldk::CompoundPtr& dst) 00475 { 00476 wns::ldk::arq::StopAndWaitCommand* command = this->activateCommand(dst->getCommandPool()); 00477 command->localTransmissionCounter = this->getCommand(src)->localTransmissionCounter; 00478 }
1.5.5