![]() |
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/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
1.5.5