![]() |
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/CumulativeACK.hpp> 00029 #include <WNS/pyconfig/View.hpp> 00030 #include <WNS/Assure.hpp> 00031 00032 #include <algorithm> 00033 00034 using namespace wns::ldk; 00035 using namespace wns::ldk::arq; 00036 00037 00038 STATIC_FACTORY_REGISTER_WITH_CREATOR(CumulativeACK, ARQ, "wns.arq.CumulativeACK", FUNConfigCreator); 00039 STATIC_FACTORY_REGISTER_WITH_CREATOR(CumulativeACK, FunctionalUnit, "wns.arq.CumulativeACK", FUNConfigCreator); 00040 00041 CumulativeACK::CumulativeACK(fun::FUN* fuNet, const wns::pyconfig::View& config) : 00042 ARQ(config), 00043 wns::ldk::fu::Plain<CumulativeACK, CumulativeACKCommand>(fuNet), 00044 Delayed<CumulativeACK>(), 00045 SuspendSupport(fuNet, config), 00046 CanTimeout(), 00047 ackCompound(CompoundPtr()), 00048 wS(config.get<unsigned long int>("windowSize")), 00049 NS(0), 00050 NSack(0), 00051 NR(0), 00052 sequenceNumberSize(config.get<int>("sequenceNumberSize")), 00053 receivingCompounds(), 00054 sendingCompounds(), 00055 resendTimeout(config.get<double>("resendTimeout")), 00056 delayingDelivery(false), 00057 delayedDeliveryNR(0), 00058 logger(config.get("logger")) 00059 { 00060 assure((wS % 2) == 0, " Invalid windowSize, it has to be even."); 00061 assure(wS >= 4, " Invalid windowSize, it is to small."); 00062 CAElement foo(this); 00063 fill_n(back_inserter(sendingCompounds),wS,foo); 00064 fill_n(back_inserter(receivingCompounds),wS,foo); 00065 } // CumulativeACK 00066 00067 CumulativeACK::~CumulativeACK() 00068 { 00069 receivingCompounds.clear(); 00070 sendingCompounds.clear(); 00071 } // ~CumulativeACK 00072 00073 00074 bool 00075 CumulativeACK::hasCapacity() const 00076 { 00077 //avoid warning 00078 int foo = wS / 2; 00079 int ret = NS - NSack; 00080 if (NS < NSack) 00081 ret = NS + wS - NSack; 00082 assure(ret <= foo, " Error : Negative Capacity !"); 00083 return (ret < foo); 00084 } // hasCapacity 00085 00086 00087 void CumulativeACK::processOutgoing(const wns::ldk::CompoundPtr& _compound) 00088 { 00089 assure(hasCapacity(), "processOutgoing called although not accepting."); 00090 assure(_compound != CompoundPtr(), "given compound is null"); 00091 00092 sendingCompounds[NS].compound = _compound; 00093 CumulativeACKCommand *command = activateCommand(_compound->getCommandPool()); 00094 command->peer.type = CumulativeACKCommand::I; 00095 command->peer.NS = NS; 00096 sendingCompounds[NS].sendNow = true; 00097 00098 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00099 m << " processOutgoing NS -> " << command->peer.NS; 00100 MESSAGE_END(); 00101 00102 NS = (NS + 1) % wS; 00103 } // processOutgoing 00104 00105 00106 const wns::ldk::CompoundPtr 00107 CumulativeACK::hasACK() const 00108 { 00109 return this->ackCompound; 00110 } // hasACK 00111 00112 00113 const wns::ldk::CompoundPtr 00114 CumulativeACK::hasData() const 00115 { 00116 unsigned int tmpNS = NS; 00117 int diff = NS - NSack ; 00118 if(diff < 0) 00119 tmpNS = NS + wS; 00120 for(unsigned int i = NSack; i < tmpNS; i++) { 00121 if(sendingCompounds[i % wS].compound != CompoundPtr() && sendingCompounds[i % wS].sendNow) 00122 return sendingCompounds[(i % wS)].compound; 00123 } 00124 00125 return CompoundPtr(); 00126 } // hasData 00127 00128 00129 wns::ldk::CompoundPtr 00130 CumulativeACK::getACK() 00131 { 00132 wns::ldk::CompoundPtr it = this->ackCompound; 00133 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00134 m << " Send ACK NR -> " << getCommand(this->ackCompound->getCommandPool())->peer.NR; 00135 MESSAGE_END(); 00136 this->ackCompound = CompoundPtr(); 00137 return it; 00138 } // getACK 00139 00140 00141 wns::ldk::CompoundPtr 00142 CumulativeACK::getData() 00143 { 00144 unsigned int tmpNS = NS; 00145 int diff = NS-NSack; 00146 if (diff < 0) 00147 tmpNS = NS + wS; 00148 for (unsigned int i = NSack ; i <= tmpNS; i++ ) { 00149 if( sendingCompounds[(i % wS)].compound != CompoundPtr() && sendingCompounds[(i % wS)].sendNow) { 00150 sendingCompounds[(i % wS)].sendNow = false; 00151 sendingCompounds[(i % wS)].setTimeout(resendTimeout); 00152 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00153 m << " Send IFrame NS -> " << getCommand(sendingCompounds[i % wS].getCompound()->getCommandPool())->peer.NS; 00154 MESSAGE_END(); 00155 //sending a copy 00156 return sendingCompounds[(i % wS)].getCompound()->copy(); 00157 } 00158 } 00159 00160 assure(false, "oops!"); 00161 return CompoundPtr(); 00162 } // getData 00163 00164 00165 void CumulativeACK::processIncoming(const wns::ldk::CompoundPtr& _compound) 00166 { 00167 wns::ldk::CompoundPtr compound = _compound; 00168 CumulativeACKCommand* command = getCommand(compound->getCommandPool()); 00169 switch(command->peer.type) 00170 { 00171 case CumulativeACKCommand::I: 00172 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00173 m << " Received IFrame NS -> " << command->peer.NS <<" expected NR -> " << NR; 00174 MESSAGE_END(); 00175 00176 if (delayingDelivery) 00177 { 00178 if ((command->peer.NS - delayedDeliveryNR + wS) % wS < wS/2) 00179 { 00180 receivingCompounds[command->peer.NS].compound = compound; 00181 00182 if(command->peer.NS == NR) { 00183 unsigned int tmpNR = NR; 00184 NR = (NR + 1) % wS; 00185 for(; receivingCompounds[NR].compound != CompoundPtr(); NR = (NR + 1) % wS) { 00186 tmpNR = NR; 00187 } 00188 00189 //send an ACK 00190 assure(receivingCompounds[tmpNR].compound != CompoundPtr(), " error ACK can not be sent "); 00191 CommandPool* ackPCI = createReply(receivingCompounds[tmpNR].compound->getCommandPool()); 00192 this->ackCompound = CompoundPtr(new wns::ldk::Compound(ackPCI)); 00193 CumulativeACKCommand* ackCommand = activateCommand(ackPCI); 00194 ackCommand->peer.type = CumulativeACKCommand::RR; 00195 ackCommand->peer.NR = NR; 00196 ackCommand->peer.NS = NR; 00197 } 00198 } 00199 } 00200 else 00201 { 00202 // this is the I Frame we waited for. 00203 if(command->peer.NS == NR) { 00204 receivingCompounds[NR].compound = compound; 00205 //Loop assures that RR-message refers to a not received PDU. 00206 unsigned int tmpNR = NR; 00207 NR = (NR + 1) % wS; 00208 for(; receivingCompounds[NR].compound != CompoundPtr(); NR = (NR + 1) % wS) { 00209 CompoundPtr tmpCompound = receivingCompounds[tmpNR].compound; 00210 getDeliverer()->getAcceptor(tmpCompound)->onData(tmpCompound); 00211 receivingCompounds[tmpNR].compound = CompoundPtr(); 00212 tmpNR = NR; 00213 } 00214 00215 //send an ACK 00216 assure(receivingCompounds[tmpNR].compound != CompoundPtr(), " error ACK can not be sent "); 00217 CommandPool* ackPCI = getFUN()->getProxy()->createReply(receivingCompounds[tmpNR].compound->getCommandPool(), this); 00218 this->ackCompound = CompoundPtr(new wns::ldk::Compound(ackPCI)); 00219 CumulativeACKCommand* ackCommand = activateCommand(ackPCI); 00220 ackCommand->peer.type = CumulativeACKCommand::RR; 00221 ackCommand->peer.NR = NR; 00222 ackCommand->peer.NS = NR; 00223 00224 getDeliverer()->getAcceptor(receivingCompounds[tmpNR].compound)->onData(receivingCompounds[tmpNR].compound); 00225 receivingCompounds[tmpNR].compound = CompoundPtr(); 00226 } 00227 // in wS but after NR -> no ACK is send as there is at least a missing PDU before 00228 else if(((command->peer.NS > NR) && (command->peer.NS < (NR + wS / 2))) // NR and NS are not divided by a frame-boundary 00229 || ((command->peer.NS + wS) < (NR + wS / 2))) { // divided by a frame-boundary 00230 receivingCompounds[command->peer.NS].compound = compound; 00231 } 00232 //earlier compound is received again -> send RR-message with current NR 00233 else { 00234 if (this->ackCompound == CompoundPtr()){ 00235 CommandPool* ackPCI = getFUN()->getProxy()->createReply(compound->getCommandPool(), this); 00236 compound = CompoundPtr(); 00237 this->ackCompound = CompoundPtr(new wns::ldk::Compound(ackPCI)); 00238 CumulativeACKCommand* ackCommand = activateCommand(ackPCI); 00239 ackCommand->peer.type = CumulativeACKCommand::RR; 00240 ackCommand->peer.NS = NR; 00241 ackCommand->peer.NR = NR; 00242 } 00243 } 00244 } 00245 break; 00246 case CumulativeACKCommand::RR: 00247 { 00248 // ACK received although unacknowledged packet does not exist 00249 if (NSack == NS) 00250 return; 00251 if ((command->peer.NR - NSack + wS - 1) % wS >= wS/2) 00252 return; 00253 //2.index helping to cope with indexHop 00254 unsigned int tmpNS = NS; 00255 //prevent warning 00256 int dif = NS - NSack; 00257 if ( dif < 0) 00258 tmpNS = NS + wS; 00259 //lower index by one 00260 unsigned int tmpI = NSack; 00261 unsigned int i; 00262 00263 for ( i = (NSack + 1) % wS ; i <= tmpNS; ++i ) { 00264 //assumes that no wrong command->peer.NS is received 00265 this->statusCollector->onSuccessfullTransmission(sendingCompounds[tmpI % wS].compound); 00266 sendingCompounds[tmpI % wS].sendNow = false; 00267 sendingCompounds[tmpI % wS].compound = CompoundPtr(); 00268 if (sendingCompounds[tmpI % wS].hasTimeoutSet()) 00269 sendingCompounds[tmpI % wS].cancelTimeout(); 00270 if( (i % wS) == command->peer.NR ) { 00271 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00272 m << " Received RRFrame NR-> " << command->peer.NR; 00273 MESSAGE_END(); 00274 NSack = i % wS; 00275 compound = CompoundPtr(); 00276 break; 00277 } 00278 tmpI = i; 00279 } 00280 // assure(compound==CompoundPtr(),"ACK compound has been received and processed but it is still referred to"); 00281 } 00282 break; 00283 default: assure(0," Unexpected PDU received!"); 00284 } 00285 trySuspend(); 00286 } // processOutgoing 00287 00288 void 00289 CumulativeACK::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const 00290 { 00291 //What are the sizes in the upper Layers 00292 getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this); 00293 00294 //Calculate PCI size 00295 commandPoolSize += static_cast<int>(ceil(log(sequenceNumberSize) / log(2))); 00296 commandPoolSize += 2; // 3 Frametypes can be represented with 2 Bits 00297 00298 } // calculateSizes 00299 00300 bool 00301 CumulativeACK::onSuspend() const 00302 { 00303 return NS == NSack; 00304 } // onSuspend 00305 00306 void 00307 CumulativeACK::doDelayDelivery() 00308 { 00309 delayingDelivery = true; 00310 delayedDeliveryNR = NR; 00311 } // doDelayDelivery 00312 00313 void 00314 CumulativeACK::doDeliver() 00315 { 00316 delayingDelivery = false; 00317 00318 for(; receivingCompounds[delayedDeliveryNR].compound != CompoundPtr(); delayedDeliveryNR = (delayedDeliveryNR + 1) % wS) { 00319 CompoundPtr tmpCompound = receivingCompounds[delayedDeliveryNR].compound; 00320 getDeliverer()->getAcceptor(tmpCompound)->onData(tmpCompound); 00321 receivingCompounds[delayedDeliveryNR].compound = CompoundPtr(); 00322 } 00323 } // doDeliver 00324 00325
1.5.5