![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * Glue * 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/timing/Backoff.hpp> 00030 00031 #include <WNS/Assure.hpp> 00032 #include <boost/bind.hpp> 00033 00034 using namespace wifimac::lowerMAC::timing; 00035 00036 Backoff::Backoff(BackoffObserver* _backoffObserver, const wns::pyconfig::View& _config) : 00037 backoffObserver(_backoffObserver), 00038 slotDuration(_config.get<wns::simulator::Time>("myConfig.slotDuration")), 00039 aifsDuration(_config.get<wns::simulator::Time>("myConfig.aifsDuration")), 00040 eifsDuration(_config.get<wns::simulator::Time>("myConfig.eifsDuration")), 00041 backoffFinished(false), 00042 transmissionWaiting(false), 00043 duringAIFS(false), 00044 rxError(false), 00045 cwMin(_config.get<int>("myConfig.cwMin")), 00046 cwMax(_config.get<int>("myConfig.cwMax")), 00047 cw(cwMin), 00048 uniform(0.0, 1.0, wns::simulator::getRNG()), 00049 logger(_config.get("backoffLogger")), 00050 // we start with an idle channel 00051 channelIsBusy(false), 00052 counter(0) 00053 { 00054 assureNotNull(backoffObserver); 00055 MESSAGE_SINGLE(NORMAL, logger, "created"); 00056 00057 // start the initial backoff 00058 startNewBackoffCountdown(aifsDuration); 00059 } 00060 00061 00062 Backoff::~Backoff() 00063 { 00064 } 00065 00066 wns::simulator::Time Backoff::finishedAt() const 00067 { 00068 wns::simulator::Time now = wns::simulator::getEventScheduler()->getTime(); 00069 if (not channelIsBusy) 00070 { 00071 if (duringAIFS) 00072 { 00073 if(not rxError) 00074 { 00075 return now + cw*slotDuration + (aifsDuration - (now - aifsStart)); 00076 } 00077 else 00078 { 00079 return now + cw*slotDuration + (eifsDuration - (now - aifsStart)); 00080 } 00081 } 00082 else 00083 { 00084 if (backoffFinished == true) 00085 { 00086 return now; 00087 } 00088 else 00089 { 00090 return now + counter * slotDuration; 00091 } 00092 } 00093 } 00094 return wns::simulator::Time(); 00095 } 00096 00097 00098 void 00099 Backoff::startNewBackoffCountdown(wns::simulator::Time ifsDuration) 00100 { 00101 assure(not channelIsBusy, "channel must be idle to start backoff"); 00102 00103 backoffFinished = false; 00104 duringAIFS = true; 00105 00106 MESSAGE_SINGLE(NORMAL, logger, "Start new backoff, waiting for AIFS=" << ifsDuration); 00107 // First stage: Try to survive AIFS 00108 setNewTimeout(ifsDuration); 00109 } 00110 00111 void 00112 Backoff::onTimeout() 00113 { 00114 assure(backoffFinished == false, "timer expired but not in backoff countdown"); 00115 00116 if(duringAIFS) 00117 { 00118 duringAIFS = false; 00119 // the constant waiting time has expired 00120 if (counter == 0) 00121 { 00122 if (not transmissionWaiting) 00123 { 00124 // obviously, no (re-)transmission is pending, so reset the cw 00125 cw = cwMin; 00126 } 00127 00128 // we need a fresh counter, so we draw the random waiting 00129 // time between [0 and cw] 00130 counter = int(uniform() * (cw+1)); 00131 if(counter > cw) 00132 { 00133 // corner case that uniform() gives exactly 1 00134 --counter; 00135 } 00136 assure(counter>=0, "counter too small"); 00137 assure(counter<=cw, "counter too big"); 00138 00139 MESSAGE_SINGLE(NORMAL, logger, "AIFS waited, start new backoff with counter " << counter << ", cw is " << cw); 00140 } 00141 else 00142 { 00143 MESSAGE_SINGLE(NORMAL, logger, "AIFS waited, continue backoff with counter " << counter); 00144 } 00145 } 00146 else 00147 { 00148 // one further slot waited 00149 --counter; 00150 MESSAGE_SINGLE(NORMAL, logger, "Slot waited, counter is now " << counter); 00151 } 00152 00153 if(counter == 0) 00154 { 00155 // backoff finished 00156 backoffFinished = true; 00157 00158 MESSAGE_SINGLE(NORMAL, logger,"Backoff has finished, transmission is " << 00159 ((transmissionWaiting) ? "waiting" : "none")); 00160 for(int i=0; i < eobObserver.size(); i++) 00161 { 00162 eobObserver[i]->backoffExpired(); 00163 } 00164 00165 if (transmissionWaiting) 00166 { 00167 transmissionWaiting = false; 00168 backoffFinished = false; 00169 backoffObserver->backoffExpired(); 00170 } 00171 } 00172 else 00173 { 00174 setTimeout(slotDuration); 00175 } 00176 } 00177 00178 bool 00179 Backoff::transmissionRequest(const int transmissionCounter) 00180 { 00181 transmissionWaiting = true; 00182 00183 assure(transmissionCounter >= 1, "transmissionCounter must be >= 1"); 00184 00185 cw = cwMin; 00186 // retransmission, compute cw 00187 for (int i = 1; i < transmissionCounter; ++i) 00188 { 00189 cw = cw * 2 + 1; 00190 if(cw > cwMax) 00191 { 00192 cw = cwMax; 00193 break; 00194 } 00195 } 00196 00197 00198 MESSAGE_SINGLE(NORMAL, logger, "Data, transmission number " << transmissionCounter << " --> contention window = " << cw << " slots"); 00199 00200 if (backoffFinished and (not channelIsBusy)) 00201 { 00202 // Postbackoff has expired, the medium is idle... go! 00203 MESSAGE_SINGLE(NORMAL, logger, "Post-Backoff has expired -> direct go for one frame"); 00204 transmissionWaiting = false; 00205 backoffFinished = false; 00206 return true; 00207 } 00208 return false; 00209 } 00210 00211 void 00212 Backoff::onChannelIdle() 00213 { 00214 assure(channelIsBusy, "Incoming onChannelIdle although channel is already idle"); 00215 channelIsBusy = false; 00216 00217 // start post-backoff 00218 aifsStart = wns::simulator::getEventScheduler()->getTime(); 00219 if(rxError) 00220 { 00221 rxError = false; 00222 startNewBackoffCountdown(eifsDuration); 00223 } 00224 else 00225 { 00226 startNewBackoffCountdown(aifsDuration); 00227 } 00228 } 00229 00230 void Backoff::onChannelBusy() 00231 { 00232 channelIsBusy = true; 00233 00234 wns::simulator::getEventScheduler()->scheduleDelay( 00235 boost::bind(&wifimac::lowerMAC::timing::Backoff::channelBusyDelay, this), 00236 1e-6); 00237 } 00238 00239 void Backoff::channelBusyDelay() 00240 { 00241 aifsStart = wns::simulator::Time(); 00242 if(channelIsBusy and hasTimeoutSet()) 00243 { 00244 // abort countdown 00245 cancelTimeout(); 00246 MESSAGE_SINGLE(NORMAL, logger, "Channel busy detected during countdown -> freeze."); 00247 } 00248 } 00249 00250 void 00251 Backoff::onRxStart(wns::simulator::Time /*expRxTime*/) 00252 { 00253 00254 } 00255 00256 void 00257 Backoff::onRxEnd() 00258 { 00259 00260 } 00261 00262 void 00263 Backoff::onRxError() 00264 { 00265 MESSAGE_SINGLE(NORMAL, logger, "onRxError -> start next bo with eifs=" << eifsDuration); 00266 rxError = true; 00267 if(not backoffFinished and duringAIFS and aifsStart == wns::simulator::getEventScheduler()->getTime()) 00268 { 00269 // got onChannelIdle signal before onRxError signal 00270 cancelTimeout(); 00271 startNewBackoffCountdown(eifsDuration); 00272 } 00273 } 00274 00275 void Backoff::registerEOBObserver(BackoffObserver * observer) 00276 { 00277 eobObserver.push_back(observer); 00278 }
1.5.5