User Manual, Developers Guide and API Documentation

Backoff.cpp

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

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