![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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 }
1.5.5