User Manual, Developers Guide and API Documentation

Concatenation.cpp

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 #include <WNS/ldk/concatenation/Concatenation.hpp>
00029 #include <WNS/ldk/Layer.hpp>
00030 
00031 using namespace wns::ldk;
00032 using namespace wns::ldk::concatenation;
00033 
00034 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00035     Concatenation,
00036     FunctionalUnit,
00037     "wns.concatenation.Concatenation",
00038     FUNConfigCreator);
00039 
00040 Concatenation::Concatenation(fun::FUN* fuNet, const wns::pyconfig::View& config) :
00041     fu::Plain<Concatenation, ConcatenationCommand>(fuNet),
00042     Delayed<Concatenation>(),
00043 
00044     maxSize(config.get<Bit>("maxSize")),
00045     currentSDUSize(0),
00046     currentCommandPoolSize(0),
00047     currentCompound(CompoundPtr()),
00048     nextCompound(CompoundPtr()),
00049     maxEntries(config.get<int>("maxEntries")),
00050     currentEntries(0),
00051 
00052     numBitsIfConcatenated(config.get<Bit>("numBitsIfConcatenated")),
00053     numBitsPerEntry(config.get<Bit>("numBitsPerEntry")),
00054     numBitsIfNotConcatenated(config.get<Bit>("numBitsIfNotConcatenated")),
00055     countPCISizeOfEntries(config.get<bool>("countPCISizeOfEntries")),
00056     entryPaddingBoundary(config.get<Bit>("entryPaddingBoundary")),
00057 
00058     logger(config.get("logger"))
00059 
00060 {
00061     MESSAGE_SINGLE(VERBOSE, logger, "created");
00062 
00063 } // Concatenation
00064 
00065 
00066 Concatenation::~Concatenation()
00067 {
00068 } // ~Concatenation
00069 
00070 
00071 void
00072 Concatenation::processIncoming(const CompoundPtr& compound)
00073 {
00074     // Extract the compounds from the PCI of the PDU
00075     ConcatenationCommand* command = getCommand(compound->getCommandPool());
00076 
00077     MESSAGE_BEGIN(NORMAL, logger, m, "Fragmenting incoming container into ");
00078     m << command->peer.compounds.size() << " part(s)";
00079     MESSAGE_END();
00080 
00081     //The PCI hold the compounds, which are send to the upper FU
00082     for(std::vector<CompoundPtr>::iterator it = command->peer.compounds.begin();
00083         it != command->peer.compounds.end();
00084         ++it)
00085     {
00086         getDeliverer()->getAcceptor(*it)->onData(*it);
00087     }
00088 
00089     // the originally received PDU is dropped
00090 } // processIncoming
00091 
00092 
00093 bool
00094 Concatenation::hasCapacity() const
00095 {
00096     return (this->nextCompound == CompoundPtr()) and (currentEntries <= maxEntries);
00097 } // hasCapacity
00098 
00099 void
00100 Concatenation::processOutgoing(const CompoundPtr& compound)
00101 {
00102     activateCommand(compound->getCommandPool());
00103 
00104     if(this->currentCompound == CompoundPtr())
00105     {
00106         // start new container compound which has the same PCI, but no
00107         // data
00108         this->currentCompound = this->createContainer(compound);
00109         this->calculateSizes(this->currentCompound->getCommandPool(), currentCommandPoolSize, currentSDUSize);
00110         this->currentEntries = getCommand(this->currentCompound->getCommandPool())->peer.compounds.size();
00111 
00112         MESSAGE_BEGIN(NORMAL, logger, m, "Start new container compound with");
00113         m << " SDU Size: " << currentSDUSize;
00114         m << " PCI Size: " << currentCommandPoolSize;
00115         m << " Entries: " << currentEntries;
00116         MESSAGE_END();
00117 
00118         return;
00119     }
00120 
00121     // try to add command
00122     ConcatenationCommand* command = getCommand(this->currentCompound->getCommandPool());
00123     command->peer.compounds.push_back(compound);
00124     int wouldBeEntries = currentEntries + 1;
00125     Bit wouldBeCommandPoolSize;
00126     Bit wouldBeSDUSize;
00127     this->calculateSizes(this->currentCompound->getCommandPool(), wouldBeCommandPoolSize, wouldBeSDUSize);
00128 
00129     if((wouldBeSDUSize + wouldBeCommandPoolSize) <= maxSize and wouldBeEntries <= maxEntries)
00130     {
00131         // addition is permitted
00132         ++currentEntries;
00133         currentSDUSize = wouldBeSDUSize;
00134         currentCommandPoolSize = wouldBeCommandPoolSize;
00135 
00136         MESSAGE_BEGIN(NORMAL, logger, m, "Adding compound " << currentEntries);
00137         m << " SDU Size: " << currentSDUSize;
00138         m << " PCI Size: " << currentCommandPoolSize;
00139         MESSAGE_END();
00140     }
00141     else
00142     {
00143         // revert operation
00144         command->peer.compounds.pop_back();
00145 
00146         //this->nextCompound will be sent next
00147         this->nextCompound = this->createContainer(compound);
00148 
00149         MESSAGE_BEGIN(NORMAL, logger, m, "Accepted compound exceeds aggregation size:");
00150         m << " bits: " << (wouldBeSDUSize + wouldBeCommandPoolSize);
00151         m << " entries: " << wouldBeEntries;
00152         MESSAGE_END();
00153     }
00154 } // processOutgoing
00155 
00156 CompoundPtr
00157 Concatenation::createContainer(const CompoundPtr& firstEntry)
00158 {
00159     CommandPool* containerCommandPool = getFUN()->createCommandPool();
00160     // new container compound has the same PCI as firstEntry, but no data
00161     getFUN()->getProxy()->partialCopy(this, containerCommandPool, firstEntry->getCommandPool());
00162     // add firstEntry to container
00163     ConcatenationCommand* containerCommand = activateCommand(containerCommandPool);
00164     containerCommand->peer.compounds.push_back(firstEntry);
00165     // create compound
00166     CompoundPtr containerCompound(new Compound(containerCommandPool));
00167 
00168     return(containerCompound);
00169 }
00170 
00171 const CompoundPtr
00172 Concatenation::hasSomethingToSend() const
00173 {
00174     return this->currentCompound;
00175 } // somethingToSend
00176 
00177 
00178 CompoundPtr
00179 Concatenation::getSomethingToSend()
00180 {
00181     assure(hasSomethingToSend(), "no concatenated PDU has been constructed");
00182 
00183     MESSAGE_SINGLE(NORMAL, logger, "Sending container with " << currentEntries << " entries");
00184 
00185     // For the next transmit this->nextCompound will be send first
00186     CompoundPtr compound = this->currentCompound;
00187     this->currentCompound = this->nextCompound;
00188     this->nextCompound = CompoundPtr();
00189 
00190     if(this->currentCompound)
00191     {
00192                 // If there is something to send
00193         this->calculateSizes(this->currentCompound->getCommandPool(), currentCommandPoolSize, currentSDUSize);
00194         currentEntries = getCommand(this->currentCompound->getCommandPool())->peer.compounds.size();
00195     }
00196     else
00197     {
00198         currentEntries = 0;
00199         currentSDUSize = 0;
00200         currentCommandPoolSize = 0;
00201     }
00202 
00203     return compound;
00204 } // getSomethingToSend
00205 
00206 void
00207 Concatenation::calculateSizes(const CommandPool* commandPool, Bit& commandPoolSize, Bit& sduSize) const
00208 {
00209     // Get the entries of the container
00210     ConcatenationCommand* command = getCommand(commandPool);
00211 
00212     if(command->peer.compounds.size() > 1)
00213     {
00214         MESSAGE_SINGLE(VERBOSE, logger, "calculateSizes: Container with " << command->peer.compounds.size() << " entries.");
00215 
00216         // initialize with zero
00217         commandPoolSize = 0;
00218         sduSize = 0;
00219 
00220         // control bits for concatenation itself
00221         commandPoolSize += this->numBitsIfConcatenated;
00222 
00223         for(std::vector<CompoundPtr>::iterator it = command->peer.compounds.begin();
00224             it != command->peer.compounds.end();
00225             ++it)
00226         {
00227             // Sizes for the upper layers of the entry
00228             Bit entrySDUSize;
00229             Bit entryCommandPoolSize;
00230             (*it)->getCommandPool()->calculateSizes(entryCommandPoolSize, entrySDUSize);
00231 
00232             if(countPCISizeOfEntries)
00233             {
00234                 entryCommandPoolSize = entryCommandPoolSize + this->numBitsPerEntry;
00235             }
00236             else
00237             {
00238                 entryCommandPoolSize = this->numBitsPerEntry;
00239             }
00240 
00241             sduSize += (entrySDUSize + this->calculatePadding(entrySDUSize + entryCommandPoolSize, this->entryPaddingBoundary));
00242             commandPoolSize += entryCommandPoolSize;
00243         }
00244         MESSAGE_BEGIN(VERBOSE, logger, m, " ");
00245         m << " -> " << sduSize << "+" << commandPoolSize;
00246         MESSAGE_END();
00247     }
00248     else
00249     {
00250         if(command->peer.compounds.size() == 1)
00251         {
00252             MESSAGE_SINGLE(VERBOSE, logger, "calculateSizes: Container with single entry.");
00253             // calculate size of single entry in container
00254             getFUN()->calculateSizes(command->peer.compounds[0]->getCommandPool(), commandPoolSize, sduSize, this);
00255             commandPoolSize += this->numBitsIfNotConcatenated;
00256         }
00257         else
00258         {
00259             MESSAGE_SINGLE(VERBOSE, logger, "calculateSizes: No container command.");
00260             // Sizes for the upper layers of the non-container command
00261             getFUN()->calculateSizes(commandPool, commandPoolSize, sduSize, this);
00262         }
00263     }
00264 } // calculateSizes
00265 
00266 Bit
00267 Concatenation::calculatePadding(Bit size, Bit paddingBoundary) const
00268 {
00269     Bit padding = paddingBoundary - (size % paddingBoundary);
00270     if(padding < paddingBoundary)
00271     {
00272         return(padding);
00273     }
00274     else
00275     {
00276         return(0);
00277     }
00278 } // appendPadding
00279 
00280 

Generated on Tue May 22 03:31:37 2012 for openWNS by  doxygen 1.5.5