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