src/devices/wifi/dcf.cc
changeset 2146 40ad60ac9912
parent 2145 8f3c8ef34b0a
child 2147 b6243a53c93f
equal deleted inserted replaced
2145:8f3c8ef34b0a 2146:40ad60ac9912
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2005 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 <math.h>
       
    22 
       
    23 #include "ns3/simulator.h"
       
    24 #include "ns3/assert.h"
       
    25 #include "ns3/log.h"
       
    26 
       
    27 #include "dcf.h"
       
    28 #include "random-stream.h"
       
    29 #include "mac-parameters.h"
       
    30 
       
    31 
       
    32 NS_LOG_COMPONENT_DEFINE ("Dcf");
       
    33 
       
    34 namespace ns3 {
       
    35 
       
    36 
       
    37 
       
    38 
       
    39 DcfAccessListener::DcfAccessListener ()
       
    40 {}
       
    41 DcfAccessListener::~DcfAccessListener ()
       
    42 {}
       
    43 
       
    44 
       
    45 
       
    46 Dcf::Dcf (uint32_t min, uint32_t max)
       
    47   : m_accessTimerEvent (),
       
    48     m_cwMin (min),
       
    49     m_cwMax (max),
       
    50     m_backoffStart (MicroSeconds (0)),
       
    51     m_backoffLeft (MicroSeconds (0)),
       
    52     m_lastNavStart (MicroSeconds (0)),
       
    53     m_lastNavDuration (MicroSeconds (0)),
       
    54     m_lastRxStart (MicroSeconds (0)),
       
    55     m_lastRxDuration (MicroSeconds (0)),
       
    56     m_lastRxReceivedOk (true),
       
    57     m_lastRxEnd (MicroSeconds (0)),
       
    58     m_lastTxStart (MicroSeconds (0)),
       
    59     m_lastTxDuration (MicroSeconds (0)),
       
    60     m_lastBusyStart (MicroSeconds (0)),
       
    61     m_lastBusyDuration (MicroSeconds (0)),
       
    62     m_rxing (false)
       
    63 {
       
    64   ResetCw ();
       
    65   m_rng = new RealRandomStream ();
       
    66 }
       
    67 
       
    68 Dcf::~Dcf ()
       
    69 {
       
    70   delete m_rng;
       
    71 }
       
    72 
       
    73 void 
       
    74 Dcf::ResetRngForTest (RandomStream *stream)
       
    75 {
       
    76   delete m_rng;
       
    77   m_rng = stream;
       
    78 }
       
    79 void
       
    80 Dcf::SetParameters (MacParameters const*parameters)
       
    81 {
       
    82   m_parameters = parameters;
       
    83 }
       
    84 
       
    85 void 
       
    86 Dcf::SetDifs (Time difs)
       
    87 {
       
    88   m_difs = difs;
       
    89 }
       
    90 void 
       
    91 Dcf::SetEifs (Time eifs)
       
    92 {
       
    93   m_eifs = eifs;
       
    94 }
       
    95 void 
       
    96 Dcf::SetCwBounds (uint32_t min, uint32_t max)
       
    97 {
       
    98   m_cwMin = min;
       
    99   m_cwMax = max;
       
   100   m_cw = min;
       
   101 }
       
   102 void 
       
   103 Dcf::RegisterAccessListener (DcfAccessListener *listener)
       
   104 {
       
   105   m_listener = listener;
       
   106 }
       
   107 
       
   108 
       
   109 /***************************************************************
       
   110  *     public API.
       
   111  ***************************************************************/ 
       
   112 
       
   113 void 
       
   114 Dcf::RequestAccess (void)
       
   115 {
       
   116   Time delayUntilAccessGranted = GetDelayUntilAccessGranted (Now ());
       
   117   if (m_listener->AccessingAndWillNotify ()) 
       
   118     {
       
   119       /* don't do anything. We will start a backoff and maybe
       
   120        * a timer when the txop notifies us of the end-of-access.
       
   121        */
       
   122       NS_LOG_DEBUG ("accessing. will be notified.");
       
   123     } 
       
   124   else if (m_accessTimerEvent.IsRunning ()) 
       
   125     {
       
   126       /* we don't need to do anything because we have an access
       
   127        * timer which will expire soon.
       
   128        */
       
   129       NS_LOG_DEBUG ("access timer running. will be notified");
       
   130     } 
       
   131   else if (IsBackoffNotCompleted (Now ()) && m_accessTimerEvent.IsExpired ()) 
       
   132     {
       
   133       /* start timer for ongoing backoff.
       
   134        */
       
   135       NS_LOG_DEBUG ("request access X delayed for="<<delayUntilAccessGranted);
       
   136       m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted, 
       
   137                                                 &Dcf::AccessTimeout, this);
       
   138     } 
       
   139   else if (IsPhyBusy () || IsNavBusy ()) 
       
   140     {
       
   141       /* someone else has accessed the medium.
       
   142        * generate a backoff, start timer.
       
   143        */
       
   144       StartBackoff ();
       
   145     } 
       
   146   else if (delayUntilAccessGranted.IsStrictlyPositive ()) 
       
   147     {
       
   148       /* medium is IDLE, we have no backoff running but we 
       
   149        * need to wait a bit before accessing the medium.
       
   150        */
       
   151       NS_LOG_DEBUG ("request access Y delayed for="<< delayUntilAccessGranted);
       
   152       NS_ASSERT (m_accessTimerEvent.IsExpired ());
       
   153       m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted, 
       
   154                                                 &Dcf::AccessTimeout, this);
       
   155     } 
       
   156   else 
       
   157     {
       
   158       /* we can access the medium now.
       
   159        */
       
   160       NS_LOG_DEBUG ("access granted immediatly");
       
   161       m_listener->AccessGrantedNow ();
       
   162     }
       
   163 }
       
   164 
       
   165 /***************************************************************
       
   166  *     Timeout method. Notifies when Access is Granted.
       
   167  ***************************************************************/ 
       
   168 
       
   169 
       
   170 void 
       
   171 Dcf::AccessTimeout ()
       
   172 {
       
   173   UpdateBackoff (Now ());
       
   174   if (m_backoffLeft.IsZero ()) 
       
   175     {
       
   176       NS_LOG_DEBUG ("timeout access granted");
       
   177       m_listener->AccessGrantedNow ();
       
   178     } 
       
   179   else 
       
   180     {
       
   181       Time delayUntilAccessGranted  = GetDelayUntilAccessGranted (Now ());
       
   182       NS_LOG_DEBUG ("timeout access delayed for "<< delayUntilAccessGranted);
       
   183       m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted, 
       
   184                                                 &Dcf::AccessTimeout, this);
       
   185     }
       
   186 }
       
   187 
       
   188 
       
   189 /***************************************************************
       
   190  *     Random trivial helper methods.
       
   191  ***************************************************************/ 
       
   192 
       
   193 Time
       
   194 Dcf::PickBackoffDelay (void)
       
   195 {
       
   196   uint32_t pickedCw = m_rng->GetNext (0, m_cw);
       
   197   NS_LOG_DEBUG ("cw="<<GetCwMin ()<<
       
   198          "<"<<m_cw<<"<"<<GetCwMax ()<<
       
   199          ", picked="<<pickedCw); 
       
   200   Time delay = Scalar (pickedCw) * m_parameters->GetSlotTime ();
       
   201   return delay;
       
   202 }
       
   203 void
       
   204 Dcf::ResetCw (void)
       
   205 {
       
   206   m_cw = GetCwMin ();
       
   207 }
       
   208 void
       
   209 Dcf::UpdateFailedCw (void)
       
   210 {
       
   211   uint32_t cw = m_cw;
       
   212   cw *= 2;
       
   213   if (cw > GetCwMax ()) 
       
   214     {
       
   215       cw = GetCwMax ();
       
   216     }
       
   217   m_cw = cw;
       
   218 }
       
   219 
       
   220 Time
       
   221 Dcf::MostRecent (Time a, Time b) const
       
   222 {
       
   223   return Max (a, b);
       
   224 }
       
   225 Time
       
   226 Dcf::MostRecent (Time a, Time b, Time c) const
       
   227 {
       
   228   Time retval;
       
   229   retval = Max (a, b);
       
   230   retval = Max (retval, c);
       
   231   return retval;
       
   232 }
       
   233 Time
       
   234 Dcf::MostRecent (Time a, Time b, Time c, Time d) const
       
   235 {
       
   236   Time e = Max (a, b);
       
   237   Time f = Max (c, d);
       
   238   Time retval = Max (e, f);
       
   239   return retval;
       
   240 }
       
   241 
       
   242 Time
       
   243 Dcf::GetDifs (void) const
       
   244 {
       
   245   return m_difs;
       
   246 }
       
   247 Time
       
   248 Dcf::GetEifs (void) const
       
   249 {
       
   250   return m_eifs;
       
   251 }
       
   252 uint32_t 
       
   253 Dcf::GetCwMin (void) const
       
   254 {
       
   255   return m_cwMin;
       
   256 }
       
   257 uint32_t 
       
   258 Dcf::GetCwMax (void) const
       
   259 {
       
   260   return m_cwMax;
       
   261 }
       
   262 
       
   263 /***************************************************************
       
   264  *     Complicated timekeeping backoff methods.
       
   265  ***************************************************************/ 
       
   266 
       
   267 bool 
       
   268 Dcf::IsPhyBusy (void) const
       
   269 {
       
   270   if (m_rxing) 
       
   271     {
       
   272       return true;
       
   273     }
       
   274   Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
       
   275   if (lastTxEnd > Simulator::Now ()) 
       
   276     {
       
   277       return true;
       
   278     }
       
   279   return false;
       
   280 }
       
   281 
       
   282 bool 
       
   283 Dcf::IsNavBusy (void) const
       
   284 {
       
   285   Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
       
   286   if (lastNavEnd > Simulator::Now ())
       
   287     {
       
   288       return true;
       
   289     }
       
   290   return false;
       
   291 }
       
   292 
       
   293 void
       
   294 Dcf::StartBackoff (void)
       
   295 {
       
   296   Time backoffStart = Now ();
       
   297   Time backoffDuration = PickBackoffDelay ();
       
   298   m_backoffTrace (backoffDuration);
       
   299   NS_ASSERT (m_backoffStart <= backoffStart);
       
   300   m_backoffStart = backoffStart;
       
   301   m_backoffLeft = backoffDuration;
       
   302   if (m_listener->AccessNeeded () && m_accessTimerEvent.IsExpired ()) 
       
   303     {
       
   304       Time delayUntilAccessGranted  = GetDelayUntilAccessGranted (Now ());
       
   305       if (delayUntilAccessGranted.IsStrictlyPositive ()) 
       
   306         {
       
   307           NS_LOG_DEBUG ("start at "<<backoffStart<<", for "<<backoffDuration);
       
   308           m_accessTimerEvent = Simulator::Schedule (delayUntilAccessGranted,
       
   309                                                     &Dcf::AccessTimeout, this);
       
   310         } 
       
   311       else 
       
   312         {
       
   313           NS_LOG_DEBUG ("access granted now");
       
   314           m_listener->AccessGrantedNow ();
       
   315         }
       
   316     } 
       
   317   else 
       
   318     {
       
   319       if (m_accessTimerEvent.IsRunning ()) 
       
   320         {
       
   321           NS_LOG_DEBUG ("no access needed because timer running.");
       
   322         } 
       
   323       if (!m_listener->AccessNeeded ()) 
       
   324         {
       
   325           NS_LOG_DEBUG ("no access needed.");
       
   326         }
       
   327       NS_LOG_DEBUG ("no access needed for now.");
       
   328     }
       
   329 }
       
   330 Time
       
   331 Dcf::GetAccessGrantedStart (void) const
       
   332 {
       
   333   /* This method evaluates the time where access to the
       
   334    * medium is allowed. The return value could be 
       
   335    * somewhere in the past or in the future.
       
   336    */
       
   337   Time rxAccessStart;
       
   338   if (m_lastRxEnd >= m_lastRxStart) 
       
   339     {
       
   340       if (m_lastRxReceivedOk) 
       
   341         {
       
   342           rxAccessStart = m_lastRxEnd + GetDifs ();
       
   343         } 
       
   344       else
       
   345         {
       
   346           rxAccessStart = m_lastRxEnd + GetEifs ();
       
   347         }
       
   348     } 
       
   349   else 
       
   350     {
       
   351       rxAccessStart = m_lastRxStart + m_lastRxDuration + GetDifs ();
       
   352     }
       
   353   Time busyAccessStart = m_lastBusyStart + m_lastBusyDuration + GetDifs ();
       
   354   Time txAccessStart = m_lastTxStart + m_lastTxDuration + GetDifs ();
       
   355   Time navAccessStart = m_lastNavStart + m_lastNavDuration + GetDifs ();
       
   356   Time accessGrantedStart = MostRecent (rxAccessStart, 
       
   357                                         busyAccessStart,
       
   358                                         txAccessStart, 
       
   359                                         navAccessStart);
       
   360   NS_LOG_DEBUG ("access granted start=" << accessGrantedStart);
       
   361   return accessGrantedStart;
       
   362 }
       
   363 
       
   364 bool
       
   365 Dcf::IsBackoffNotCompleted (Time now)
       
   366 {
       
   367   UpdateBackoff (now);
       
   368   if (m_backoffLeft.IsStrictlyPositive ()) 
       
   369     {
       
   370       return true;
       
   371     } 
       
   372   else 
       
   373     {
       
   374       return false;
       
   375     }
       
   376 }
       
   377 
       
   378 
       
   379 Time
       
   380 Dcf::GetDelayUntilAccessGranted (Time now)
       
   381 {
       
   382   Time deltaTo = GetAccessGrantedStart () - now;
       
   383   Time retval = Max (deltaTo, Seconds (0));
       
   384   UpdateBackoff (now);
       
   385   retval += m_backoffLeft;
       
   386   return retval;
       
   387 }
       
   388 void
       
   389 Dcf::UpdateBackoff (Time time)
       
   390 {
       
   391   if (m_backoffLeft.IsZero ()) 
       
   392     {
       
   393       return;
       
   394     }
       
   395   
       
   396   //NS_LOG_DEBUG ("time: %f, backoffstart: %f\n", time, m_backoffStart);
       
   397   NS_ASSERT (time >= m_backoffStart);
       
   398 
       
   399   Time mostRecentEvent = MostRecent (m_backoffStart,
       
   400                                      GetAccessGrantedStart ());
       
   401   if (mostRecentEvent < time) 
       
   402     {
       
   403       Time newBackoffLeft = m_backoffLeft - (time - mostRecentEvent);
       
   404       m_backoffLeft = Max (newBackoffLeft, Seconds (0)); 
       
   405       m_backoffStart = time;
       
   406     }
       
   407   NS_LOG_DEBUG ("backoff at="<<m_backoffStart<<", left="<< m_backoffLeft);
       
   408 }
       
   409 
       
   410 /***************************************************************
       
   411  *     Notification methods.
       
   412  ***************************************************************/ 
       
   413 void
       
   414 Dcf::NotifyNavReset (Time navStart, Time duration)
       
   415 {
       
   416   NS_LOG_DEBUG ("nav reset at="<<navStart<<", for="<<duration);
       
   417   m_lastNavStart = navStart;
       
   418   m_lastNavDuration = duration;
       
   419   Time navEnd = navStart + duration;
       
   420   Time newDelayUntilAccessGranted = GetDelayUntilAccessGranted (navEnd);
       
   421   NS_ASSERT (newDelayUntilAccessGranted.IsStrictlyPositive ());
       
   422   /* This is quite unfortunate but we need to cancel the access timer
       
   423    * because this nav reset might have brought the time of
       
   424    * possible access closer to us than expected.
       
   425    */
       
   426   if (m_accessTimerEvent.IsRunning ()) 
       
   427     {
       
   428       m_accessTimerEvent.Cancel ();
       
   429       m_accessTimerEvent = Simulator::Schedule (newDelayUntilAccessGranted,
       
   430                                                 &Dcf::AccessTimeout, this);
       
   431     }
       
   432 }
       
   433 void
       
   434 Dcf::NotifyNavStart (Time navStart, Time duration)
       
   435 {
       
   436   NS_ASSERT (m_lastNavStart < navStart);
       
   437   NS_LOG_DEBUG ("nav start at="<<navStart<<", for="<<duration);
       
   438   UpdateBackoff (navStart);
       
   439   m_lastNavStart = navStart;
       
   440   m_lastNavDuration = duration;
       
   441 }
       
   442 void
       
   443 Dcf::NotifyNavContinue (Time navStart, Time duration)
       
   444 {
       
   445   NotifyNavStart (navStart, duration);
       
   446 }
       
   447 
       
   448 void 
       
   449 Dcf::NotifyRxStartNow (Time duration)
       
   450 {
       
   451   Time now = Now ();
       
   452   NS_LOG_DEBUG ("rx start at="<<now<<", for="<<duration);
       
   453   UpdateBackoff (now);
       
   454   m_lastRxStart = now;
       
   455   m_lastRxDuration = duration;
       
   456   m_rxing = true;
       
   457 }
       
   458 void 
       
   459 Dcf::NotifyRxEndOkNow (void)
       
   460 {
       
   461   Time now = Now ();
       
   462   NS_LOG_DEBUG ("rx end ok at="<<now);
       
   463   m_lastRxEnd = now;
       
   464   m_lastRxReceivedOk = true;
       
   465   m_rxing = false;
       
   466 }
       
   467 void 
       
   468 Dcf::NotifyRxEndErrorNow (void)
       
   469 {
       
   470   Time now = Now ();
       
   471   NS_LOG_DEBUG ("rx end error at=");
       
   472   m_lastRxEnd = now;
       
   473   m_lastRxReceivedOk = false;
       
   474   m_rxing = false;
       
   475 }
       
   476 void 
       
   477 Dcf::NotifyTxStartNow (Time duration)
       
   478 {
       
   479   Time now = Now ();
       
   480   NS_LOG_DEBUG ("tx start at="<<now<<" for "<<duration);
       
   481   UpdateBackoff (now);
       
   482   m_lastTxStart = now;
       
   483   m_lastTxDuration = duration;
       
   484 }
       
   485 
       
   486 void 
       
   487 Dcf::NotifyCcaBusyStartNow (Time duration)
       
   488 {
       
   489   Time now = Now ();
       
   490   NS_LOG_DEBUG ("busy start at="<<now<<" for "<<duration);
       
   491   UpdateBackoff (now);
       
   492   m_lastBusyStart = now;
       
   493   m_lastBusyDuration = duration;
       
   494 }
       
   495 
       
   496 } // namespace ns3
       
   497 
       
   498 #ifdef RUN_SELF_TESTS
       
   499 #include "ns3/test.h"
       
   500 #include <list>
       
   501 
       
   502 namespace ns3 {
       
   503 
       
   504 class DcfTest : public Test {
       
   505 public:
       
   506   DcfTest ();
       
   507   virtual bool RunTests (void);
       
   508 
       
   509   // callback from DcfListener
       
   510   void AccessGrantedNow (void);
       
   511   bool AccessNeeded (void);
       
   512   bool AccessingAndWillNotify (void);
       
   513 private:
       
   514 
       
   515   void AddRxOkEvt (uint64_t at, uint64_t duration);
       
   516   void AddRxErrorEvt (uint64_t at, uint64_t duration);
       
   517   void AddTxEvt (uint64_t at, uint64_t duration);
       
   518   void AddNavReset (uint64_t at, uint64_t start, uint64_t duration);
       
   519   void AddNavStart (uint64_t at, uint64_t start, uint64_t duration);
       
   520   void AddNavContinue (uint64_t at, uint64_t start, uint64_t duration);
       
   521   void AddAccessRequest (uint64_t time);
       
   522   void AddAccessError (uint64_t time);
       
   523   void AddAccessErrorButOk (uint64_t time);
       
   524   void AddAccessOk (uint64_t time);
       
   525 
       
   526   void ExpectAccessGranted (uint64_t time);
       
   527   
       
   528   // callback to forward to DCF
       
   529   void AccessError (uint64_t time);
       
   530   void AccessErrorButOk (uint64_t time);
       
   531   void AccessOk (uint64_t time);
       
   532 
       
   533   void StartTest (void);
       
   534   void EndTest (void);
       
   535 
       
   536   Dcf *m_dcf;
       
   537   MacParameters *m_parameters;
       
   538   class TestAccessListener *m_listener;
       
   539   std::list<uint64_t> m_accessGrantedExpected;
       
   540   bool m_failed;
       
   541 };
       
   542 
       
   543 class TestAccessListener : public DcfAccessListener {
       
   544 public:
       
   545   TestAccessListener (DcfTest *test)
       
   546     : m_test (test) {}
       
   547   virtual ~TestAccessListener () {}
       
   548   virtual void AccessGrantedNow (void) {
       
   549     m_test->AccessGrantedNow ();
       
   550   }
       
   551   virtual bool AccessNeeded (void) {
       
   552     return m_test->AccessNeeded ();
       
   553   }
       
   554   virtual bool AccessingAndWillNotify (void) {
       
   555     return m_test->AccessingAndWillNotify ();
       
   556   }
       
   557 private:
       
   558   DcfTest *m_test;
       
   559 };
       
   560 
       
   561 
       
   562 
       
   563 DcfTest::DcfTest ()
       
   564   : Test ("Dcf") {}
       
   565 
       
   566 void 
       
   567 DcfTest::AccessGrantedNow (void)
       
   568 {
       
   569   if (m_accessGrantedExpected.empty ()) 
       
   570     {
       
   571       Failure () << "DCF "
       
   572                  << "Failure: unexpected access granted at="<<Simulator::Now ()
       
   573                  << std::endl;
       
   574       m_failed = true;
       
   575       return;
       
   576     }
       
   577   uint64_t expected = m_accessGrantedExpected.front ();
       
   578   uint64_t actual = Simulator::Now ().GetMicroSeconds ();
       
   579   if (expected != actual) 
       
   580     {
       
   581       Failure () << "DCF "
       
   582                  << "Failure: access granted at=" << Simulator::Now ()
       
   583                  << ", expected at="<<expected<<"us"
       
   584                  << std::endl;
       
   585       m_failed = true;
       
   586       return;
       
   587     }
       
   588   m_accessGrantedExpected.erase (m_accessGrantedExpected.begin ());
       
   589 }
       
   590 bool 
       
   591 DcfTest::AccessNeeded (void)
       
   592 {
       
   593   return true;
       
   594 }
       
   595 bool 
       
   596 DcfTest::AccessingAndWillNotify (void)
       
   597 {
       
   598   return false;
       
   599 }
       
   600 
       
   601 void 
       
   602 DcfTest::AddRxOkEvt (uint64_t at, uint64_t duration)
       
   603 {
       
   604   Simulator::Schedule (MicroSeconds (at) - Now (), 
       
   605                        &Dcf::NotifyRxStartNow, m_dcf, 
       
   606                        MicroSeconds (duration));
       
   607   Simulator::Schedule (MicroSeconds (at+duration) - Now (), 
       
   608                        &Dcf::NotifyRxEndOkNow, m_dcf);
       
   609 }
       
   610 void 
       
   611 DcfTest::AddRxErrorEvt (uint64_t at, uint64_t duration)
       
   612 {
       
   613   Simulator::Schedule (MicroSeconds (at) - Now (), 
       
   614                        &Dcf::NotifyRxStartNow, m_dcf, 
       
   615                        MicroSeconds (duration));
       
   616   Simulator::Schedule (MicroSeconds (at+duration) - Now (), 
       
   617                        &Dcf::NotifyRxEndErrorNow, m_dcf);
       
   618 }
       
   619 void 
       
   620 DcfTest::AddTxEvt (uint64_t at, uint64_t duration)
       
   621 {
       
   622   Simulator::Schedule (MicroSeconds (at) - Now (), 
       
   623                        &Dcf::NotifyTxStartNow, m_dcf, 
       
   624                        MicroSeconds (duration));
       
   625 }
       
   626 void 
       
   627 DcfTest::AddNavReset (uint64_t at, uint64_t start, uint64_t duration)
       
   628 {
       
   629   Simulator::Schedule (MicroSeconds (at) - Now (), 
       
   630                        &Dcf::NotifyNavReset, m_dcf, 
       
   631                        MicroSeconds (start), 
       
   632                        MicroSeconds (duration));
       
   633 }
       
   634 void 
       
   635 DcfTest::AddNavStart (uint64_t at, uint64_t start, uint64_t duration)
       
   636 {
       
   637   Simulator::Schedule (MicroSeconds (at) - Now (), 
       
   638                        &Dcf::NotifyNavStart, m_dcf, 
       
   639                        MicroSeconds (start), MicroSeconds (duration));
       
   640 }
       
   641 void 
       
   642 DcfTest::AddNavContinue (uint64_t at, uint64_t start, uint64_t duration)
       
   643 {
       
   644   Simulator::Schedule (MicroSeconds (at) - Now (), 
       
   645                        &Dcf::NotifyNavContinue, m_dcf, 
       
   646                        MicroSeconds (start), 
       
   647                        MicroSeconds (duration));
       
   648 }
       
   649 void 
       
   650 DcfTest::AddAccessRequest (uint64_t time)
       
   651 {
       
   652   Simulator::Schedule (MicroSeconds (time) - Now (), 
       
   653                        &Dcf::RequestAccess, m_dcf);
       
   654 }
       
   655 void 
       
   656 DcfTest::AddAccessError (uint64_t time)
       
   657 {
       
   658   Simulator::Schedule (MicroSeconds (time) - Now (), 
       
   659                        &DcfTest::AccessError, this, 
       
   660                        time);
       
   661 }
       
   662 void 
       
   663 DcfTest::AddAccessErrorButOk (uint64_t time)
       
   664 {
       
   665   Simulator::Schedule (MicroSeconds (time) - Now (), 
       
   666                        &DcfTest::AccessErrorButOk, this, 
       
   667                        time);
       
   668 }
       
   669 void 
       
   670 DcfTest::AddAccessOk (uint64_t time)
       
   671 {
       
   672   Simulator::Schedule (MicroSeconds (time) - Now (), 
       
   673                        &DcfTest::AccessOk, this, 
       
   674                        time);
       
   675 }
       
   676 
       
   677 void 
       
   678 DcfTest::AccessError (uint64_t time)
       
   679 {
       
   680   m_dcf->UpdateFailedCw ();
       
   681   m_dcf->StartBackoff ();
       
   682 }
       
   683 void 
       
   684 DcfTest::AccessErrorButOk (uint64_t time)
       
   685 {
       
   686   m_dcf->ResetCw ();
       
   687   m_dcf->StartBackoff ();
       
   688 }
       
   689 void 
       
   690 DcfTest::AccessOk (uint64_t time)
       
   691 {
       
   692   m_dcf->ResetCw ();
       
   693   m_dcf->StartBackoff ();
       
   694 }
       
   695 
       
   696 void 
       
   697 DcfTest::ExpectAccessGranted (uint64_t time)
       
   698 {
       
   699   m_accessGrantedExpected.push_back (time);
       
   700 }
       
   701 
       
   702 void 
       
   703 DcfTest::StartTest (void)
       
   704 {
       
   705   m_dcf = new Dcf (8, 64);
       
   706   TestRandomStream *stream = new TestRandomStream ();
       
   707   stream->AddNext (1);
       
   708   stream->AddNext (1);
       
   709   stream->AddNext (1);
       
   710   stream->AddNext (1);
       
   711   stream->AddNext (1);
       
   712   stream->AddNext (1);
       
   713   m_dcf->ResetRngForTest (stream);
       
   714   m_parameters = new MacParameters ();
       
   715   m_listener = new TestAccessListener (this);
       
   716   m_dcf->SetParameters (m_parameters);
       
   717   m_dcf->RegisterAccessListener (m_listener);  
       
   718 
       
   719   m_parameters->SetSlotTime (MicroSeconds (1));
       
   720   m_dcf->SetDifs (MicroSeconds (3));
       
   721   m_dcf->SetEifs (MicroSeconds (4));
       
   722 }
       
   723 void 
       
   724 DcfTest::EndTest (void)
       
   725 {
       
   726   if (!m_accessGrantedExpected.empty ()) 
       
   727     {
       
   728       Failure () << "DCF: access not granted as expected"
       
   729                  << std::endl;
       
   730     }
       
   731   m_accessGrantedExpected.erase (m_accessGrantedExpected.begin (),
       
   732                                  m_accessGrantedExpected.end ());
       
   733   Simulator::Destroy ();
       
   734   delete m_dcf;
       
   735   delete m_parameters;
       
   736   delete m_listener;
       
   737 }
       
   738 
       
   739 bool
       
   740 DcfTest::RunTests (void)
       
   741 {
       
   742   m_failed = false;
       
   743 
       
   744   //                    32        37
       
   745   //                     | rx ok   |
       
   746   // | idle   |  rx ok | nav busy      | difs  | backoff |
       
   747   // 0       10       30              40      43        44
       
   748   //
       
   749   StartTest ();
       
   750   AddRxOkEvt (10, 20);
       
   751   AddNavStart (30, 30, 2+8);
       
   752   AddRxOkEvt (32, 5);
       
   753   AddAccessRequest (15);
       
   754   AddAccessRequest (16);
       
   755   AddAccessRequest (20);
       
   756   ExpectAccessGranted (44);
       
   757   Simulator::Run ();
       
   758   EndTest ();
       
   759 
       
   760   //                    32           39
       
   761   //                     | rx ok      |
       
   762   // | idle   |  rx ok | nav busy  |  | difs  | backoff |
       
   763   // 0       10       30          37         42        43
       
   764   //
       
   765   StartTest ();
       
   766   AddRxOkEvt (10, 20);
       
   767   AddNavStart (30, 30, 2+5);
       
   768   AddRxOkEvt (32, 7);
       
   769   AddAccessRequest (15);
       
   770   AddAccessRequest (16);
       
   771   AddAccessRequest (20);
       
   772   ExpectAccessGranted (43);
       
   773   Simulator::Run ();
       
   774   EndTest ();
       
   775 
       
   776   StartTest ();
       
   777   AddAccessRequest (10);
       
   778   ExpectAccessGranted (10);
       
   779   Simulator::Run ();
       
   780   EndTest ();
       
   781 
       
   782   //                    32        39
       
   783   //                     | rx ok   |
       
   784   // | idle   |  rx ok | nav busy    | difs  |
       
   785   // 0       10       30            40      43
       
   786   //
       
   787   StartTest ();
       
   788   AddRxOkEvt (10, 20);
       
   789   AddNavStart (30, 30, 2+8);
       
   790   AddRxOkEvt (32, 7);
       
   791   AddAccessRequest (40);
       
   792   ExpectAccessGranted (43);
       
   793   Simulator::Run ();
       
   794   EndTest ();
       
   795 
       
   796   //                    32        39
       
   797   //                     | rx ok   |
       
   798   // | idle   |  rx ok | nav busy    | difs  |
       
   799   // 0       10       30            40      43
       
   800   //
       
   801   StartTest ();
       
   802   AddRxOkEvt (10, 20);
       
   803   AddNavStart (30, 30, 2+8);
       
   804   AddRxOkEvt (32, 7);
       
   805   AddAccessRequest (41);
       
   806   ExpectAccessGranted (43);
       
   807   Simulator::Run ();
       
   808   EndTest ();
       
   809 
       
   810   //                    32        39
       
   811   //                     | rx ok   |
       
   812   // | idle   |  rx ok | nav busy    | difs  |
       
   813   // 0       10       30            40      43
       
   814   //
       
   815   StartTest ();
       
   816   AddRxOkEvt (10, 20);
       
   817   AddNavStart (30, 30, 2+8);
       
   818   AddRxOkEvt (32, 7);
       
   819   AddAccessRequest (43);
       
   820   ExpectAccessGranted (43);
       
   821   Simulator::Run ();
       
   822   EndTest ();
       
   823 
       
   824   //
       
   825   // | idle   |  rx error | idle   | rx ok  | difs |
       
   826   // 0       10          30       31       38     41
       
   827   //
       
   828   StartTest ();
       
   829   AddRxErrorEvt (10, 20);
       
   830   AddRxOkEvt (31, 7);
       
   831   AddAccessRequest (39);
       
   832   ExpectAccessGranted (41);
       
   833   Simulator::Run ();
       
   834   EndTest ();
       
   835 
       
   836   //
       
   837   // | idle   |  rx error | idle   | rx error  | eifs |
       
   838   // 0       10          30       31          38     42
       
   839   //
       
   840   StartTest ();
       
   841   AddRxErrorEvt (10, 20);
       
   842   AddRxErrorEvt (31, 7);
       
   843   AddAccessRequest (39);
       
   844   ExpectAccessGranted (42);
       
   845   Simulator::Run ();
       
   846   EndTest ();
       
   847 
       
   848 
       
   849   //
       
   850   //                  30               45
       
   851   //                   | nav busy       |
       
   852   // | idle   |  rx ok | idle   | rx ok | difs | backoff |
       
   853   // 0       10       30       35      45     48        49
       
   854   //
       
   855   StartTest ();
       
   856   AddRxOkEvt (10, 20);
       
   857   AddNavStart (30, 30, 200);
       
   858   AddRxOkEvt (35, 10);
       
   859   AddNavReset (45, 45, 0);
       
   860   AddAccessRequest (32);
       
   861   ExpectAccessGranted (49);
       
   862   Simulator::Run ();
       
   863   EndTest ();
       
   864 
       
   865   //
       
   866   //                  30               45
       
   867   //                   | nav busy       |
       
   868   // | idle   |  rx ok | idle   | rx ok | 
       
   869   // 0       10       30       35      45 
       
   870   //
       
   871   StartTest ();
       
   872   AddRxOkEvt (10, 20);
       
   873   AddNavStart (30, 30, 200);
       
   874   AddRxOkEvt (35, 10);
       
   875   AddNavReset (45, 45, 0);
       
   876   Simulator::Run ();
       
   877   EndTest ();
       
   878 
       
   879   //
       
   880   //                  30               45
       
   881   //                   | nav busy       |
       
   882   // | idle   |  rx ok | idle   | rx ok | difs |
       
   883   // 0       10       30       35      45     48
       
   884   //
       
   885   StartTest ();
       
   886   AddRxOkEvt (10, 20);
       
   887   AddNavStart (30, 30, 200);
       
   888   AddRxOkEvt (35, 10);
       
   889   AddNavReset (45, 45, 0);
       
   890   AddAccessRequest (49);
       
   891   ExpectAccessGranted (49);
       
   892   Simulator::Run ();
       
   893   EndTest ();
       
   894 
       
   895 
       
   896   return !m_failed;
       
   897 }
       
   898 
       
   899 static DcfTest gDcfTest;
       
   900 
       
   901 } // namespace ns3
       
   902 
       
   903 
       
   904 #endif /* RUN_SELF_TESTS */