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/frame-exchange-manager.h"
25 #include "ns3/qos-txop.h"
26 
27 using namespace ns3;
28 
29 template <typename TxopType>
31 
38 template <typename TxopType>
39 class TxopTest : public TxopType
40 {
41 public:
48  TxopTest (ChannelAccessManagerTest<TxopType> *test, uint32_t i);
49 
55  void QueueTx (uint64_t txTime, uint64_t expectedGrantTime);
56 
57 private:
59  friend class ChannelAccessManagerTest<TxopType>;
60 
62  void DoDispose (void) override;
64  void NotifyChannelAccessed (Time txopDuration = Seconds (0)) override;
66  void NotifyInternalCollision (void) override;
68  bool HasFramesToTransmit (void) override;
70  void NotifyChannelSwitching (void) override;
72  void NotifySleep (void) override;
74  void NotifyWakeUp (void) override;
76  void GenerateBackoff (void) override;
77 
78  typedef std::pair<uint64_t,uint64_t> ExpectedGrant;
79  typedef std::list<ExpectedGrant> ExpectedGrants;
80  struct ExpectedBackoff
82  {
83  uint64_t at;
84  uint32_t nSlots;
85  };
86  typedef std::list<struct ExpectedBackoff> ExpectedBackoffs;
87 
91 
98  uint32_t m_i;
99 };
100 
108 {
109 public:
111  {
112  }
118  void SetSifs (Time sifs)
119  {
120  m_sifs = sifs;
121  }
127  void SetSlot (Time slot)
128  {
129  m_slot = slot;
130  }
136  void SetEifsNoDifs (Time eifsNoDifs)
137  {
138  m_eifsNoDifs = eifsNoDifs;
139  }
140 
141 private:
142  Time GetSifs (void) const override
143  {
144  return m_sifs;
145  }
146 
147  Time GetSlot (void) const override
148  {
149  return m_slot;
150  }
151 
152  Time GetEifsNoDifs (void) const override
153  {
154  return m_eifsNoDifs;
155  }
156 
160 };
161 
169 {
170 public:
172  {
173  }
181  bool StartTransmission (Ptr<Txop> dcf) override
182  {
183  dcf->NotifyChannelAccessed ();
184  return true;
185  }
186 };
187 
194 template <typename TxopType>
195 class ChannelAccessManagerTest : public TestCase
196 {
197 public:
199  void DoRun (void) override;
200 
205  void NotifyAccessGranted (uint32_t i);
210  void NotifyInternalCollision (uint32_t i);
215  void GenerateBackoff (uint32_t i);
220  void NotifyChannelSwitching (uint32_t i);
221 
222 
223 private:
231  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20);
236  void AddTxop (uint32_t aifsn);
238  void EndTest (void);
245  void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
252  void ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from);
258  void ExpectBusy (uint64_t time, bool busy);
263  void DoCheckBusy (bool busy);
269  void AddRxOkEvt (uint64_t at, uint64_t duration);
275  void AddRxErrorEvt (uint64_t at, uint64_t duration);
282  void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
288  void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
294  void AddTxEvt (uint64_t at, uint64_t duration);
300  void AddNavReset (uint64_t at, uint64_t duration);
306  void AddNavStart (uint64_t at, uint64_t duration);
311  void AddAckTimeoutReset (uint64_t at);
319  void AddAccessRequest (uint64_t at, uint64_t txTime,
320  uint64_t expectedGrantTime, uint32_t from);
328  void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
329  uint64_t expectedGrantTime, uint32_t from);
338  void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
339  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
346  void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest<TxopType>> state);
352  void AddCcaBusyEvt (uint64_t at, uint64_t duration);
358  void AddSwitchingEvt (uint64_t at, uint64_t duration);
364  void AddRxStartEvt (uint64_t at, uint64_t duration);
365 
366  typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
367 
371  uint32_t m_ackTimeoutValue;
372 };
373 
374 template <typename TxopType>
375 void
376 TxopTest<TxopType>::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
377 {
378  m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
379 }
380 
381 template <typename TxopType>
383  : m_test (test),
384  m_i (i)
385 {
386 }
387 
388 template <typename TxopType>
389 void
391 {
392  m_test = 0;
393  TxopType::DoDispose ();
394 }
395 
396 template <typename TxopType>
397 void
399 {
400  Txop::m_access = Txop::NOT_REQUESTED;
401  m_test->NotifyAccessGranted (m_i);
402 }
403 
404 template <typename TxopType>
405 void
407 {
408  m_test->NotifyInternalCollision (m_i);
409 }
410 
411 template <typename TxopType>
412 void
414 {
415  m_test->GenerateBackoff (m_i);
416 }
417 
418 template <typename TxopType>
419 bool
421 {
422  return !m_expectedGrants.empty ();
423 }
424 
425 template <typename TxopType>
426 void
428 {
429  m_test->NotifyChannelSwitching (m_i);
430 }
431 
432 template <typename TxopType>
433 void
435 {
436 }
437 
438 template <typename TxopType>
439 void
441 {
442 }
443 
444 template <typename TxopType>
446  : TestCase ("ChannelAccessManager")
447 {
448 }
449 
450 template <typename TxopType>
451 void
453 {
454  Ptr<TxopTest<TxopType>> state = m_txop[i];
455  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
456  if (!state->m_expectedGrants.empty ())
457  {
458  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
459  state->m_expectedGrants.pop_front ();
460  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
461  m_ChannelAccessManager->NotifyTxStartNow (MicroSeconds (expected.first));
462  m_ChannelAccessManager->NotifyAckTimeoutStartNow (MicroSeconds (m_ackTimeoutValue + expected.first));
463  }
464 }
465 
466 template <typename TxopType>
467 void
468 ChannelAccessManagerTest<TxopType>::AddTxEvt (uint64_t at, uint64_t duration)
469 {
470  Simulator::Schedule (MicroSeconds (at) - Now (),
471  &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
472  MicroSeconds (duration));
473 }
474 
475 template <typename TxopType>
476 void
478 {
479  Ptr<TxopTest<TxopType>> state = m_txop[i];
480  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
481  if (!state->m_expectedInternalCollision.empty ())
482  {
483  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedInternalCollision.front ();
484  state->m_expectedInternalCollision.pop_front ();
485  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
486  state->StartBackoffNow (expected.nSlots);
487  }
488 }
489 
490 template <typename TxopType>
491 void
493 {
494  Ptr<TxopTest<TxopType>> state = m_txop[i];
495  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs");
496  if (!state->m_expectedBackoff.empty ())
497  {
498  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front ();
499  state->m_expectedBackoff.pop_front ();
500  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now");
501  state->StartBackoffNow (expected.nSlots);
502  }
503 }
504 
505 template <typename TxopType>
506 void
508 {
509  Ptr<TxopTest<TxopType>> state = m_txop[i];
510  if (!state->m_expectedGrants.empty ())
511  {
512  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
513  state->m_expectedGrants.pop_front ();
514  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
515  }
516  state->Txop::m_access = Txop::NOT_REQUESTED;
517 }
518 
519 template <typename TxopType>
520 void
521 ChannelAccessManagerTest<TxopType>::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from)
522 {
523  Ptr<TxopTest<TxopType>> state = m_txop[from];
524  struct TxopTest<TxopType>::ExpectedBackoff col;
525  col.at = time;
526  col.nSlots = nSlots;
527  state->m_expectedInternalCollision.push_back (col);
528 }
529 
530 template <typename TxopType>
531 void
532 ChannelAccessManagerTest<TxopType>::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from)
533 {
534  Ptr<TxopTest<TxopType>> state = m_txop[from];
535  struct TxopTest<TxopType>::ExpectedBackoff backoff;
536  backoff.at = time;
537  backoff.nSlots = nSlots;
538  state->m_expectedBackoff.push_back (backoff);
539 }
540 
541 template <typename TxopType>
542 void
543 ChannelAccessManagerTest<TxopType>::ExpectBusy (uint64_t time, bool busy)
544 {
545  Simulator::Schedule (MicroSeconds (time) - Now (),
547 }
548 
549 template <typename TxopType>
550 void
552 {
553  NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
554 }
555 
556 template <typename TxopType>
557 void
558 ChannelAccessManagerTest<TxopType>::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue)
559 {
560  m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub> ();
561  m_feManager = CreateObject<FrameExchangeManagerStub> ();
562  m_ChannelAccessManager->SetupFrameExchangeManager (m_feManager);
563  m_ChannelAccessManager->SetSlot (MicroSeconds (slotTime));
564  m_ChannelAccessManager->SetSifs (MicroSeconds (sifs));
565  m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
566  m_ackTimeoutValue = ackTimeoutValue;
567 }
568 
569 template <typename TxopType>
570 void
572 {
573  Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
574  txop->SetAifsn (aifsn);
575  m_txop.push_back (txop);
576  txop->SetChannelAccessManager (m_ChannelAccessManager);
577 }
578 
579 template <typename TxopType>
580 void
582 {
583  Simulator::Run ();
584 
585  for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
586  {
587  Ptr<TxopTest<TxopType>> state = *i;
588  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
589  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
590  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs");
591  state->Dispose ();
592  state = 0;
593  }
594  m_txop.clear ();
595 
596  m_ChannelAccessManager->Dispose ();
597  m_ChannelAccessManager = 0;
598  m_feManager = 0;
599  Simulator::Destroy ();
600 }
601 
602 template <typename TxopType>
603 void
604 ChannelAccessManagerTest<TxopType>::AddRxOkEvt (uint64_t at, uint64_t duration)
605 {
606  Simulator::Schedule (MicroSeconds (at) - Now (),
607  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
608  MicroSeconds (duration));
609  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
610  &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
611 }
612 
613 template <typename TxopType>
614 void
616 {
617  Simulator::Schedule (MicroSeconds (at) - Now (),
618  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
619  MicroSeconds (duration));
620 }
621 
622 template <typename TxopType>
623 void
625 {
626  Simulator::Schedule (MicroSeconds (at) - Now (),
627  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
628  MicroSeconds (duration));
629  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
630  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
631 }
632 
633 template <typename TxopType>
634 void
635 ChannelAccessManagerTest<TxopType>::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
636 {
637  Simulator::Schedule (MicroSeconds (at) - Now (),
638  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
639  MicroSeconds (duration));
640  Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
641  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
642 }
643 
644 
645 template <typename TxopType>
646 void
647 ChannelAccessManagerTest<TxopType>::AddNavReset (uint64_t at, uint64_t duration)
648 {
649  Simulator::Schedule (MicroSeconds (at) - Now (),
650  &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
651  MicroSeconds (duration));
652 }
653 
654 template <typename TxopType>
655 void
656 ChannelAccessManagerTest<TxopType>::AddNavStart (uint64_t at, uint64_t duration)
657 {
658  Simulator::Schedule (MicroSeconds (at) - Now (),
659  &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
660  MicroSeconds (duration));
661 }
662 
663 template <typename TxopType>
664 void
666 {
667  Simulator::Schedule (MicroSeconds (at) - Now (),
668  &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
669 }
670 
671 template <typename TxopType>
672 void
674  uint64_t expectedGrantTime, uint32_t from)
675 {
676  AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
677 }
678 
679 template <typename TxopType>
680 void
682  uint64_t expectedGrantTime, uint32_t from)
683 {
684  Simulator::Schedule (MicroSeconds (at) - Now (),
686  txTime, expectedGrantTime, m_txop[from]);
687 }
688 
689 template <typename TxopType>
690 void
692  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
693 {
694  NS_ASSERT (ackDelay < m_ackTimeoutValue);
695  Simulator::Schedule (MicroSeconds (at) - Now (),
697  txTime, expectedGrantTime, m_txop[from]);
698  AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
699 }
700 
701 template <typename TxopType>
702 void
703 ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
704  Ptr<TxopTest<TxopType>> state)
705 {
706  if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
707  {
708  state->GenerateBackoff ();
709  }
710  state->QueueTx (txTime, expectedGrantTime);
711  m_ChannelAccessManager->RequestAccess (state);
712 }
713 
714 template <typename TxopType>
715 void
717 {
718  Simulator::Schedule (MicroSeconds (at) - Now (),
719  &ChannelAccessManager::NotifyMaybeCcaBusyStartNow, m_ChannelAccessManager,
720  MicroSeconds (duration));
721 }
722 
723 template <typename TxopType>
724 void
726 {
727  Simulator::Schedule (MicroSeconds (at) - Now (),
728  &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
729  MicroSeconds (duration));
730 }
731 
732 template <typename TxopType>
733 void
735 {
736  Simulator::Schedule (MicroSeconds (at) - Now (),
737  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
738  MicroSeconds (duration));
739 }
740 
741 /*
742  * Specialization of DoRun () method for DCF
743  */
744 template <>
745 void
747 {
748  // DCF immediate access (no backoff)
749  // 1 4 5 6 8 11 12
750  // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
751  //
752  StartTest (1, 3, 10);
753  AddTxop (1);
754  AddAccessRequest (1, 1, 5, 0);
755  AddAccessRequest (8, 2, 12, 0);
756  EndTest ();
757  // Check that receiving inside SIFS shall be cancelled properly:
758  // 1 4 5 6 9 10 14 17 18
759  // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
760  // |
761  // 7 start rx
762  //
763 
764  StartTest (1, 3, 10);
765  AddTxop (1);
766  AddAccessRequest (1, 1, 5, 0);
767  AddRxInsideSifsEvt (7, 10);
768  AddTxEvt (9, 1);
769  AddAccessRequest (14, 2, 18, 0);
770  EndTest ();
771  // The test below mainly intends to test the case where the medium
772  // becomes busy in the middle of a backoff slot: the backoff counter
773  // must not be decremented for this backoff slot. This is the case
774  // below for the backoff slot starting at time 78us.
775  //
776  // 20 60 66 70 74 78 80 100 106 110 114 118 120
777  // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
778  // |
779  // 30 request access. backoff slots: 4
780 
781  StartTest (4, 6, 10);
782  AddTxop (1);
783  AddRxOkEvt (20, 40);
784  AddRxOkEvt (80, 20);
785  AddAccessRequest (30, 2, 118, 0);
786  ExpectBackoff (30, 4, 0); //backoff: 4 slots
787  EndTest ();
788  // Test the case where the backoff slots is zero.
789  //
790  // 20 60 66 70 72
791  // | rx | sifs | aifsn | tx |
792  // |
793  // 30 request access. backoff slots: 0
794 
795  StartTest (4, 6, 10);
796  AddTxop (1);
797  AddRxOkEvt (20, 40);
798  AddAccessRequest (30, 2, 70, 0);
799  ExpectBackoff (30, 0, 0); // backoff: 0 slots
800  EndTest ();
801  // Test shows when two frames are received without interval between
802  // them:
803  // 20 60 100 106 110 112
804  // | rx | rx |sifs | aifsn | tx |
805  // |
806  // 30 request access. backoff slots: 0
807 
808  StartTest (4, 6, 10);
809  AddTxop (1);
810  AddRxOkEvt (20, 40);
811  AddRxOkEvt (60, 40);
812  AddAccessRequest (30, 2, 110, 0);
813  ExpectBackoff (30, 0, 0); //backoff: 0 slots
814  EndTest ();
815 
816  // Requesting access within SIFS interval (DCF immediate access)
817  //
818  // 20 60 62 68 72
819  // | rx | idle | sifs | aifsn | tx |
820  //
821  StartTest (4, 6, 10);
822  AddTxop (1);
823  AddRxOkEvt (20, 40);
824  AddAccessRequest (62, 2, 72, 0);
825  EndTest ();
826 
827  // Requesting access after DIFS (DCF immediate access)
828  //
829  // 20 60 70 76 80
830  // | rx | idle | sifs | aifsn | tx |
831  //
832  StartTest (4, 6, 10);
833  AddTxop (1);
834  AddRxOkEvt (20, 40);
835  AddAccessRequest (70, 2, 80, 0);
836  EndTest ();
837 
838  // Test an EIFS
839  //
840  // 20 60 66 76 86 90 94 98 102 106
841  // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
842  // | | <------eifs------>|
843  // 30 request access. backoff slots: 4
844  StartTest (4, 6, 10);
845  AddTxop (1);
846  AddRxErrorEvt (20, 40);
847  AddAccessRequest (30, 2, 102, 0);
848  ExpectBackoff (30, 4, 0); //backoff: 4 slots
849  EndTest ();
850 
851  // Test DCF immediate access after an EIFS (EIFS is greater)
852  //
853  // 20 60 66 76 86
854  // | <----+-eifs------>|
855  // | rx | sifs | acktxttime | sifs + aifsn | tx |
856  // | sifs + aifsn |
857  // request access 70 80
858  StartTest (4, 6, 10);
859  AddTxop (1);
860  AddRxErrorEvt (20, 40);
861  AddAccessRequest (70, 2, 86, 0);
862  EndTest ();
863 
864  // Test that channel stays busy for first frame's duration after Rx error
865  //
866  // 20 60
867  // | rx |
868  // |
869  // 40 force Rx error
870  StartTest (4, 6, 10);
871  AddTxop (1);
872  AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
873  ExpectBusy (41, true); // channel should remain busy for remaining duration
874  ExpectBusy (59, true);
875  ExpectBusy (61, false);
876  EndTest ();
877 
878  // Test an EIFS which is interrupted by a successful transmission.
879  //
880  // 20 60 66 69 75 81 85 89 93 97 101 103
881  // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
882  // | | <--eifs-->|
883  // 30 request access. backoff slots: 4
884  StartTest (4, 6, 10);
885  AddTxop (1);
886  AddRxErrorEvt (20, 40);
887  AddAccessRequest (30, 2, 101, 0);
888  ExpectBackoff (30, 4, 0); //backoff: 4 slots
889  AddRxOkEvt (69, 6);
890  EndTest ();
891 
892  // Test two DCFs which suffer an internal collision. the first DCF has a higher
893  // priority than the second DCF.
894  //
895  // 20 60 66 70 74 78 88
896  // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
897  // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
898  // 94 98 102 106 110 112
899  StartTest (4, 6, 10);
900  AddTxop (1); //high priority DCF
901  AddTxop (3); //low priority DCF
902  AddRxOkEvt (20, 40);
903  AddAccessRequest (30, 10, 78, 0);
904  ExpectBackoff (30, 2, 0); //backoff: 2 slot
905  AddAccessRequest (40, 2, 110, 1);
906  ExpectBackoff (40, 0, 1); //backoff: 0 slot
907  ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
908  EndTest ();
909 
910  // Test of AckTimeout handling: First queue requests access and ack procedure fails,
911  // inside the Ack timeout second queue with higher priority requests access.
912  //
913  // 20 26 34 54 74 80
914  // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
915  // DCF0 - high | | | sifs | tx |
916  // ^ request access
917  StartTest (4, 6, 10);
918  AddTxop (0); //high priority DCF
919  AddTxop (2); //low priority DCF
920  AddAccessRequestWithAckTimeout (20, 20, 34, 1);
921  AddAccessRequest (64, 10, 80, 0);
922  EndTest ();
923 
924  // Test of AckTimeout handling:
925  //
926  // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
927  // inside this interval second queue with higher priority requests access.
928  //
929  // 20 26 34 54 56 62
930  // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
931  // DCF0 - high | | | sifs | tx |
932  // ^ request access
933  StartTest (4, 6, 10);
934  AddTxop (0); //high priority DCF
935  AddTxop (2); //low priority DCF
936  AddAccessRequestWithSuccessfullAck (20, 20, 34, 2, 1);
937  AddAccessRequest (55, 10, 62, 0);
938  EndTest ();
939 
940  //Repeat the same but with one queue:
941  // 20 26 34 54 60 62 68 76 80
942  // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
943  // ^ request access
944  StartTest (4, 6, 10);
945  AddTxop (2);
946  AddAccessRequest (20, 20, 34, 0);
947  AddRxOkEvt (60, 2); // Ack
948  AddAccessRequest (61, 10, 80, 0);
949  ExpectBackoff (61, 1, 0); // 1 slot
950  EndTest ();
951 
952  // test simple NAV count. This scenario models a simple Data+Ack handshake
953  // where the data rate used for the Ack is higher than expected by the Data source
954  // so, the data exchange completes before the end of NAV.
955  StartTest (4, 6, 10);
956  AddTxop (1);
957  AddRxOkEvt (20, 40);
958  AddNavStart (60, 15);
959  AddRxOkEvt (66, 5);
960  AddNavStart (71, 0);
961  AddAccessRequest (30, 10, 93, 0);
962  ExpectBackoff (30, 2, 0); //backoff: 2 slots
963  EndTest ();
964 
965  // test more complex NAV handling by a CF-poll. This scenario models a
966  // simple Data+Ack handshake interrupted by a CF-poll which resets the
967  // NAV counter.
968  StartTest (4, 6, 10);
969  AddTxop (1);
970  AddRxOkEvt (20, 40);
971  AddNavStart (60, 15);
972  AddRxOkEvt (66, 5);
973  AddNavReset (71, 2);
974  AddAccessRequest (30, 10, 91, 0);
975  ExpectBackoff (30, 2, 0); //backoff: 2 slots
976  EndTest ();
977 
978 
979  // 20 60 80 86 94
980  // | rx | idle | sifs | aifsn | tx |
981  // ^ request access
982  StartTest (4, 6, 10);
983  AddTxop (2);
984  AddRxOkEvt (20, 40);
985  AddAccessRequest (80, 10, 94, 0);
986  EndTest ();
987 
988 
989  StartTest (4, 6, 10);
990  AddTxop (2);
991  AddRxOkEvt (20, 40);
992  AddRxOkEvt (78, 8);
993  AddAccessRequest (30, 50, 108, 0);
994  ExpectBackoff (30, 3, 0); //backoff: 3 slots
995  EndTest ();
996 
997 
998  // Channel switching tests
999 
1000  // 0 20 21 24 25 26
1001  // | switching | idle | sifs | aifsn | tx |
1002  // ^ access request.
1003  StartTest (1, 3, 10);
1004  AddTxop (1);
1005  AddSwitchingEvt (0, 20);
1006  AddAccessRequest (21, 1, 25, 0);
1007  EndTest ();
1008 
1009  // 20 40 50 53 54 55 56 57
1010  // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1011  // | |
1012  // 30 busy. 45 access request.
1013  //
1014  StartTest (1, 3, 10);
1015  AddTxop (1);
1016  AddSwitchingEvt (20,20);
1017  AddCcaBusyEvt (30,20);
1018  ExpectBackoff (45, 2, 0); //backoff: 2 slots
1019  AddAccessRequest (45, 1, 56, 0);
1020  EndTest ();
1021 
1022  // 20 30 50 51 54 55 56
1023  // | rx | switching | idle | sifs | aifsn | tx |
1024  // ^ access request.
1025  //
1026  StartTest (1, 3, 10);
1027  AddTxop (1);
1028  AddRxStartEvt (20, 40);
1029  AddSwitchingEvt (30, 20);
1030  AddAccessRequest (51, 1, 55, 0);
1031  EndTest ();
1032 
1033  // 20 30 50 51 54 55 56
1034  // | busy | switching | idle | sifs | aifsn | tx |
1035  // ^ access request.
1036  //
1037  StartTest (1, 3, 10);
1038  AddTxop (1);
1039  AddCcaBusyEvt (20, 40);
1040  AddSwitchingEvt (30, 20);
1041  AddAccessRequest (51, 1, 55, 0);
1042  EndTest ();
1043 
1044  // 20 30 50 51 54 55 56
1045  // | nav | switching | idle | sifs | aifsn | tx |
1046  // ^ access request.
1047  //
1048  StartTest (1, 3, 10);
1049  AddTxop (1);
1050  AddNavStart (20,40);
1051  AddSwitchingEvt (30,20);
1052  AddAccessRequest (51, 1, 55, 0);
1053  EndTest ();
1054 
1055  // 20 23 24 44 54 59 60 63 64 65
1056  // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1057  // | |
1058  // 49 access request. ^ access request.
1059  //
1060  StartTest (1, 3, 10);
1061  AddTxop (1);
1062  AddAccessRequestWithAckTimeout (20, 20, 24, 0);
1063  AddAccessRequest (49, 1, 54, 0);
1064  AddSwitchingEvt (54, 5);
1065  AddAccessRequest (60, 1, 64, 0);
1066  EndTest ();
1067 
1068  // 20 60 66 70 74 78 80 100 101 107 111 113
1069  // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1070  // | |
1071  // 30 access request. ^ access request.
1072  //
1073  StartTest (4, 6, 10);
1074  AddTxop (1);
1075  AddRxOkEvt (20,40);
1076  AddAccessRequest (30, 2, 80, 0);
1077  ExpectBackoff (30, 4, 0); //backoff: 4 slots
1078  AddSwitchingEvt (80,20);
1079  AddAccessRequest (101, 2, 111, 0);
1080  EndTest ();
1081 }
1082 
1083 /*
1084  * Specialization of DoRun () method for EDCA
1085  */
1086 template <>
1087 void
1089 {
1090  // Check alignment at slot boundary after successful reception (backoff = 0):
1091  // 20 50 56 60 80
1092  // | rx | sifs | aifsn | tx |
1093  // |
1094  // 52 request access
1095  StartTest (4, 6, 10);
1096  AddTxop (1);
1097  AddRxOkEvt (20, 30);
1098  AddAccessRequest (52, 20, 60, 0);
1099  EndTest ();
1100 
1101  // Check alignment at slot boundary after successful reception (backoff = 0):
1102  // 20 50 56 60 80
1103  // | rx | sifs | aifsn | tx |
1104  // |
1105  // 58 request access
1106  StartTest (4, 6, 10);
1107  AddTxop (1);
1108  AddRxOkEvt (20, 30);
1109  AddAccessRequest (58, 20, 60, 0);
1110  EndTest ();
1111 
1112  // Check alignment at slot boundary after successful reception (backoff = 0):
1113  // 20 50 56 60 64 84
1114  // | rx | sifs | aifsn | idle | tx |
1115  // |
1116  // 62 request access
1117  StartTest (4, 6, 10);
1118  AddTxop (1);
1119  AddRxOkEvt (20, 30);
1120  AddAccessRequest (62, 20, 64, 0);
1121  EndTest ();
1122 
1123  // Check alignment at slot boundary after failed reception (backoff = 0):
1124  // 20 50 56 66 76 96
1125  // | | <------eifs------>| | |
1126  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1127  // |
1128  // 55 request access
1129  StartTest (4, 6, 10);
1130  AddTxop (1);
1131  AddRxErrorEvt (20, 30);
1132  AddAccessRequest (55, 20, 76, 0);
1133  EndTest ();
1134 
1135  // Check alignment at slot boundary after failed reception (backoff = 0):
1136  // 20 50 56 66 76 96
1137  // | | <------eifs------>| | |
1138  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1139  // |
1140  // 70 request access
1141  StartTest (4, 6, 10);
1142  AddTxop (1);
1143  AddRxErrorEvt (20, 30);
1144  AddAccessRequest (70, 20, 76, 0);
1145  EndTest ();
1146 
1147  // Check alignment at slot boundary after failed reception (backoff = 0):
1148  // 20 50 56 66 76 84
1149  // | | <------eifs------>| | |
1150  // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1151  // |
1152  // 82 request access
1153  StartTest (4, 6, 10);
1154  AddTxop (1);
1155  AddRxErrorEvt (20, 30);
1156  AddAccessRequest (82, 20, 84, 0);
1157  EndTest ();
1158 
1159  // Check backoff decrement at slot boundaries. Medium idle during backoff
1160  // 20 50 56 60 64 68 72 76 96
1161  // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1162  // | | | | |
1163  // 30 request access. decrement decrement decrement decrement
1164  // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1165  StartTest (4, 6, 10);
1166  AddTxop (1);
1167  AddRxOkEvt (20, 30);
1168  AddAccessRequest (30, 20, 76, 0);
1169  ExpectBackoff (30, 4, 0);
1170  EndTest ();
1171 
1172  // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1173  // 20 50 56 60 61 71 77 81 85 87 97 103 107 127
1174  // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx |
1175  // | | | |
1176  // 30 request access. decrement decrement decrement
1177  // backoff slots: 3 slots: 2 slots: 1 slots: 0
1178  StartTest (4, 6, 10);
1179  AddTxop (1);
1180  AddRxOkEvt (20, 30);
1181  AddRxOkEvt (61, 10);
1182  AddRxOkEvt (87, 10);
1183  AddAccessRequest (30, 20, 107, 0);
1184  ExpectBackoff (30, 3, 0);
1185  EndTest ();
1186 }
1187 
1194 class TxopTestSuite : public TestSuite
1195 {
1196 public:
1197  TxopTestSuite ();
1198 };
1199 
1201  : TestSuite ("wifi-devices-dcf", UNIT)
1202 {
1203  AddTestCase (new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1204 }
1205 
1207 
1215 {
1216 public:
1217  QosTxopTestSuite ();
1218 };
1219 
1221  : TestSuite ("wifi-devices-edca", UNIT)
1222 {
1223  AddTestCase (new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1224 }
1225 
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
ExpectedBackoffs m_expectedBackoff
expected backoff (not due to an internal collision)
Time GetEifsNoDifs(void) const override
Return the EIFS duration minus a DIFS.
TxopTest(ChannelAccessManagerTest< TxopType > *test, uint32_t i)
Constructor.
void AddSwitchingEvt(uint64_t at, uint64_t duration)
Add switching event function.
void DoRun(void) override
Implementation to actually run this TestCase.
void AddRxOkEvt(uint64_t at, uint64_t duration)
Add receive OK event function.
TxopTest Txop Test.
std::list< struct ExpectedBackoff > ExpectedBackoffs
expected backoffs typedef
A suite of tests to run.
Definition: test.h:1343
void AddNavStart(uint64_t at, uint64_t duration)
Add NAV start function.
std::list< ExpectedGrant > ExpectedGrants
the collection of expected grants typedef
void AddAccessRequestWithSuccessfullAck(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
Add access request with successful ack.
#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 QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
Queue transmit function.
void DoAccessRequest(uint64_t txTime, uint64_t expectedGrantTime, Ptr< TxopTest< TxopType >> state)
Add access request with successful Ack.
#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:283
Manage a set of ns3::TxopHandle a set of independent ns3::Txop, each of which represents a single DCF...
static TxopTestSuite g_dcfTestSuite
TxopTests m_txop
the vector of Txop test instances
encapsulates test code
Definition: test.h:1153
void SetSifs(Time sifs)
Set the Short Interframe Space (SIFS).
ExpectedGrants m_expectedGrants
expected grants
void AddTxop(uint32_t aifsn)
Add Txop function.
bool HasFramesToTransmit(void) override
Check if the Txop has frames to transmit.
void NotifyWakeUp(void) override
When wake up operation occurs, channel access will be restarted.
ExpectedBackoff structure.
void NotifyChannelAccessed(Time txopDuration=Seconds(0)) override
Called by the FrameExchangeManager to notify that channel access has been granted for the given amoun...
Time GetSifs(void) const override
Return the Short Interframe Space (SIFS) for this PHY.
void AddCcaBusyEvt(uint64_t at, uint64_t duration)
Add CCA busy event function.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
static QosTxopTestSuite g_edcaTestSuite
std::vector< Ptr< TxopTest< TxopType > > > TxopTests
the TXOP tests typedef
Channel Access Manager Test.
void AddRxStartEvt(uint64_t at, uint64_t duration)
Add receive start event function.
uint32_t m_ackTimeoutValue
the Ack timeout value
void GenerateBackoff(uint32_t i)
Generate backoff function.
void DoDispose(void) override
Destructor implementation.
void GenerateBackoff(void) override
Generate a new backoff now.
void AddAckTimeoutReset(uint64_t at)
Add Ack timeout reset function.
void NotifyInternalCollision(void) override
Notify the Txop that internal collision has occurred.
void NotifyAccessGranted(uint32_t i)
Notify access granted function.
void SetEifsNoDifs(Time eifsNoDifs)
Set the duration of EIFS - DIFS.
void AddTxEvt(uint64_t at, uint64_t duration)
Add transmit event function.
void EndTest(void)
End test function.
bool StartTransmission(Ptr< Txop > dcf) override
Request the FrameExchangeManager to start a frame exchange sequence.
std::pair< uint64_t, uint64_t > ExpectedGrant
the expected grant typedef
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ChannelAccessManager Stub.
FrameExchangeManager is a base class handling the basic frame exchange sequences for non-QoS stations...
Ptr< ChannelAccessManagerStub > m_ChannelAccessManager
the channel access manager
virtual void NotifyChannelAccessed(Time txopDuration=Seconds(0))
Called by the FrameExchangeManager to notify that channel access has been granted for the given amoun...
Definition: txop.cc:342
void AddRxInsideSifsEvt(uint64_t at, uint64_t duration)
Add receive inside SIFS event function.
Ptr< FrameExchangeManagerStub > m_feManager
the Frame Exchange Manager stubbed
Time GetSlot(void) const override
Return the slot duration for this PHY.
void AddRxErrorEvt(uint64_t at, uint64_t duration)
Add receive error event function for error at end of frame.
uint32_t m_i
the index of the Txop
void ExpectInternalCollision(uint64_t time, uint32_t nSlots, uint32_t from)
Expect internal collision function.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
void DoCheckBusy(bool busy)
Perform check that channel access manager is busy or idle.
void NotifyChannelSwitching(uint32_t i)
Notify channel switching function.
void NotifyChannelSwitching(void) override
When a channel switching occurs, enqueued packets are removed.
void NotifyInternalCollision(uint32_t i)
Notify internal collision function.
Frame Exchange Manager Stub.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
void AddAccessRequestWithAckTimeout(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access request with Ack timeout.
ExpectedBackoffs m_expectedInternalCollision
expected backoff due to an internal collision
void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access function.
void StartTest(uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue=20)
Start test function.
ChannelAccessManagerTest< TxopType > * m_test
Check if the Txop has frames to transmit.
void SetSlot(Time slot)
Set the slot duration.
void AddNavReset(uint64_t at, uint64_t duration)
Add NAV reset function.
void NotifySleep(void) override
When sleep operation occurs, if there is a pending packet transmission, it will be reinserted to the ...
Time m_eifsNoDifs
EIFS duration minus a DIFS.