A Discrete-Event Network Simulator
API
channel-access-manager-test.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/test.h"
22 #include "ns3/simulator.h"
23 #include "ns3/channel-access-manager.h"
24 #include "ns3/txop.h"
25 #include "ns3/mac-low.h"
26 
27 using namespace ns3;
28 
30 
37 class TxopTest : public Txop
38 {
39 public:
46  TxopTest (ChannelAccessManagerTest *test, uint32_t i);
47 
53  void QueueTx (uint64_t txTime, uint64_t expectedGrantTime);
54 
55 private:
58 
59  typedef std::pair<uint64_t,uint64_t> ExpectedGrant;
60  typedef std::list<ExpectedGrant> ExpectedGrants;
61  struct ExpectedCollision
63  {
64  uint64_t at;
65  uint32_t nSlots;
66  };
67  typedef std::list<struct ExpectedCollision> ExpectedCollisions;
68 
72 
73  bool IsAccessRequested (void) const;
74  void NotifyAccessRequested (void);
75  void NotifyAccessGranted (void);
76  void NotifyInternalCollision (void);
77  void NotifyCollision (void);
78  void NotifyChannelSwitching (void);
79  void NotifySleep (void);
80  void NotifyWakeUp (void);
81  void DoDispose (void);
82 
84  uint32_t m_i;
86 };
87 
94 class MacLowStub : public MacLow
95 {
96 public:
98  {
99  }
103  bool IsCfPeriod (void) const
104  {
105  return false;
106  }
107 };
108 
116 {
117 public:
119  virtual void DoRun (void);
120 
125  void NotifyAccessGranted (uint32_t i);
130  void NotifyInternalCollision (uint32_t i);
135  void NotifyCollision (uint32_t i);
140  void NotifyChannelSwitching (uint32_t i);
141 
142 
143 private:
151  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20);
156  void AddDcfState (uint32_t aifsn);
158  void EndTest (void);
165  void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
172  void ExpectCollision (uint64_t time, uint32_t nSlots, uint32_t from);
178  void ExpectBusy (uint64_t time, bool busy);
183  void DoCheckBusy (bool busy);
189  void AddRxOkEvt (uint64_t at, uint64_t duration);
195  void AddRxErrorEvt (uint64_t at, uint64_t duration);
202  void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
208  void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
214  void AddTxEvt (uint64_t at, uint64_t duration);
220  void AddNavReset (uint64_t at, uint64_t duration);
226  void AddNavStart (uint64_t at, uint64_t duration);
231  void AddAckTimeoutReset (uint64_t at);
239  void AddAccessRequest (uint64_t at, uint64_t txTime,
240  uint64_t expectedGrantTime, uint32_t from);
248  void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
249  uint64_t expectedGrantTime, uint32_t from);
258  void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
259  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
266  void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest> state);
272  void AddCcaBusyEvt (uint64_t at, uint64_t duration);
278  void AddSwitchingEvt (uint64_t at, uint64_t duration);
284  void AddRxStartEvt (uint64_t at, uint64_t duration);
285 
286  typedef std::vector<Ptr<TxopTest> > TxopTests;
287 
291  uint32_t m_ackTimeoutValue;
292 };
293 
294 void
295 TxopTest::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
296 {
297  m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
298 }
299 
301  : m_test (test),
302  m_i (i),
303  m_accessRequested (false)
304 {
305 }
306 
307 void
309 {
310  m_test = 0;
311  Txop::DoDispose ();
312 }
313 
314 bool
316 {
317  return m_accessRequested;
318 }
319 
320 void
322 {
323  m_accessRequested = true;
324 }
325 
326 void
328 {
329  m_accessRequested = false;
331 }
332 
333 void
335 {
337 }
338 
339 void
341 {
343 }
344 
345 void
347 {
349 }
350 
351 void
353 {
354 }
355 
356 void
358 {
359 }
360 
362  : TestCase ("ChannelAccessManager")
363 {
364 }
365 
366 void
368 {
369  Ptr<TxopTest> state = m_txop[i];
370  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
371  if (!state->m_expectedGrants.empty ())
372  {
373  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
374  state->m_expectedGrants.pop_front ();
375  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
378  }
379 }
380 
381 void
382 ChannelAccessManagerTest::AddTxEvt (uint64_t at, uint64_t duration)
383 {
384  Simulator::Schedule (MicroSeconds (at) - Now (),
385  &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
386  MicroSeconds (duration));
387 }
388 
389 void
391 {
392  Ptr<TxopTest> state = m_txop[i];
393  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
394  if (!state->m_expectedInternalCollision.empty ())
395  {
396  struct TxopTest::ExpectedCollision expected = state->m_expectedInternalCollision.front ();
397  state->m_expectedInternalCollision.pop_front ();
398  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
399  state->StartBackoffNow (expected.nSlots);
400  }
401 }
402 
403 void
405 {
406  Ptr<TxopTest> state = m_txop[i];
407  NS_TEST_EXPECT_MSG_EQ (state->m_expectedCollision.empty (), false, "Have expected collisions");
408  if (!state->m_expectedCollision.empty ())
409  {
410  struct TxopTest::ExpectedCollision expected = state->m_expectedCollision.front ();
411  state->m_expectedCollision.pop_front ();
412  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected collision is now");
413  state->StartBackoffNow (expected.nSlots);
414  }
415 }
416 
417 void
419 {
420  Ptr<TxopTest> state = m_txop[i];
421  if (!state->m_expectedGrants.empty ())
422  {
423  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
424  state->m_expectedGrants.pop_front ();
425  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
426  }
427  state->m_accessRequested = false;
428 }
429 
430 void
431 ChannelAccessManagerTest::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from)
432 {
433  Ptr<TxopTest> state = m_txop[from];
434  struct TxopTest::ExpectedCollision col;
435  col.at = time;
436  col.nSlots = nSlots;
437  state->m_expectedInternalCollision.push_back (col);
438 }
439 
440 void
441 ChannelAccessManagerTest::ExpectCollision (uint64_t time, uint32_t nSlots, uint32_t from)
442 {
443  Ptr<TxopTest> state = m_txop[from];
444  struct TxopTest::ExpectedCollision col;
445  col.at = time;
446  col.nSlots = nSlots;
447  state->m_expectedCollision.push_back (col);
448 }
449 
450 void
451 ChannelAccessManagerTest::ExpectBusy (uint64_t time, bool busy)
452 {
453  Simulator::Schedule (MicroSeconds (time) - Now (),
455 }
456 
457 void
459 {
460  NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
461 }
462 
463 void
464 ChannelAccessManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue)
465 {
466  m_ChannelAccessManager = CreateObject<ChannelAccessManager> ();
467  m_low = CreateObject<MacLowStub> ();
471  m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
472  m_ackTimeoutValue = ackTimeoutValue;
473 }
474 
475 void
477 {
478  Ptr<TxopTest> txop = CreateObject<TxopTest> (this, m_txop.size ());
479  txop->SetAifsn (aifsn);
480  m_txop.push_back (txop);
481  m_ChannelAccessManager->Add (txop);
482 }
483 
484 void
486 {
487  Simulator::Run ();
488  Simulator::Destroy ();
489 
490  for (TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
491  {
492  Ptr<TxopTest> state = *i;
493  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
494  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
495  NS_TEST_EXPECT_MSG_EQ (state->m_expectedCollision.empty (), true, "Have no expected collisions");
496  state = 0;
497  }
498  m_txop.clear ();
499 
500  for (TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
501  {
502  Ptr<TxopTest> txop = *i;
503  txop->Dispose ();
504  txop = 0;
505  }
506  m_txop.clear ();
507 
509  m_low = 0;
510 }
511 
512 void
513 ChannelAccessManagerTest::AddRxOkEvt (uint64_t at, uint64_t duration)
514 {
515  Simulator::Schedule (MicroSeconds (at) - Now (),
516  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
517  MicroSeconds (duration));
518  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
519  &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
520 }
521 
522 void
524 {
525  Simulator::Schedule (MicroSeconds (at) - Now (),
526  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
527  MicroSeconds (duration));
528 }
529 
530 void
531 ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration)
532 {
533  Simulator::Schedule (MicroSeconds (at) - Now (),
534  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
535  MicroSeconds (duration));
536  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
537  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
538 }
539 
540 void
541 ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
542 {
543  Simulator::Schedule (MicroSeconds (at) - Now (),
544  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
545  MicroSeconds (duration));
546  Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
547  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
548 }
549 
550 
551 void
552 ChannelAccessManagerTest::AddNavReset (uint64_t at, uint64_t duration)
553 {
554  Simulator::Schedule (MicroSeconds (at) - Now (),
555  &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
556  MicroSeconds (duration));
557 }
558 
559 void
560 ChannelAccessManagerTest::AddNavStart (uint64_t at, uint64_t duration)
561 {
562  Simulator::Schedule (MicroSeconds (at) - Now (),
563  &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
564  MicroSeconds (duration));
565 }
566 
567 void
569 {
570  Simulator::Schedule (MicroSeconds (at) - Now (),
571  &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
572 }
573 
574 void
576  uint64_t expectedGrantTime, uint32_t from)
577 {
578  AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
579 }
580 
581 void
583  uint64_t expectedGrantTime, uint32_t from)
584 {
585  Simulator::Schedule (MicroSeconds (at) - Now (),
587  txTime, expectedGrantTime, m_txop[from]);
588 }
589 
590 void
592  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
593 {
594  NS_ASSERT (ackDelay < m_ackTimeoutValue);
595  Simulator::Schedule (MicroSeconds (at) - Now (),
597  txTime, expectedGrantTime, m_txop[from]);
598  AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
599 }
600 
601 void
602 ChannelAccessManagerTest::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest> state)
603 {
604  state->QueueTx (txTime, expectedGrantTime);
606 }
607 
608 void
609 ChannelAccessManagerTest::AddCcaBusyEvt (uint64_t at, uint64_t duration)
610 {
611  Simulator::Schedule (MicroSeconds (at) - Now (),
612  &ChannelAccessManager::NotifyMaybeCcaBusyStartNow, m_ChannelAccessManager,
613  MicroSeconds (duration));
614 }
615 
616 void
617 ChannelAccessManagerTest::AddSwitchingEvt (uint64_t at, uint64_t duration)
618 {
619  Simulator::Schedule (MicroSeconds (at) - Now (),
620  &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
621  MicroSeconds (duration));
622 }
623 
624 void
625 ChannelAccessManagerTest::AddRxStartEvt (uint64_t at, uint64_t duration)
626 {
627  Simulator::Schedule (MicroSeconds (at) - Now (),
628  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
629  MicroSeconds (duration));
630 }
631 
632 void
634 {
635  // Bug 2369 addresses this case
636  // 0 3 4 5 8 9 10 12
637  // | sifs | aifsn | tx | sifs | aifsn | | tx |
638  //
639  StartTest (1, 3, 10);
640  AddDcfState (1);
641  AddAccessRequest (1, 1, 4, 0);
642  // Generate backoff when the request is within SIFS
643  ExpectCollision (1, 0, 0); // 0 slots
644  AddAccessRequest (10, 2, 10, 0);
645  EndTest ();
646  // Bug 2369 addresses this case
647  // 0 3 5 6 9 11 12 13
648  // | sifs | aifsn | tx | sifs | aifsn | | tx |
649  //
650  StartTest (1, 3, 10);
651  AddDcfState (2);
652  AddAccessRequest (4, 1, 5, 0);
653  // Generate backoff when the request is within AIFSN
654  ExpectCollision (4, 0, 0); // 0 slots
655  AddAccessRequest (12, 2, 12, 0);
656  EndTest ();
657  // Check that receiving inside SIFS shall be cancelled properly:
658  // 0 3 4 5 8 9 12 13 14
659  // | sifs | aifsn | tx | sifs | ack | sifs | aifsn | |tx |
660  //
661 
662  StartTest (1, 3, 10);
663  AddDcfState (1);
664  AddAccessRequest (1, 1, 4, 0);
665  ExpectCollision (1, 0, 0);
666  AddRxInsideSifsEvt (6, 10);
667  AddTxEvt (8, 1);
668  AddAccessRequest (14, 2, 14, 0);
669  EndTest ();
670  // The test below mainly intends to test the case where the medium
671  // becomes busy in the middle of a backoff slot: the backoff counter
672  // must not be decremented for this backoff slot. This is the case
673  // below for the backoff slot starting at time 78us.
674  //
675  // 20 60 66 70 74 78 80 100 106 110 114 118 120
676  // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
677  // |
678  // 30 request access. backoff slots: 4
679 
680  StartTest (4, 6, 10);
681  AddDcfState (1);
682  AddRxOkEvt (20, 40);
683  AddRxOkEvt (80, 20);
684  AddAccessRequest (30, 2, 118, 0);
685  ExpectCollision (30, 4, 0); //backoff: 4 slots
686  EndTest ();
687  // Test the case where the backoff slots is zero.
688  //
689  // 20 60 66 70 72
690  // | rx | sifs | aifsn | tx |
691  // |
692  // 30 request access. backoff slots: 0
693 
694  StartTest (4, 6, 10);
695  AddDcfState (1);
696  AddRxOkEvt (20, 40);
697  AddAccessRequest (30, 2, 70, 0);
698  ExpectCollision (30, 0, 0); // backoff: 0 slots
699  EndTest ();
700  // Test shows when two frames are received without interval between
701  // them:
702  // 20 60 100 106 110 112
703  // | rx | rx |sifs | aifsn | tx |
704  // |
705  // 30 request access. backoff slots: 0
706 
707  StartTest (4, 6, 10);
708  AddDcfState (1);
709  AddRxOkEvt (20, 40);
710  AddRxOkEvt (60, 40);
711  AddAccessRequest (30, 2, 110, 0);
712  ExpectCollision (30, 0, 0); //backoff: 0 slots
713  EndTest ();
714 
715  // Bug 2369. Test case of requesting access within SIFS interval
716  //
717  // 20 60 66 70 74
718  // | rx | sifs | aifsn | backoff | tx |
719  // |
720  // 62 request access.
721  //
722  StartTest (4, 6, 10);
723  AddDcfState (1);
724  AddRxOkEvt (20, 40);
725  AddAccessRequest (62, 2, 74, 0);
726  ExpectCollision (62, 1, 0); //backoff: 1 slots
727  EndTest ();
728 
729  // Bug 2369. Test case of requesting access after DIFS (no backoff)
730  //
731  // 20 60 66 70
732  // | rx | sifs | aifsn | tx |
733  // |
734  // 70 request access.
735  //
736  StartTest (4, 6, 10);
737  AddDcfState (1);
738  AddRxOkEvt (20, 40);
739  AddAccessRequest (70, 2, 70, 0);
740  EndTest ();
741 
742  // Test an EIFS
743  //
744  // 20 60 66 76 86 90 94 98 102 106
745  // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
746  // | | <------eifs------>|
747  // 30 request access. backoff slots: 4
748  StartTest (4, 6, 10);
749  AddDcfState (1);
750  AddRxErrorEvt (20, 40);
751  AddAccessRequest (30, 2, 102, 0);
752  ExpectCollision (30, 4, 0); //backoff: 4 slots
753  EndTest ();
754 
755  // Test that channel stays busy for first frame's duration after Rx error
756  //
757  // 20 60
758  // | rx |
759  // |
760  // 40 force Rx error
761  StartTest (4, 6, 10);
762  AddDcfState (1);
763  AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
764  ExpectBusy (41, true); // channel should remain busy for remaining duration
765  ExpectBusy (59, true);
766  ExpectBusy (61, false);
767  EndTest ();
768 
769  // Test an EIFS which is interrupted by a successful transmission.
770  //
771  // 20 60 66 69 75 81 85 89 93 97 101 103
772  // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
773  // | | <--eifs-->|
774  // 30 request access. backoff slots: 4
775  StartTest (4, 6, 10);
776  AddDcfState (1);
777  AddRxErrorEvt (20, 40);
778  AddAccessRequest (30, 2, 101, 0);
779  ExpectCollision (30, 4, 0); //backoff: 4 slots
780  AddRxOkEvt (69, 6);
781  EndTest ();
782 
783  // Test two DCFs which suffer an internal collision. the first DCF has a higher
784  // priority than the second DCF.
785  //
786  // 20 60 66 70 74 78 88
787  // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
788  // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
789  // 94 98 102 106 110 112
790  StartTest (4, 6, 10);
791  AddDcfState (1); //high priority DCF
792  AddDcfState (3); //low priority DCF
793  AddRxOkEvt (20, 40);
794  AddAccessRequest (30, 10, 78, 0);
795  ExpectCollision (30, 2, 0); //backoff: 2 slot
796  AddAccessRequest (40, 2, 110, 1);
797  ExpectCollision (40, 0, 1); //backoff: 0 slot
798  ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
799  EndTest ();
800 
801  // Test of AckTimeout handling: First queue requests access and ack procedure fails,
802  // inside the ack timeout second queue with higher priority requests access.
803  //
804  // 20 40 50 60 66 76
805  // DCF0 - low | tx | ack timeout |sifs| |
806  // DCF1 - high | | |sifs| tx |
807  // ^ request access
808  StartTest (4, 6, 10);
809  AddDcfState (2); //high priority DCF
810  AddDcfState (0); //low priority DCF
811  AddAccessRequestWithAckTimeout (20, 20, 20, 0);
812  AddAccessRequest (50, 10, 66, 1);
813  ExpectCollision (50, 0, 1);
814  EndTest ();
815 
816  // Test of AckTimeout handling:
817  //
818  // First queue requests access and ack is 2 us delayed (got ack interval at the picture),
819  // inside this interval second queue with higher priority requests access.
820  //
821  // 20 40 41 42 48 58
822  // DCF0 - low | tx |got ack |sifs| |
823  // DCF1 - high | | |sifs| tx |
824  // ^ request access
825  StartTest (4, 6, 10);
826  AddDcfState (2); //high priority DCF
827  AddDcfState (0); //low priority DCF
828  AddAccessRequestWithSuccessfullAck (20, 20, 20, 2, 0);
829  AddAccessRequest (41, 10, 48, 1);
830  ExpectCollision (41, 0, 1);
831  EndTest ();
832 
833  //Repeat the same but with one queue:
834  // 20 40 41 42 48 58
835  // DCF0 - low | tx |got ack |sifs| |
836  // ^ request access
837  StartTest (4, 6, 10);
838  AddDcfState (2);
839  AddAccessRequestWithSuccessfullAck (20, 20, 20, 2, 0);
840  AddAccessRequest (41, 10, 56, 0);
841  ExpectCollision (41, 0, 0);
842  EndTest ();
843 
844  // test simple NAV count. This scenario modelizes a simple DATA+ACK handshake
845  // where the data rate used for the ACK is higher than expected by the DATA source
846  // so, the data exchange completes before the end of nav.
847  StartTest (4, 6, 10);
848  AddDcfState (1);
849  AddRxOkEvt (20, 40);
850  AddNavStart (60, 15);
851  AddRxOkEvt (66, 5);
852  AddNavStart (71, 0);
853  AddAccessRequest (30, 10, 93, 0);
854  ExpectCollision (30, 2, 0); //backoff: 2 slot
855  EndTest ();
856 
857  // test more complex NAV handling by a CF-poll. This scenario modelizes a
858  // simple DATA+ACK handshake interrupted by a CF-poll which resets the
859  // NAV counter.
860  StartTest (4, 6, 10);
861  AddDcfState (1);
862  AddRxOkEvt (20, 40);
863  AddNavStart (60, 15);
864  AddRxOkEvt (66, 5);
865  AddNavReset (71, 2);
866  AddAccessRequest (30, 10, 91, 0);
867  ExpectCollision (30, 2, 0); //backoff: 2 slot
868  EndTest ();
869 
870 
871  StartTest (4, 6, 10);
872  AddDcfState (2);
873  AddRxOkEvt (20, 40);
874  AddAccessRequest (80, 10, 80, 0);
875  EndTest ();
876 
877 
878  StartTest (4, 6, 10);
879  AddDcfState (2);
880  AddRxOkEvt (20, 40);
881  AddRxOkEvt (78, 8);
882  AddAccessRequest (30, 50, 108, 0);
883  ExpectCollision (30, 3, 0); //backoff: 3 slots
884  EndTest ();
885 
886 
887  // Channel switching tests
888 
889  // 0 20 23 24 25
890  // | switching | sifs | aifsn | tx |
891  // |
892  // 21 access request.
893  StartTest (1, 3, 10);
894  AddDcfState (1);
895  AddSwitchingEvt (0,20);
896  AddAccessRequest (21, 1, 24, 0);
897  ExpectCollision (21, 0, 0);
898  EndTest ();
899 
900  // 20 40 50 53 54 55 56 57
901  // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
902  // | |
903  // 30 busy. 45 access request.
904  //
905  StartTest (1, 3, 10);
906  AddDcfState (1);
907  AddSwitchingEvt (20,20);
908  AddCcaBusyEvt (30,20);
909  ExpectCollision (45, 2, 0); //backoff: 2 slots
910  AddAccessRequest (45, 1, 56, 0);
911  EndTest ();
912 
913  // 20 30 50 53 54 55
914  // | rx | switching | sifs | aifsn | tx |
915  // |
916  // 51 access request.
917  //
918  StartTest (1, 3, 10);
919  AddDcfState (1);
920  AddRxStartEvt (20,40);
921  AddSwitchingEvt (30,20);
922  AddAccessRequest (51, 1, 54, 0);
923  ExpectCollision (51, 0, 0);
924  EndTest ();
925 
926  // 20 30 50 53 54 55
927  // | busy | switching | sifs | aifsn | tx |
928  // |
929  // 51 access request.
930  //
931  StartTest (1, 3, 10);
932  AddDcfState (1);
933  AddCcaBusyEvt (20,40);
934  AddSwitchingEvt (30,20);
935  AddAccessRequest (51, 1, 54, 0);
936  ExpectCollision (51, 0, 0);
937  EndTest ();
938 
939  // 20 30 50 53 54 55
940  // | nav | switching | sifs | aifsn | tx |
941  // |
942  // 51 access request.
943  //
944  StartTest (1, 3, 10);
945  AddDcfState (1);
946  AddNavStart (20,40);
947  AddSwitchingEvt (30,20);
948  AddAccessRequest (51, 1, 54, 0);
949  ExpectCollision (51, 0, 0);
950  EndTest ();
951 
952  // 20 40 50 55 58 59 60
953  // | tx | ack timeout | switching | sifs | aifsn | tx |
954  // | |
955  // 45 access request. 56 access request.
956  //
957  StartTest (1, 3, 10);
958  AddDcfState (1);
959  AddAccessRequestWithAckTimeout (20, 20, 20, 0);
960  AddAccessRequest (45, 1, 50, 0);
961  ExpectCollision (45, 0, 0);
962  AddSwitchingEvt (50,5);
963  AddAccessRequest (56, 1, 59, 0);
964  ExpectCollision (56, 0, 0);
965  EndTest ();
966 
967  // 20 60 66 70 74 78 80 100 106 110 112
968  // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | sifs | aifsn | tx |
969  // | |
970  // 30 access request. 101 access request.
971  //
972  StartTest (4, 6, 10);
973  AddDcfState (1);
974  AddRxOkEvt (20,40);
975  AddAccessRequest (30, 2, 80, 0);
976  ExpectCollision (30, 4, 0); //backoff: 4 slots
977  AddSwitchingEvt (80,20);
978  AddAccessRequest (101, 2, 110, 0);
979  ExpectCollision (101, 0, 0); //backoff: 0 slots
980  EndTest ();
981 }
982 
983 
990 class DcfTestSuite : public TestSuite
991 {
992 public:
993  DcfTestSuite ();
994 };
995 
997  : TestSuite ("wifi-devices-dcf", UNIT)
998 {
999  AddTestCase (new ChannelAccessManagerTest, TestCase::QUICK);
1000 }
1001 
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
Ptr< MacLowStub > m_low
the MAC low stubbed
void AddRxOkEvt(uint64_t at, uint64_t duration)
Add expect collision function.
void NotifyAccessGranted(void)
Notify the DCF that access has been granted.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
ExpectedCollision structure.
ExpectedCollisions m_expectedCollision
expected collision
void NotifyCollision(void)
Notify the DCF that collision has occurred.
void NotifyChannelSwitching(uint32_t i)
Notify channel switching function.
uint32_t m_ackTimeoutValue
the ack timeout value
TxopTest Txop Test.
A suite of tests to run.
Definition: test.h:1342
bool IsCfPeriod(void) const
This function indicates whether it is the CF period.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void DoCheckBusy(bool busy)
Perform check that channel access manager is busy or idle.
ChannelAccessManagerTest * m_test
the test DCF manager
bool IsBusy(void) const
Check if the device is busy sending or receiving, or NAV or CCA busy.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:285
void NotifyCollision(uint32_t i)
Notify collision function.
encapsulates test code
Definition: test.h:1155
void QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
Queue transmit function.
bool IsAccessRequested(void) const
std::list< ExpectedGrant > ExpectedGrants
the collection of expected grants typedef
void NotifyChannelSwitching(void)
When a channel switching occurs, enqueued packets are removed.
void EndTest(void)
End test function.
TxopTest(ChannelAccessManagerTest *test, uint32_t i)
Constructor.
void AddDcfState(uint32_t aifsn)
Add DCF state function.
std::vector< Ptr< TxopTest > > TxopTests
the TXOP tests typedef
void SetEifsNoDifs(Time eifsNoDifs)
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
void NotifyWakeUp(void)
When wake up operation occurs, channel access will be restarted.
void AddRxInsideSifsEvt(uint64_t at, uint64_t duration)
Add receive inside SIFS event function.
void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access function.
void ExpectCollision(uint64_t time, uint32_t nSlots, uint32_t from)
Expect internal collision function.
Ptr< ChannelAccessManager > m_ChannelAccessManager
the DCF manager
void AddSwitchingEvt(uint64_t at, uint64_t duration)
Add switching event function.
void AddAccessRequestWithAckTimeout(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access request with ack timeout.
void AddAccessRequestWithSuccessfullAck(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
Add access request with successful ack.
void AddCcaBusyEvt(uint64_t at, uint64_t duration)
Add CCA busy event function.
void DoDispose(void)
Destructor implementation.
void NotifyInternalCollision(void)
Notify the DCF that internal collision has occurred.
void NotifyAckTimeoutStartNow(Time duration)
Notify that ACK timer has started for the given duration.
void DoAccessRequest(uint64_t txTime, uint64_t expectedGrantTime, Ptr< TxopTest > state)
Add access request with successful ack.
void NotifyInternalCollision(uint32_t i)
Notify internal collision function.
void AddNavStart(uint64_t at, uint64_t duration)
Add NAV start function.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
uint32_t m_i
the DCF state
void AddRxErrorEvt(uint64_t at, uint64_t duration)
Add receive error event function for error at end of frame.
void ExpectInternalCollision(uint64_t time, uint32_t nSlots, uint32_t from)
Expect internal collision function.
bool m_accessRequested
true if access requested
static DcfTestSuite g_dcfTestSuite
void StartTest(uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue=20)
Start test function.
void AddAckTimeoutReset(uint64_t at)
Add ack timeout reset function.
std::list< struct ExpectedCollision > ExpectedCollisions
expected collisions typedef
void AddNavReset(uint64_t at, uint64_t duration)
Add NAV reset function.
handle RTS/CTS/DATA/ACK transactions.
Definition: mac-low.h:59
void AddTxEvt(uint64_t at, uint64_t duration)
Add transmit event function.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddRxStartEvt(uint64_t at, uint64_t duration)
Add receive start event function.
std::pair< uint64_t, uint64_t > ExpectedGrant
the expected grant typedef
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1078
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:309
void NotifyAccessGranted(uint32_t i)
Notify access granted function.
void SetAifsn(uint8_t aifsn)
Set the number of slots that make up an AIFS.
Definition: txop.cc:269
void NotifyTxStartNow(Time duration)
ExpectedGrants m_expectedGrants
expected grants
void SetupLow(Ptr< MacLow > low)
Set up listener for MacLow events.
void NotifyAccessRequested(void)
Notify that access request has been received.
void StartBackoffNow(uint32_t nSlots)
Definition: txop.cc:253
void RequestAccess(Ptr< Txop > state, bool isCfPeriod=false)
void NotifySleep(void)
When sleep operation occurs, if there is a pending packet transmission, it will be reinserted to the ...
ExpectedCollisions m_expectedInternalCollision
expected internal collisions
void ExpectBusy(uint64_t time, bool busy)
Schedule a check that the channel access manager is busy or idle.
Handle packet fragmentation and retransmissions for data and management frames.
Definition: txop.h:65