![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * WiMeMac * 00003 * This file is part of openWNS (open Wireless Network Simulator) 00004 * _____________________________________________________________________________ 00005 * 00006 * Copyright (C) 2004-2011 00007 * Chair of Communication Networks (ComNets) 00008 * Kopernikusstr. 5, 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 <WIMEMAC/lowerMAC/TXOP.hpp> 00030 #include <WIMEMAC/FrameType.hpp> 00031 00032 #include <WNS/probe/bus/utils.hpp> 00033 00034 #include <algorithm> 00035 #include "IManagerServices.hpp" 00036 00037 using namespace wimemac::lowerMAC; 00038 00039 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00040 TXOP, 00041 wns::ldk::FunctionalUnit, 00042 "wimemac.lowerMAC.TXOP", 00043 wns::ldk::FUNConfigCreator); 00044 00045 TXOP::TXOP(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config_) : 00046 wns::ldk::fu::Plain<TXOP, wns::ldk::EmptyCommand>(fun), 00047 managerName(config_.get<std::string>("managerName")), 00048 protocolCalculatorName(config_.get<std::string>("protocolCalculatorName")), 00049 txopWindowName(config_.get<std::string>("txopWindowName")), 00050 //raName(config_.get<std::string>("raName")), 00051 sifsDuration(config_.get<wns::simulator::Time>("myConfig.sifsDuration")), 00052 maximumACKDuration(config_.get<wns::simulator::Time>("myConfig.maximumACKDuration")), 00053 txopLimit(config_.get<wns::simulator::Time>("myConfig.txopLimit")), 00054 singleReceiver(config_.get<bool>("myConfig.singleReceiver")), 00055 maxOutTXOP(config_.get<bool>("myConfig.maxOutTXOP")), 00056 remainingTXOPDuration(0), 00057 txopReceiver(), 00058 logger(config_.get("logger")) 00059 { 00060 // either no TXOP (==0) or TXOP limit long enough to contain SIFS duration and ACK response 00061 /* if (txopLimit > 0) 00062 { 00063 assure (txopLimit > sifsDuration + maximumACKDuration, 00064 "TXOP limit too small (must be greater than SIFS duration + maximum ACK Duration or 0 for no TXOP)"); 00065 } 00066 */ MESSAGE_SINGLE(NORMAL, this->logger, "created"); 00067 00068 friends.manager = NULL; 00069 protocolCalculator = NULL; 00070 friends.txopWindow = NULL; 00071 //friends.ra = NULL; 00072 00073 // read the localIDs from the config 00074 wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection()); 00075 for (int ii = 0; ii<config_.len("localIDs.keys()"); ++ii) 00076 { 00077 std::string key = config_.get<std::string>("localIDs.keys()",ii); 00078 unsigned int value = config_.get<unsigned int>("localIDs.values()",ii); 00079 localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value)); 00080 MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value); 00081 } 00082 TXOPDurationProbe = wns::probe::bus::collector(localContext, config_, "TXOPDurationProbeName"); 00083 } 00084 00085 00086 TXOP::~TXOP() 00087 { 00088 } 00089 00090 void TXOP::onFUNCreated() 00091 { 00092 MESSAGE_SINGLE(NORMAL, this->logger, "onFUNCreated() started"); 00093 00094 friends.manager = getFUN()->findFriend<IManagerServices*>(managerName); 00095 friends.txopWindow = getFUN()->findFriend<ITXOPWindow*>(txopWindowName); 00096 //friends.ra = getFUN()->findFriend<RateAdaptation*>(raName); 00097 protocolCalculator = getFUN()->getLayer<dll::ILayer2*>()->getManagementService<wimemac::management::ProtocolCalculator>(protocolCalculatorName); 00098 } 00099 00100 void 00101 TXOP::processIncoming(const wns::ldk::CompoundPtr& compound) 00102 { 00103 // reset frame type if necessary 00104 //if(friends.manager->getCompoundType(compound->getCommandPool()) == DATA_TXOP) 00105 //{ 00106 // friends.manager->setCompoundType(compound->getCommandPool(), DATA); 00107 //} 00108 } 00109 00110 00111 00112 00113 void 00114 TXOP::processOutgoing(const wns::ldk::CompoundPtr& compound) 00115 { 00116 switch(friends.manager->getCompoundType(compound->getCommandPool())) 00117 { 00118 case DATA: 00119 { 00120 if(this->remainingTXOPDuration == 0) 00121 { 00122 // start of the TXOP 00123 this->remainingTXOPDuration = this->txopLimit; 00124 if(singleReceiver) 00125 { 00126 this->txopReceiver = friends.manager->getReceiverAddress(compound->getCommandPool()); 00127 } 00128 MESSAGE_BEGIN(NORMAL, this->logger, m, "Outgoing data compound to "); 00129 m << friends.manager->getReceiverAddress(compound->getCommandPool()); 00130 m << ", starting TXOP with duration " << this->remainingTXOPDuration; 00131 MESSAGE_END(); 00132 } 00133 else 00134 { 00135 // we have an ongoing TXOP 00136 00137 // no need check if frame fits into current TXOP: 00138 // Either, this frame is the expected frame and fits perfectly, or 00139 // the frame is a retransmission which is allowed to be send without 00140 // looking at the txop limit 00141 00142 // Another SIFS Duration was waited between two frames of a TXOP 00143 this->remainingTXOPDuration -= this->sifsDuration; 00144 00145 friends.manager->setCompoundType(compound->getCommandPool(), DATA_TXOP); 00146 MESSAGE_BEGIN(NORMAL, this->logger, m, "Outgoing data compound to "); 00147 m << friends.manager->getReceiverAddress(compound->getCommandPool()); 00148 m << ", continue TXOP with duration " << this->remainingTXOPDuration; 00149 MESSAGE_END(); 00150 } 00151 00152 // cut TXOP duration by current frame 00153 wimemac::convergence::PhyMode phyMode = friends.manager->getPhyMode(compound->getCommandPool()); 00154 wns::simulator::Time duration = protocolCalculator->getDuration()->MSDU_PPDU(compound->getLengthInBits(), 00155 phyMode); 00156 00157 wns::simulator::Time cutTXOPDuration = this->remainingTXOPDuration 00158 - duration 00159 - this->sifsDuration 00160 - this->maximumACKDuration; 00161 00162 lastFTDuration = duration + this->sifsDuration + this->maximumACKDuration + this->sifsDuration; 00163 00164 MESSAGE_SINGLE(NORMAL, this->logger, "Current compound cuts TXOP to " << cutTXOPDuration); 00165 00166 if(cutTXOPDuration <= 0) 00167 { 00168 // no time for additional frames -> no (more) TXOP 00169 MESSAGE_SINGLE(NORMAL, this->logger, "Current compound fills complete TXOP"); 00170 closeTXOP(); 00171 return; 00172 } 00173 this->remainingTXOPDuration = cutTXOPDuration; 00174 00175 // check if next frame would fit into TXOP 00176 wns::simulator::Time nextDuration = friends.txopWindow->getNextTransmissionDuration(); 00177 00178 if(nextDuration == 0) 00179 { 00180 // no next compound, no (more) TXOP 00181 MESSAGE_SINGLE(NORMAL, this->logger, "No next compound, no (more) TXOP"); 00182 closeTXOP(); 00183 return; 00184 } 00185 00186 // if(singleReceiver and (this->txopReceiver != friends.txopWindow->getNextReceiver())) 00187 // { 00188 // MESSAGE_BEGIN(NORMAL, this->logger, m, "TXOP is restricted to receiver "); 00189 // m << this->txopReceiver << " and next compound is addressed to "; 00190 // m << friends.txopWindow->getNextReceiver(); 00191 // m << "no (more) TXOP"; 00192 // MESSAGE_END(); 00193 // closeTXOP(); 00194 // return; 00195 // } 00196 00197 wns::simulator::Time nextFrameExchangeDuration; 00198 00199 if (not maxOutTXOP) 00200 { 00201 nextFrameExchangeDuration = this->sifsDuration 00202 + nextDuration 00203 + this->sifsDuration 00204 + this->maximumACKDuration; 00205 } 00206 else 00207 { 00208 nextFrameExchangeDuration = this->remainingTXOPDuration; 00209 } 00210 00211 if (this->remainingTXOPDuration < nextFrameExchangeDuration) 00212 { 00213 // next frame does not fit -> no (more) TXOP 00214 MESSAGE_SINGLE(NORMAL, this->logger, "Next frame has duration " << nextFrameExchangeDuration << ", does not fit"); 00215 closeTXOP(); 00216 return; 00217 } 00218 00219 // next frame fits -> extend frame exchange duration by complete 00220 // next frame exchange 00221 friends.manager->setFrameExchangeDuration(compound->getCommandPool(), 00222 friends.manager->getFrameExchangeDuration(compound->getCommandPool()) + nextFrameExchangeDuration); 00223 00224 MESSAGE_BEGIN(NORMAL, this->logger, m, "Next frame has duration "); 00225 m << nextFrameExchangeDuration; 00226 m << ", fit into TXOP, set NAV to "; 00227 m << friends.manager->getFrameExchangeDuration(compound->getCommandPool()); 00228 MESSAGE_END(); 00229 00230 break; 00231 } 00232 00233 case ACK: 00234 { 00235 // do not change the ACK in any way before transmission 00236 break; 00237 } 00238 default: 00239 { 00240 throw wns::Exception("Unknown frame type"); 00241 break; 00242 } 00243 } 00244 00245 00246 } 00247 00248 bool TXOP::doIsAccepting(const wns::ldk::CompoundPtr& compound) const 00249 { 00250 if((friends.manager->getCompoundType(compound->getCommandPool()) == DATA) and 00251 (this->remainingTXOPDuration > 0)) 00252 { 00253 // we have an ongoing TXOP 00254 00255 // no need check if frame fits into current TXOP: 00256 // Either, this frame is the expected frame and fits perfectly, or 00257 // the frame is a retransmission which is allowed to be send without 00258 // looking at the txop limit 00259 00260 // copy the compound and change type so that the right path in the FUN 00261 // is taken 00262 wns::ldk::CompoundPtr txopCompound = compound->copy(); 00263 friends.manager->setCompoundType(txopCompound->getCommandPool(), DATA_TXOP); 00264 00265 return wns::ldk::Processor<TXOP>::doIsAccepting(txopCompound); 00266 } 00267 else 00268 { 00269 // no special handling 00270 return wns::ldk::Processor<TXOP>::doIsAccepting(compound); 00271 } 00272 } 00273 00274 00275 void TXOP::closeTXOP(bool forwardCall) 00276 { 00277 TXOPDurationProbe->put(this->txopLimit - this->remainingTXOPDuration); 00278 this->remainingTXOPDuration = 0; 00279 for(int i=0; i < observers.size();i++) 00280 { 00281 observers[i]->onTXOPClosed(); 00282 } 00283 00284 if(forwardCall) friends.manager->txOPCloseIn(lastFTDuration); 00285 } 00286 00287 00288 void TXOP::setTXOPLimit(wns::simulator::Time limit) 00289 { 00290 /* if (limit > 0) 00291 { 00292 assure (txopLimit > sifsDuration + maximumACKDuration, 00293 "TXOP limit too small (must be greater than SIFS duration + maximum ACK Duration or 0 for no TXOP)"); 00294 } 00295 */ this->txopLimit = limit; 00296 this->remainingTXOPDuration = 0; 00297 }
1.5.5