![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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/StopAndWait.hpp> 00029 00030 #include <WNS/pyconfig/View.hpp> 00031 #include <WNS/Assure.hpp> 00032 00033 using namespace wns::ldk; 00034 using namespace wns::ldk::arq; 00035 00036 00037 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00038 StopAndWait, 00039 ARQ, 00040 "wns.arq.StopAndWait", 00041 FUNConfigCreator); 00042 00043 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00044 StopAndWait, 00045 FunctionalUnit, 00046 "wns.arq.StopAndWait", 00047 FUNConfigCreator); 00048 00049 StopAndWait::StopAndWait(fun::FUN* fuNet, const wns::pyconfig::View& config) : 00050 ARQ(config), 00051 wns::ldk::fu::Plain<StopAndWait, StopAndWaitCommand>(fuNet), 00052 Delayed<StopAndWait>(), 00053 SuspendSupport(fuNet, config), 00054 CanTimeout(), 00055 00056 resendTimeout(config.get<double>("resendTimeout")), 00057 bitsPerIFrame(config.get<int>("bitsPerIFrame")), 00058 bitsPerRRFrame(config.get<int>("bitsPerRRFrame")), 00059 00060 NS(0), 00061 NR(0), 00062 activeCompound(CompoundPtr()), 00063 ackCompound(CompoundPtr()), 00064 sendNow(false), 00065 logger(config.get("logger")) 00066 { 00067 } // StopAndWait 00068 00069 00070 StopAndWait::~StopAndWait() 00071 { 00072 } // ~StopAndWait 00073 00074 00075 bool 00076 StopAndWait::hasCapacity() const 00077 { 00078 return !this->activeCompound; 00079 } // hasCapacity 00080 00081 00082 void 00083 StopAndWait::processOutgoing(const CompoundPtr& compound) 00084 { 00085 assure(this->hasCapacity(), "processOutgoing called although not accepting."); 00086 this->activeCompound = compound; 00087 00088 StopAndWaitCommand* command = this->activateCommand(compound->getCommandPool()); 00089 00090 command->peer.type = StopAndWaitCommand::I; 00091 command->peer.NS = this->NS; 00092 command->localTransmissionCounter = 1; 00093 00094 MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName()); 00095 m << " processOutgoing(compound)," 00096 << " sequence number (NS) of compound: " << command->peer.NS; 00097 MESSAGE_END(); 00098 00099 ++this->NS; 00100 00101 this->sendNow = true; 00102 } // processOutgoing 00103 00104 00105 const wns::ldk::CompoundPtr 00106 StopAndWait::hasACK() const 00107 { 00108 return this->ackCompound; 00109 } // hasACK 00110 00111 00112 const wns::ldk::CompoundPtr 00113 StopAndWait::hasData() const 00114 { 00115 if(this->sendNow) 00116 { 00117 return this->activeCompound; 00118 } 00119 else 00120 { 00121 return CompoundPtr(); 00122 } 00123 } // hasData 00124 00125 00126 wns::ldk::CompoundPtr 00127 StopAndWait::getACK() 00128 { 00129 CompoundPtr it = this->ackCompound; 00130 this->ackCompound = CompoundPtr(); 00131 00132 return it; 00133 } // getACK 00134 00135 00136 wns::ldk::CompoundPtr 00137 StopAndWait::getData() 00138 { 00139 this->sendNow = false; 00140 this->setTimeout(this->resendTimeout); 00141 00142 // send a copy 00143 return this->activeCompound->copy(); 00144 } // getData 00145 00146 00147 void 00148 StopAndWait::onTimeout() 00149 { 00150 assure(this->activeCompound, "Unexpected timeout."); 00151 00152 this->statusCollector->onFailedTransmission(this->activeCompound); 00153 00154 StopAndWaitCommand* command = this->getCommand(this->activeCompound); 00155 command->localTransmissionCounter++; 00156 00157 MESSAGE_SINGLE( 00158 NORMAL, 00159 this->logger, 00160 "Timeout for compound with sequence number (NS) " << command->peer.NS << 00161 ". Increased transmission counter to " << command->localTransmissionCounter); 00162 00163 this->sendNow = true; 00164 this->tryToSend(); 00165 } // onTimeout 00166 00167 00168 void 00169 StopAndWait::processIncoming(const CompoundPtr& compound) 00170 { 00171 StopAndWaitCommand *command = this->getCommand(compound->getCommandPool()); 00172 00173 switch(command->peer.type) 00174 { 00175 case StopAndWaitCommand::I: 00176 { 00177 MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName()); 00178 m << " processIncoming(compound), Received I frame " 00179 << " expected (this->NR) " << this->NR 00180 << " received (command->peer.NS) " << command->peer.NS; 00181 MESSAGE_END(); 00182 00183 // The I-Frame must be either the one we're expecting (NR) or 00184 // the one before the one we're expecting (NR-1). If it is NR-1 00185 // it is a duplicate, that we've already acknowledged. May be 00186 // our ACK got lost. So we send it again. 00187 if(command->peer.NS == NR || command->peer.NS == NR-1) 00188 { 00189 if(command->peer.NS == NR) 00190 { 00191 MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " This was the next expected I frame"); 00192 this->getDeliverer()->getAcceptor(compound)->onData(compound); 00193 this->NR++; 00194 } 00195 else 00196 { 00197 MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " Already received this I frame (duplicate)"); 00198 } 00199 00200 // As stated above ACK is sent in any case 00201 CommandPool* ackPCI = this->getFUN()->getProxy()->createReply(compound->getCommandPool(), this); 00202 ackCompound = CompoundPtr(new Compound(ackPCI)); 00203 StopAndWaitCommand* ackCommand = this->activateCommand(ackPCI); 00204 00205 ackCommand->peer.type = StopAndWaitCommand::RR; 00206 ackCommand->peer.NS = NR; 00207 MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " Prepared RR frame (ACK) with NS=" << ackCommand->peer.NS << " (the next I frame we're expexcting)"); 00208 } 00209 else 00210 { 00211 // this can not happen. 00212 wns::Exception e; 00213 e << "StopAndWait-ARQ received an I frame that neither (NR) nor (NR-1). " 00214 << "This can not happen and is most probably an implementation error"; 00215 throw e; 00216 } 00217 00218 break; 00219 } 00220 00221 case StopAndWaitCommand::RR: 00222 { 00223 MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName()); 00224 m << " processIncoming(compound), Received RR frame " 00225 << " expected (this->NS) " << this->NS 00226 << " received (command->peer.NS) " << command->peer.NS; 00227 MESSAGE_END(); 00228 00229 if(!(command->peer.NS == NS || command->peer.NS == NS-1)) 00230 { 00231 // this can not happen. 00232 wns::Exception e; 00233 e << "StopAndWait-ARQ received an ACK that with neither (NS) nor (NS-1). " 00234 << "This can not happen and is most probably an implementation error"; 00235 // stop here 00236 throw e; 00237 } 00238 00239 // only compounds with NS == NS or NS == NS-1 are left 00240 if(command->peer.NS == NS-1) 00241 { 00242 // duplicate ACK (must be due to duplicate I) 00243 MESSAGE_BEGIN(NORMAL, this->logger, m, this->getFUN()->getName()); 00244 m << " Unexpected RR frame (due to duplicate I frame)."; 00245 m << "\nHINT: Check your resend timeout. This indicates it is too short."; 00246 MESSAGE_END(); 00247 break; 00248 } else { 00249 // this is the ACK we've been waiting for -> we can stop 00250 // the timeout 00251 MESSAGE_SINGLE(NORMAL, this->logger, this->getFUN()->getName() << " This is the RR frame (ACK) for the last sent I frame (compound)"); 00252 this->statusCollector->onSuccessfullTransmission(this->activeCompound); 00253 00254 this->activeCompound = CompoundPtr(); 00255 this->trySuspend(); 00256 00257 if (this->hasTimeoutSet() == true) 00258 { 00259 MESSAGE_SINGLE(VERBOSE, this->logger, this->getFUN()->getName() << "Stopping timeout."); 00260 this->cancelTimeout(); 00261 } 00262 MESSAGE_SINGLE(VERBOSE, this->logger, this->getFUN()->getName() << " Ready for next compound from higher FU."); 00263 } 00264 break; 00265 } 00266 00267 default: 00268 { 00269 wns::Exception e; 00270 e << this->getFUN()->getName() 00271 << " StopAndWait-ARQ: Unknown frame type received (" << command->peer.type << ")."; 00272 // stop here 00273 throw e; 00274 break; 00275 } 00276 } 00277 } 00278 00279 void 00280 StopAndWait::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const 00281 { 00282 //What are the sizes in the upper Layers 00283 this->getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this); 00284 00285 StopAndWaitCommand* command = this->getCommand(commandPool); 00286 00287 switch(command->peer.type) 00288 { 00289 case StopAndWaitCommand::I: 00290 { 00291 commandPoolSize += this->bitsPerIFrame; 00292 break; 00293 } 00294 case StopAndWaitCommand::RR: 00295 { 00296 commandPoolSize += this->bitsPerRRFrame; 00297 break; 00298 } 00299 default: 00300 { 00301 wns::Exception e; 00302 e << this->getFUN()->getName() 00303 << " StopAndWait-ARQ: Unknown frame type in size calculation (" << command->peer.type << ")."; 00304 // stop here 00305 throw e; 00306 break; 00307 } 00308 } 00309 } // calculateSizes 00310 00311 00312 bool 00313 StopAndWait::onSuspend() const 00314 { 00315 return !activeCompound; 00316 } // onSuspend 00317 00318 00319
1.5.5