A Discrete-Event Network Simulator
API
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2019 University of Washington
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: Sébastien Deronne <sebastien.deronne@gmail.com>
19 */
20
21#include "ns3/log.h"
22#include "ns3/test.h"
23#include "ns3/node.h"
24#include "ns3/pointer.h"
25#include "ns3/string.h"
26#include "ns3/double.h"
27#include "ns3/boolean.h"
28#include "ns3/simulator.h"
29#include "ns3/rng-seed-manager.h"
30#include "ns3/constant-position-mobility-model.h"
31#include "ns3/wifi-spectrum-signal-parameters.h"
32#include "ns3/wifi-spectrum-value-helper.h"
33#include "ns3/multi-model-spectrum-channel.h"
34#include "ns3/spectrum-wifi-phy.h"
35#include "ns3/nist-error-rate-model.h"
36#include "ns3/wifi-mac-header.h"
37#include "ns3/wifi-net-device.h"
38#include "ns3/wifi-psdu.h"
39#include "ns3/he-ppdu.h"
40#include "ns3/wifi-utils.h"
41#include "ns3/ap-wifi-mac.h"
42#include "ns3/sta-wifi-mac.h"
43#include "ns3/he-configuration.h"
44#include "ns3/ctrl-headers.h"
45#include "ns3/threshold-preamble-detection-model.h"
46#include "ns3/he-phy.h"
47#include "ns3/waveform-generator.h"
48#include "ns3/non-communicating-net-device.h"
49#include "ns3/spectrum-wifi-helper.h"
50#include "ns3/mobility-helper.h"
51
52using namespace ns3;
53
54NS_LOG_COMPONENT_DEFINE ("WifiPhyOfdmaTest");
55
56static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
57static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
59static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
60static const uint16_t DEFAULT_GUARD_WIDTH = DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
61
66class OfdmaTestHePhy : public HePhy
67{
68public:
74 OfdmaTestHePhy (uint16_t staId);
75 virtual ~OfdmaTestHePhy ();
76
84 uint16_t GetStaId (const Ptr<const WifiPpdu> ppdu) const override;
85
91 void SetGlobalPpduUid (uint64_t uid);
92
93private:
94 uint16_t m_staId;
95}; //class OfdmaTestHePhy
96
98 : HePhy (),
99 m_staId (staId)
100{
101}
102
104{
105}
106
107uint16_t
109{
110 if (ppdu->GetType () == WIFI_PPDU_TYPE_DL_MU)
111 {
112 return m_staId;
113 }
114 return HePhy::GetStaId (ppdu);
115}
116
117void
119{
120 m_globalPpduUid = uid;
121}
122
127{
128public:
133 static TypeId GetTypeId (void);
139 OfdmaSpectrumWifiPhy (uint16_t staId);
140 virtual ~OfdmaSpectrumWifiPhy ();
141
142 void DoInitialize (void) override;
143 void DoDispose (void) override;
144
145 using WifiPhy::Reset;
146
152 typedef void (*TxPpduUidCallback)(uint64_t uid);
153
157 void StartTx (Ptr<WifiPpdu> ppdu) override;
162 uint16_t GetGuardBandwidth (uint16_t currentChannelWidth) const override;
163
169 void SetPpduUid (uint64_t uid);
170
176 void SetTriggerFrameUid (uint64_t uid);
177
181 std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > & GetCurrentPreambleEvents (void);
186
197 Time GetEnergyDuration (double energyW, WifiSpectrumBand band);
198
202 Ptr<const HePhy> GetHePhy (void) const;
203
204private:
207}; //class OfdmaSpectrumWifiPhy
208
209TypeId
211{
212 static TypeId tid = TypeId ("ns3::OfdmaSpectrumWifiPhy")
214 .SetGroupName ("Wifi")
215 .AddTraceSource ("TxPpduUid",
216 "UID of the PPDU to be transmitted",
218 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback")
219 ;
220 return tid;
221}
222
224 : SpectrumWifiPhy ()
225{
226 m_ofdmTestHePhy = Create<OfdmaTestHePhy> (staId);
228}
229
231{
232}
233
234void
236{
237 //Replace HE PHY instance with test instance
239 SpectrumWifiPhy::DoInitialize ();
240}
241
242void
244{
245 m_ofdmTestHePhy = 0;
246 SpectrumWifiPhy::DoDispose ();
247}
248
249void
251{
254}
255
256void
258{
260}
261
262void
264{
265 m_phyTxPpduUidTrace (ppdu->GetUid ());
266 SpectrumWifiPhy::StartTx (ppdu);
267}
268
269std::map <std::pair<uint64_t, WifiPreamble>, Ptr<Event> > &
271{
273}
274
275uint16_t
276OfdmaSpectrumWifiPhy::GetGuardBandwidth (uint16_t currentChannelWidth) const
277{
278 // return a small enough value to avoid having too much out of band transmission
279 // knowing that slopes are not configurable yet.
280 return 1;
281}
282
285{
286 return m_currentEvent;
287}
288
289Time
291{
292 return m_interference.GetEnergyDuration (energyW, band);
293}
294
297{
298 return DynamicCast<const HePhy> (GetPhyEntity (WIFI_MOD_CLASS_HE));
299}
300
308{
309public:
312
313private:
314 void DoSetup (void) override;
315 void DoTeardown (void) override;
316 void DoRun (void) override;
317
325 void RxSuccessSta1 (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
326 WifiTxVector txVector, std::vector<bool> statusPerMpdu);
334 void RxSuccessSta2 (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
335 WifiTxVector txVector, std::vector<bool> statusPerMpdu);
343 void RxSuccessSta3 (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
344 WifiTxVector txVector, std::vector<bool> statusPerMpdu);
345
350 void RxFailureSta1 (Ptr<WifiPsdu> psdu);
355 void RxFailureSta2 (Ptr<WifiPsdu> psdu);
360 void RxFailureSta3 (Ptr<WifiPsdu> psdu);
361
368 void CheckResultsSta1 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes);
375 void CheckResultsSta2 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes);
382 void CheckResultsSta3 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes);
383
387 void ResetResults ();
388
394 void SendMuPpdu (uint16_t rxStaId1, uint16_t rxStaId2);
395
401 void GenerateInterference (Ptr<SpectrumValue> interferencePsd, Time duration);
405 void StopInterference (void);
406
410 void RunOne ();
411
424
434
440
441 uint16_t m_frequency;
442 uint16_t m_channelWidth;
444};
445
447 : TestCase ("DL-OFDMA PHY test"),
448 m_countRxSuccessSta1 (0),
449 m_countRxSuccessSta2 (0),
450 m_countRxSuccessSta3 (0),
451 m_countRxFailureSta1 (0),
452 m_countRxFailureSta2 (0),
453 m_countRxFailureSta3 (0),
454 m_countRxBytesSta1 (0),
455 m_countRxBytesSta2 (0),
456 m_countRxBytesSta3 (0),
457 m_frequency (DEFAULT_FREQUENCY),
458 m_channelWidth (DEFAULT_CHANNEL_WIDTH),
459 m_expectedPpduDuration (NanoSeconds (306400))
460{
461}
462
463void
465{
475}
476
477void
478TestDlOfdmaPhyTransmission::SendMuPpdu (uint16_t rxStaId1, uint16_t rxStaId2)
479{
480 NS_LOG_FUNCTION (this << rxStaId1 << rxStaId2);
481 WifiConstPsduMap psdus;
482 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_MU, 800, 1, 1, 0, m_channelWidth, false, false);
483 HeRu::RuType ruType = HeRu::RU_106_TONE;
484 if (m_channelWidth == 20)
485 {
486 ruType = HeRu::RU_106_TONE;
487 }
488 else if (m_channelWidth == 40)
489 {
490 ruType = HeRu::RU_242_TONE;
491 }
492 else if (m_channelWidth == 80)
493 {
494 ruType = HeRu::RU_484_TONE;
495 }
496 else if (m_channelWidth == 160)
497 {
498 ruType = HeRu::RU_996_TONE;
499 }
500 else
501 {
502 NS_ASSERT_MSG (false, "Unsupported channel width");
503 }
504
505 HeRu::RuSpec ru1 (ruType, 1, true);
506 txVector.SetRu (ru1, rxStaId1);
507 txVector.SetMode (HePhy::GetHeMcs7 (), rxStaId1);
508 txVector.SetNss (1, rxStaId1);
509
510 HeRu::RuSpec ru2 (ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
511 txVector.SetRu (ru2, rxStaId2);
512 txVector.SetMode (HePhy::GetHeMcs9 (), rxStaId2);
513 txVector.SetNss (1, rxStaId2);
514
515 Ptr<Packet> pkt1 = Create<Packet> (1000);
516 WifiMacHeader hdr1;
518 hdr1.SetQosTid (0);
519 hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
520 hdr1.SetSequenceNumber (1);
521 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu> (pkt1, hdr1);
522 psdus.insert (std::make_pair (rxStaId1, psdu1));
523
524 Ptr<Packet> pkt2 = Create<Packet> (1500);
525 WifiMacHeader hdr2;
527 hdr2.SetQosTid (0);
528 hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
529 hdr2.SetSequenceNumber (2);
530 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu> (pkt2, hdr2);
531 psdus.insert (std::make_pair (rxStaId2, psdu2));
532
533 m_phyAp->Send (psdus, txVector);
534}
535
536void
538{
540 m_phyInterferer->SetPeriod (duration);
542 Simulator::Schedule (duration, &TestDlOfdmaPhyTransmission::StopInterference, this);
543}
544
545void
547{
549}
550
552{
553}
554
555void
557 WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
558{
559 NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
561 m_countRxBytesSta1 += (psdu->GetSize () - 30);
562}
563
564void
566 WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
567{
568 NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
570 m_countRxBytesSta2 += (psdu->GetSize () - 30);
571}
572
573void
575 WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
576{
577 NS_LOG_FUNCTION (this << *psdu << rxSignalInfo << txVector);
579 m_countRxBytesSta3 += (psdu->GetSize () - 30);
580}
581
582void
584{
585 NS_LOG_FUNCTION (this << *psdu);
587}
588
589void
591{
592 NS_LOG_FUNCTION (this << *psdu);
594}
595
596void
598{
599 NS_LOG_FUNCTION (this << *psdu);
601}
602
603void
604TestDlOfdmaPhyTransmission::CheckResultsSta1 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
605{
606 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessSta1, expectedRxSuccess, "The number of successfully received packets by STA 1 is not correct!");
607 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureSta1, expectedRxFailure, "The number of unsuccessfully received packets by STA 1 is not correct!");
608 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesSta1, expectedRxBytes, "The number of bytes received by STA 1 is not correct!");
609}
610
611void
612TestDlOfdmaPhyTransmission::CheckResultsSta2 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
613{
614 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessSta2, expectedRxSuccess, "The number of successfully received packets by STA 2 is not correct!");
615 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureSta2, expectedRxFailure, "The number of unsuccessfully received packets by STA 2 is not correct!");
616 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesSta2, expectedRxBytes, "The number of bytes received by STA 2 is not correct!");
617}
618
619void
620TestDlOfdmaPhyTransmission::CheckResultsSta3 (uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
621{
622 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessSta3, expectedRxSuccess, "The number of successfully received packets by STA 3 is not correct!");
623 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureSta3, expectedRxFailure, "The number of unsuccessfully received packets by STA 3 is not correct!");
624 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesSta3, expectedRxBytes, "The number of bytes received by STA 3 is not correct!");
625}
626
627void
629{
630 //This is needed to make sure PHY state will be checked as the last event if a state change occured at the exact same time as the check
631 Simulator::ScheduleNow (&TestDlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
632}
633
634void
636{
637 WifiPhyState currentState;
638 PointerValue ptr;
639 phy->GetAttribute ("State", ptr);
640 Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
641 currentState = state->GetState ();
642 NS_LOG_FUNCTION (this << currentState);
643 NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
644}
645
646void
648{
649 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
650 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
651 lossModel->SetFrequency (m_frequency * 1e6);
652 spectrumChannel->AddPropagationLossModel (lossModel);
653 Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
654 spectrumChannel->SetPropagationDelayModel (delayModel);
655
656 Ptr<Node> apNode = CreateObject<Node> ();
657 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
658 m_phyAp = CreateObject<SpectrumWifiPhy> ();
661 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
662 m_phyAp->SetErrorRateModel (error);
663 m_phyAp->SetDevice (apDev);
664 m_phyAp->SetChannel (spectrumChannel);
665 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
666 m_phyAp->SetMobility (apMobility);
667 apDev->SetPhy (m_phyAp);
668 apNode->AggregateObject (apMobility);
669 apNode->AddDevice (apDev);
670
671 Ptr<Node> sta1Node = CreateObject<Node> ();
672 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
673 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
677 m_phySta1->SetDevice (sta1Dev);
678 m_phySta1->SetChannel (spectrumChannel);
681 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
682 m_phySta1->SetMobility (sta1Mobility);
683 sta1Dev->SetPhy (m_phySta1);
684 sta1Node->AggregateObject (sta1Mobility);
685 sta1Node->AddDevice (sta1Dev);
686
687 Ptr<Node> sta2Node = CreateObject<Node> ();
688 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
689 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
693 m_phySta2->SetDevice (sta2Dev);
694 m_phySta2->SetChannel (spectrumChannel);
697 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
698 m_phySta2->SetMobility (sta2Mobility);
699 sta2Dev->SetPhy (m_phySta2);
700 sta2Node->AggregateObject (sta2Mobility);
701 sta2Node->AddDevice (sta2Dev);
702
703 Ptr<Node> sta3Node = CreateObject<Node> ();
704 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice> ();
705 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy> (3);
709 m_phySta3->SetDevice (sta3Dev);
710 m_phySta3->SetChannel (spectrumChannel);
713 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel> ();
714 m_phySta3->SetMobility (sta3Mobility);
715 sta3Dev->SetPhy (m_phySta3);
716 sta3Node->AggregateObject (sta3Mobility);
717 sta3Node->AddDevice (sta3Dev);
718
719 Ptr<Node> interfererNode = CreateObject<Node> ();
720 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice> ();
721 m_phyInterferer = CreateObject<WaveformGenerator> ();
722 m_phyInterferer->SetDevice (interfererDev);
723 m_phyInterferer->SetChannel (spectrumChannel);
725 interfererNode->AddDevice (interfererDev);
726}
727
728void
730{
731 m_phyAp->Dispose ();
732 m_phyAp = 0;
733 m_phySta1->Dispose ();
734 m_phySta1 = 0;
735 m_phySta2->Dispose ();
736 m_phySta2 = 0;
737 m_phySta3->Dispose ();
738 m_phySta3 = 0;
740 m_phyInterferer = 0;
741}
742
743void
745{
746 RngSeedManager::SetSeed (1);
747 RngSeedManager::SetRun (1);
748 int64_t streamNumber = 0;
749 m_phyAp->AssignStreams (streamNumber);
750 m_phySta1->AssignStreams (streamNumber);
751 m_phySta2->AssignStreams (streamNumber);
752 m_phySta3->AssignStreams (streamNumber);
753
754 auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, m_frequency, m_channelWidth,
757
759 (int)(WIFI_PHY_BAND_5GHZ), 0});
761 (int)(WIFI_PHY_BAND_5GHZ), 0});
763 (int)(WIFI_PHY_BAND_5GHZ), 0});
765 (int)(WIFI_PHY_BAND_5GHZ), 0});
766
767 Simulator::Schedule (Seconds (0.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
768
769 //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
770 //Each STA should receive its PSDU.
771 Simulator::Schedule (Seconds (1.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
772
773 //Since it takes m_expectedPpduDuration to transmit the PPDU,
774 //all 3 PHYs should be back to IDLE at the same time,
775 //even the PHY that has no PSDU addressed to it.
782
783 //One PSDU of 1000 bytes should have been successfully received by STA 1
784 Simulator::Schedule (Seconds (1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 1, 0, 1000);
785 //One PSDU of 1500 bytes should have been successfully received by STA 2
786 Simulator::Schedule (Seconds (1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 1, 0, 1500);
787 //No PSDU should have been received by STA 3
788 Simulator::Schedule (Seconds (1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
789
790 Simulator::Schedule (Seconds (1.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
791
792 //Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
793 //STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
794 //but should keep its PHY busy during all PPDU duration.
795 Simulator::Schedule (Seconds (2.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 3);
796
797 //Since it takes m_expectedPpduDuration to transmit the PPDU,
798 //all 3 PHYs should be back to IDLE at the same time,
799 //even the PHY that has no PSDU addressed to it.
806
807 //One PSDU of 1000 bytes should have been successfully received by STA 1
808 Simulator::Schedule (Seconds (2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 1, 0, 1000);
809 //No PSDU should have been received by STA 2
810 Simulator::Schedule (Seconds (2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 0, 0);
811 //One PSDU of 1500 bytes should have been successfully received by STA 3
812 Simulator::Schedule (Seconds (2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 1, 0, 1500);
813
814 Simulator::Schedule (Seconds (2.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
815
816 //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
817 Simulator::Schedule (Seconds (3.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
818
819 //A strong non-wifi interference is generated on RU 1 during PSDU reception
820 BandInfo bandInfo;
821 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
822 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
823 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
824 Bands bands;
825 bands.push_back (bandInfo);
826
827 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel> (bands);
828 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue> (SpectrumInterferenceRu1);
829 double interferencePower = 0.1; //watts
830 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
831
832 Simulator::Schedule (Seconds (3.0) + MicroSeconds (50), &TestDlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu1, MilliSeconds (100));
833
834 //Since it takes m_expectedPpduDuration to transmit the PPDU,
835 //both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
836 //even the PHY that has no PSDU addressed to it.
843
844 //One PSDU of 1000 bytes should have been unsuccessfully received by STA 1 (since interference occupies RU 1)
845 Simulator::Schedule (Seconds (3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
846 //One PSDU of 1500 bytes should have been successfully received by STA 2
847 Simulator::Schedule (Seconds (3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 1, 0, 1500);
848 //No PSDU should have been received by STA3
849 Simulator::Schedule (Seconds (3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
850
851 Simulator::Schedule (Seconds (3.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
852
853 //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
854 Simulator::Schedule (Seconds (4.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
855
856 //A strong non-wifi interference is generated on RU 2 during PSDU reception
857 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
858 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
859 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
860 bands.clear ();
861 bands.push_back (bandInfo);
862
863 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel> (bands);
864 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue> (SpectrumInterferenceRu2);
865 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
866
867 Simulator::Schedule (Seconds (4.0) + MicroSeconds (50), &TestDlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu2, MilliSeconds (100));
868
869 //Since it takes m_expectedPpduDuration to transmit the PPDU,
870 //both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the same time,
871 //even the PHY that has no PSDU addressed to it.
878
879 //One PSDU of 1000 bytes should have been successfully received by STA 1
880 Simulator::Schedule (Seconds (4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 1, 0, 1000);
881 //One PSDU of 1500 bytes should have been unsuccessfully received by STA 2 (since interference occupies RU 2)
882 Simulator::Schedule (Seconds (4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
883 //No PSDU should have been received by STA3
884 Simulator::Schedule (Seconds (4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
885
886 Simulator::Schedule (Seconds (4.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
887
888 //Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
889 Simulator::Schedule (Seconds (5.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
890
891 //A strong non-wifi interference is generated on the full band during PSDU reception
892 bandInfo.fc = m_frequency * 1e6;
893 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
894 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
895 bands.clear ();
896 bands.push_back (bandInfo);
897
898 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel> (bands);
899 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue> (SpectrumInterferenceAll);
900 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
901
902 Simulator::Schedule (Seconds (5.0) + MicroSeconds (50), &TestDlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdAll, MilliSeconds (100));
903
904 //Since it takes m_expectedPpduDuration to transmit the PPDU,
905 //both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
906 //even the PHY that has no PSDU addressed to it.
913
914 //One PSDU of 1000 bytes should have been unsuccessfully received by STA 1 (since interference occupies RU 1)
915 Simulator::Schedule (Seconds (5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
916 //One PSDU of 1500 bytes should have been unsuccessfully received by STA 2 (since interference occupies RU 2)
917 Simulator::Schedule (Seconds (5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
918 //No PSDU should have been received by STA3
919 Simulator::Schedule (Seconds (5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
920
921 Simulator::Schedule (Seconds (5.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
922
923 Simulator::Run ();
924}
925
926void
928{
929 m_frequency = 5180;
930 m_channelWidth = 20;
932 RunOne ();
933
934 m_frequency = 5190;
935 m_channelWidth = 40;
937 RunOne ();
938
939 m_frequency = 5210;
940 m_channelWidth = 80;
942 RunOne ();
943
944 m_frequency = 5250;
945 m_channelWidth = 160;
947 RunOne ();
948
949 Simulator::Destroy ();
950}
951
952
960{
961public:
963 virtual ~TestUlOfdmaPpduUid ();
964
965private:
966 void DoSetup (void) override;
967 void DoTeardown (void) override;
968 void DoRun (void) override;
969
974 void TxPpduAp (uint64_t uid);
979 void TxPpduSta1 (uint64_t uid);
984 void TxPpduSta2 (uint64_t uid);
988 void ResetPpduUid (void);
989
993 void SendMuPpdu (void);
997 void SendTbPpdu (void);
1002 void SendSuPpdu (uint16_t txStaId);
1003
1009 void CheckUid (uint16_t staId, uint64_t expectedUid);
1010
1014
1015 uint64_t m_ppduUidAp;
1016 uint64_t m_ppduUidSta1;
1017 uint64_t m_ppduUidSta2;
1018};
1019
1021 : TestCase ("UL-OFDMA PPDU UID attribution test"),
1022 m_ppduUidAp (UINT64_MAX),
1023 m_ppduUidSta1 (UINT64_MAX),
1024 m_ppduUidSta2 (UINT64_MAX)
1025{
1026}
1027
1029{
1030}
1031
1032void
1034{
1035 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
1036 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
1037 lossModel->SetFrequency (DEFAULT_FREQUENCY);
1038 spectrumChannel->AddPropagationLossModel (lossModel);
1039 Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
1040 spectrumChannel->SetPropagationDelayModel (delayModel);
1041
1042 Ptr<Node> apNode = CreateObject<Node> ();
1043 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
1044 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy> (0);
1047 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
1048 m_phyAp->SetErrorRateModel (error);
1049 auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, DEFAULT_FREQUENCY,
1054 (int)(WIFI_PHY_BAND_5GHZ), 0});
1055 m_phyAp->SetDevice (apDev);
1056 m_phyAp->SetChannel (spectrumChannel);
1058 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
1059 m_phyAp->SetMobility (apMobility);
1060 apDev->SetPhy (m_phyAp);
1061 apNode->AggregateObject (apMobility);
1062 apNode->AddDevice (apDev);
1063
1064 Ptr<Node> sta1Node = CreateObject<Node> ();
1065 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
1066 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
1071 (int)(WIFI_PHY_BAND_5GHZ), 0});
1072 m_phySta1->SetDevice (sta1Dev);
1073 m_phySta1->SetChannel (spectrumChannel);
1075 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
1076 m_phySta1->SetMobility (sta1Mobility);
1077 sta1Dev->SetPhy (m_phySta1);
1078 sta1Node->AggregateObject (sta1Mobility);
1079 sta1Node->AddDevice (sta1Dev);
1080
1081 Ptr<Node> sta2Node = CreateObject<Node> ();
1082 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
1083 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
1088 (int)(WIFI_PHY_BAND_5GHZ), 0});
1089 m_phySta2->SetDevice (sta2Dev);
1090 m_phySta2->SetChannel (spectrumChannel);
1092 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
1093 m_phySta2->SetMobility (sta2Mobility);
1094 sta2Dev->SetPhy (m_phySta2);
1095 sta2Node->AggregateObject (sta2Mobility);
1096 sta2Node->AddDevice (sta2Dev);
1097}
1098
1099void
1101{
1102 m_phyAp->Dispose ();
1103 m_phyAp = 0;
1104 m_phySta1->Dispose ();
1105 m_phySta1 = 0;
1106 m_phySta2->Dispose ();
1107 m_phySta2 = 0;
1108}
1109
1110void
1111TestUlOfdmaPpduUid::CheckUid (uint16_t staId, uint64_t expectedUid)
1112{
1113 uint64_t uid;
1114 std::string device;
1115 switch (staId)
1116 {
1117 case 0:
1118 uid = m_ppduUidAp;
1119 device = "AP";
1120 break;
1121 case 1:
1122 uid = m_ppduUidSta1;
1123 device = "STA1";
1124 break;
1125 case 2:
1126 uid = m_ppduUidSta2;
1127 device = "STA2";
1128 break;
1129 default:
1130 NS_ABORT_MSG ("Unexpected STA-ID");
1131 }
1132 NS_TEST_ASSERT_MSG_EQ (uid, expectedUid, "UID " << uid << " does not match expected one " << expectedUid << " for " << device << " at " << Simulator::Now ());
1133}
1134
1135void
1137{
1138 NS_LOG_FUNCTION (this << uid);
1139 m_ppduUidAp = uid;
1140}
1141
1142void
1144{
1145 NS_LOG_FUNCTION (this << uid);
1146 m_ppduUidSta1 = uid;
1147}
1148
1149void
1151{
1152 NS_LOG_FUNCTION (this << uid);
1153 m_ppduUidSta2 = uid;
1154}
1155
1156void
1158{
1159 NS_LOG_FUNCTION (this);
1160 m_phyAp->SetPpduUid (0); //one is enough since it's a global attribute
1161 return;
1162}
1163
1164void
1166{
1167 WifiConstPsduMap psdus;
1168 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_MU, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1169
1170 uint16_t rxStaId1 = 1;
1171 HeRu::RuSpec ru1 (HeRu::RU_106_TONE, 1, false);
1172 txVector.SetRu (ru1, rxStaId1);
1173 txVector.SetMode (HePhy::GetHeMcs7 (), rxStaId1);
1174 txVector.SetNss (1, rxStaId1);
1175
1176 uint16_t rxStaId2 = 2;
1177 HeRu::RuSpec ru2 (HeRu::RU_106_TONE, 2, false);
1178 txVector.SetRu (ru2, rxStaId2);
1179 txVector.SetMode (HePhy::GetHeMcs9 (), rxStaId2);
1180 txVector.SetNss (1, rxStaId2);
1181
1182 Ptr<Packet> pkt1 = Create<Packet> (1000);
1183 WifiMacHeader hdr1;
1185 hdr1.SetQosTid (0);
1186 hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:01"));
1187 hdr1.SetSequenceNumber (1);
1188 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu> (pkt1, hdr1);
1189 psdus.insert (std::make_pair (rxStaId1, psdu1));
1190
1191 Ptr<Packet> pkt2 = Create<Packet> (1500);
1192 WifiMacHeader hdr2;
1194 hdr2.SetQosTid (0);
1195 hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:02"));
1196 hdr2.SetSequenceNumber (2);
1197 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu> (pkt2, hdr2);
1198 psdus.insert (std::make_pair (rxStaId2, psdu2));
1199
1200 m_phyAp->Send (psdus, txVector);
1201}
1202
1203void
1205{
1206 WifiConstPsduMap psdus1;
1207 WifiConstPsduMap psdus2;
1208 WifiTxVector txVector1 = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1209 WifiTxVector txVector2 = txVector1;
1210
1211 uint16_t rxStaId1 = 1;
1212 HeRu::RuSpec ru1 (HeRu::RU_106_TONE, 1, false);
1213 txVector1.SetRu (ru1, rxStaId1);
1214 txVector1.SetMode (HePhy::GetHeMcs7 (), rxStaId1);
1215 txVector1.SetNss (1, rxStaId1);
1216
1217 Ptr<Packet> pkt1 = Create<Packet> (1000);
1218 WifiMacHeader hdr1;
1220 hdr1.SetQosTid (0);
1221 hdr1.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1222 hdr1.SetSequenceNumber (1);
1223 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu> (pkt1, hdr1);
1224 psdus1.insert (std::make_pair (rxStaId1, psdu1));
1225
1226 uint16_t rxStaId2 = 2;
1227 HeRu::RuSpec ru2 (HeRu::RU_106_TONE, 2, false);
1228 txVector2.SetRu (ru2, rxStaId2);
1229 txVector2.SetMode (HePhy::GetHeMcs9 (), rxStaId2);
1230 txVector2.SetNss (1, rxStaId2);
1231
1232 Ptr<Packet> pkt2 = Create<Packet> (1500);
1233 WifiMacHeader hdr2;
1235 hdr2.SetQosTid (0);
1236 hdr2.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1237 hdr2.SetSequenceNumber (2);
1238 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu> (pkt2, hdr2);
1239 psdus2.insert (std::make_pair (rxStaId2, psdu2));
1240
1241 Time txDuration1 = m_phySta1->CalculateTxDuration (psdu1->GetSize (), txVector1,
1242 m_phySta1->GetPhyBand (), rxStaId1);
1243 Time txDuration2 = m_phySta2->CalculateTxDuration (psdu2->GetSize (), txVector2,
1244 m_phySta1->GetPhyBand (), rxStaId2);
1245 Time txDuration = std::max (txDuration1, txDuration2);
1246
1247 txVector1.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector1, m_phySta1->GetPhyBand ()).first);
1248 txVector2.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector2, m_phySta2->GetPhyBand ()).first);
1249
1250 m_phySta1->Send (psdus1, txVector1);
1251 m_phySta2->Send (psdus2, txVector2);
1252}
1253
1254void
1256{
1257 WifiConstPsduMap psdus;
1258 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1259
1260 Ptr<Packet> pkt = Create<Packet> (1000);
1261 WifiMacHeader hdr;
1263 hdr.SetQosTid (0);
1264 hdr.SetAddr1 (Mac48Address::GetBroadcast ());
1265 hdr.SetSequenceNumber (1);
1266 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
1267 psdus.insert (std::make_pair (SU_STA_ID, psdu));
1268
1269 switch (txStaId)
1270 {
1271 case 0:
1272 m_phyAp->Send (psdus, txVector);
1273 break;
1274 case 1:
1275 m_phySta1->Send (psdus, txVector);
1276 break;
1277 case 2:
1278 m_phySta2->Send (psdus, txVector);
1279 break;
1280 default:
1281 NS_ABORT_MSG ("Unexpected STA-ID");
1282 }
1283}
1284
1285void
1287{
1288 RngSeedManager::SetSeed (1);
1289 RngSeedManager::SetRun (1);
1290 int64_t streamNumber = 0;
1291 m_phyAp->AssignStreams (streamNumber);
1292 m_phySta1->AssignStreams (streamNumber);
1293 m_phySta2->AssignStreams (streamNumber);
1294
1295 //Reset PPDU UID so as not to be dependent on previously executed test cases,
1296 //since global attribute will be changed).
1297 ResetPpduUid ();
1298
1299 //Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
1300 //PPDU UID should be equal to 0 (the first counter value).
1301 Simulator::Schedule (Seconds (1.0), &TestUlOfdmaPpduUid::SendMuPpdu, this);
1302 Simulator::Schedule (Seconds (1.0), &TestUlOfdmaPpduUid::CheckUid, this, 0, 0);
1303
1304 //Send HE SU PPDU from AP.
1305 //PPDU UID should be incremented since this is a new PPDU.
1306 Simulator::Schedule (Seconds (1.1), &TestUlOfdmaPpduUid::SendSuPpdu, this, 0);
1307 Simulator::Schedule (Seconds (1.1), &TestUlOfdmaPpduUid::CheckUid, this, 0, 1);
1308
1309 //Send HE TB PPDU from STAs to AP.
1310 //PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
1311 //preceding correctly received PPDU (which normally contains the trigger frame).
1312 Simulator::Schedule (Seconds (1.15), &TestUlOfdmaPpduUid::SendTbPpdu, this);
1313 Simulator::Schedule (Seconds (1.15), &TestUlOfdmaPpduUid::CheckUid, this, 1, 1);
1314 Simulator::Schedule (Seconds (1.15), &TestUlOfdmaPpduUid::CheckUid, this, 2, 1);
1315
1316 //Send HE SU PPDU from STA1.
1317 //PPDU UID should be incremented since this is a new PPDU.
1318 Simulator::Schedule (Seconds (1.2), &TestUlOfdmaPpduUid::SendSuPpdu, this, 1);
1319 Simulator::Schedule (Seconds (1.2), &TestUlOfdmaPpduUid::CheckUid, this, 1, 2);
1320
1321 Simulator::Run ();
1322 Simulator::Destroy ();
1323}
1324
1332{
1333public:
1335 virtual ~TestMultipleHeTbPreambles ();
1336
1337private:
1338 void DoSetup (void) override;
1339 void DoTeardown (void) override;
1340 void DoRun (void) override;
1341
1350 void RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
1351
1366
1373
1377 void Reset (void);
1378
1384 void CheckHeTbPreambles (size_t nEvents, std::vector <uint64_t> uids);
1385
1390 void CheckBytesDropped (size_t expectedBytesDropped);
1391
1393
1396};
1397
1399 : TestCase ("UL-OFDMA multiple RX events test"),
1400 m_totalBytesDropped (0),
1401 m_trigVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false)
1402{
1403}
1404
1406{
1407}
1408
1409void
1411{
1412 NS_LOG_FUNCTION (this);
1414 //We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
1415 m_phy->Reset ();
1416 m_trigVector.GetHeMuUserInfoMap ().clear ();
1417}
1418
1419void
1421{
1422 NS_LOG_FUNCTION (this << p << reason);
1423 m_totalBytesDropped += (p->GetSize () - 30);
1424}
1425
1426void
1427TestMultipleHeTbPreambles::CheckHeTbPreambles (size_t nEvents, std::vector <uint64_t> uids)
1428{
1429 auto events = m_phy->GetCurrentPreambleEvents ();
1430 NS_TEST_ASSERT_MSG_EQ (events.size (), nEvents, "The number of UL MU events is not correct!");
1431 for (auto const& uid : uids)
1432 {
1433 auto pair = std::make_pair (uid, WIFI_PREAMBLE_HE_TB);
1434 auto it = events.find (pair);
1435 bool found = (it != events.end ());
1436 NS_TEST_ASSERT_MSG_EQ (found, true, "HE TB PPDU with UID " << uid << " has not been received!");
1437 }
1438}
1439
1440void
1442{
1443 NS_TEST_ASSERT_MSG_EQ (m_totalBytesDropped, expectedBytesDropped, "The number of dropped bytes is not correct!");
1444}
1445
1446void
1447TestMultipleHeTbPreambles::RxHeTbPpdu (uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
1448{
1449 WifiConstPsduMap psdus;
1450 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false);
1451
1452 HeRu::RuSpec ru (HeRu::RU_106_TONE, staId, false);
1454 txVector.SetRu (ru, staId);
1455 txVector.SetMode (HePhy::GetHeMcs7 (), staId);
1456 txVector.SetNss (1, staId);
1457
1458 m_trigVector.GetHeMuUserInfoMap ().insert ({staId, HeMuUserInfo {ru, HePhy::GetHeMcs7 (), 1}});
1459
1460 Ptr<Packet> pkt = Create<Packet> (payloadSize);
1461 WifiMacHeader hdr;
1463 hdr.SetQosTid (0);
1464 hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1465 hdr.SetSequenceNumber (1);
1466 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
1467 psdus.insert (std::make_pair (staId, psdu));
1468
1469 Time ppduDuration = m_phy->CalculateTxDuration (psdu->GetSize (), txVector, m_phy->GetPhyBand (), staId);
1470 Ptr<HePpdu> ppdu = Create<HePpdu> (psdus, txVector, ppduDuration, WIFI_PHY_BAND_5GHZ, uid,
1471 HePpdu::PSD_HE_TB_NON_OFDMA_PORTION, 0);
1472
1473 //Send non-OFDMA part
1474 Time nonOfdmaDuration = m_phy->GetHePhy ()->CalculateNonOfdmaDurationForHeTb (txVector);
1475 uint32_t centerFrequency = m_phy->GetHePhy ()->GetCenterFrequencyForNonOfdmaPart (txVector, staId);
1476 uint16_t ruWidth = HeRu::GetBandwidth (txVector.GetRu (staId).GetRuType ());
1477 uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
1478 Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity (centerFrequency, channelWidth, txPowerWatts, m_phy->GetGuardBandwidth (channelWidth));
1479 Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters> ();
1480 rxParams->psd = rxPsd;
1481 rxParams->txPhy = 0;
1482 rxParams->duration = nonOfdmaDuration;
1483 rxParams->ppdu = ppdu;
1484
1485 uint16_t length;
1486 std::tie (length, ppduDuration) = HePhy::ConvertHeTbPpduDurationToLSigLength (ppduDuration, txVector, m_phy->GetPhyBand ());
1487 txVector.SetLength (length);
1488 m_trigVector.SetLength (length);
1489 auto hePhy = DynamicCast<HePhy> (m_phy->GetPhyEntity (WIFI_MOD_CLASS_HE));
1490 hePhy->SetTrigVector (m_trigVector, ppduDuration);
1491 m_phy->StartRx (rxParams);
1492
1493 //Schedule OFDMA part
1494 Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu> (ppdu->Copy ()); //since flag will be modified
1495 ppduOfdma->SetTxPsdFlag (HePpdu::PSD_HE_TB_OFDMA_PORTION);
1496 WifiSpectrumBand band = m_phy->GetHePhy ()->GetRuBandForRx (txVector, staId);
1497 Ptr<SpectrumValue> rxPsdOfdma = WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity (DEFAULT_FREQUENCY, DEFAULT_CHANNEL_WIDTH, txPowerWatts, DEFAULT_GUARD_WIDTH, band);
1498 Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters> ();
1499 rxParamsOfdma->psd = rxPsd;
1500 rxParamsOfdma->txPhy = 0;
1501 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
1502 rxParamsOfdma->ppdu = ppduOfdma;
1503 Simulator::Schedule (nonOfdmaDuration, &TestMultipleHeTbPreambles::RxHeTbPpduOfdmaPart, this, rxParamsOfdma);
1504}
1505
1506void
1508{
1509 Simulator::ScheduleNow (&TestMultipleHeTbPreambles::DoRxHeTbPpduOfdmaPart, this, rxParamsOfdma);
1510}
1511
1512void
1514{
1515 //This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should end at the exact same time as the start
1516 //For normal WifiNetDevices, this the reception of the OFDMA part is scheduled after end of HE-SIG-A decoding.
1517 m_phy->StartRx (rxParamsOfdma);
1518}
1519
1520void
1522{
1523 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice> ();
1524 m_phy = CreateObject<OfdmaSpectrumWifiPhy> (0);
1526 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
1527 Ptr<ApWifiMac> mac = CreateObject<ApWifiMac> ();
1528 mac->SetAttribute ("BeaconGeneration", BooleanValue (false));
1529 dev->SetMac (mac);
1530 m_phy->SetErrorRateModel (error);
1532 (int)(WIFI_PHY_BAND_5GHZ), 0});
1534 m_phy->SetDevice (dev);
1535 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel> ();
1536 preambleDetectionModel->SetAttribute ("Threshold", DoubleValue (4));
1537 preambleDetectionModel->SetAttribute ("MinimumRssi", DoubleValue (-82));
1538 m_phy->SetPreambleDetectionModel (preambleDetectionModel);
1539}
1540
1541void
1543{
1544 m_phy->Dispose ();
1545 m_phy = 0;
1546}
1547
1548void
1550{
1551 RngSeedManager::SetSeed (1);
1552 RngSeedManager::SetRun (1);
1553 int64_t streamNumber = 0;
1554 m_phy->AssignStreams (streamNumber);
1555
1556 double txPowerWatts = 0.01;
1557
1558 {
1559 //Verify a single UL MU transmission with two stations belonging to the same BSS
1560 std::vector<uint64_t> uids {0};
1561 Simulator::Schedule (Seconds (1), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1562 Simulator::Schedule (Seconds (1) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1563 //Check that we received a single UL MU transmission with the corresponding UID
1564 Simulator::Schedule (Seconds (1.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, uids);
1565 Simulator::Schedule (Seconds (1.5), &TestMultipleHeTbPreambles::Reset, this);
1566 }
1567
1568 {
1569 //Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where the second transmission
1570 //arrives during the preamble detection window and with half the power of the first transmission.
1571 std::vector<uint64_t> uids {1, 2};
1572 Simulator::Schedule (Seconds (2), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1573 Simulator::Schedule (Seconds (2) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1574 Simulator::Schedule (Seconds (2) + NanoSeconds (200), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts / 2, 1003);
1575 Simulator::Schedule (Seconds (2) + NanoSeconds (300), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts / 2, 1004);
1576 //Check that we received the correct reception of 2 UL MU transmissions with the corresponding UIDs
1577 Simulator::Schedule (Seconds (2.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 2, uids);
1578 Simulator::Schedule (Seconds (2.5), &TestMultipleHeTbPreambles::Reset, this);
1579 //TODO: verify PPDUs from second UL MU transmission are dropped
1580 }
1581
1582 {
1583 //Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where the second transmission
1584 //arrives during the preamble detection window and with twice the power of the first transmission.
1585 std::vector<uint64_t> uids {3, 4};
1586 Simulator::Schedule (Seconds (3), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts / 2, 1001);
1587 Simulator::Schedule (Seconds (3) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts / 2, 1002);
1588 Simulator::Schedule (Seconds (3) + NanoSeconds (200), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts, 1003);
1589 Simulator::Schedule (Seconds (3) + NanoSeconds (300), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts, 1004);
1590 //Check that we received the correct reception of 2 UL MU transmissions with the corresponding UIDs
1591 Simulator::Schedule (Seconds (3.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 2, uids);
1592 Simulator::Schedule (Seconds (3.5), &TestMultipleHeTbPreambles::Reset, this);
1593 //TODO: verify PPDUs from first UL MU transmission are dropped
1594 }
1595
1596 {
1597 //Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where the second transmission
1598 //arrives during PHY header reception and with the same power as the first transmission.
1599 std::vector<uint64_t> uids {5, 6};
1600 Simulator::Schedule (Seconds (4), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1601 Simulator::Schedule (Seconds (4) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1602 Simulator::Schedule (Seconds (4) + MicroSeconds (5), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts, 1003);
1603 Simulator::Schedule (Seconds (4) + MicroSeconds (5) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts, 1004);
1604 //Check that we received the correct reception of the first UL MU transmission with the corresponding UID (second one dropped)
1605 Simulator::Schedule (Seconds (4.0) + MicroSeconds (10), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, std::vector<uint64_t> {uids[0]});
1606 //The packets of the second UL MU transmission should have been dropped
1607 Simulator::Schedule (Seconds (4.0) + MicroSeconds (10), &TestMultipleHeTbPreambles::CheckBytesDropped, this, 1003 + 1004);
1608 Simulator::Schedule (Seconds (4.5), &TestMultipleHeTbPreambles::Reset, this);
1609 }
1610
1611 {
1612 //Verify the correct reception of one UL MU transmission out of 2 with two stations per BSS, where the second transmission
1613 //arrives during payload reception and with the same power as the first transmission.
1614 std::vector<uint64_t> uids {7, 8};
1615 Simulator::Schedule (Seconds (5), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1616 Simulator::Schedule (Seconds (5) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1617 Simulator::Schedule (Seconds (5) + MicroSeconds (50), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 1, txPowerWatts, 1003);
1618 Simulator::Schedule (Seconds (5) + MicroSeconds (50) + NanoSeconds (100), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[1], 2, txPowerWatts, 1004);
1619 //Check that we received the correct reception of the first UL MU transmission with the corresponding UID (second one dropped)
1620 Simulator::Schedule (Seconds (5.0) + MicroSeconds (100), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, std::vector<uint64_t> {uids[0]});
1621 //The packets of the second UL MU transmission should have been dropped
1622 Simulator::Schedule (Seconds (5.0) + MicroSeconds (100), &TestMultipleHeTbPreambles::CheckBytesDropped, this, 1003 + 1004);
1623 Simulator::Schedule (Seconds (5.5), &TestMultipleHeTbPreambles::Reset, this);
1624 }
1625
1626 {
1627 //Verify the correct reception of a single UL MU transmission with two stations belonging to the same BSS,
1628 //and the second PPDU arrives 500ns after the first PPDU
1629 std::vector<uint64_t> uids {9};
1630 Simulator::Schedule (Seconds (6), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 1, txPowerWatts, 1001);
1631 Simulator::Schedule (Seconds (6) + NanoSeconds (500), &TestMultipleHeTbPreambles::RxHeTbPpdu, this, uids[0], 2, txPowerWatts, 1002);
1632 //Check that we received a single UL MU transmission with the corresponding UID
1633 Simulator::Schedule (Seconds (6.0) + MicroSeconds (1), &TestMultipleHeTbPreambles::CheckHeTbPreambles, this, 1, uids);
1634 //No packet is dropped (we check after 5us to verify that PD is successful)
1635 Simulator::Schedule (Seconds (6.0) + MicroSeconds (5), &TestMultipleHeTbPreambles::CheckBytesDropped, this, 0);
1636 Simulator::Schedule (Seconds (6.5), &TestMultipleHeTbPreambles::Reset, this);
1637 }
1638
1639 Simulator::Run ();
1640 Simulator::Destroy ();
1641}
1642
1650{
1651public:
1656 {
1657 NONE = 0,
1662 MCS
1664
1666 virtual ~TestUlOfdmaPhyTransmission ();
1667
1668private:
1669 void DoSetup (void) override;
1670 void DoTeardown (void) override;
1671 void DoRun (void) override;
1672
1680 WifiTxVector GetTxVectorForHeTbPpdu (uint16_t txStaId, std::size_t index, uint8_t bssColor) const;
1687 void SetTrigVector (uint8_t bssColor, TrigVectorInfo error);
1696 void SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
1697
1705 void SendHeSuPpdu (uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
1706
1712 void SetBssColor (Ptr<WifiPhy> phy, uint8_t bssColor);
1713
1719 void SetPsdLimit (Ptr<WifiPhy> phy, double psdLimit);
1720
1726 void GenerateInterference (Ptr<SpectrumValue> interferencePsd, Time duration);
1730 void StopInterference (void);
1731
1735 void RunOne ();
1736
1743 void CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
1744
1751 void CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
1752
1759 void CheckNonOfdmaRxPower (Ptr<OfdmaSpectrumWifiPhy> phy, WifiSpectrumBand band, double expectedRxPower);
1766 void CheckOfdmaRxPower (Ptr<OfdmaSpectrumWifiPhy> phy, WifiSpectrumBand band, double expectedRxPower);
1767
1771 void VerifyEventsCleared (void);
1772
1781
1785 void Reset ();
1786
1794 void RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> statusPerMpdu);
1795
1800 void RxFailure (Ptr<WifiPsdu> psdu);
1801
1819 void ScheduleTest (Time delay, bool solicited, WifiPhyState expectedStateAtEnd,
1820 uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1,
1821 uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2,
1822 bool scheduleTxSta1 = true, WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
1823 TrigVectorInfo error = NONE);
1824
1834 void SchedulePowerMeasurementChecks (Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2,
1835 double rxPowerOfdmaRu1, double rxPowerOfdmaRu2);
1841 void LogScenario (std::string log) const;
1842
1847
1849
1856
1857 uint16_t m_frequency;
1860};
1861
1863 : TestCase ("UL-OFDMA PHY test"),
1864 m_countRxSuccessFromSta1 (0),
1865 m_countRxSuccessFromSta2 (0),
1866 m_countRxFailureFromSta1 (0),
1867 m_countRxFailureFromSta2 (0),
1868 m_countRxBytesFromSta1 (0),
1869 m_countRxBytesFromSta2 (0),
1870 m_frequency (DEFAULT_FREQUENCY),
1871 m_channelWidth (DEFAULT_CHANNEL_WIDTH),
1872 m_expectedPpduDuration (NanoSeconds (271200))
1873{
1874}
1875
1876void
1877TestUlOfdmaPhyTransmission::SendHeSuPpdu (uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
1878{
1879 NS_LOG_FUNCTION (this << txStaId << payloadSize << uid << +bssColor);
1880 WifiConstPsduMap psdus;
1881
1882 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, m_channelWidth, false, false, false, bssColor);
1883
1884 Ptr<Packet> pkt = Create<Packet> (payloadSize);
1885 WifiMacHeader hdr;
1887 hdr.SetQosTid (0);
1888 hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
1889 std::ostringstream addr;
1890 addr << "00:00:00:00:00:0" << txStaId;
1891 hdr.SetAddr2 (Mac48Address (addr.str ().c_str ()));
1892 hdr.SetSequenceNumber (1);
1893 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
1894 psdus.insert (std::make_pair (SU_STA_ID, psdu));
1895
1897 if (txStaId == 1)
1898 {
1899 phy = m_phySta1;
1900 }
1901 else if (txStaId == 2)
1902 {
1903 phy = m_phySta2;
1904 }
1905 else if (txStaId == 3)
1906 {
1907 phy = m_phySta3;
1908 }
1909 else if (txStaId == 0)
1910 {
1911 phy = m_phyAp;
1912 }
1913 phy->SetPpduUid (uid);
1914 phy->Send (psdus, txVector);
1915}
1916
1918TestUlOfdmaPhyTransmission::GetTxVectorForHeTbPpdu (uint16_t txStaId, std::size_t index, uint8_t bssColor) const
1919{
1920 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, m_channelWidth, false, false, false, bssColor);
1921
1922 HeRu::RuType ruType = HeRu::RU_106_TONE;
1923 if (m_channelWidth == 20)
1924 {
1925 ruType = HeRu::RU_106_TONE;
1926 }
1927 else if (m_channelWidth == 40)
1928 {
1929 ruType = HeRu::RU_242_TONE;
1930 }
1931 else if (m_channelWidth == 80)
1932 {
1933 ruType = HeRu::RU_484_TONE;
1934 }
1935 else if (m_channelWidth == 160)
1936 {
1937 ruType = HeRu::RU_996_TONE;
1938 }
1939 else
1940 {
1941 NS_ASSERT_MSG (false, "Unsupported channel width");
1942 }
1943
1944 bool primary80MHz = true;
1945 if (m_channelWidth == 160 && index == 2)
1946 {
1947 primary80MHz = false;
1948 index = 1;
1949 }
1950 HeRu::RuSpec ru (ruType, index, primary80MHz);
1952 txVector.SetRu (ru, txStaId);
1953 txVector.SetMode (HePhy::GetHeMcs7 (), txStaId);
1954 txVector.SetNss (1, txStaId);
1955 return txVector;
1956}
1957
1958void
1960{
1961 uint16_t channelWidth = m_channelWidth;
1962 if (error == CHANNEL_WIDTH)
1963 {
1964 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
1965 }
1966
1967 WifiTxVector txVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0,
1968 channelWidth, false, false, false, bssColor);
1969
1970 HeRu::RuType ruType = HeRu::RU_106_TONE;
1971 if (channelWidth == 20)
1972 {
1973 ruType = (error == RU_TYPE ? HeRu::RU_52_TONE : HeRu::RU_106_TONE);
1974 }
1975 else if (channelWidth == 40)
1976 {
1977 ruType = (error == RU_TYPE ? HeRu::RU_106_TONE : HeRu::RU_242_TONE);
1978 }
1979 else if (channelWidth == 80)
1980 {
1981 ruType = (error == RU_TYPE ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1982 }
1983 else if (channelWidth == 160)
1984 {
1985 ruType = (error == RU_TYPE ? HeRu::RU_484_TONE : HeRu::RU_996_TONE);
1986 }
1987 else
1988 {
1989 NS_ASSERT_MSG (false, "Unsupported channel width");
1990 }
1991
1992 uint16_t aid1 = (error == AID ? 3 : 1);
1993 uint16_t aid2 = (error == AID ? 4 : 2);
1994
1995 HeRu::RuSpec ru1 (ruType, 1, true);
1996 ru1.SetPhyIndex (channelWidth, 0);
1997 txVector.SetRu (ru1, aid1);
1998 txVector.SetMode ((error == MCS ? HePhy::GetHeMcs5 () : HePhy::GetHeMcs7 ()), aid1);
1999 txVector.SetNss (1, aid1);
2000
2001 HeRu::RuSpec ru2 (ruType, (channelWidth == 160 ? 1 : 2),
2002 (channelWidth == 160 ? false : true));
2003 ru2.SetPhyIndex (channelWidth, 0);
2004 txVector.SetRu (ru2, aid2);
2005 txVector.SetMode ((error == MCS ? HePhy::GetHeMcs5 () : HePhy::GetHeMcs7 ()), aid2);
2006 txVector.SetNss (1, aid2);
2007
2008 uint16_t length;
2009 std::tie (length, m_expectedPpduDuration) = HePhy::ConvertHeTbPpduDurationToLSigLength (m_expectedPpduDuration,
2010 txVector,
2011 m_phyAp->GetPhyBand ());
2012 if (error == UL_LENGTH)
2013 {
2014 ++length;
2015 }
2016 txVector.SetLength (length);
2017 auto hePhyAp = DynamicCast<HePhy> (m_phyAp->GetPhyEntity (WIFI_MOD_CLASS_HE));
2018 hePhyAp->SetTrigVector (txVector, m_expectedPpduDuration);
2019}
2020
2021void
2022TestUlOfdmaPhyTransmission::SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
2023{
2024 NS_LOG_FUNCTION (this << txStaId << index << payloadSize << uid << +bssColor);
2025 WifiConstPsduMap psdus;
2026
2027 WifiTxVector txVector = GetTxVectorForHeTbPpdu (txStaId, index, bssColor);
2028 Ptr<Packet> pkt = Create<Packet> (payloadSize);
2029 WifiMacHeader hdr;
2031 hdr.SetQosTid (0);
2032 hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
2033 std::ostringstream addr;
2034 addr << "00:00:00:00:00:0" << txStaId;
2035 hdr.SetAddr2 (Mac48Address (addr.str ().c_str ()));
2036 hdr.SetSequenceNumber (1);
2037 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
2038 psdus.insert (std::make_pair (txStaId, psdu));
2039
2041 if (txStaId == 1)
2042 {
2043 phy = m_phySta1;
2044 }
2045 else if (txStaId == 2)
2046 {
2047 phy = m_phySta2;
2048 }
2049 else if (txStaId == 3)
2050 {
2051 phy = m_phySta3;
2052 }
2053
2054 Time txDuration = phy->CalculateTxDuration (psdu->GetSize (), txVector, phy->GetPhyBand (), txStaId);
2055 txVector.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector, phy->GetPhyBand ()).first);
2056
2057 phy->SetPpduUid (uid);
2058 phy->Send (psdus, txVector);
2059}
2060
2061void
2063{
2064 NS_LOG_FUNCTION (this << duration);
2065 m_phyInterferer->SetTxPowerSpectralDensity (interferencePsd);
2066 m_phyInterferer->SetPeriod (duration);
2068 Simulator::Schedule (duration, &TestUlOfdmaPhyTransmission::StopInterference, this);
2069}
2070
2071void
2073{
2075}
2076
2078{
2079}
2080
2081void
2082TestUlOfdmaPhyTransmission::RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
2083{
2084 NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 () << rxSignalInfo << txVector);
2085 if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
2086 {
2088 m_countRxBytesFromSta1 += (psdu->GetSize () - 30);
2089 }
2090 else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
2091 {
2093 m_countRxBytesFromSta2 += (psdu->GetSize () - 30);
2094 }
2095}
2096
2097void
2099{
2100 NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 ());
2101 if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
2102 {
2104 }
2105 else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
2106 {
2108 }
2109}
2110
2111void
2112TestUlOfdmaPhyTransmission::CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
2113{
2114 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta1, expectedSuccess, "The number of successfully received packets from STA 1 is not correct!");
2115 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta1, expectedFailures, "The number of unsuccessfully received packets from STA 1 is not correct!");
2116 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta1, expectedBytes, "The number of bytes received from STA 1 is not correct!");
2117}
2118
2119void
2120TestUlOfdmaPhyTransmission::CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
2121{
2122 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta2, expectedSuccess, "The number of successfully received packets from STA 2 is not correct!");
2123 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta2, expectedFailures, "The number of unsuccessfully received packets from STA 2 is not correct!");
2124 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta2, expectedBytes, "The number of bytes received from STA 2 is not correct!");
2125}
2126
2127void
2129{
2130 Ptr<Event> event = phy->GetCurrentEvent ();
2131 NS_ASSERT (event);
2132 double rxPower = event->GetRxPowerW (band);
2133 NS_LOG_FUNCTION (this << band.first << band.second << expectedRxPower << rxPower);
2134 //Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
2135 NS_TEST_ASSERT_MSG_EQ_TOL (rxPower, expectedRxPower, 5e-3, "RX power " << rxPower << " over (" << band.first << ", " << band.second << ") does not match expected power " << expectedRxPower << " at " << Simulator::Now ());
2136}
2137
2138void
2140{
2146 NS_LOG_FUNCTION (this << band.first << band.second << expectedRxPower);
2147 double step = 5e-3;
2148 if (expectedRxPower > 0.0)
2149 {
2150 NS_TEST_ASSERT_MSG_EQ (phy->GetEnergyDuration (expectedRxPower - step, band).IsStrictlyPositive (), true,
2151 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band.first << ", " << band.second << ") at " << Simulator::Now ());
2152 NS_TEST_ASSERT_MSG_EQ (phy->GetEnergyDuration (expectedRxPower + step, band).IsStrictlyPositive (), false,
2153 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first << ", " << band.second << ") at " << Simulator::Now ());
2154 }
2155 else
2156 {
2157 NS_TEST_ASSERT_MSG_EQ (phy->GetEnergyDuration (expectedRxPower + step, band).IsStrictlyPositive (), false,
2158 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first << ", " << band.second << ") at " << Simulator::Now ());
2159 }
2160}
2161
2162void
2164{
2165 NS_TEST_ASSERT_MSG_EQ (m_phyAp->GetCurrentEvent (), 0, "m_currentEvent for AP was not cleared");
2166 NS_TEST_ASSERT_MSG_EQ (m_phySta1->GetCurrentEvent (), 0, "m_currentEvent for STA 1 was not cleared");
2167 NS_TEST_ASSERT_MSG_EQ (m_phySta2->GetCurrentEvent (), 0, "m_currentEvent for STA 2 was not cleared");
2168}
2169
2170void
2172{
2173 //This is needed to make sure PHY state will be checked as the last event if a state change occurred at the exact same time as the check
2174 Simulator::ScheduleNow (&TestUlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
2175}
2176
2177void
2179{
2180 WifiPhyState currentState;
2181 PointerValue ptr;
2182 phy->GetAttribute ("State", ptr);
2183 Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
2184 currentState = state->GetState ();
2185 NS_LOG_FUNCTION (this << currentState);
2186 NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
2187}
2188
2189void
2191{
2198 m_phySta1->SetPpduUid (0);
2201 SetBssColor (m_phyAp, 0);
2202}
2203
2204void
2206{
2207 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (phy->GetDevice ());
2208 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration ();
2209 heConfiguration->SetAttribute ("BssColor", UintegerValue (bssColor));
2210}
2211
2212void
2214{
2215 NS_LOG_FUNCTION (this << phy << psdLimit);
2216 phy->SetAttribute ("PowerDensityLimit", DoubleValue (psdLimit));
2217}
2218
2219void
2221{
2222 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
2223 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
2224 lossModel->SetFrequency (m_frequency);
2225 spectrumChannel->AddPropagationLossModel (lossModel);
2226 Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
2227 spectrumChannel->SetPropagationDelayModel (delayModel);
2228
2229 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel = CreateObject<ThresholdPreambleDetectionModel> ();
2230 preambleDetectionModel->SetAttribute ("MinimumRssi", DoubleValue (-8)); //to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
2231 preambleDetectionModel->SetAttribute ("Threshold", DoubleValue (-100)); //no limit on SNR
2232
2233 Ptr<Node> apNode = CreateObject<Node> ();
2234 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
2236 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac> ();
2237 apMac->SetAttribute ("BeaconGeneration", BooleanValue (false));
2238 apDev->SetMac (apMac);
2239 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy> (0);
2242 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration> ();
2243 apDev->SetHeConfiguration (heConfiguration);
2244 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
2245 m_phyAp->SetErrorRateModel (error);
2246 m_phyAp->SetDevice (apDev);
2247 m_phyAp->SetChannel (spectrumChannel);
2250 m_phyAp->SetPreambleDetectionModel (preambleDetectionModel);
2251 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
2252 m_phyAp->SetMobility (apMobility);
2253 apDev->SetPhy (m_phyAp);
2254 apNode->AggregateObject (apMobility);
2255 apNode->AddDevice (apDev);
2256
2257 Ptr<Node> sta1Node = CreateObject<Node> ();
2258 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
2259 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
2263 m_phySta1->SetDevice (sta1Dev);
2264 m_phySta1->SetChannel (spectrumChannel);
2265 m_phySta1->SetPreambleDetectionModel (preambleDetectionModel);
2266 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
2267 m_phySta1->SetMobility (sta1Mobility);
2268 sta1Dev->SetPhy (m_phySta1);
2269 sta1Node->AggregateObject (sta1Mobility);
2270 sta1Node->AddDevice (sta1Dev);
2271
2272 Ptr<Node> sta2Node = CreateObject<Node> ();
2273 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
2274 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
2278 m_phySta2->SetDevice (sta2Dev);
2279 m_phySta2->SetChannel (spectrumChannel);
2280 m_phySta2->SetPreambleDetectionModel (preambleDetectionModel);
2281 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
2282 m_phySta2->SetMobility (sta2Mobility);
2283 sta2Dev->SetPhy (m_phySta2);
2284 sta2Node->AggregateObject (sta2Mobility);
2285 sta2Node->AddDevice (sta2Dev);
2286
2287 Ptr<Node> sta3Node = CreateObject<Node> ();
2288 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice> ();
2289 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy> (3);
2293 m_phySta3->SetDevice (sta3Dev);
2294 m_phySta3->SetChannel (spectrumChannel);
2295 m_phySta3->SetPreambleDetectionModel (preambleDetectionModel);
2296 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel> ();
2297 m_phySta3->SetMobility (sta3Mobility);
2298 sta3Dev->SetPhy (m_phySta3);
2299 sta3Node->AggregateObject (sta3Mobility);
2300 sta3Node->AddDevice (sta3Dev);
2301
2302 Ptr<Node> interfererNode = CreateObject<Node> ();
2303 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice> ();
2304 m_phyInterferer = CreateObject<WaveformGenerator> ();
2305 m_phyInterferer->SetDevice (interfererDev);
2306 m_phyInterferer->SetChannel (spectrumChannel);
2308 interfererNode->AddDevice (interfererDev);
2309
2310 //Configure power attributes of all wifi devices
2311 std::list<Ptr<WifiPhy>> phys {m_phyAp, m_phySta1, m_phySta2, m_phySta3};
2312 for (auto & phy : phys)
2313 {
2314 phy->SetAttribute ("TxGain", DoubleValue (1.0));
2315 phy->SetAttribute ("TxPowerStart", DoubleValue (16.0));
2316 phy->SetAttribute ("TxPowerEnd", DoubleValue (16.0));
2317 phy->SetAttribute ("PowerDensityLimit", DoubleValue (100.0)); //no impact by default
2318 phy->SetAttribute ("RxGain", DoubleValue (2.0));
2319 }
2320}
2321
2322void
2324{
2325 m_phyAp->Dispose ();
2326 m_phyAp = 0;
2327 m_phySta1->Dispose ();
2328 m_phySta1 = 0;
2329 m_phySta2->Dispose ();
2330 m_phySta2 = 0;
2331 m_phySta3->Dispose ();
2332 m_phySta3 = 0;
2334 m_phyInterferer = 0;
2335}
2336
2337void
2339{
2340 NS_LOG_INFO (log);
2341}
2342
2343void
2344TestUlOfdmaPhyTransmission::ScheduleTest (Time delay, bool solicited, WifiPhyState expectedStateAtEnd,
2345 uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1,
2346 uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2,
2347 bool scheduleTxSta1, WifiPhyState expectedStateBeforeEnd,
2348 TrigVectorInfo error)
2349{
2350 static uint64_t uid = 0;
2351
2352 //AP sends an SU packet preceding HE TB PPDUs
2353 Simulator::Schedule (delay - MilliSeconds (10), &TestUlOfdmaPhyTransmission::SendHeSuPpdu, this, 0, 50, ++uid, 0);
2354 if (!solicited)
2355 {
2356 // UID of TB PPDUs will be different than the one of the preceding frame
2357 ++uid;
2358 }
2359 else
2360 {
2361 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SetTrigVector, this, 0, error);
2362 }
2363 //STA1 and STA2 send MU UL PPDUs addressed to AP
2364 if (scheduleTxSta1)
2365 {
2366 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 1, 1, 1000, uid, 0);
2367 }
2368 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 2, 2, 1001, uid, 0);
2369
2370 //Verify it takes m_expectedPpduDuration to transmit the PPDUs
2371 Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), &TestUlOfdmaPhyTransmission::CheckPhyState, this, m_phyAp, expectedStateBeforeEnd);
2372 Simulator::Schedule (delay + m_expectedPpduDuration, &TestUlOfdmaPhyTransmission::CheckPhyState, this, m_phyAp, expectedStateAtEnd);
2373 //TODO: add checks on TX stop for STAs
2374
2375 delay += MilliSeconds (100);
2376 //Check reception state from STA 1
2377 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::CheckRxFromSta1, this,
2378 expectedSuccessFromSta1, expectedFailuresFromSta1, expectedBytesFromSta1);
2379 //Check reception state from STA 2
2380 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::CheckRxFromSta2, this,
2381 expectedSuccessFromSta2, expectedFailuresFromSta2, expectedBytesFromSta2);
2382 //Verify events data have been cleared
2383 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
2384
2385 delay += MilliSeconds (100);
2386 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::Reset, this);
2387}
2388
2389void
2390TestUlOfdmaPhyTransmission::SchedulePowerMeasurementChecks (Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2,
2391 double rxPowerOfdmaRu1, double rxPowerOfdmaRu2)
2392{
2393 Time detectionDuration = WifiPhy::GetPreambleDetectionDuration ();
2394 WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu (1, 1, 0);
2395 WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu (2, 2, 0);
2396 Ptr<const HePhy> hePhy = m_phyAp->GetHePhy ();
2397 Time nonOfdmaDuration = hePhy->CalculateNonOfdmaDurationForHeTb (txVectorSta2);
2398 NS_ASSERT (nonOfdmaDuration == hePhy->CalculateNonOfdmaDurationForHeTb (txVectorSta1));
2399
2400 std::vector<double> rxPowerNonOfdma { rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2 };
2401 std::vector<WifiSpectrumBand> nonOfdmaBand { hePhy->GetNonOfdmaBand (txVectorSta1, 1), hePhy->GetNonOfdmaBand (txVectorSta2, 2) };
2402 std::vector<double> rxPowerOfdma { rxPowerOfdmaRu1, rxPowerOfdmaRu2 };
2403 std::vector<WifiSpectrumBand> ofdmaBand { hePhy->GetRuBandForRx (txVectorSta1, 1), hePhy->GetRuBandForRx (txVectorSta2, 2) };
2404
2405 for (uint8_t i = 0; i < 2; ++i)
2406 {
2410 //Check received power on non-OFDMA portion
2411 Simulator::Schedule (delay + detectionDuration + NanoSeconds (1), //just after beginning of portion (once event is stored)
2413 nonOfdmaBand[i], rxPowerNonOfdma[i]);
2414 Simulator::Schedule (delay + nonOfdmaDuration - NanoSeconds (1), //just before end of portion
2416 nonOfdmaBand[i], rxPowerNonOfdma[i]);
2417 //Check received power on OFDMA portion
2418 Simulator::Schedule (delay + nonOfdmaDuration + NanoSeconds (1), //just after beginning of portion
2420 ofdmaBand[i], rxPowerOfdma[i]);
2421 Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), //just before end of portion
2423 ofdmaBand[i], rxPowerOfdma[i]);
2424
2430 //Check received power on non-OFDMA portion
2431 Simulator::Schedule (delay + detectionDuration + NanoSeconds (1), //just after beginning of portion (once event is stored)
2433 nonOfdmaBand[i], rxPowerNonOfdma[i]);
2434 Simulator::Schedule (delay + nonOfdmaDuration - NanoSeconds (1), //just before end of portion
2436 nonOfdmaBand[i], rxPowerNonOfdma[i]);
2437 //Check received power on OFDMA portion
2438 Simulator::Schedule (delay + nonOfdmaDuration + NanoSeconds (1), //just after beginning of portion
2440 ofdmaBand[i], rxPowerOfdma[i]);
2441 Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), //just before end of portion
2443 ofdmaBand[i], rxPowerOfdma[i]);
2444 }
2445
2446 if (rxPowerOfdmaRu1 != 0.0)
2447 {
2453 double rxPowerNonOfdmaSta1Only = (m_channelWidth >= 40) ? rxPowerNonOfdma[0] : rxPowerNonOfdma[0] / 2; //both STAs transmit over the same 20 MHz channel
2454 //Check received power on non-OFDMA portion
2455 Simulator::Schedule (delay + detectionDuration + NanoSeconds (1), //just after beginning of portion (once event is stored)
2457 nonOfdmaBand[0], rxPowerNonOfdmaSta1Only);
2458 Simulator::Schedule (delay + nonOfdmaDuration - NanoSeconds (1), //just before end of portion
2460 nonOfdmaBand[0], rxPowerNonOfdmaSta1Only);
2461 //Check received power on OFDMA portion
2462 Simulator::Schedule (delay + nonOfdmaDuration + NanoSeconds (1), //just after beginning of portion
2464 ofdmaBand[0], rxPowerOfdma[0]);
2465 Simulator::Schedule (delay + m_expectedPpduDuration - NanoSeconds (1), //just before end of portion
2467 ofdmaBand[0], rxPowerOfdma[0]);
2468 }
2469}
2470
2471void
2473{
2474 RngSeedManager::SetSeed (1);
2475 RngSeedManager::SetRun (1);
2476 int64_t streamNumber = 0;
2477 m_phyAp->AssignStreams (streamNumber);
2478 m_phySta1->AssignStreams (streamNumber);
2479 m_phySta2->AssignStreams (streamNumber);
2480 m_phySta3->AssignStreams (streamNumber);
2481
2482 auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, m_frequency, m_channelWidth,
2485
2487 (int)(WIFI_PHY_BAND_5GHZ), 0});
2489 (int)(WIFI_PHY_BAND_5GHZ), 0});
2491 (int)(WIFI_PHY_BAND_5GHZ), 0});
2493 (int)(WIFI_PHY_BAND_5GHZ), 0});
2494
2495 Time delay = Seconds (0.0);
2496 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::Reset, this);
2497 delay += Seconds (1.0);
2498
2507 //---------------------------------------------------------------------------
2508 //Verify that both solicited HE TB PPDUs have been corrected received
2509 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2510 "Reception of solicited HE TB PPDUs");
2511 ScheduleTest (delay, true,
2513 1, 0, 1000, //One PSDU of 1000 bytes should have been successfully received from STA 1
2514 1, 0, 1001); //One PSDU of 1001 bytes should have been successfully received from STA 2
2515 delay += Seconds (1.0);
2516
2517 //---------------------------------------------------------------------------
2518 //Verify that no unsolicited HE TB PPDU is received
2519 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2520 "Dropping of unsolicited HE TB PPDUs");
2521 ScheduleTest (delay, false,
2523 0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2524 0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2526 delay += Seconds (1.0);
2527
2528 //---------------------------------------------------------------------------
2529 //Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
2530 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2531 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
2532 ScheduleTest (delay, true,
2534 0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2535 0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2537 delay += Seconds (1.0);
2538
2539 //---------------------------------------------------------------------------
2540 //Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
2541 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2542 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
2543 ScheduleTest (delay, true,
2545 0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2546 0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2548 delay += Seconds (1.0);
2549
2550 //---------------------------------------------------------------------------
2551 //Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
2552 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2553 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
2554 ScheduleTest (delay, true,
2556 0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2557 0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2559 delay += Seconds (1.0);
2560
2561 //---------------------------------------------------------------------------
2562 //Verify that HE TB PPDUs with RU type differing from TRIGVECTOR are discarded
2563 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2564 "Dropping of HE TB PPDUs with RU type differing from TRIGVECTOR");
2565 ScheduleTest (delay, true,
2567 0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2568 0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2570 delay += Seconds (1.0);
2571
2572 //---------------------------------------------------------------------------
2573 //Verify that HE TB PPDUs with MCS differing from TRIGVECTOR are discarded
2574 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2575 "Dropping of HE TB PPDUs with MCS differing from TRIGVECTOR");
2576 ScheduleTest (delay, true,
2578 0, 0, 0, //PSDU from STA 1 is not received (no TRIGVECTOR)
2579 0, 0, 0, //PSDU from STA 2 is not received (no TRIGVECTOR)
2581 delay += Seconds (1.0);
2582
2583 //---------------------------------------------------------------------------
2584 //Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been impacted
2585 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2586 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
2587 //A strong non-wifi interference is generated on RU 1 during PSDU reception
2588 BandInfo bandInfo;
2589 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
2590 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
2591 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
2592 Bands bands;
2593 bands.push_back (bandInfo);
2594
2595 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel> (bands);
2596 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue> (SpectrumInterferenceRu1);
2597 double interferencePower = 0.1; //watts
2598 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
2599
2600 Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu1, MilliSeconds (100));
2601 ScheduleTest (delay, true,
2602 WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference
2603 0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
2604 1, 0, 1001); //One PSDU of 1001 bytes should have been successfully received from STA 2
2605 delay += Seconds (1.0);
2606
2607 //---------------------------------------------------------------------------
2608 //Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been impacted
2609 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2610 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
2611 //A strong non-wifi interference is generated on RU 2 during PSDU reception
2612 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
2613 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
2614 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
2615 bands.clear ();
2616 bands.push_back (bandInfo);
2617
2618 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel> (bands);
2619 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue> (SpectrumInterferenceRu2);
2620 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
2621
2622 Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdRu2, MilliSeconds (100));
2623 ScheduleTest (delay, true,
2624 WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY since measurement channel encompasses total channel width
2625 1, 0, 1000, //One PSDU of 1000 bytes should have been successfully received from STA 1
2626 0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference occupies RU 2)
2627 delay += Seconds (1.0);
2628
2629 //---------------------------------------------------------------------------
2630 //Generate an interference on the full band and verify that both solicited HE TB PPDUs have been impacted
2631 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2632 "Reception of solicited HE TB PPDUs with interference on the full band during PSDU reception");
2633 //A strong non-wifi interference is generated on the full band during PSDU reception
2634 bandInfo.fc = m_frequency * 1e6;
2635 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
2636 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
2637 bands.clear ();
2638 bands.push_back (bandInfo);
2639
2640 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel> (bands);
2641 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue> (SpectrumInterferenceAll);
2642 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
2643
2644 Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::GenerateInterference, this, interferencePsdAll, MilliSeconds (100));
2645 ScheduleTest (delay, true,
2646 WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference
2647 0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
2648 0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference occupies RU 2)
2649 delay += Seconds (1.0);
2650
2651 //---------------------------------------------------------------------------
2652 //Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both solicited HE TB PPDUs have been impacted if they are on the same
2653 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
2654 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2655 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU 1 during PSDU reception");
2656 //Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
2657 Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 3, 1, 1002, 1, 0);
2658 //Expected figures from STA 2
2659 uint32_t succ, fail, bytes;
2660 if (m_channelWidth > 20)
2661 {
2662 //One PSDU of 1001 bytes should have been successfully received from STA 2 (since interference from STA 3 on distinct 20 MHz channel)
2663 succ = 1;
2664 fail = 0;
2665 bytes = 1001;
2666 }
2667 else
2668 {
2669 //Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on same 20 MHz channel)
2670 succ = 0;
2671 fail = 1;
2672 bytes = 0;
2673 }
2674 ScheduleTest (delay, true,
2675 WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference on measurement channel width
2676 0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on same 20 MHz channel)
2677 succ, fail, bytes);
2678 delay += Seconds (1.0);
2679
2680 //---------------------------------------------------------------------------
2681 //Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both solicited HE TB PPDUs have been impacted if they are on the same
2682 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
2683 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2684 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU 2 during PSDU reception");
2685 //Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
2686 Simulator::Schedule (delay + MicroSeconds (50), &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 3, 2, 1002, 1, 0);
2687 //Expected figures from STA 1
2688 if (m_channelWidth > 20)
2689 {
2690 //One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference from STA 3 on distinct 20 MHz channel)
2691 succ = 1;
2692 fail = 0;
2693 bytes = 1000;
2694 }
2695 else
2696 {
2697 //Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on same 20 MHz channel)
2698 succ = 0;
2699 fail = 1;
2700 bytes = 0;
2701 }
2702 ScheduleTest (delay, true,
2703 WifiPhyState::CCA_BUSY, //PHY should move to CCA_BUSY instead of IDLE due to the interference on measurement channel width
2704 succ, fail, bytes,
2705 0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on same 20 MHz channel)
2706 delay += Seconds (1.0);
2707
2708 //---------------------------------------------------------------------------
2709 //Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been impacted
2710 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2711 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
2712 //One HE SU arrives at AP during the 400ns window
2713 Simulator::Schedule (delay + NanoSeconds (300), &TestUlOfdmaPhyTransmission::SendHeSuPpdu, this, 3, 1002, 1, 0);
2714 ScheduleTest (delay, true,
2716 0, 1, 0, //Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
2717 0, 1, 0); //Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
2718 delay += Seconds (1.0);
2719
2720 //---------------------------------------------------------------------------
2721 //Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly received
2722 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2723 "Reception of solicited HE TB PPDU only on RU 2");
2724 //Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE otherwise
2726 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY); //PHY should move to CCA_BUSY instead of IDLE if HE TB PPDU on primary channel;
2727 ScheduleTest (delay, true,
2729 0, 0, 0, //No transmission scheduled for STA 1
2730 1, 0, 1001, //One PSDU of 1001 bytes should have been successfully received from STA 2
2731 false, WifiPhyState::RX); //Measurement channel is total channel width
2732 delay += Seconds (1.0);
2733
2734 //---------------------------------------------------------------------------
2735 //Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
2736 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2737 "Measure power for reception of HE TB PPDU only on RU 2");
2738 double rxPower = DbmToW (19); //16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
2740 (m_channelWidth >= 40) ? 0.0 : rxPower, rxPower, //power detected on RU1 only if same 20 MHz as RU 2
2741 0.0, rxPower);
2742 ScheduleTest (delay, true,
2744 0, 0, 0, //No transmission scheduled for STA 1
2745 1, 0, 1001, //One PSDU of 1001 bytes should have been successfully received from STA 2
2746 false, WifiPhyState::RX); //Measurement channel is total channel width
2747 delay += Seconds (1.0);
2748
2749 //---------------------------------------------------------------------------
2750 //Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density limitation enforced
2751 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2752 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
2753 //Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz, 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
2754 Simulator::Schedule (delay - NanoSeconds (1), //just before sending HE TB
2756
2757 rxPower = (m_channelWidth > 40) ? DbmToW (19) : DbmToW (18.0103); //15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA transmitted only on one 20 MHz channel
2758 double rxPowerOfdma = rxPower;
2759 if (m_channelWidth <= 40)
2760 {
2761 rxPowerOfdma = (m_channelWidth == 20) ? DbmToW (14.0309) //11.0309+1 dBm at STA and +2 at AP if 106-tone RU
2762 : DbmToW (18.0103); //15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
2763 }
2765 (m_channelWidth >= 40) ? 0.0 : rxPower, rxPower, //power detected on RU1 only if same 20 MHz as RU 2
2766 0.0, rxPowerOfdma);
2767
2768 //Reset PSD limitation once HE TB has been sent
2769 Simulator::Schedule (delay + m_expectedPpduDuration,
2771 ScheduleTest (delay, true,
2773 0, 0, 0, //No transmission scheduled for STA 1
2774 1, 0, 1001, //One PSDU of 1001 bytes should have been successfully received from STA 2
2775 false, WifiPhyState::RX); //Measurement channel is total channel width
2776 delay += Seconds (1.0);
2777
2778 //---------------------------------------------------------------------------
2779 //Measure the power of 2 solicited HE TB PPDU from both STAs
2780 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2781 "Measure power for reception of HE TB PPDU on both RUs");
2782 rxPower = DbmToW (19); //16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
2783 double rxPowerNonOfdma = (m_channelWidth >= 40) ? rxPower : rxPower * 2; //both STAs transmit over the same 20 MHz channel
2785 rxPowerNonOfdma, rxPowerNonOfdma,
2786 rxPower, rxPower);
2787 ScheduleTest (delay, true,
2789 1, 0, 1000, //One PSDU of 1000 bytes should have been successfully received from STA 1
2790 1, 0, 1001); //One PSDU of 1001 bytes should have been successfully received from STA 2
2791 delay += Seconds (1.0);
2792
2793 //---------------------------------------------------------------------------
2794 //Verify that an HE SU PPDU from another BSS has been correctly received (no UL MU transmission ongoing)
2795 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::LogScenario, this,
2796 "Reception of an HE SU PPDU from another BSS");
2797 //One HE SU from another BSS (BSS color 2) arrives at AP (BSS color 1)
2798 Simulator::Schedule (delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
2799 Simulator::Schedule (delay + MilliSeconds (100), &TestUlOfdmaPhyTransmission::SendHeTbPpdu, this, 3, 1, 1002, 1, 2);
2800
2801 //Verify events data have been cleared
2802 Simulator::Schedule (delay + MilliSeconds (200), &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
2803
2804 Simulator::Schedule (delay + MilliSeconds (500), &TestUlOfdmaPhyTransmission::Reset, this);
2805 delay += Seconds (1.0);
2806
2807 Simulator::Run ();
2808}
2809
2810void
2812{
2813 m_frequency = 5180;
2814 m_channelWidth = 20;
2816 NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2817 RunOne ();
2818
2819 m_frequency = 5190;
2820 m_channelWidth = 40;
2822 NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2823 RunOne ();
2824
2825 m_frequency = 5210;
2826 m_channelWidth = 80;
2828 NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2829 RunOne ();
2830
2831 m_frequency = 5250;
2832 m_channelWidth = 160;
2834 NS_LOG_DEBUG ("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
2835 RunOne ();
2836
2837 Simulator::Destroy ();
2838}
2839
2847{
2848public:
2850 virtual ~TestPhyPaddingExclusion ();
2851
2852private:
2853 void DoSetup (void) override;
2854 void DoTeardown (void) override;
2855 void DoRun (void) override;
2856
2864 void SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration);
2870 void SetTrigVector (Time ppduDuration);
2871
2877 void GenerateInterference (Ptr<SpectrumValue> interferencePsd, Time duration);
2881 void StopInterference (void);
2882
2886 void RunOne ();
2887
2894 void CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
2895
2902 void CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes);
2903
2907 void VerifyEventsCleared (void);
2908
2917
2921 void Reset ();
2922
2930 void RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> statusPerMpdu);
2931
2936 void RxFailure (Ptr<WifiPsdu> psdu);
2937
2941
2943
2950};
2951
2953 : TestCase ("PHY padding exclusion test"),
2954 m_countRxSuccessFromSta1 (0),
2955 m_countRxSuccessFromSta2 (0),
2956 m_countRxFailureFromSta1 (0),
2957 m_countRxFailureFromSta2 (0),
2958 m_countRxBytesFromSta1 (0),
2959 m_countRxBytesFromSta2 (0)
2960{
2961}
2962
2963void
2964TestPhyPaddingExclusion::SendHeTbPpdu (uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
2965{
2966 WifiConstPsduMap psdus;
2967
2968 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0, DEFAULT_CHANNEL_WIDTH, false, false, 1);
2969
2970 HeRu::RuSpec ru (HeRu::RU_106_TONE, index, false);
2971 txVector.SetRu (ru, txStaId);
2972 txVector.SetMode (HePhy::GetHeMcs7 (), txStaId);
2973 txVector.SetNss (1, txStaId);
2974
2975 Ptr<Packet> pkt = Create<Packet> (payloadSize);
2976 WifiMacHeader hdr;
2978 hdr.SetQosTid (0);
2979 hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:00"));
2980 std::ostringstream addr;
2981 addr << "00:00:00:00:00:0" << txStaId;
2982 hdr.SetAddr2 (Mac48Address (addr.str ().c_str ()));
2983 hdr.SetSequenceNumber (1);
2984 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (pkt, hdr);
2985 psdus.insert (std::make_pair (txStaId, psdu));
2986
2988 if (txStaId == 1)
2989 {
2990 phy = m_phySta1;
2991 }
2992 else if (txStaId == 2)
2993 {
2994 phy = m_phySta2;
2995 }
2996
2997 txVector.SetLength (HePhy::ConvertHeTbPpduDurationToLSigLength (txDuration, txVector, phy->GetPhyBand ()).first);
2998
2999 phy->SetPpduUid (0);
3000 phy->Send (psdus, txVector);
3001}
3002
3003void
3005{
3006 m_phyInterferer->SetTxPowerSpectralDensity (interferencePsd);
3007 m_phyInterferer->SetPeriod (duration);
3009 Simulator::Schedule (duration, &TestPhyPaddingExclusion::StopInterference, this);
3010}
3011
3012void
3014{
3016}
3017
3019{
3020}
3021
3022void
3023TestPhyPaddingExclusion::RxSuccess (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
3024{
3025 NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 () << rxSignalInfo << txVector);
3026 if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
3027 {
3029 m_countRxBytesFromSta1 += (psdu->GetSize () - 30);
3030 }
3031 else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
3032 {
3034 m_countRxBytesFromSta2 += (psdu->GetSize () - 30);
3035 }
3036}
3037
3038void
3040{
3041 NS_LOG_FUNCTION (this << *psdu << psdu->GetAddr2 ());
3042 if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:01"))
3043 {
3045 }
3046 else if (psdu->GetAddr2 () == Mac48Address ("00:00:00:00:00:02"))
3047 {
3049 }
3050}
3051
3052void
3053TestPhyPaddingExclusion::CheckRxFromSta1 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
3054{
3055 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta1, expectedSuccess, "The number of successfully received packets from STA 1 is not correct!");
3056 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta1, expectedFailures, "The number of unsuccessfully received packets from STA 1 is not correct!");
3057 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta1, expectedBytes, "The number of bytes received from STA 1 is not correct!");
3058}
3059
3060void
3061TestPhyPaddingExclusion::CheckRxFromSta2 (uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
3062{
3063 NS_TEST_ASSERT_MSG_EQ (m_countRxSuccessFromSta2, expectedSuccess, "The number of successfully received packets from STA 2 is not correct!");
3064 NS_TEST_ASSERT_MSG_EQ (m_countRxFailureFromSta2, expectedFailures, "The number of unsuccessfully received packets from STA 2 is not correct!");
3065 NS_TEST_ASSERT_MSG_EQ (m_countRxBytesFromSta2, expectedBytes, "The number of bytes received from STA 2 is not correct!");
3066}
3067
3068void
3070{
3071 NS_TEST_ASSERT_MSG_EQ (m_phyAp->GetCurrentEvent (), 0, "m_currentEvent for AP was not cleared");
3072 NS_TEST_ASSERT_MSG_EQ (m_phySta1->GetCurrentEvent (), 0, "m_currentEvent for STA 1 was not cleared");
3073 NS_TEST_ASSERT_MSG_EQ (m_phySta2->GetCurrentEvent (), 0, "m_currentEvent for STA 2 was not cleared");
3074}
3075
3076void
3078{
3079 //This is needed to make sure PHY state will be checked as the last event if a state change occurred at the exact same time as the check
3080 Simulator::ScheduleNow (&TestPhyPaddingExclusion::DoCheckPhyState, this, phy, expectedState);
3081}
3082
3083void
3085{
3086 WifiPhyState currentState = phy->GetState ()->GetState ();
3087 NS_LOG_FUNCTION (this << currentState);
3088 NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
3089}
3090
3091void
3093{
3100 m_phySta1->SetPpduUid (0);
3103}
3104
3105void
3107{
3108 RngSeedManager::SetSeed (1);
3109 RngSeedManager::SetRun (1);
3110 int64_t streamNumber = 0;
3111
3112 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
3113 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
3114 lossModel->SetFrequency (DEFAULT_FREQUENCY * 1e6);
3115 spectrumChannel->AddPropagationLossModel (lossModel);
3116 Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
3117 spectrumChannel->SetPropagationDelayModel (delayModel);
3118
3119 Ptr<Node> apNode = CreateObject<Node> ();
3120 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice> ();
3121 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac> ();
3122 apMac->SetAttribute ("BeaconGeneration", BooleanValue (false));
3123 apDev->SetMac (apMac);
3124 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy> (0);
3127 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration> ();
3128 apDev->SetHeConfiguration (heConfiguration);
3129 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel> ();
3130 m_phyAp->SetErrorRateModel (error);
3131 m_phyAp->SetDevice (apDev);
3132 m_phyAp->SetChannel (spectrumChannel);
3133 m_phyAp->AssignStreams (streamNumber);
3134 auto channelNum = std::get<0> (*WifiPhyOperatingChannel::FindFirst (0, DEFAULT_FREQUENCY,
3138
3140 (int)(WIFI_PHY_BAND_5GHZ), 0});
3143 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel> ();
3144 m_phyAp->SetMobility (apMobility);
3145 apDev->SetPhy (m_phyAp);
3146 apNode->AggregateObject (apMobility);
3147 apNode->AddDevice (apDev);
3148
3149 Ptr<Node> sta1Node = CreateObject<Node> ();
3150 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice> ();
3151 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy> (1);
3155 m_phySta1->SetDevice (sta1Dev);
3156 m_phySta1->SetChannel (spectrumChannel);
3157 m_phySta1->AssignStreams (streamNumber);
3159 (int)(WIFI_PHY_BAND_5GHZ), 0});
3160 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel> ();
3161 m_phySta1->SetMobility (sta1Mobility);
3162 sta1Dev->SetPhy (m_phySta1);
3163 sta1Node->AggregateObject (sta1Mobility);
3164 sta1Node->AddDevice (sta1Dev);
3165
3166 Ptr<Node> sta2Node = CreateObject<Node> ();
3167 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice> ();
3168 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy> (2);
3172 m_phySta2->SetDevice (sta2Dev);
3173 m_phySta2->SetChannel (spectrumChannel);
3174 m_phySta2->AssignStreams (streamNumber);
3176 (int)(WIFI_PHY_BAND_5GHZ), 0});
3177 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel> ();
3178 m_phySta2->SetMobility (sta2Mobility);
3179 sta2Dev->SetPhy (m_phySta2);
3180 sta2Node->AggregateObject (sta2Mobility);
3181 sta2Node->AddDevice (sta2Dev);
3182
3183 Ptr<Node> interfererNode = CreateObject<Node> ();
3184 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice> ();
3185 m_phyInterferer = CreateObject<WaveformGenerator> ();
3186 m_phyInterferer->SetDevice (interfererDev);
3187 m_phyInterferer->SetChannel (spectrumChannel);
3189 interfererNode->AddDevice (interfererDev);
3190}
3191
3192void
3194{
3195 m_phyAp->Dispose ();
3196 m_phyAp = 0;
3197 m_phySta1->Dispose ();
3198 m_phySta1 = 0;
3199 m_phySta2->Dispose ();
3200 m_phySta2 = 0;
3202 m_phyInterferer = 0;
3203}
3204
3205void
3207{
3208 WifiTxVector trigVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_TB, 800, 1, 1, 0,
3209 DEFAULT_CHANNEL_WIDTH, false, false, 1);
3210 trigVector.SetRu (HeRu::RuSpec (HeRu::RU_106_TONE, 1, false), 1);
3211 trigVector.SetMode (HePhy::GetHeMcs7 (), 1);
3212 trigVector.SetNss (1, 1);
3213 trigVector.SetRu (HeRu::RuSpec (HeRu::RU_106_TONE, 2, false), 2);
3214 trigVector.SetMode (HePhy::GetHeMcs7 (), 2);
3215 trigVector.SetNss (1, 2);
3216 uint16_t length;
3217 std::tie (length, ppduDuration) = HePhy::ConvertHeTbPpduDurationToLSigLength (ppduDuration,
3218 trigVector,
3219 m_phyAp->GetPhyBand ());
3220 trigVector.SetLength (length);
3221 auto hePhyAp = DynamicCast<HePhy> (m_phyAp->GetPhyEntity (WIFI_MOD_CLASS_HE));
3222 hePhyAp->SetTrigVector (trigVector, ppduDuration);
3223}
3224
3225void
3227{
3228 Time expectedPpduDuration = NanoSeconds (279200);
3229 Time ppduWithPaddingDuration = expectedPpduDuration + 10 * NanoSeconds (12800 + 800 /* GI */); //add 10 extra OFDM symbols
3230
3231 Simulator::Schedule (Seconds (0.0), &TestPhyPaddingExclusion::Reset, this);
3232
3233 //STA1 and STA2 send MU UL PPDUs addressed to AP:
3234 Simulator::Schedule (Seconds (1.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 1, 1, 1000, ppduWithPaddingDuration);
3235 Simulator::Schedule (Seconds (1.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 2, 2, 1001, ppduWithPaddingDuration);
3236
3237 // Set TRIGVECTOR on AP
3238 Simulator::Schedule (Seconds (1.0), &TestPhyPaddingExclusion::SetTrigVector, this,
3239 ppduWithPaddingDuration);
3240
3241 //Verify it takes expectedPpduDuration + padding to transmit the PPDUs
3242 Simulator::Schedule (Seconds (1.0) + ppduWithPaddingDuration - NanoSeconds (1), &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::RX);
3243 Simulator::Schedule (Seconds (1.0) + ppduWithPaddingDuration, &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::IDLE);
3244
3245 //One PSDU of 1000 bytes should have been successfully received from STA 1
3246 Simulator::Schedule (Seconds (1.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
3247 //One PSDU of 1001 bytes should have been successfully received from STA 2
3248 Simulator::Schedule (Seconds (1.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
3249 //Verify events data have been cleared
3250 Simulator::Schedule (Seconds (1.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
3251
3252 Simulator::Schedule (Seconds (1.5), &TestPhyPaddingExclusion::Reset, this);
3253
3254
3255 //STA1 and STA2 send MU UL PPDUs addressed to AP:
3256 Simulator::Schedule (Seconds (2.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 1, 1, 1000, ppduWithPaddingDuration);
3257 Simulator::Schedule (Seconds (2.0), &TestPhyPaddingExclusion::SendHeTbPpdu, this, 2, 2, 1001, ppduWithPaddingDuration);
3258
3259 // Set TRIGVECTOR on AP
3260 Simulator::Schedule (Seconds (2.0), &TestPhyPaddingExclusion::SetTrigVector, this,
3261 ppduWithPaddingDuration);
3262
3263 //A strong non-wifi interference is generated on RU 1 during padding reception
3264 BandInfo bandInfo;
3265 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
3266 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
3267 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
3268 Bands bands;
3269 bands.push_back (bandInfo);
3270
3271 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel> (bands);
3272 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue> (SpectrumInterferenceRu1);
3273 double interferencePower = 0.1; //watts
3274 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
3275
3276 Simulator::Schedule (Seconds (2.0) + MicroSeconds (50) + expectedPpduDuration, &TestPhyPaddingExclusion::GenerateInterference, this, interferencePsdRu1, MilliSeconds (100));
3277
3278 //Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to CCA_BUSY instead of IDLE due to the interference)
3279 Simulator::Schedule (Seconds (2.0) + ppduWithPaddingDuration - NanoSeconds (1), &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::RX);
3280 Simulator::Schedule (Seconds (2.0) + ppduWithPaddingDuration, &TestPhyPaddingExclusion::CheckPhyState, this, m_phyAp, WifiPhyState::CCA_BUSY);
3281
3282 //One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference occupies RU 1 after payload, during PHY padding)
3283 Simulator::Schedule (Seconds (2.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
3284 //One PSDU of 1001 bytes should have been successfully received from STA 2
3285 Simulator::Schedule (Seconds (2.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
3286 //Verify events data have been cleared
3287 Simulator::Schedule (Seconds (2.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
3288
3289 Simulator::Schedule (Seconds (2.5), &TestPhyPaddingExclusion::Reset, this);
3290
3291 Simulator::Run ();
3292
3293 Simulator::Destroy ();
3294}
3295
3303{
3304public:
3306 virtual ~TestUlOfdmaPowerControl ();
3307
3308private:
3309 void DoSetup (void) override;
3310 void DoTeardown (void) override;
3311 void DoRun (void) override;
3312
3318 void SendMuBar (std::vector <uint16_t> staIds);
3319
3326 void SetupBa (Address destination);
3327
3334 void RunOne (bool setupBa);
3335
3340 void ReplaceReceiveOkCallbackOfAp (void);
3341
3351 void ReceiveOkCallbackAtAp (Ptr<WifiPsdu> psdu, RxSignalInfo rxSignalInfo,
3352 WifiTxVector txVector, std::vector<bool> statusPerMpdu);
3353
3354 uint8_t m_bssColor;
3355
3359
3361
3366
3369
3370 double m_rssiSta1;
3371 double m_rssiSta2;
3372
3373 double m_tol;
3374};
3375
3377 : TestCase ("UL-OFDMA power control test"),
3378 m_bssColor (1),
3379 m_txPowerAp (0),
3380 m_txPowerStart (0),
3381 m_txPowerEnd (0),
3382 m_txPowerLevels (0),
3383 m_requestedRssiSta1 (0),
3384 m_requestedRssiSta2 (0),
3385 m_rssiSta1 (0),
3386 m_rssiSta2 (0),
3387 m_tol (0.1)
3388{
3389}
3390
3392{
3393 m_phyAp = 0;
3394 m_apDev = 0;
3395 m_sta1Dev = 0;
3396 m_sta2Dev = 0;
3397}
3398
3399void
3401{
3402 //Only one packet is sufficient to set up BA since AP and STAs are HE capable
3403 Ptr<Packet> pkt = Create<Packet> (100); // 100 dummy bytes of data
3404 m_apDev->Send (pkt, destination, 0);
3405}
3406
3407void
3408TestUlOfdmaPowerControl::SendMuBar (std::vector <uint16_t> staIds)
3409{
3410 NS_ASSERT (!staIds.empty () && staIds.size () <= 2);
3411
3412 //Build MU-BAR trigger frame
3413 CtrlTriggerHeader muBar;
3414 muBar.SetType (MU_BAR_TRIGGER);
3415 muBar.SetMoreTF (true);
3416 muBar.SetCsRequired (true);
3418 muBar.SetGiAndLtfType (1600, 2);
3419 muBar.SetApTxPower (static_cast<int8_t> (m_txPowerAp));
3420 muBar.SetUlSpatialReuse (60500);
3421
3422 HeRu::RuType ru = (staIds.size () == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
3423 std::size_t index = 1;
3424 int8_t ulTargetRssi = -40; //will be overwritten
3425 for (auto const& staId : staIds)
3426 {
3428 ui.SetAid12 (staId);
3429 ui.SetRuAllocation ({ru, index, true});
3430 ui.SetUlFecCodingType (true);
3431 ui.SetUlMcs (7);
3432 ui.SetUlDcm (false);
3433 ui.SetSsAllocation (1, 1);
3434 if (staId == 1)
3435 {
3436 ulTargetRssi = m_requestedRssiSta1;
3437 }
3438 else if (staId == 2)
3439 {
3440 ulTargetRssi = m_requestedRssiSta2;
3441 }
3442 else
3443 {
3444 NS_ABORT_MSG ("Unknown STA-ID (" << staId << ")");
3445 }
3446 ui.SetUlTargetRssi (ulTargetRssi);
3447
3449 bar.SetType (BlockAckReqType::COMPRESSED);
3450 bar.SetTidInfo (0);
3451 bar.SetStartingSequence (4095);
3453
3454 ++index;
3455 }
3456
3457 WifiTxVector tbTxVector = muBar.GetHeTbTxVector (staIds.front ());
3458 muBar.SetUlLength (HePhy::ConvertHeTbPpduDurationToLSigLength (MicroSeconds (128), tbTxVector, WIFI_PHY_BAND_5GHZ).first);
3459
3460 WifiConstPsduMap psdus;
3461 WifiTxVector txVector = WifiTxVector (HePhy::GetHeMcs7 (), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0,
3462 DEFAULT_CHANNEL_WIDTH, false, false, false, m_bssColor);
3463
3464 Ptr<Packet> bar = Create<Packet> ();
3465 bar->AddHeader (muBar);
3466
3467 Mac48Address receiver = Mac48Address::GetBroadcast ();
3468 if (staIds.size () == 1)
3469 {
3470 uint16_t aidSta1 = DynamicCast<StaWifiMac> (m_sta1Dev->GetMac ())->GetAssociationId ();
3471 if (staIds.front () == aidSta1)
3472 {
3473 receiver = Mac48Address::ConvertFrom (m_sta1Dev->GetAddress ());
3474 }
3475 else
3476 {
3477 NS_ASSERT (staIds.front () == DynamicCast<StaWifiMac> (m_sta2Dev->GetMac ())->GetAssociationId ());
3478 receiver = Mac48Address::ConvertFrom (m_sta2Dev->GetAddress ());
3479 }
3480 }
3481
3482 WifiMacHeader hdr;
3484 hdr.SetAddr1 (receiver);
3485 hdr.SetAddr2 (Mac48Address::ConvertFrom (m_apDev->GetAddress ()));
3486 hdr.SetAddr3 (Mac48Address::ConvertFrom (m_apDev->GetAddress ()));
3487 hdr.SetDsNotTo ();
3488 hdr.SetDsFrom ();
3489 hdr.SetNoRetry ();
3490 hdr.SetNoMoreFragments ();
3491 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (bar, hdr);
3492
3493 Time nav = m_apDev->GetPhy ()->GetSifs ();
3494 uint16_t staId = staIds.front (); //either will do
3495 nav += m_phyAp->CalculateTxDuration (GetBlockAckSize (BlockAckType::COMPRESSED), tbTxVector, DEFAULT_WIFI_BAND, staId);
3496 psdu->SetDuration (nav);
3497 psdus.insert (std::make_pair (SU_STA_ID, psdu));
3498
3499 m_phyAp->Send (psdus, txVector);
3500}
3501
3502void
3504 WifiTxVector txVector, std::vector<bool> /*statusPerMpdu*/)
3505{
3506 NS_TEST_ASSERT_MSG_EQ (txVector.GetPreambleType (), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
3507 double rssi = rxSignalInfo.rssi;
3508 NS_ASSERT (psdu->GetNMpdus () == 1);
3509 WifiMacHeader hdr = psdu->GetHeader (0);
3510 NS_TEST_ASSERT_MSG_EQ (hdr.GetType (), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
3511 if (hdr.GetAddr2 () == m_sta1Dev->GetAddress ())
3512 {
3513 NS_TEST_ASSERT_MSG_EQ_TOL (rssi, m_rssiSta1, m_tol, "The obtained RSSI from STA 1 at AP is different from the expected one (" << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
3514 }
3515 else if (psdu->GetAddr2 () == m_sta2Dev->GetAddress ())
3516 {
3517 NS_TEST_ASSERT_MSG_EQ_TOL (rssi, m_rssiSta2, m_tol, "The obtained RSSI from STA 2 at AP is different from the expected one (" << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
3518 }
3519 else
3520 {
3521 NS_ABORT_MSG ("The receiver address is unknown");
3522 }
3523}
3524
3525void
3527{
3528 //Now that BA session has been established we can plug our method
3530}
3531
3532void
3534{
3535 Ptr<Node> apNode = CreateObject<Node> ();
3536 NodeContainer staNodes;
3537 staNodes.Create (2);
3538
3539 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
3540 Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel> ();
3541 spectrumChannel->AddPropagationLossModel (lossModel);
3542 Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
3543 spectrumChannel->SetPropagationDelayModel (delayModel);
3544
3545 SpectrumWifiPhyHelper spectrumPhy;
3546 spectrumPhy.SetChannel (spectrumChannel);
3547 spectrumPhy.SetErrorRateModel ("ns3::NistErrorRateModel");
3548 spectrumPhy.Set ("ChannelSettings", StringValue ("{0, 0, BAND_5GHZ, 0}"));
3549
3551 wifi.SetStandard (WIFI_STANDARD_80211ax);
3552 wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
3553 "DataMode", StringValue ("HeMcs7"),
3554 "ControlMode", StringValue ("HeMcs7"));
3555
3557 mac.SetType ("ns3::StaWifiMac");
3558 NetDeviceContainer staDevs = wifi.Install (spectrumPhy, mac, staNodes);
3559 wifi.AssignStreams (staDevs, 0);
3560 m_sta1Dev = DynamicCast<WifiNetDevice> (staDevs.Get (0));
3562 m_sta2Dev = DynamicCast<WifiNetDevice> (staDevs.Get (1));
3564
3565 //Set the beacon interval long enough so that associated STAs may not consider link lost when
3566 //beacon generation is disabled during the actual tests. Having such a long interval also
3567 //avoids bloating logs with beacons during the set up phase.
3568 mac.SetType ("ns3::ApWifiMac",
3569 "BeaconGeneration", BooleanValue (true),
3570 "BeaconInterval", TimeValue (MicroSeconds (1024 * 600)));
3571 m_apDev = DynamicCast<WifiNetDevice> (wifi.Install (spectrumPhy, mac, apNode).Get (0));
3573 m_apDev->GetHeConfiguration ()->SetAttribute ("BssColor", UintegerValue (m_bssColor));
3574 m_phyAp = DynamicCast<SpectrumWifiPhy> (m_apDev->GetPhy ());
3576 //ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been set up for both STAs
3577
3579 mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
3580 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
3581 positionAlloc->Add (Vector (0.0, 0.0, 0.0));
3582 positionAlloc->Add (Vector (1.0, 0.0, 0.0)); // put close enough in order to use MCS
3583 positionAlloc->Add (Vector (2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
3584 mobility.SetPositionAllocator (positionAlloc);
3585
3586 mobility.Install (apNode);
3587 mobility.Install (staNodes);
3588
3589 lossModel->SetDefaultLoss (50.0);
3590 lossModel->SetLoss (apNode->GetObject<MobilityModel> (), staNodes.Get (1)->GetObject<MobilityModel> (),
3591 56.0, true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
3592}
3593
3594void
3596{
3597 m_phyAp->Dispose ();
3598 m_phyAp = 0;
3599 m_apDev->Dispose ();
3600 m_apDev = 0;
3601 m_sta1Dev->Dispose ();
3602 m_sta1Dev = 0;
3603 m_sta2Dev->Dispose ();
3604 m_sta2Dev = 0;
3605}
3606
3607void
3609{
3610 RngSeedManager::SetSeed (1);
3611 RngSeedManager::SetRun (1);
3612 int64_t streamNumber = 0;
3613
3614 Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy ();
3615 Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy ();
3616
3617 m_phyAp->AssignStreams (streamNumber);
3618 phySta1->AssignStreams (streamNumber);
3619 phySta2->AssignStreams (streamNumber);
3620
3621 m_phyAp->SetAttribute ("TxPowerStart", DoubleValue (m_txPowerAp));
3622 m_phyAp->SetAttribute ("TxPowerEnd", DoubleValue (m_txPowerAp));
3623 m_phyAp->SetAttribute ("TxPowerLevels", UintegerValue (1));
3624
3625 phySta1->SetAttribute ("TxPowerStart", DoubleValue (m_txPowerStart));
3626 phySta1->SetAttribute ("TxPowerEnd", DoubleValue (m_txPowerEnd));
3627 phySta1->SetAttribute ("TxPowerLevels", UintegerValue (m_txPowerLevels));
3628
3629 phySta2->SetAttribute ("TxPowerStart", DoubleValue (m_txPowerStart));
3630 phySta2->SetAttribute ("TxPowerEnd", DoubleValue (m_txPowerEnd));
3631 phySta2->SetAttribute ("TxPowerLevels", UintegerValue (m_txPowerLevels));
3632
3633 Time relativeStart = MilliSeconds (0);
3634 if (setupBa)
3635 {
3636 //Set up BA for each station once the association phase has ended
3637 //so that a BA session is established when the MU-BAR is received.
3638 Simulator::Schedule (MilliSeconds (800), &TestUlOfdmaPowerControl::SetupBa, this, m_sta1Dev->GetAddress ());
3639 Simulator::Schedule (MilliSeconds (850), &TestUlOfdmaPowerControl::SetupBa, this, m_sta2Dev->GetAddress ());
3640 relativeStart = MilliSeconds (1000);
3641 }
3642 else
3643 {
3644 Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac> (m_apDev->GetMac ());
3645 NS_ASSERT (apMac);
3646 apMac->SetAttribute ("BeaconGeneration", BooleanValue (false));
3647 }
3648
3649 Simulator::Schedule (relativeStart, &TestUlOfdmaPowerControl::ReplaceReceiveOkCallbackOfAp, this);
3650
3651 {
3652 //Verify that the RSSI from STA 1 is consistent with what was requested
3653 std::vector<uint16_t> staIds {1};
3654 Simulator::Schedule (relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
3655 }
3656
3657 {
3658 //Verify that the RSSI from STA 2 is consistent with what was requested
3659 std::vector<uint16_t> staIds {2};
3660 Simulator::Schedule (relativeStart + MilliSeconds (20), &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
3661 }
3662
3663 {
3664 //Verify that the RSSI from STA 1 and 2 is consistent with what was requested
3665 std::vector<uint16_t> staIds {1, 2};
3666 Simulator::Schedule (relativeStart + MilliSeconds (40), &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
3667 }
3668
3669 Simulator::Stop (relativeStart + MilliSeconds (100));
3670 Simulator::Run ();
3671}
3672
3673void
3675{
3676 //Power configurations
3677 m_txPowerAp = 20; //dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
3678 //since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
3679 m_txPowerStart = 15; //dBm
3680
3681 //Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
3682 m_requestedRssiSta1 = -30.0;
3683 m_requestedRssiSta2 = -36.0;
3684
3685 //Test single power level
3686 {
3687 //STA power configurations: 15 dBm only
3688 m_txPowerEnd = 15;
3689 m_txPowerLevels = 1;
3690
3691 //Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
3692 //regardless of the estimated path loss.
3693 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
3694 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
3695
3696 RunOne (true);
3697 }
3698
3699 //Test 2 dBm granularity
3700 {
3701 //STA power configurations: [15:2:25] dBm
3702 m_txPowerEnd = 25;
3703 m_txPowerLevels = 6;
3704
3705 //Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than requested
3706 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
3707 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
3708
3709 RunOne (false);
3710 }
3711
3712 //Test 1 dBm granularity
3713 {
3714 //STA power configurations: [15:1:25] dBm
3715 m_txPowerEnd = 25;
3716 m_txPowerLevels = 11;
3717
3718 //Expected UL RSSIs, considering that we can correctly tune the transmit power
3719 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
3720 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
3721
3722 RunOne (false);
3723 }
3724
3725 //Ask for different power levels (3 dB difference between HE_TB_PPDUs)
3726 {
3727 //STA power configurations: [15:1:25] dBm
3728 m_txPowerEnd = 25;
3729 m_txPowerLevels = 11;
3730
3731 //Requested UL RSSIs
3732 m_requestedRssiSta1 = -28.0; //2 dB higher than previously -> Tx power = 22 dBm at STA 1
3733 m_requestedRssiSta2 = -37.0; //1 dB less than previously -> Tx power = 19 dBm at STA 2
3734
3735 //Expected UL RSSIs, considering that we can correctly tune the transmit power
3736 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
3737 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
3738
3739 RunOne (false);
3740 }
3741
3742 Simulator::Destroy ();
3743}
3744
3745
3753{
3754public:
3756};
3757
3759 : TestSuite ("wifi-phy-ofdma", UNIT)
3760{
3761 AddTestCase (new TestDlOfdmaPhyTransmission, TestCase::QUICK);
3762 AddTestCase (new TestUlOfdmaPpduUid, TestCase::QUICK);
3763 AddTestCase (new TestMultipleHeTbPreambles, TestCase::QUICK);
3764 AddTestCase (new TestUlOfdmaPhyTransmission, TestCase::QUICK);
3765 AddTestCase (new TestPhyPaddingExclusion, TestCase::QUICK);
3766 AddTestCase (new TestUlOfdmaPowerControl, TestCase::QUICK);
3767}
3768
#define max(a, b)
Definition: 80211b.c:43
SpectrumWifiPhy used for testing OFDMA.
Time GetEnergyDuration(double energyW, WifiSpectrumBand band)
Wrapper to InterferenceHelper method.
void SetTriggerFrameUid(uint64_t uid)
Since we assume trigger frame was previously received from AP, this is used to set its UID.
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void StartTx(Ptr< WifiPpdu > ppdu) override
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
Ptr< Event > GetCurrentEvent(void)
void DoInitialize(void) override
Initialize() implementation.
Ptr< const HePhy > GetHePhy(void) const
Ptr< OfdmaTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for OFDMA test.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
void DoDispose(void) override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents(void)
static TypeId GetTypeId(void)
Get the type ID.
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
uint16_t m_frequency
frequency in MHz
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxSuccessSta3(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 3.
void RunOne()
Run one function.
void RxFailureSta2(Ptr< WifiPsdu > psdu)
Receive failure function for STA 2.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Time m_expectedPpduDuration
expected duration to send MU PPDU
void RxFailureSta1(Ptr< WifiPsdu > psdu)
Receive failure function for STA 1.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void DoRun(void) override
Implementation to actually run this TestCase.
void RxSuccessSta2(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
void StopInterference(void)
Stop interference function.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void RxFailureSta3(Ptr< WifiPsdu > psdu)
Receive failure function for STA 3.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void RxSuccessSta1(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
Ptr< OfdmaSpectrumWifiPhy > m_phy
Phy.
void Reset(void)
Reset function.
void DoRun(void) override
Implementation to actually run this TestCase.
void RxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void CheckHeTbPreambles(size_t nEvents, std::vector< uint64_t > uids)
Check the received HE TB preambles.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
Receive HE TB PPDU function.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
PHY padding exclusion test.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void VerifyEventsCleared(void)
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void RxFailure(Ptr< WifiPsdu > psdu)
Receive failure function.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
void StopInterference(void)
Stop interference function.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void RxSuccess(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void DoRun(void) override
Implementation to actually run this TestCase.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void VerifyEventsCleared(void)
Verify all events are cleared at end of TX or RX.
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBand band, double expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
void StopInterference(void)
Stop interference function.
void RxFailure(Ptr< WifiPsdu > psdu)
Receive failure function.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
uint16_t m_frequency
frequency in MHz
TrigVectorInfo
Erroneous info included in a TRIGVECTOR.
void SchedulePowerMeasurementChecks(Time delay, double rxPowerNonOfdmaRu1, double rxPowerNonOfdmaRu2, double rxPowerOfdmaRu1, double rxPowerOfdmaRu2)
Schedule power measurement related checks.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void LogScenario(std::string log) const
Log scenario description.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
void SetPsdLimit(Ptr< WifiPhy > phy, double psdLimit)
Set the PSD limit.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void DoRun(void) override
Implementation to actually run this TestCase.
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBand band, double expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void RxSuccess(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
Ptr< OfdmaSpectrumWifiPhy > m_phySta3
PHY of STA 3.
uint16_t m_channelWidth
channel width in MHz
void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE TB PPDU function.
void SetTrigVector(uint8_t bssColor, TrigVectorInfo error)
Set TRIGVECTOR for HE TB PPDU.
Time m_expectedPpduDuration
expected duration to send MU PPDU
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
UL-OFDMA power control test.
double m_requestedRssiSta1
requested RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
double m_txPowerStart
minimum transmission power (in dBm) for STAs
double m_rssiSta2
expected RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
void DoRun(void) override
Implementation to actually run this TestCase.
double m_txPowerEnd
maximum transmission power (in dBm) for STAs
void SetupBa(Address destination)
Send a QoS Data packet to the destination station in order to set up a block Ack session (so that the...
Ptr< WifiNetDevice > m_sta1Dev
network device of STA 1
double m_tol
tolerance (in dB) between received and expected RSSIs
Ptr< WifiNetDevice > m_apDev
network device of AP
double m_rssiSta1
expected RSSI (in dBm) from STA 1 at AP for HE TB PPDUs
uint8_t m_txPowerLevels
number of transmission power levels for STAs
double m_requestedRssiSta2
requested RSSI (in dBm) from STA 2 at AP for HE TB PPDUs
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
double m_txPowerAp
transmit power (in dBm) of AP
void ReplaceReceiveOkCallbackOfAp(void)
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void ReceiveOkCallbackAtAp(Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive OK callback function at AP.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
void SendMuPpdu(void)
Send MU-PPDU toward both STAs.
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
void DoRun(void) override
Implementation to actually run this TestCase.
void DoTeardown(void) override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu(void)
Send TB-PPDU from both STAs.
void ResetPpduUid(void)
Reset the global PPDU UID counter in WifiPhy.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAckRequest.
Definition: ctrl-headers.h:49
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
Headers for Trigger frames.
Definition: ctrl-headers.h:886
CtrlTriggerUserInfoField & AddUserInfoField(void)
Append a new User Info field to this Trigger frame and return a non-const reference to it.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
User Info field of Trigger frames.
Definition: ctrl-headers.h:582
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
PHY entity for HE (11ax)
Definition: he-phy.h:61
RU Specification.
Definition: he-ru.h:68
RuType GetRuType(void) const
Get the RU type.
Definition: he-ru.cc:167
void SetPhyIndex(uint16_t bw, uint8_t p20Index)
Set the RU PHY index.
Definition: he-ru.cc:188
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
Time GetEnergyDuration(double energyW, WifiSpectrumBand band)
an EUI-48 address
Definition: mac48-address.h:44
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:130
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:252
void Dispose(void)
Dispose of this Object.
Definition: object.cc:214
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:82
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:809
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get(void) const
Definition: pointer.h:201
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(Ptr< SpectrumChannel > channel)
802.11 PHY layer model
void SetChannel(const Ptr< SpectrumChannel > channel)
Set the SpectrumChannel this SpectrumWifiPhy is to be connected to.
void StartRx(Ptr< SpectrumSignalParameters > rxParams)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void CreateWifiSpectrumPhyInterface(Ptr< NetDevice > device)
Method to encapsulate the creation of the WifiSpectrumPhyInterface object (used to bind the WifiSpect...
Hold variables of type string.
Definition: string.h:41
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
AttributeValue implementation for Time.
Definition: nstime.h:1308
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
void SetChannel(Ptr< SpectrumChannel > c)
Set the channel attached to this device.
void SetDevice(Ptr< NetDevice > d)
Set the associated NetDevice instance.
virtual void Start()
Start the waveform generator.
void SetTxPowerSpectralDensity(Ptr< SpectrumValue > txs)
Set the Power Spectral Density used for outgoing waveforms.
void SetDutyCycle(double value)
void SetPeriod(Time period)
Set the period according to which the WaveformGenerator switches on and off.
virtual void Stop()
Stop the waveform generator.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:323
Implements the IEEE 802.11 MAC header.
void SetNoRetry(void)
Un-set the Retry bit in the Frame Control field.
void SetNoMoreFragments(void)
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
Mac48Address GetAddr2(void) const
Return the address in the Address 2 field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetDsFrom(void)
Set the From DS bit in the Frame Control field.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
create MAC layers for a ns3::WifiNetDevice.
void SetMac(const Ptr< WifiMac > mac)
void SetHeConfiguration(Ptr< HeConfiguration > heConfiguration)
Ptr< WifiMac > GetMac(void) const
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Address GetAddress(void) const override
Ptr< WifiPhy > GetPhy(void) const
void SetStandard(WifiStandard standard)
Set the Wifi standard.
void SetPhy(const Ptr< WifiPhy > phy)
Ptr< HeConfiguration > GetHeConfiguration(void) const
void SetErrorRateModel(std::string name, std::string n0="", const AttributeValue &v0=EmptyAttributeValue(), std::string n1="", const AttributeValue &v1=EmptyAttributeValue(), std::string n2="", const AttributeValue &v2=EmptyAttributeValue(), std::string n3="", const AttributeValue &v3=EmptyAttributeValue(), std::string n4="", const AttributeValue &v4=EmptyAttributeValue(), std::string n5="", const AttributeValue &v5=EmptyAttributeValue(), std::string n6="", const AttributeValue &v6=EmptyAttributeValue(), std::string n7="", const AttributeValue &v7=EmptyAttributeValue())
Definition: wifi-helper.cc:147
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:141
void Send(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector)
This function is a wrapper for the Send variant that accepts a WifiConstPsduMap as first argument.
Definition: wifi-phy.cc:1485
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > m_currentPreambleEvents
store event associated to a PPDU (that has a unique ID and preamble combination) whose preamble is be...
Definition: wifi-phy.h:1145
WifiPhyBand GetPhyBand(void) const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:870
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:390
InterferenceHelper m_interference
the class handling interference computations
Definition: wifi-phy.h:1134
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:818
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1306
void Reset(void)
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1592
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1166
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:913
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1144
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class, for the WifiPhy instance.
Definition: wifi-phy.cc:627
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1147
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:526
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:577
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:659
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:538
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:384
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:832
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:1995
void SetErrorRateModel(const Ptr< ErrorRateModel > rate)
Sets the error rate model.
Definition: wifi-phy.cc:557
This objects implements the PHY state machine of the Wifi device.
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:260
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:266
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:319
Mac48Address GetAddr2(void) const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:126
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition: wifi-psdu.cc:156
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiPreamble GetPreambleType(void) const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#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
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
void Reset(void)
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition: config.cc:820
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:141
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
Definition: test.h:323
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ MU_BAR_TRIGGER
Definition: ctrl-headers.h:564
Definition: first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
std::pair< uint32_t, uint32_t > WifiSpectrumBand
typedef for a pair of start and stop sub-band indexes
std::vector< BandInfo > Bands
Container of BandInfo.
double DbmToW(double dBm)
Convert from dBm to Watts.
Definition: wifi-utils.cc:37
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_CTL_BACKRESP
@ WIFI_MAC_QOSDATA
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
Definition: wifi-utils.cc:63
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
mac
Definition: third.py:96
wifi
Definition: third.py:99
mobility
Definition: third.py:107
phy
Definition: third.py:93
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
HE MU specific user transmission parameters.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:67
double rssi
RSSI in dBm.
Definition: phy-entity.h:69
#define SU_STA_ID
Definition: wifi-mode.h:32
static const uint16_t DEFAULT_CHANNEL_WIDTH
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const uint16_t DEFAULT_GUARD_WIDTH
static const uint32_t DEFAULT_FREQUENCY
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ RX
The PHY layer is receiving a packet.
@ IDLE
The PHY layer is IDLE.