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