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