User Manual, Developers Guide and API Documentation

SAR.hpp

Go to the documentation of this file.
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 

Generated on Fri May 25 03:31:46 2012 for openWNS by  doxygen 1.5.5