User Manual, Developers Guide and API Documentation

Backoff.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  * Glue                                                                       *
00003  * __________________________________________________________________________ *
00004  *                                                                            *
00005  * Copyright (C) 2005-2006                                                    *
00006  * Lehrstuhl fuer Kommunikationsnetze (ComNets)                               *
00007  * Kopernikusstr. 16, D-52074 Aachen, Germany                                 *
00008  * phone: ++49-241-80-27910 (phone), fax: ++49-241-80-22242                   *
00009  * email: wns@comnets.rwth-aachen.de                                          *
00010  * www: http://wns.comnets.rwth-aachen.de                                     *
00011  ******************************************************************************/
00012 
00013 #include <GLUE/mac/Backoff.hpp>
00014 
00015 #include <WNS/events/scheduler/Interface.hpp>
00016 #include <WNS/container/UntypedRegistry.hpp>
00017 #include <WNS/Assure.hpp>
00018 
00019 using namespace glue::mac;
00020 
00021 
00022 Backoff::Backoff(
00023     BackoffObserver* _backoffObserver,
00024     wns::simulator::Time _sifsLength,
00025     wns::simulator::Time _slotLength,
00026     wns::simulator::Time _ackLength,
00027     const wns::logger::Logger& _logger) :
00028 
00029     backoffObserver(_backoffObserver),
00030     sifsLength(_sifsLength),
00031     slotLength(_slotLength),
00032     ackLength(_ackLength),
00033     difsLength(_sifsLength + 2.0*slotLength),
00034     eifsLength(_sifsLength + slotLength + _ackLength),
00035     state(idle),
00036     transmissionState(none),
00037     cwMin(7),
00038     cwMax(255),
00039     cw(cwMin),
00040     uniform(0.0, 1.0, wns::simulator::getRNG()),
00041     currentSignal(),
00042     logger(_logger),
00043     // we start with an idle carrier
00044     carrierSenseResult(carrierIdle),
00045     counter(0)
00046 {
00047     assureNotNull(backoffObserver);
00048 
00049     if (this->carrierSenseResult == carrierIdle)
00050     {
00051         this->startNewBackoffCountdown(this->difsLength);
00052     }
00053 }
00054 
00055 
00056 Backoff::~Backoff()
00057 {
00058 }
00059 
00060 void
00061 Backoff::startNewBackoffCountdown(wns::simulator::Time ifsLength)
00062 {
00063     assure(this->carrierSenseResult == carrierIdle, "carrier must be idle to start backoff");
00064     // draw backoff
00065     // it includes the DIFS, so add one
00066     this->counter = int(this->uniform() * this->cw) + 1;
00067     MESSAGE_SINGLE(
00068         NORMAL,
00069         this->logger,
00070         "Draw new backoff from 0-" << this->cw << " -> " << this->counter << " slots, waiting for " << ifsLength);
00071     // First stage: Try to survive (A|D|E)IFS
00072     this->waitForTimer(ifsLength);
00073 }
00074 
00075 void
00076 Backoff::waitForTimer(wns::simulator::Time& waitLength)
00077 {
00078     assure(this->currentSignal == NULL, "Only one active signal at a time allowed");
00079         this->currentSignal =
00080             wns::simulator::getEventScheduler()->
00081             scheduleDelay( LocalSignal(this, &Backoff::timerExpired), waitLength);
00082     this->state = inSlotCountdown;
00083 }
00084 
00085 void
00086 Backoff::timerExpired()
00087 {
00088     assure(this->state == inSlotCountdown, "timer expired but not in state inWait");
00089     this->currentSignal = wns::events::scheduler::IEventPtr();
00090     --this->counter;
00091     if(this->counter == 0)
00092     {
00093         // backoff finished
00094         MESSAGE_SINGLE(
00095             NORMAL,
00096             this->logger,
00097             "Backoff has finished, transmission state is " << ((this->transmissionState == pending) ? "pending -> tx" : "none"));
00098         if (this->transmissionState == pending)
00099         {
00100             this->state = finished;
00101             this->transmissionState = transmitting;
00102             this->backoffObserver->backoffExpired();
00103         }
00104         else
00105         {
00106             this->state = idle;
00107         }
00108     }
00109     else
00110     {
00111         MESSAGE_SINGLE(
00112             NORMAL,
00113             this->logger,
00114             "Counting down backoff, now " << this->counter << " slots, waiting for " << this->slotLength);
00115         this->waitForTimer(this->slotLength);
00116     }
00117 }
00118 
00119 void
00120 Backoff::transmissionRequest(const bool isRetransmission)
00121 {
00122 
00123     assure(this->transmissionState == none, "already one transmission pending");
00124     this->transmissionState = pending;
00125 
00126     if ((this->state == idle) && (this->carrierSenseResult == carrierIdle))
00127     {
00128         // Postbackoff has expired, the medium is idle... go!
00129         MESSAGE_SINGLE(
00130             NORMAL,
00131             logger,
00132             "Post-Backoff has expired -> direct go");
00133         this->transmissionState = transmitting;
00134         this->backoffObserver->backoffExpired();
00135         return;
00136     }
00137 
00138     // compute backoff window
00139     if(isRetransmission)
00140     {
00141         if (this->cw < this->cwMax)
00142         {
00143             this->cw = this->cw * 2 + 1;
00144         }
00145         else
00146         {
00147             this->cw = this->cwMax;
00148         }
00149         // retransmission requires new backoff window
00150         this->counter = int(this->uniform() * this->cw) + 1;
00151         MESSAGE_SINGLE(
00152             NORMAL,
00153             logger,
00154             "Data is retransmission -> cw = " << this->cw << " slots, new counter = " << this->counter);
00155     }
00156     else
00157     {
00158         this->cw = this->cwMin;
00159         MESSAGE_SINGLE(
00160             NORMAL,
00161             logger,
00162             "Data, first transmission attempt, lowering contention window to " << this->cw << " slots");
00163     }
00164 }
00165 
00166 void
00167 Backoff::onCarrierIdle()
00168 {
00169     wns::simulator::Time nextWaitTime;
00170     CarrierSensingResult lastCarrierSense = this->carrierSenseResult;
00171 
00172     this->carrierSenseResult = carrierIdle;
00173 
00174     if(lastCarrierSense != carrierIdle)
00175     {
00176         if(this->transmissionState == transmitting)
00177         {
00178             this->carrierSenseResult = carrierIdle;
00179             // it was our transmission, which is finished now
00180             this->transmissionState = none;
00181             // Do a new (post-) backoff
00182             this->startNewBackoffCountdown(this->difsLength);
00183         }
00184         else
00185         {
00186             // it was another transmission, so continue backoff
00187             // starting with DIFS or EIFS, depending on the last state
00188             if(lastCarrierSense == carrierError)
00189             {
00190                 nextWaitTime = this->eifsLength;
00191             }
00192             else
00193             {
00194                 nextWaitTime = this->difsLength;
00195             }
00196             this->carrierSenseResult = carrierIdle;
00197             ++this->counter;
00198             this->waitForTimer(nextWaitTime);
00199         }
00200     }
00201 }
00202 
00203 void
00204 Backoff::onCarrierBusy()
00205 {
00206     this->carrierSenseResult = carrierBusy;
00207     if(this->state == inSlotCountdown)
00208     {
00209         // Abort countdown
00210         assureNotNull(this->currentSignal);
00211         // delete current event waiting for DIFS of BackoffSlotElapsed
00212         wns::simulator::getEventScheduler()->cancelEvent(this->currentSignal);
00213         this->currentSignal = wns::events::scheduler::IEventPtr();
00214         this->state = waitingForCarrierIdle;
00215         MESSAGE_SINGLE(
00216             NORMAL,
00217             this->logger,
00218             "Carrier busy detected during countdown -> freeze.");
00219     }
00220 }
00221 
00222 void
00223 Backoff::onCollision()
00224 {
00225     this->carrierSenseResult = carrierError;
00226     if (this->state == inSlotCountdown)
00227     {
00228         assureNotNull(this->currentSignal);
00229         // delete current event waiting for DIFS of BackoffSlotElapsed
00230         wns::simulator::getEventScheduler()->cancelEvent(this->currentSignal);
00231         this->currentSignal = wns::events::scheduler::IEventPtr();
00232         this->state = waitingForCarrierIdle;
00233         MESSAGE_SINGLE(
00234             NORMAL,
00235             this->logger,
00236             "CarrierError detected during countdown -> abort + EIFS.");
00237     }
00238 }
00239 
00240 bool
00241 Backoff::isCarrierIdle() const
00242 {
00243     return this->carrierSenseResult == carrierIdle;
00244 }

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