![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * WiFiMac * 00003 * This file is part of openWNS (open Wireless Network Simulator) 00004 * _____________________________________________________________________________ 00005 * 00006 * Copyright (C) 2004-2007 00007 * Chair of Communication Networks (ComNets) 00008 * Kopernikusstr. 16, D-52074 Aachen, Germany 00009 * phone: ++49-241-80-27910, 00010 * fax: ++49-241-80-22242 00011 * email: info@openwns.org 00012 * www: http://www.openwns.org 00013 * _____________________________________________________________________________ 00014 * 00015 * openWNS is free software; you can redistribute it and/or modify it under the 00016 * terms of the GNU Lesser General Public License version 2 as published by the 00017 * Free Software Foundation; 00018 * 00019 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00020 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00021 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00022 * details. 00023 * 00024 * You should have received a copy of the GNU Lesser General Public License 00025 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00026 * 00027 ******************************************************************************/ 00028 00029 #include <WIFIMAC/draftn/DeAggregation.hpp> 00030 00031 #include <DLL/Layer2.hpp> 00032 00033 #include <WNS/ldk/concatenation/Concatenation.hpp> 00034 00035 00036 using namespace wifimac::draftn; 00037 00038 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00039 wifimac::draftn::DeAggregation, 00040 wns::ldk::FunctionalUnit, 00041 "wifimac.draftn.DeAggregation", 00042 wns::ldk::FUNConfigCreator); 00043 00044 DeAggregation::DeAggregation(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) : 00045 wns::ldk::fu::Plain<DeAggregation, DeAggregationCommand>(fun), 00046 00047 managerName(config_.get<std::string>("managerName")), 00048 protocolCalculatorName(config_.get<std::string>("protocolCalculatorName")), 00049 txStartEndName(config_.get<std::string>("phyUserName")), 00050 aggregationCommandName(config_.get<std::string>("aggregationCommandName")), 00051 00052 txQueue(), 00053 currentTxCompound(), 00054 currentRxContainer(), 00055 doSignalTxStart(false), 00056 numEntries(0), 00057 00058 logger(config_.get("logger")) 00059 { 00060 MESSAGE_SINGLE(NORMAL, this->logger, "created"); 00061 00062 protocolCalculator = NULL; 00063 friends.manager = NULL; 00064 } 00065 00066 00067 DeAggregation::~DeAggregation() 00068 { 00069 } 00070 00071 void DeAggregation::onFUNCreated() 00072 { 00073 MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started"); 00074 protocolCalculator = getFUN()->getLayer<dll::ILayer2*>()->getManagementService<wifimac::management::ProtocolCalculator>(protocolCalculatorName); 00075 friends.manager = getFUN()->findFriend<wifimac::lowerMAC::Manager*>(managerName); 00076 00077 // Observe txStartEnd 00078 this->wns::Observer<wifimac::convergence::ITxStartEnd>::startObserving(getFUN()->findFriend<wifimac::convergence::TxStartEndNotification*>(txStartEndName)); 00079 } 00080 00081 void 00082 DeAggregation::processIncoming(const wns::ldk::CompoundPtr& compound) 00083 { 00084 DeAggregationCommand* command = getCommand(compound->getCommandPool()); 00085 00086 if(command->peer.singleFragment) 00087 { 00088 // no aggregation at all 00089 MESSAGE_SINGLE(NORMAL, this->logger, "Single fragment -> deliver"); 00090 getDeliverer()->getAcceptor(compound)->onData(compound); 00091 return; 00092 } 00093 00094 MESSAGE_SINGLE(NORMAL, this->logger, "Process incoming aggregation fragment from " << friends.manager->getTransmitterAddress(compound->getCommandPool())); 00095 00096 if(friends.manager->getFrameType(compound->getCommandPool()) == PREAMBLE) 00097 { 00098 // new aggregation 00099 if(this->currentRxContainer) 00100 { 00101 // capture effect: we receive a preamble of a different compound 00102 // before the current container is received completely. 00103 MESSAGE_SINGLE(NORMAL, this->logger, "Received aggregation preamble, during aggregation -> deliver old with " << this->numEntries << " entries"); 00104 getDeliverer()->getAcceptor(this->currentRxContainer)->onData(this->currentRxContainer); 00105 this->currentRxContainer = wns::ldk::CompoundPtr(); 00106 this->numEntries = 0; 00107 this->cancelTimeout(); 00108 } 00109 00110 // generate container from preamble 00111 this->currentRxContainer = compound->copy(); 00112 friends.manager->setFrameType(this->currentRxContainer->getCommandPool(), DATA); 00113 00114 // clear compound container 00115 getFUN()->getCommandReader(aggregationCommandName)-> 00116 readCommand<wns::ldk::concatenation::ConcatenationCommand>(this->currentRxContainer->getCommandPool())->peer.compounds.clear(); 00117 00118 MESSAGE_SINGLE(NORMAL, this->logger, "Received aggregation preamble, create container"); 00119 00120 // set timeout for the delivery of the compounds 00121 this->setTimeout(friends.manager->getFrameExchangeDuration(compound->getCommandPool()) + 10e-9); 00122 00123 // deliver preamble 00124 getDeliverer()->getAcceptor(compound)->onData(compound); 00125 return; 00126 } 00127 00128 assure(not (this->currentRxContainer == wns::ldk::CompoundPtr()), 00129 "Received A-MPDU fragment, but rxContainer is empty!"); 00130 00131 // append current compound 00132 wns::ldk::concatenation::ConcatenationCommand* aggCommand = getFUN()->getCommandReader(aggregationCommandName)-> 00133 readCommand<wns::ldk::concatenation::ConcatenationCommand>(this->currentRxContainer->getCommandPool()); 00134 aggCommand->peer.compounds.push_back(compound); 00135 00136 MESSAGE_SINGLE(NORMAL, this->logger, "Received aggregation fragment, append"); 00137 this->numEntries++; 00138 00139 if(command->peer.finalFragment) 00140 { 00141 MESSAGE_SINGLE(NORMAL, this->logger, "Received last aggregation fragment, deliver container with " << this->numEntries << " entries"); 00142 // final fragment -> deliver complete aggregated compound 00143 wns::ldk::CompoundPtr it = this->currentRxContainer->copy(); 00144 this->currentRxContainer = wns::ldk::CompoundPtr(); 00145 this->numEntries = 0; 00146 this->cancelTimeout(); 00147 00148 getDeliverer()->getAcceptor(it)->onData(it); 00149 } 00150 } 00151 00152 void DeAggregation::onTimeout() 00153 { 00154 if(this->numEntries > 0) 00155 { 00156 assure(this->currentRxContainer, "No current container"); 00157 MESSAGE_SINGLE(NORMAL, this->logger, "Timeout for last aggregation fragment, deliver container with " << this->numEntries << " entries"); 00158 getDeliverer()->getAcceptor(this->currentRxContainer)->onData(this->currentRxContainer); 00159 this->currentRxContainer = wns::ldk::CompoundPtr(); 00160 this->numEntries = 0; 00161 } 00162 else 00163 { 00164 MESSAGE_SINGLE(NORMAL, this->logger, "Timeout for aggregation, no entries successfully received"); 00165 this->currentRxContainer = wns::ldk::CompoundPtr(); 00166 } 00167 } 00168 00169 00170 void 00171 DeAggregation::processOutgoing(const wns::ldk::CompoundPtr& compound) 00172 { 00173 assure(this->currentTxCompound == wns::ldk::CompoundPtr(), "processOutgoing, but currentTxCompound is not free"); 00174 assure(this->txQueue.empty(), "processOutgoing, but txQueue is not empty"); 00175 00176 // calculate tx duration 00177 DeAggregationCommand* command = activateCommand(compound->getCommandPool()); 00178 wifimac::convergence::PhyMode phyMode = friends.manager->getPhyMode(compound->getCommandPool()); 00179 wns::simulator::Time preambleTxDuration = protocolCalculator->getDuration()->preamble(phyMode); 00180 00181 if(friends.manager->getFrameType(compound->getCommandPool()) == PREAMBLE) 00182 { 00183 command->local.txDuration = preambleTxDuration; 00184 if(getFUN()->getCommandReader(aggregationCommandName)->commandIsActivated(compound->getCommandPool())) 00185 { 00186 // preamble of aggregation command 00187 command->peer.singleFragment = false; 00188 command->peer.finalFragment = false; 00189 } 00190 else 00191 { 00192 command->peer.singleFragment = true; 00193 } 00194 this->txQueue.push_back(compound); 00195 return; 00196 } 00197 00198 this->currentTxCompound = compound; 00199 this->doSignalTxStart = true; 00200 00201 wns::simulator::Time frameTxDuration = protocolCalculator->getDuration()->MPDU_PPDU(compound->getLengthInBits(), phyMode) - preambleTxDuration; 00202 00203 if(not getFUN()->getCommandReader(aggregationCommandName)->commandIsActivated(compound->getCommandPool())) 00204 { 00205 // not an aggregation container command, schedule transmission for now 00206 command->local.txDuration = frameTxDuration; 00207 command->peer.singleFragment = true; 00208 this->txQueue.push_back(compound); 00209 return; 00210 } 00211 00212 wns::simulator::Time nav = friends.manager->getFrameExchangeDuration(compound->getCommandPool()); 00213 assure(frameTxDuration > 0, "Cannot transmit a frame with duration <= 0"); 00214 00215 MESSAGE_SINGLE(NORMAL, logger, "Outgoing aggregated compound with frame duration " << frameTxDuration); 00216 00217 // split aggregation container into single compounds 00218 std::vector<Bit> sduSizes = std::vector<Bit>(); 00219 Bit completeSize = 0; 00220 00221 // iterate over the compounds to get the complete and single sizes 00222 // note that those sizes do NOT include any padding done by the Aggregation/Concatanation FU thus sizes differ from 00223 // those of the Aggregation FU. HOWEVER since the frameTxDuration is correct and sizes are only used to calculate 00224 // fractions of this duration, the mechanism still works (-: 00225 00226 wns::ldk::concatenation::ConcatenationCommand* aggCommand = getFUN()->getCommandReader(aggregationCommandName)-> 00227 readCommand<wns::ldk::concatenation::ConcatenationCommand>(compound->getCommandPool()); 00228 for (std::vector<wns::ldk::CompoundPtr>::iterator it = aggCommand->peer.compounds.begin(); 00229 it != aggCommand->peer.compounds.end(); 00230 ++it) 00231 { 00232 completeSize += (*it)->getLengthInBits(); 00233 sduSizes.push_back((*it)->getLengthInBits()); 00234 } 00235 00236 MESSAGE_SINGLE(NORMAL, logger, aggCommand->peer.compounds.size() << " entries in aggregation container, complete size " << completeSize); 00237 00238 // iterate over the compounds and queue transmissions 00239 wns::simulator::Time nextStart = 0.0; 00240 std::vector<Bit>::iterator itS = sduSizes.begin(); 00241 00242 for (std::vector<wns::ldk::CompoundPtr>::iterator itC = aggCommand->peer.compounds.begin(); 00243 itC != aggCommand->peer.compounds.end(); 00244 ++itC, ++itS) 00245 { 00246 // set duration field to end of transmission + former nav 00247 wns::simulator::Time currentDuration = static_cast<double>(*itS)/static_cast<double>(completeSize) * frameTxDuration; 00248 friends.manager->setFrameExchangeDuration((*itC)->getCommandPool(), (frameTxDuration - nextStart - currentDuration) + nav); 00249 00250 // all fragments must have the same phyMode 00251 friends.manager->setPhyMode((*itC)->getCommandPool(), friends.manager->getPhyMode(compound->getCommandPool())); 00252 00253 // schedule fragment transmission 00254 DeAggregationCommand* currentCommand = activateCommand((*itC)->getCommandPool()); 00255 currentCommand->local.txDuration = currentDuration; 00256 00257 nextStart = nextStart + currentDuration; 00258 00259 currentCommand->peer.singleFragment = false; 00260 // mark last compound 00261 currentCommand->peer.finalFragment = (itC+1 == aggCommand->peer.compounds.end()); 00262 00263 // next fragment, queue for transmission 00264 this->txQueue.push_back(*itC); 00265 00266 MESSAGE_BEGIN(NORMAL, logger, m, " * size " << (*itS)); 00267 m << ", fraction " << static_cast<double>(*itS)/static_cast<double>(completeSize); 00268 m << "-> delay " << nextStart - currentDuration; 00269 m << " duration " << currentDuration; 00270 m << " final " << currentCommand->peer.finalFragment; 00271 MESSAGE_END(); 00272 } 00273 } 00274 00275 const wns::ldk::CompoundPtr 00276 DeAggregation::hasSomethingToSend() const 00277 { 00278 if(txQueue.empty()) 00279 { 00280 return(wns::ldk::CompoundPtr()); 00281 } 00282 else 00283 { 00284 return(*(txQueue.begin())); 00285 } 00286 } 00287 00288 wns::ldk::CompoundPtr 00289 DeAggregation::getSomethingToSend() 00290 { 00291 wns::ldk::CompoundPtr send = *(this->txQueue.begin()); 00292 this->txQueue.pop_front(); 00293 return(send); 00294 } 00295 00296 bool 00297 DeAggregation::hasCapacity() const 00298 { 00299 return(this->currentTxCompound == wns::ldk::CompoundPtr()); 00300 } 00301 00302 void 00303 DeAggregation::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const 00304 { 00305 00306 getFUN()->getProxy()->calculateSizes(commandPool, commandPoolSize, dataSize, this); 00307 } 00308 00309 void 00310 DeAggregation::onTxStart(const wns::ldk::CompoundPtr& /*compound*/) 00311 { 00312 if(this->doSignalTxStart) 00313 { 00314 this->doSignalTxStart = false; 00315 this->wns::Subject<ITxStartEnd>::forEachObserver(OnTxStartEnd(this->currentTxCompound, wifimac::convergence::start)); 00316 } 00317 } 00318 00319 void 00320 DeAggregation::onTxEnd(const wns::ldk::CompoundPtr& /*compound*/) 00321 { 00322 if((this->txQueue.empty()) and (this->currentTxCompound != wns::ldk::CompoundPtr())) 00323 { 00324 // signal tx end of complete frame 00325 this->wns::Subject<ITxStartEnd>::forEachObserver(OnTxStartEnd(this->currentTxCompound, wifimac::convergence::end)); 00326 this->currentTxCompound = wns::ldk::CompoundPtr(); 00327 } 00328 }
1.5.5