![]() |
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 #ifndef WNS_LDK_SAR_HPP 00029 #define WNS_LDK_SAR_HPP 00030 00031 #include <WNS/logger/Logger.hpp> 00032 00033 #include <WNS/ldk/CommandTypeSpecifier.hpp> 00034 #include <WNS/ldk/HasReceptor.hpp> 00035 #include <WNS/ldk/HasConnector.hpp> 00036 #include <WNS/ldk/HasDeliverer.hpp> 00037 #include <WNS/ldk/Delayed.hpp> 00038 #include <WNS/ldk/SuspendableInterface.hpp> 00039 #include <WNS/ldk/SuspendSupport.hpp> 00040 00041 #include <WNS/pyconfig/View.hpp> 00042 00043 #include <list> 00044 00045 namespace wns { namespace ldk { namespace sar { 00046 00047 class SARCommand : 00048 public Command 00049 { 00050 public: 00051 SARCommand() 00052 { 00053 peer.lastFragment = true; 00054 magic.pos = -1; 00055 magic.fragmentNumber = -1; 00056 magic.segmentSize = -1; 00057 magic.preserving = true; 00058 } // SARCommand 00059 00060 struct {} local; 00061 struct { 00062 bool lastFragment; 00063 } peer; 00064 struct { 00065 int pos; 00066 int fragmentNumber; 00067 int segmentSize; 00068 bool preserving; 00069 } magic; 00070 }; 00071 00078 template <typename COMMANDTYPE> 00079 class SAR : 00080 virtual public FunctionalUnit, 00081 virtual public DelayedInterface, 00082 public CommandTypeSpecifier<COMMANDTYPE>, 00083 virtual public SuspendableInterface, 00084 public SuspendSupport 00085 { 00086 public: 00087 SAR(fun::FUN* fuNet, const wns::pyconfig::View& config) : 00088 CommandTypeSpecifier<COMMANDTYPE>(fuNet), 00089 SuspendSupport(fuNet, config), 00090 outgoing(), 00091 nextSegment(), 00092 nextPos(), 00093 totalSize(), 00094 segmentSize(config.get<Bit>("segmentSize")), 00095 headerSize(config.get<Bit>("headerSize")), 00096 preserving(config.get<bool>("preserving")), 00097 logger(config.get("logger")) 00098 {} // SAR 00099 00100 virtual 00101 ~SAR() 00102 { 00103 outgoing = CompoundPtr(); 00104 nextSegment = CompoundPtr(); 00105 backupCompound = CompoundPtr(); 00106 } // ~SAR 00107 00108 00109 // 00110 // interface 00111 // 00112 00113 void setSegmentSize(const Bit size) 00114 { 00115 MESSAGE_BEGIN(NORMAL, logger, m, ""); 00116 m 00117 << "changing segment size from " 00118 << segmentSize 00119 << " to " 00120 << size 00121 << " bits."; 00122 MESSAGE_END(); 00123 00124 // undo preparation of last segment 00125 Bit capacity = segmentSize - this->getCommandSize() - ( preserving ? oldPCISize : 0 ); 00126 nextPos -= capacity; 00127 --fragmentNumber; 00128 00129 if(outgoing == CompoundPtr() && nextSegment != CompoundPtr() ) 00130 { 00131 outgoing = backupCompound->copy(); 00132 } 00133 00134 nextSegment = CompoundPtr(); 00135 00136 // set new segment size 00137 segmentSize = size; 00138 00139 00140 // and re-do the preparation 00141 prepareSegment(); 00142 00143 } // setMTU 00144 00145 Bit getSegmentSize() const 00146 { 00147 return segmentSize; 00148 } // getSegmentSize 00149 00150 virtual void processOutgoing(const CompoundPtr& compound) 00151 { 00152 assure(hasCapacity(), "processOutgoing called although not accepting."); 00153 00154 outgoing = compound; 00155 backupCompound = compound->copy(); 00156 00157 nextPos = 0; 00158 fragmentNumber = 0; 00159 00160 CommandPool* commandPool = outgoing->getCommandPool(); 00161 00162 getFUN()->calculateSizes(commandPool, 00163 oldPCISize, 00164 oldSDUSize); 00165 00166 totalSize = oldPCISize + oldSDUSize; 00167 00168 MESSAGE_BEGIN(NORMAL, logger, m, ""); 00169 m 00170 << "size of previous Commands: " 00171 << oldPCISize 00172 << " size of SDU: " 00173 << oldSDUSize 00174 << " - cutting " 00175 << totalSize 00176 << " bits into segments of " << segmentSize << " bits."; 00177 MESSAGE_END(); 00178 00179 prepareSegment(); 00180 } // processOutgoing 00181 00182 virtual CompoundPtr getSomethingToSend() 00183 { 00184 assure(hasSomethingToSend(), "getSomethingToSend called although there's nothing to send."); 00185 00186 CompoundPtr returnValue = nextSegment; // store next segment as 00187 // return value 00188 prepareSegment(); // and prepare the subsequent segment 00189 00190 return returnValue; 00191 } // getSomethingToSend 00192 00193 // partial implementation of delayed 00194 virtual bool hasCapacity() const 00195 { 00196 return (outgoing == CompoundPtr() && nextSegment == CompoundPtr()); 00197 } // hasCapacity 00198 00199 virtual const CompoundPtr hasSomethingToSend() const 00200 { 00201 trySuspend(); 00202 00203 return nextSegment; 00204 } 00205 00206 // 00207 // PCI size calculation 00208 // 00209 Bit 00210 getCommandSize() const 00211 { 00212 return headerSize; 00213 } 00214 00215 // 00216 // PDU size modification 00217 // 00218 virtual void calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const 00219 { 00220 getFUN()->calculateSizes(commandPool, commandPoolSize, dataSize, this); 00221 00222 // now we have the size of all previous Commands and of the original Compound 00223 00224 COMMANDTYPE* command = this->getCommand(commandPool); 00225 00226 Bit capacity = command->magic.segmentSize - this->getCommandSize() - ( command->magic.preserving ? commandPoolSize : 0 ); 00227 00228 if(command->peer.lastFragment) { 00229 dataSize = dataSize - command->magic.pos + ( command->magic.preserving ? 0 : commandPoolSize ); 00230 } else 00231 dataSize = capacity; 00232 00233 // overwrite the commandPoolSize, because after the segmentation, only our own 00234 // command is visible until the reassembly is performed. 00235 // :FIXME: at a later point, we may also have to deal with flows :-( 00236 if (command->magic.preserving) 00237 commandPoolSize += this->getCommandSize(); 00238 else 00239 commandPoolSize = this->getCommandSize(); 00240 } 00241 00242 00243 protected: 00244 CompoundPtr outgoing; 00245 CompoundPtr nextSegment; 00252 CompoundPtr backupCompound; 00253 00254 Bit nextPos; 00255 int fragmentNumber; 00256 00257 Bit totalSize; 00258 Bit oldPCISize; 00259 Bit oldSDUSize; 00260 00261 Bit segmentSize; 00262 Bit headerSize; 00263 bool preserving; 00264 00265 logger::Logger logger; 00266 00267 virtual 00268 void prepareSegment(){ 00269 if (!outgoing){ 00270 // nothing to do 00271 nextSegment = wns::ldk::CompoundPtr(); 00272 00273 return; 00274 } 00275 00276 SARCommand* command; 00277 00278 Bit capacity = segmentSize - this->getCommandSize() - ( preserving ? oldPCISize : 0 ); 00279 MESSAGE_BEGIN(NORMAL, logger, m, ""); 00280 m << "SAR: capacity=" << capacity; 00281 m << ", Commandsize=" << this->getCommandSize(); 00282 MESSAGE_END(); 00283 if( totalSize - nextPos > capacity ) { 00284 nextSegment = outgoing->copy(); 00285 command = activateCommand(nextSegment->getCommandPool()); 00286 command->peer.lastFragment = false; 00287 command->magic.pos = nextPos; 00288 nextPos += capacity; 00289 command->magic.fragmentNumber = fragmentNumber; 00290 ++fragmentNumber; 00291 command->magic.segmentSize = segmentSize; 00292 command->magic.preserving = preserving; 00293 } else { 00294 nextSegment = outgoing; 00295 command = activateCommand(nextSegment->getCommandPool()); 00296 command->peer.lastFragment = true; 00297 command->magic.pos = nextPos; 00298 nextPos += capacity; 00299 command->magic.fragmentNumber = fragmentNumber; 00300 command->magic.segmentSize = segmentSize; 00301 command->magic.preserving = preserving; 00302 ++fragmentNumber; 00303 outgoing = CompoundPtr(); 00304 } 00305 00306 this->commitSizes(nextSegment->getCommandPool()); 00307 00308 MESSAGE_BEGIN(NORMAL, logger, m, ""); 00309 m << "#" << command->magic.fragmentNumber 00310 << ", length=" 00311 << nextSegment->getLengthInBits() 00312 << " last=" 00313 << ( command->peer.lastFragment ? "yes" : "no"); 00314 if (!command->peer.lastFragment) 00315 m << " nextPos=" << nextPos; 00316 MESSAGE_END(); 00317 } 00318 00319 private: 00320 virtual bool 00321 onSuspend() const 00322 { 00323 return hasCapacity(); 00324 } 00325 00326 }; 00327 }}} 00328 00329 #endif // NOT defined WNS_LDK_SAR_HPP 00330 00331
1.5.5