A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
dcf-manager.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 #include "ns3/simulator.h"
24 #include <cmath>
25 
26 #include "dcf-manager.h"
27 #include "wifi-phy.h"
28 #include "wifi-mac.h"
29 #include "mac-low.h"
30 
31 NS_LOG_COMPONENT_DEFINE ("DcfManager");
32 
33 #define MY_DEBUG(x) \
34  NS_LOG_DEBUG (Simulator::Now () << " " << this << " " << x)
35 
36 namespace ns3 {
37 
38 /****************************************************************
39  * Implement the DCF state holder
40  ****************************************************************/
41 
43  : m_backoffSlots (0),
44  m_backoffStart (Seconds (0.0)),
45  m_cwMin (0),
46  m_cwMax (0),
47  m_cw (0),
48  m_accessRequested (false)
49 {
50 }
51 
53 {
54 }
55 
56 void
57 DcfState::SetAifsn (uint32_t aifsn)
58 {
59  m_aifsn = aifsn;
60 }
61 void
62 DcfState::SetCwMin (uint32_t minCw)
63 {
64  m_cwMin = minCw;
65  ResetCw ();
66 }
67 void
68 DcfState::SetCwMax (uint32_t maxCw)
69 {
70  m_cwMax = maxCw;
71  ResetCw ();
72 }
73 uint32_t
74 DcfState::GetAifsn (void) const
75 {
76  return m_aifsn;
77 }
78 uint32_t
79 DcfState::GetCwMin (void) const
80 {
81  return m_cwMin;
82 }
83 uint32_t
84 DcfState::GetCwMax (void) const
85 {
86  return m_cwMax;
87 }
88 
89 void
91 {
92  m_cw = m_cwMin;
93 }
94 void
96 {
97  // see 802.11-2007, section 9.9.1.5
98  m_cw = std::min ( 2 * (m_cw + 1) - 1, m_cwMax);
99 }
100 void
101 DcfState::UpdateBackoffSlotsNow (uint32_t nSlots, Time backoffUpdateBound)
102 {
103  m_backoffSlots -= nSlots;
104  m_backoffStart = backoffUpdateBound;
105  MY_DEBUG ("update slots=" << nSlots << " slots, backoff=" << m_backoffSlots);
106 }
107 
108 void
109 DcfState::StartBackoffNow (uint32_t nSlots)
110 {
111  NS_ASSERT (m_backoffSlots == 0);
112  MY_DEBUG ("start backoff=" << nSlots << " slots");
113  m_backoffSlots = nSlots;
115 }
116 
117 uint32_t
118 DcfState::GetCw (void) const
119 {
120  return m_cw;
121 }
122 uint32_t
124 {
125  return m_backoffSlots;
126 }
127 Time
129 {
130  return m_backoffStart;
131 }
132 bool
134 {
135  return m_accessRequested;
136 }
137 void
139 {
140  m_accessRequested = true;
141 }
142 void
144 {
146  m_accessRequested = false;
148 }
149 void
151 {
153 }
154 void
156 {
158 }
159 void
161 {
163 }
164 
165 
166 /***************************************************************
167  * Listener for Nav events. Forwards to DcfManager
168  ***************************************************************/
169 
171 {
172 public:
174  : m_dcf (dcf)
175  {
176  }
177  virtual ~LowDcfListener ()
178  {
179  }
180  virtual void NavStart (Time duration)
181  {
182  m_dcf->NotifyNavStartNow (duration);
183  }
184  virtual void NavReset (Time duration)
185  {
186  m_dcf->NotifyNavResetNow (duration);
187  }
188  virtual void AckTimeoutStart (Time duration)
189  {
190  m_dcf->NotifyAckTimeoutStartNow (duration);
191  }
192  virtual void AckTimeoutReset ()
193  {
195  }
196  virtual void CtsTimeoutStart (Time duration)
197  {
198  m_dcf->NotifyCtsTimeoutStartNow (duration);
199  }
200  virtual void CtsTimeoutReset ()
201  {
203  }
204 private:
206 };
207 
208 /***************************************************************
209  * Listener for PHY events. Forwards to DcfManager
210  ***************************************************************/
211 
213 {
214 public:
216  : m_dcf (dcf)
217  {
218  }
219  virtual ~PhyListener ()
220  {
221  }
222  virtual void NotifyRxStart (Time duration)
223  {
224  m_dcf->NotifyRxStartNow (duration);
225  }
226  virtual void NotifyRxEndOk (void)
227  {
229  }
230  virtual void NotifyRxEndError (void)
231  {
233  }
234  virtual void NotifyTxStart (Time duration)
235  {
236  m_dcf->NotifyTxStartNow (duration);
237  }
238  virtual void NotifyMaybeCcaBusyStart (Time duration)
239  {
240  m_dcf->NotifyMaybeCcaBusyStartNow (duration);
241  }
242  virtual void NotifySwitchingStart (Time duration)
243  {
244  m_dcf->NotifySwitchingStartNow (duration);
245  }
246 private:
248 };
249 
250 /****************************************************************
251  * Implement the DCF manager of all DCF state holders
252  ****************************************************************/
253 
255  : m_lastAckTimeoutEnd (MicroSeconds (0)),
256  m_lastCtsTimeoutEnd (MicroSeconds (0)),
257  m_lastNavStart (MicroSeconds (0)),
258  m_lastNavDuration (MicroSeconds (0)),
259  m_lastRxStart (MicroSeconds (0)),
260  m_lastRxDuration (MicroSeconds (0)),
261  m_lastRxReceivedOk (true),
262  m_lastRxEnd (MicroSeconds (0)),
263  m_lastTxStart (MicroSeconds (0)),
264  m_lastTxDuration (MicroSeconds (0)),
265  m_lastBusyStart (MicroSeconds (0)),
266  m_lastBusyDuration (MicroSeconds (0)),
267  m_lastSwitchingStart (MicroSeconds (0)),
268  m_lastSwitchingDuration (MicroSeconds (0)),
269  m_rxing (false),
270  m_slotTimeUs (0),
271  m_sifs (Seconds (0.0)),
272  m_phyListener (0),
273  m_lowListener (0)
274 {
275  NS_LOG_FUNCTION (this);
276 }
277 
279 {
280  delete m_phyListener;
281  delete m_lowListener;
282  m_phyListener = 0;
283  m_lowListener = 0;
284 }
285 
286 void
288 {
289  NS_LOG_FUNCTION (this << phy);
290  m_phyListener = new PhyListener (this);
292 }
293 void
295 {
296  NS_LOG_FUNCTION (this << low);
297  m_lowListener = new LowDcfListener (this);
299 }
300 
301 void
303 {
304  NS_LOG_FUNCTION (this << slotTime);
305  m_slotTimeUs = slotTime.GetMicroSeconds ();
306 }
307 void
309 {
310  NS_LOG_FUNCTION (this << sifs);
311  m_sifs = sifs;
312 }
313 void
315 {
316  NS_LOG_FUNCTION (this << eifsNoDifs);
317  m_eifsNoDifs = eifsNoDifs;
318 }
319 Time
321 {
322  NS_LOG_FUNCTION (this);
323  return m_eifsNoDifs;
324 }
325 
326 void
328 {
329  NS_LOG_FUNCTION (this << dcf);
330  m_states.push_back (dcf);
331 }
332 
333 Time
335 {
336  NS_LOG_FUNCTION (this << a << b);
337  return Max (a, b);
338 }
339 Time
341 {
342  NS_LOG_FUNCTION (this << a << b << c);
343  Time retval;
344  retval = Max (a, b);
345  retval = Max (retval, c);
346  return retval;
347 }
348 Time
350 {
351  NS_LOG_FUNCTION (this << a << b << c << d);
352  Time e = Max (a, b);
353  Time f = Max (c, d);
354  Time retval = Max (e, f);
355  return retval;
356 }
357 Time
359 {
360  NS_LOG_FUNCTION (this << a << b << c << d << e << f);
361  Time g = Max (a, b);
362  Time h = Max (c, d);
363  Time i = Max (e, f);
364  Time k = Max (g, h);
365  Time retval = Max (k, i);
366  return retval;
367 }
368 
369 Time
370 DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f, Time g) const
371 {
372  NS_LOG_FUNCTION (this << a << b << c << d << e << f << g);
373  Time h = Max (a, b);
374  Time i = Max (c, d);
375  Time j = Max (e, f);
376  Time k = Max (h, i);
377  Time l = Max (j, g);
378  Time retval = Max (k, l);
379  return retval;
380 }
381 
382 bool
383 DcfManager::IsBusy (void) const
384 {
385  NS_LOG_FUNCTION (this);
386  // PHY busy
387  if (m_rxing)
388  {
389  return true;
390  }
391  Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
392  if (lastTxEnd > Simulator::Now ())
393  {
394  return true;
395  }
396  // NAV busy
397  Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
398  if (lastNavEnd > Simulator::Now ())
399  {
400  return true;
401  }
402  return false;
403 }
404 
405 
406 void
408 {
409  NS_LOG_FUNCTION (this << state);
410  UpdateBackoff ();
411  NS_ASSERT (!state->IsAccessRequested ());
412  state->NotifyAccessRequested ();
417  if (state->GetBackoffSlots () == 0
418  && IsBusy ())
419  {
420  MY_DEBUG ("medium is busy: collision");
421  /* someone else has accessed the medium.
422  * generate a backoff.
423  */
424  state->NotifyCollision ();
425  }
426  DoGrantAccess ();
428 }
429 
430 void
432 {
433  NS_LOG_FUNCTION (this);
434  uint32_t k = 0;
435  for (States::const_iterator i = m_states.begin (); i != m_states.end (); k++)
436  {
437  DcfState *state = *i;
438  if (state->IsAccessRequested ()
439  && GetBackoffEndFor (state) <= Simulator::Now () )
440  {
445  MY_DEBUG ("dcf " << k << " needs access. backoff expired. access granted. slots=" << state->GetBackoffSlots ());
446  i++; // go to the next item in the list.
447  k++;
448  std::vector<DcfState *> internalCollisionStates;
449  for (States::const_iterator j = i; j != m_states.end (); j++, k++)
450  {
451  DcfState *otherState = *j;
452  if (otherState->IsAccessRequested ()
453  && GetBackoffEndFor (otherState) <= Simulator::Now ())
454  {
455  MY_DEBUG ("dcf " << k << " needs access. backoff expired. internal collision. slots=" <<
456  otherState->GetBackoffSlots ());
462  internalCollisionStates.push_back (otherState);
463  }
464  }
465 
473  state->NotifyAccessGranted ();
474  for (std::vector<DcfState *>::const_iterator k = internalCollisionStates.begin ();
475  k != internalCollisionStates.end (); k++)
476  {
477  (*k)->NotifyInternalCollision ();
478  }
479  break;
480  }
481  i++;
482  }
483 }
484 
485 void
487 {
488  NS_LOG_FUNCTION (this);
489  UpdateBackoff ();
490  DoGrantAccess ();
492 }
493 
494 Time
496 {
497  NS_LOG_FUNCTION (this);
498  Time rxAccessStart;
499  if (!m_rxing)
500  {
501  rxAccessStart = m_lastRxEnd + m_sifs;
502  if (!m_lastRxReceivedOk)
503  {
504  rxAccessStart += m_eifsNoDifs;
505  }
506  }
507  else
508  {
509  rxAccessStart = m_lastRxStart + m_lastRxDuration + m_sifs;
510  }
511  Time busyAccessStart = m_lastBusyStart + m_lastBusyDuration + m_sifs;
512  Time txAccessStart = m_lastTxStart + m_lastTxDuration + m_sifs;
513  Time navAccessStart = m_lastNavStart + m_lastNavDuration + m_sifs;
514  Time ackTimeoutAccessStart = m_lastAckTimeoutEnd + m_sifs;
515  Time ctsTimeoutAccessStart = m_lastCtsTimeoutEnd + m_sifs;
516  Time switchingAccessStart = m_lastSwitchingStart + m_lastSwitchingDuration + m_sifs;
517  Time accessGrantedStart = MostRecent (rxAccessStart,
518  busyAccessStart,
519  txAccessStart,
520  navAccessStart,
521  ackTimeoutAccessStart,
522  ctsTimeoutAccessStart,
523  switchingAccessStart
524  );
525  NS_LOG_INFO ("access grant start=" << accessGrantedStart <<
526  ", rx access start=" << rxAccessStart <<
527  ", busy access start=" << busyAccessStart <<
528  ", tx access start=" << txAccessStart <<
529  ", nav access start=" << navAccessStart);
530  return accessGrantedStart;
531 }
532 
533 Time
535 {
536  NS_LOG_FUNCTION (this << state);
537  Time mostRecentEvent = MostRecent (state->GetBackoffStart (),
539 
540  return mostRecentEvent;
541 }
542 
543 Time
545 {
546  return GetBackoffStartFor (state) + MicroSeconds (state->GetBackoffSlots () * m_slotTimeUs);
547 }
548 
549 void
551 {
552  NS_LOG_FUNCTION (this);
553  uint32_t k = 0;
554  for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++, k++)
555  {
556  DcfState *state = *i;
557 
558  Time backoffStart = GetBackoffStartFor (state);
559  if (backoffStart <= Simulator::Now ())
560  {
561  uint32_t nus = (Simulator::Now () - backoffStart).GetMicroSeconds ();
562  uint32_t nIntSlots = nus / m_slotTimeUs;
563  uint32_t n = std::min (nIntSlots, state->GetBackoffSlots ());
564  MY_DEBUG ("dcf " << k << " dec backoff slots=" << n);
565  Time backoffUpdateBound = backoffStart + MicroSeconds (n * m_slotTimeUs);
566  state->UpdateBackoffSlotsNow (n, backoffUpdateBound);
567  }
568  }
569 }
570 
571 void
573 {
574  NS_LOG_FUNCTION (this);
579  bool accessTimeoutNeeded = false;
580  Time expectedBackoffEnd = Simulator::GetMaximumSimulationTime ();
581  for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++)
582  {
583  DcfState *state = *i;
584  if (state->IsAccessRequested ())
585  {
586  Time tmp = GetBackoffEndFor (state);
587  if (tmp > Simulator::Now ())
588  {
589  accessTimeoutNeeded = true;
590  expectedBackoffEnd = std::min (expectedBackoffEnd, tmp);
591  }
592  }
593  }
594  if (accessTimeoutNeeded)
595  {
596  MY_DEBUG ("expected backoff end=" << expectedBackoffEnd);
597  Time expectedBackoffDelay = expectedBackoffEnd - Simulator::Now ();
599  && Simulator::GetDelayLeft (m_accessTimeout) > expectedBackoffDelay)
600  {
602  }
603  if (m_accessTimeout.IsExpired ())
604  {
605  m_accessTimeout = Simulator::Schedule (expectedBackoffDelay,
607  }
608  }
609 }
610 
611 void
613 {
614  NS_LOG_FUNCTION (this << duration);
615  MY_DEBUG ("rx start for=" << duration);
616  UpdateBackoff ();
618  m_lastRxDuration = duration;
619  m_rxing = true;
620 }
621 void
623 {
624  NS_LOG_FUNCTION (this);
625  MY_DEBUG ("rx end ok");
627  m_lastRxReceivedOk = true;
628  m_rxing = false;
629 }
630 void
632 {
633  NS_LOG_FUNCTION (this);
634  MY_DEBUG ("rx end error");
636  m_lastRxReceivedOk = false;
637  m_rxing = false;
638 }
639 void
641 {
642  NS_LOG_FUNCTION (this << duration);
643  if (m_rxing)
644  {
645  //this may be caused only if PHY has started to receive a packet
646  //inside SIFS, so, we check that lastRxStart was maximum a SIFS
647  //ago
651  m_lastRxReceivedOk = true;
652  m_rxing = false;
653  }
654  MY_DEBUG ("tx start for " << duration);
655  UpdateBackoff ();
657  m_lastTxDuration = duration;
658 }
659 void
661 {
662  NS_LOG_FUNCTION (this << duration);
663  MY_DEBUG ("busy start for " << duration);
664  UpdateBackoff ();
666  m_lastBusyDuration = duration;
667 }
668 
669 
670 void
672 {
673  NS_LOG_FUNCTION (this << duration);
674  Time now = Simulator::Now ();
677 
678  if (m_rxing)
679  {
680  // channel switching during packet reception
683  m_lastRxReceivedOk = true;
684  m_rxing = false;
685  }
686  if (m_lastNavStart + m_lastNavDuration > now)
687  {
689  }
691  {
693  }
694  if (m_lastAckTimeoutEnd > now)
695  {
696  m_lastAckTimeoutEnd = now;
697  }
698  if (m_lastCtsTimeoutEnd > now)
699  {
700  m_lastCtsTimeoutEnd = now;
701  }
702 
703  // Cancel timeout
704  if (m_accessTimeout.IsRunning ())
705  {
707  }
708 
709  // Reset backoffs
710  for (States::iterator i = m_states.begin (); i != m_states.end (); i++)
711  {
712  DcfState *state = *i;
713  uint32_t remainingSlots = state->GetBackoffSlots ();
714  if (remainingSlots > 0)
715  {
716  state->UpdateBackoffSlotsNow (remainingSlots, now);
717  NS_ASSERT (state->GetBackoffSlots () == 0);
718  }
719  state->ResetCw ();
720  state->m_accessRequested = false;
721  state->NotifyChannelSwitching ();
722  }
723 
724  MY_DEBUG ("switching start for " << duration);
726  m_lastSwitchingDuration = duration;
727 
728 }
729 
730 void
732 {
733  NS_LOG_FUNCTION (this << duration);
734  MY_DEBUG ("nav reset for=" << duration);
735  UpdateBackoff ();
737  m_lastNavDuration = duration;
738  UpdateBackoff ();
746 }
747 void
749 {
750  NS_LOG_FUNCTION (this << duration);
752  MY_DEBUG ("nav start for=" << duration);
753  UpdateBackoff ();
754  Time newNavEnd = Simulator::Now () + duration;
755  Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
756  if (newNavEnd > lastNavEnd)
757  {
759  m_lastNavDuration = duration;
760  }
761 }
762 void
764 {
765  NS_LOG_FUNCTION (this << duration);
767  m_lastAckTimeoutEnd = Simulator::Now () + duration;
768 }
769 void
771 {
772  NS_LOG_FUNCTION (this);
775 }
776 void
778 {
779  NS_LOG_FUNCTION (this << duration);
780  m_lastCtsTimeoutEnd = Simulator::Now () + duration;
781 }
782 void
784 {
785  NS_LOG_FUNCTION (this);
788 }
789 } // namespace ns3