00001
00002
00003 #include "ns3/assert.h"
00004 #include "ns3/log.h"
00005 #include "ns3/simulator.h"
00006 #include <math.h>
00007
00008 #include "dcf-manager.h"
00009 #include "wifi-phy.h"
00010 #include "wifi-mac.h"
00011 #include "mac-low.h"
00012
00013 NS_LOG_COMPONENT_DEFINE ("DcfManager");
00014
00015 #define MY_DEBUG(x) \
00016 NS_LOG_DEBUG (Simulator::Now () << " " << this << " " << x)
00017
00018 namespace ns3 {
00019
00020
00021
00022
00023
00024 DcfState::DcfState ()
00025 : m_backoffSlots (0),
00026 m_backoffStart (Seconds (0.0)),
00027 m_cwMin (0),
00028 m_cwMax (0),
00029 m_cw (0),
00030 m_accessRequested (false)
00031 {}
00032
00033 DcfState::~DcfState ()
00034 {}
00035
00036 void
00037 DcfState::SetAifsn (uint32_t aifsn)
00038 {
00039 m_aifsn = aifsn;
00040 }
00041 void
00042 DcfState::SetCwMin (uint32_t minCw)
00043 {
00044 m_cwMin = minCw;
00045 ResetCw ();
00046 }
00047 void
00048 DcfState::SetCwMax (uint32_t maxCw)
00049 {
00050 m_cwMax = maxCw;
00051 ResetCw ();
00052 }
00053 uint32_t
00054 DcfState::GetAifsn (void) const
00055 {
00056 return m_aifsn;
00057 }
00058 uint32_t
00059 DcfState::GetCwMin (void) const
00060 {
00061 return m_cwMin;
00062 }
00063 uint32_t
00064 DcfState::GetCwMax (void) const
00065 {
00066 return m_cwMax;
00067 }
00068
00069 void
00070 DcfState::ResetCw (void)
00071 {
00072 m_cw = m_cwMin;
00073 }
00074 void
00075 DcfState::UpdateFailedCw (void)
00076 {
00077 uint32_t cw = m_cw;
00078 cw *= 2;
00079 cw = std::min (m_cwMax, cw);
00080 m_cw = cw;
00081 }
00082 void
00083 DcfState::UpdateBackoffSlotsNow (uint32_t nSlots, Time backoffUpdateBound)
00084 {
00085 m_backoffSlots -= nSlots;
00086 m_backoffStart = backoffUpdateBound;
00087 MY_DEBUG ("update slots="<<nSlots<<" slots, backoff="<<m_backoffSlots);
00088 }
00089
00090 void
00091 DcfState::StartBackoffNow (uint32_t nSlots)
00092 {
00093 NS_ASSERT (m_backoffSlots == 0);
00094 MY_DEBUG ("start backoff="<<nSlots<<" slots");
00095 m_backoffSlots = nSlots;
00096 m_backoffStart = Simulator::Now ();
00097 }
00098
00099 uint32_t
00100 DcfState::GetCw (void) const
00101 {
00102 return m_cw;
00103 }
00104 uint32_t
00105 DcfState::GetBackoffSlots (void) const
00106 {
00107 return m_backoffSlots;
00108 }
00109 Time
00110 DcfState::GetBackoffStart (void) const
00111 {
00112 return m_backoffStart;
00113 }
00114 bool
00115 DcfState::IsAccessRequested (void) const
00116 {
00117 return m_accessRequested;
00118 }
00119 void
00120 DcfState::NotifyAccessRequested (void)
00121 {
00122 m_accessRequested = true;
00123 }
00124 void
00125 DcfState::NotifyAccessGranted (void)
00126 {
00127 NS_ASSERT (m_accessRequested);
00128 m_accessRequested = false;
00129 DoNotifyAccessGranted ();
00130 }
00131 void
00132 DcfState::NotifyCollision (void)
00133 {
00134 DoNotifyCollision ();
00135 }
00136 void
00137 DcfState::NotifyInternalCollision (void)
00138 {
00139 DoNotifyInternalCollision ();
00140 }
00141
00142
00143
00144
00145
00146
00147 class LowNavListener : public ns3::MacLowNavListener {
00148 public:
00149 LowNavListener (ns3::DcfManager *dcf)
00150 : m_dcf (dcf) {}
00151 virtual ~LowNavListener () {}
00152 virtual void NavStart (Time duration) {
00153 m_dcf->NotifyNavStartNow (duration);
00154 }
00155 virtual void NavReset (Time duration) {
00156 m_dcf->NotifyNavResetNow (duration);
00157 }
00158 private:
00159 ns3::DcfManager *m_dcf;
00160 };
00161
00162
00163
00164
00165
00166 class PhyListener : public ns3::WifiPhyListener {
00167 public:
00168 PhyListener (ns3::DcfManager *dcf)
00169 : m_dcf (dcf) {}
00170 virtual ~PhyListener () {}
00171 virtual void NotifyRxStart (Time duration) {
00172 m_dcf->NotifyRxStartNow (duration);
00173 }
00174 virtual void NotifyRxEndOk (void) {
00175 m_dcf->NotifyRxEndOkNow ();
00176 }
00177 virtual void NotifyRxEndError (void) {
00178 m_dcf->NotifyRxEndErrorNow ();
00179 }
00180 virtual void NotifyTxStart (Time duration) {
00181 m_dcf->NotifyTxStartNow (duration);
00182 }
00183 virtual void NotifyMaybeCcaBusyStart (Time duration) {
00184 m_dcf->NotifyMaybeCcaBusyStartNow (duration);
00185 }
00186 private:
00187 ns3::DcfManager *m_dcf;
00188 };
00189
00190
00191
00192
00193
00194 DcfManager::DcfManager ()
00195 : m_lastNavStart (MicroSeconds (0)),
00196 m_lastNavDuration (MicroSeconds (0)),
00197 m_lastRxStart (MicroSeconds (0)),
00198 m_lastRxDuration (MicroSeconds (0)),
00199 m_lastRxReceivedOk (true),
00200 m_lastRxEnd (MicroSeconds (0)),
00201 m_lastTxStart (MicroSeconds (0)),
00202 m_lastTxDuration (MicroSeconds (0)),
00203 m_lastBusyStart (MicroSeconds (0)),
00204 m_lastBusyDuration (MicroSeconds (0)),
00205 m_rxing (false),
00206 m_slotTime (Seconds (0.0)),
00207 m_sifs (Seconds (0.0)),
00208 m_phyListener (0),
00209 m_lowListener (0)
00210 {}
00211
00212 DcfManager::~DcfManager ()
00213 {
00214 delete m_phyListener;
00215 delete m_lowListener;
00216 m_phyListener = 0;
00217 m_lowListener = 0;
00218 }
00219
00220 void
00221 DcfManager::SetupPhyListener (Ptr<WifiPhy> phy)
00222 {
00223 m_phyListener = new PhyListener (this);
00224 phy->RegisterListener (m_phyListener);
00225 }
00226 void
00227 DcfManager::SetupLowListener (Ptr<MacLow> low)
00228 {
00229 m_lowListener = new LowNavListener (this);
00230 low->RegisterNavListener (m_lowListener);
00231 }
00232
00233 void
00234 DcfManager::SetSlot (Time slotTime)
00235 {
00236 m_slotTime = slotTime;
00237 }
00238 void
00239 DcfManager::SetSifs (Time sifs)
00240 {
00241 m_sifs = sifs;
00242 }
00243 void
00244 DcfManager::SetEifsNoDifs (Time eifsNoDifs)
00245 {
00246 m_eifsNoDifs = eifsNoDifs;
00247 }
00248
00249 void
00250 DcfManager::Add (DcfState *dcf)
00251 {
00252 m_states.push_back (dcf);
00253 }
00254
00255 Time
00256 DcfManager::MostRecent (Time a, Time b) const
00257 {
00258 return Max (a, b);
00259 }
00260 Time
00261 DcfManager::MostRecent (Time a, Time b, Time c) const
00262 {
00263 Time retval;
00264 retval = Max (a, b);
00265 retval = Max (retval, c);
00266 return retval;
00267 }
00268 Time
00269 DcfManager::MostRecent (Time a, Time b, Time c, Time d) const
00270 {
00271 Time e = Max (a, b);
00272 Time f = Max (c, d);
00273 Time retval = Max (e, f);
00274 return retval;
00275 }
00276
00277 bool
00278 DcfManager::IsBusy (void) const
00279 {
00280
00281 if (m_rxing)
00282 {
00283 return true;
00284 }
00285 Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
00286 if (lastTxEnd > Simulator::Now ())
00287 {
00288 return true;
00289 }
00290
00291 Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
00292 if (lastNavEnd > Simulator::Now ())
00293 {
00294 return true;
00295 }
00296 return false;
00297 }
00298
00299
00300 void
00301 DcfManager::RequestAccess (DcfState *state)
00302 {
00303 UpdateBackoff ();
00304 NS_ASSERT (!state->IsAccessRequested ());
00305 state->NotifyAccessRequested ();
00306
00307
00308
00309
00310 if (state->GetBackoffSlots () == 0 &&
00311 IsBusy ())
00312 {
00313 MY_DEBUG ("medium is busy: collision");
00314
00315
00316
00317 state->NotifyCollision ();
00318 }
00319 DoGrantAccess ();
00320 DoRestartAccessTimeoutIfNeeded ();
00321 }
00322
00323 void
00324 DcfManager::DoGrantAccess (void)
00325 {
00326 Time accessGrantStart = GetAccessGrantStart ();
00327
00328 uint32_t k = 0;
00329 for (States::const_iterator i = m_states.begin (); i != m_states.end (); k++)
00330 {
00331 DcfState *state = *i;
00332 if (state->IsAccessRequested () &&
00333 GetBackoffEndFor (state) <= Simulator::Now ())
00334 {
00335
00336
00337
00338
00339 MY_DEBUG ("dcf " << k << " needs access. backoff expired. access granted. slots="<<state->GetBackoffSlots ());
00340 i++;
00341 k++;
00342 std::vector<DcfState *> internalCollisionStates;
00343 for (States::const_iterator j = i; j != m_states.end (); j++, k++)
00344 {
00345 DcfState *otherState = *j;
00346 if (otherState->IsAccessRequested () &&
00347 GetBackoffEndFor (otherState) <= Simulator::Now ())
00348 {
00349 MY_DEBUG ("dcf " << k << " needs access. backoff expired. internal collision. slots=" <<
00350 otherState->GetBackoffSlots ());
00351
00352
00353
00354
00355
00356 internalCollisionStates.push_back (otherState);
00357 }
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367 state->NotifyAccessGranted ();
00368 for (std::vector<DcfState *>::const_iterator k = internalCollisionStates.begin ();
00369 k != internalCollisionStates.end (); k++)
00370 {
00371 (*k)->NotifyInternalCollision ();
00372 }
00373 break;
00374 }
00375 i++;
00376 }
00377 }
00378
00379 void
00380 DcfManager::AccessTimeout (void)
00381 {
00382 UpdateBackoff ();
00383 DoGrantAccess ();
00384 DoRestartAccessTimeoutIfNeeded ();
00385 }
00386
00387 Time
00388 DcfManager::GetAccessGrantStart (void) const
00389 {
00390 Time rxAccessStart;
00391 if (m_lastRxEnd >= m_lastRxStart)
00392 {
00393 rxAccessStart = m_lastRxEnd;
00394 if (!m_lastRxReceivedOk)
00395 {
00396 rxAccessStart += m_eifsNoDifs;
00397 }
00398 else
00399 {
00400 rxAccessStart += m_sifs;
00401 }
00402 }
00403 else
00404 {
00405 rxAccessStart = m_lastRxStart + m_lastRxDuration + m_sifs;
00406 }
00407 Time busyAccessStart = m_lastBusyStart + m_lastBusyDuration + m_sifs;
00408 Time txAccessStart = m_lastTxStart + m_lastTxDuration + m_sifs;
00409 Time navAccessStart = m_lastNavStart + m_lastNavDuration + m_sifs;
00410 Time accessGrantedStart = MostRecent (rxAccessStart,
00411 busyAccessStart,
00412 txAccessStart,
00413 navAccessStart);
00414 NS_LOG_INFO ("access grant start=" << accessGrantedStart <<
00415 ", rx access start=" << rxAccessStart <<
00416 ", busy access start=" << busyAccessStart <<
00417 ", tx access start=" << txAccessStart <<
00418 ", nav access start=" << navAccessStart);
00419 return accessGrantedStart;
00420 }
00421
00422 Time
00423 DcfManager::GetBackoffStartFor (DcfState *state)
00424 {
00425 Time mostRecentEvent = MostRecent (state->GetBackoffStart (),
00426 GetAccessGrantStart () + Scalar (state->GetAifsn ()) * m_slotTime);
00427
00428 return mostRecentEvent;
00429 }
00430
00431 Time
00432 DcfManager::GetBackoffEndFor (DcfState *state)
00433 {
00434 return GetBackoffStartFor (state) + Scalar (state->GetBackoffSlots ()) * m_slotTime;
00435 }
00436
00437 void
00438 DcfManager::UpdateBackoff (void)
00439 {
00440 uint32_t k = 0;
00441 for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++, k++)
00442 {
00443 DcfState *state = *i;
00444
00445 Time backoffStart = GetBackoffStartFor (state);
00446 if (backoffStart <= Simulator::Now ())
00447 {
00448 Scalar nSlots = (Simulator::Now () - backoffStart) / m_slotTime;
00449 uint32_t nIntSlots = lrint (nSlots.GetDouble ());
00450 uint32_t n = std::min (nIntSlots, state->GetBackoffSlots ());
00451 MY_DEBUG ("dcf " << k << " dec backoff slots=" << n);
00452 Time backoffUpdateBound = backoffStart + Scalar (n) * m_slotTime;
00453 state->UpdateBackoffSlotsNow (n, backoffUpdateBound);
00454 }
00455 }
00456 }
00457
00458 void
00459 DcfManager::DoRestartAccessTimeoutIfNeeded (void)
00460 {
00461
00462
00463
00464
00465 bool accessTimeoutNeeded = false;
00466 Time expectedBackoffEnd = Simulator::GetMaximumSimulationTime ();
00467 for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++)
00468 {
00469 DcfState *state = *i;
00470 if (state->IsAccessRequested ())
00471 {
00472 Time tmp = GetBackoffEndFor (state);
00473 if (tmp > Simulator::Now ())
00474 {
00475 accessTimeoutNeeded = true;
00476 expectedBackoffEnd = std::min (expectedBackoffEnd, tmp);
00477 }
00478 }
00479 }
00480 if (accessTimeoutNeeded)
00481 {
00482 MY_DEBUG ("expected backoff end="<<expectedBackoffEnd);
00483 Time expectedBackoffDelay = expectedBackoffEnd - Simulator::Now ();
00484 if (m_accessTimeout.IsRunning () &&
00485 Simulator::GetDelayLeft (m_accessTimeout) > expectedBackoffDelay)
00486 {
00487 m_accessTimeout.Cancel ();
00488 }
00489 if (m_accessTimeout.IsExpired ())
00490 {
00491 m_accessTimeout = Simulator::Schedule (expectedBackoffDelay,
00492 &DcfManager::AccessTimeout, this);
00493 }
00494 }
00495 }
00496
00497 void
00498 DcfManager::NotifyRxStartNow (Time duration)
00499 {
00500 MY_DEBUG ("rx start for="<<duration);
00501 UpdateBackoff ();
00502 m_lastRxStart = Simulator::Now ();
00503 m_lastRxDuration = duration;
00504 m_rxing = true;
00505 }
00506 void
00507 DcfManager::NotifyRxEndOkNow (void)
00508 {
00509 MY_DEBUG ("rx end ok");
00510 m_lastRxEnd = Simulator::Now ();
00511 m_lastRxReceivedOk = true;
00512 m_rxing = false;
00513 }
00514 void
00515 DcfManager::NotifyRxEndErrorNow (void)
00516 {
00517 MY_DEBUG ("rx end error");
00518 m_lastRxEnd = Simulator::Now ();
00519 m_lastRxReceivedOk = false;
00520 m_rxing = false;
00521 }
00522 void
00523 DcfManager::NotifyTxStartNow (Time duration)
00524 {
00525 MY_DEBUG ("tx start for "<<duration);
00526 UpdateBackoff ();
00527 m_lastTxStart = Simulator::Now ();
00528 m_lastTxDuration = duration;
00529 }
00530 void
00531 DcfManager::NotifyMaybeCcaBusyStartNow (Time duration)
00532 {
00533 MY_DEBUG ("busy start for "<<duration);
00534 UpdateBackoff ();
00535 m_lastBusyStart = Simulator::Now ();
00536 m_lastBusyDuration = duration;
00537 }
00538 void
00539 DcfManager::NotifyNavResetNow (Time duration)
00540 {
00541 MY_DEBUG ("nav reset for="<<duration);
00542 UpdateBackoff ();
00543 m_lastNavStart = Simulator::Now ();
00544 m_lastNavDuration = duration;
00545 UpdateBackoff ();
00546
00547
00548
00549
00550
00551
00552 DoRestartAccessTimeoutIfNeeded ();
00553 }
00554 void
00555 DcfManager::NotifyNavStartNow (Time duration)
00556 {
00557 NS_ASSERT (m_lastNavStart < Simulator::Now ());
00558 MY_DEBUG ("nav start for="<<duration);
00559 UpdateBackoff ();
00560 Time newNavEnd = Simulator::Now () + duration;
00561 Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
00562 if (newNavEnd > lastNavEnd)
00563 {
00564 m_lastNavStart = Simulator::Now ();
00565 m_lastNavDuration = duration;
00566 }
00567 }
00568
00569 }