User Manual, Developers Guide and API Documentation

Backoff.cpp

Go to the documentation of this file.
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 }

Generated on Sun May 27 03:32:11 2012 for openWNS by  doxygen 1.5.5