A Discrete-Event Network Simulator
API
wifi-phy-ofdma-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2019 University of Washington
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18 */
19
20#include "ns3/ap-wifi-mac.h"
21#include "ns3/boolean.h"
22#include "ns3/constant-position-mobility-model.h"
23#include "ns3/ctrl-headers.h"
24#include "ns3/double.h"
25#include "ns3/he-configuration.h"
26#include "ns3/he-phy.h"
27#include "ns3/he-ppdu.h"
28#include "ns3/interference-helper.h"
29#include "ns3/log.h"
30#include "ns3/mobility-helper.h"
31#include "ns3/multi-model-spectrum-channel.h"
32#include "ns3/nist-error-rate-model.h"
33#include "ns3/node.h"
34#include "ns3/non-communicating-net-device.h"
35#include "ns3/pointer.h"
36#include "ns3/rng-seed-manager.h"
37#include "ns3/simulator.h"
38#include "ns3/spectrum-wifi-helper.h"
39#include "ns3/spectrum-wifi-phy.h"
40#include "ns3/sta-wifi-mac.h"
41#include "ns3/string.h"
42#include "ns3/test.h"
43#include "ns3/threshold-preamble-detection-model.h"
44#include "ns3/waveform-generator.h"
45#include "ns3/wifi-mac-header.h"
46#include "ns3/wifi-net-device.h"
47#include "ns3/wifi-phy-listener.h"
48#include "ns3/wifi-psdu.h"
49#include "ns3/wifi-spectrum-signal-parameters.h"
50#include "ns3/wifi-spectrum-value-helper.h"
51#include "ns3/wifi-utils.h"
52
53#include <algorithm>
54#include <iterator>
55#include <memory>
56
57using namespace ns3;
58
59NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
60
61static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
62static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
64static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
65static const uint16_t DEFAULT_GUARD_WIDTH =
66 DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
67
72class OfdmaTestHePhy : public HePhy
73{
74 public:
80 OfdmaTestHePhy(uint16_t staId);
81 ~OfdmaTestHePhy() override;
82
90 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
91
97 void SetGlobalPpduUid(uint64_t uid);
98
99 private:
100 uint16_t m_staId;
101}; // class OfdmaTestHePhy
102
104 : HePhy(),
105 m_staId(staId)
106{
107}
108
110{
111}
112
113uint16_t
115{
116 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
117 {
118 return m_staId;
119 }
120 return HePhy::GetStaId(ppdu);
121}
122
123void
125{
126 m_globalPpduUid = uid;
127}
128
133{
134 public:
139 static TypeId GetTypeId();
145 OfdmaSpectrumWifiPhy(uint16_t staId);
146 ~OfdmaSpectrumWifiPhy() override;
147
148 void DoInitialize() override;
149 void DoDispose() override;
150
151 using WifiPhy::Reset;
152
158 typedef void (*TxPpduUidCallback)(uint64_t uid);
159
164 void StartTx(Ptr<const WifiPpdu> ppdu, const WifiTxVector& txVector) override;
165
171 void SetPpduUid(uint64_t uid);
172
178 void SetTriggerFrameUid(uint64_t uid);
179
183 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
188
199 Time GetEnergyDuration(double energyW, WifiSpectrumBand band);
200
205
206 private:
210}; // class OfdmaSpectrumWifiPhy
211
212TypeId
214{
215 static TypeId tid =
216 TypeId("ns3::OfdmaSpectrumWifiPhy")
218 .SetGroupName("Wifi")
219 .AddTraceSource("TxPpduUid",
220 "UID of the PPDU to be transmitted",
222 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
223 return tid;
224}
225
228{
229 m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
231}
232
234{
235}
236
237void
239{
240 // Replace HE PHY instance with test instance
242 SpectrumWifiPhy::DoInitialize();
243}
244
245void
247{
248 m_ofdmTestHePhy = nullptr;
249 SpectrumWifiPhy::DoDispose();
250}
251
252void
254{
257}
258
259void
261{
263}
264
265void
267{
268 m_phyTxPpduUidTrace(ppdu->GetUid());
269 SpectrumWifiPhy::StartTx(ppdu, txVector);
270}
271
272std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
274{
276}
277
280{
281 return m_currentEvent;
282}
283
284Time
286{
287 return m_interference->GetEnergyDuration(energyW, band);
288}
289
292{
293 return DynamicCast<const HePhy>(GetPhyEntity(WIFI_MOD_CLASS_HE));
294}
295
303{
304 public:
307
308 private:
309 void DoSetup() override;
310 void DoTeardown() override;
311 void DoRun() override;
312
321 RxSignalInfo rxSignalInfo,
322 WifiTxVector txVector,
323 std::vector<bool> statusPerMpdu);
332 RxSignalInfo rxSignalInfo,
333 WifiTxVector txVector,
334 std::vector<bool> statusPerMpdu);
343 RxSignalInfo rxSignalInfo,
344 WifiTxVector txVector,
345 std::vector<bool> statusPerMpdu);
346
362
369 void CheckResultsSta1(uint32_t expectedRxSuccess,
370 uint32_t expectedRxFailure,
371 uint32_t expectedRxBytes);
378 void CheckResultsSta2(uint32_t expectedRxSuccess,
379 uint32_t expectedRxFailure,
380 uint32_t expectedRxBytes);
387 void CheckResultsSta3(uint32_t expectedRxSuccess,
388 uint32_t expectedRxFailure,
389 uint32_t expectedRxBytes);
390
394 void ResetResults();
395
401 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
402
408 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
412 void StopInterference();
413
417 void RunOne();
418
431
441
447
448 uint16_t m_frequency;
449 uint16_t m_channelWidth;
451};
452
454 : TestCase("DL-OFDMA PHY test"),
455 m_countRxSuccessSta1(0),
456 m_countRxSuccessSta2(0),
457 m_countRxSuccessSta3(0),
458 m_countRxFailureSta1(0),
459 m_countRxFailureSta2(0),
460 m_countRxFailureSta3(0),
461 m_countRxBytesSta1(0),
462 m_countRxBytesSta2(0),
463 m_countRxBytesSta3(0),
464 m_frequency(DEFAULT_FREQUENCY),
465 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
466 m_expectedPpduDuration(NanoSeconds(306400))
467{
468}
469
470void
472{
482}
483
484void
485TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
486{
487 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
488 WifiConstPsduMap psdus;
489 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
490 0,
492 800,
493 1,
494 1,
495 0,
497 false,
498 false);
499 HeRu::RuType ruType = HeRu::RU_106_TONE;
500 if (m_channelWidth == 20)
501 {
502 ruType = HeRu::RU_106_TONE;
503 txVector.SetRuAllocation({96});
504 }
505 else if (m_channelWidth == 40)
506 {
507 ruType = HeRu::RU_242_TONE;
508 txVector.SetRuAllocation({192, 192});
509 }
510 else if (m_channelWidth == 80)
511 {
512 ruType = HeRu::RU_484_TONE;
513 txVector.SetRuAllocation({200, 200, 200, 200});
514 }
515 else if (m_channelWidth == 160)
516 {
517 ruType = HeRu::RU_996_TONE;
518 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208});
519 }
520 else
521 {
522 NS_ASSERT_MSG(false, "Unsupported channel width");
523 }
524
525 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
526
527 HeRu::RuSpec ru1(ruType, 1, true);
528 txVector.SetRu(ru1, rxStaId1);
529 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
530 txVector.SetNss(1, rxStaId1);
531
532 HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
533 txVector.SetRu(ru2, rxStaId2);
534 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
535 txVector.SetNss(1, rxStaId2);
536
537 Ptr<Packet> pkt1 = Create<Packet>(1000);
538 WifiMacHeader hdr1;
540 hdr1.SetQosTid(0);
541 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
542 hdr1.SetSequenceNumber(1);
543 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
544 psdus.insert(std::make_pair(rxStaId1, psdu1));
545
546 Ptr<Packet> pkt2 = Create<Packet>(1500);
547 WifiMacHeader hdr2;
549 hdr2.SetQosTid(0);
550 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
551 hdr2.SetSequenceNumber(2);
552 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
553 psdus.insert(std::make_pair(rxStaId2, psdu2));
554
555 m_phyAp->Send(psdus, txVector);
556}
557
558void
560{
562 m_phyInterferer->SetPeriod(duration);
564 Simulator::Schedule(duration, &TestDlOfdmaPhyTransmission::StopInterference, this);
565}
566
567void
569{
571}
572
574{
575}
576
577void
579 RxSignalInfo rxSignalInfo,
580 WifiTxVector txVector,
581 std::vector<bool> /*statusPerMpdu*/)
582{
583 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
585 m_countRxBytesSta1 += (psdu->GetSize() - 30);
586}
587
588void
590 RxSignalInfo rxSignalInfo,
591 WifiTxVector txVector,
592 std::vector<bool> /*statusPerMpdu*/)
593{
594 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
596 m_countRxBytesSta2 += (psdu->GetSize() - 30);
597}
598
599void
601 RxSignalInfo rxSignalInfo,
602 WifiTxVector txVector,
603 std::vector<bool> /*statusPerMpdu*/)
604{
605 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
607 m_countRxBytesSta3 += (psdu->GetSize() - 30);
608}
609
610void
612{
613 NS_LOG_FUNCTION(this << *psdu);
615}
616
617void
619{
620 NS_LOG_FUNCTION(this << *psdu);
622}
623
624void
626{
627 NS_LOG_FUNCTION(this << *psdu);
629}
630
631void
633 uint32_t expectedRxFailure,
634 uint32_t expectedRxBytes)
635{
637 expectedRxSuccess,
638 "The number of successfully received packets by STA 1 is not correct!");
640 expectedRxFailure,
641 "The number of unsuccessfully received packets by STA 1 is not correct!");
643 expectedRxBytes,
644 "The number of bytes received by STA 1 is not correct!");
645}
646
647void
649 uint32_t expectedRxFailure,
650 uint32_t expectedRxBytes)
651{
653 expectedRxSuccess,
654 "The number of successfully received packets by STA 2 is not correct!");
656 expectedRxFailure,
657 "The number of unsuccessfully received packets by STA 2 is not correct!");
659 expectedRxBytes,
660 "The number of bytes received by STA 2 is not correct!");
661}
662
663void
665 uint32_t expectedRxFailure,
666 uint32_t expectedRxBytes)
667{
669 expectedRxSuccess,
670 "The number of successfully received packets by STA 3 is not correct!");
672 expectedRxFailure,
673 "The number of unsuccessfully received packets by STA 3 is not correct!");
675 expectedRxBytes,
676 "The number of bytes received by STA 3 is not correct!");
677}
678
679void
681{
682 // This is needed to make sure PHY state will be checked as the last event if a state change
683 // occured at the exact same time as the check
684 Simulator::ScheduleNow(&TestDlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
685}
686
687void
689 WifiPhyState expectedState)
690{
691 WifiPhyState currentState;
692 PointerValue ptr;
693 phy->GetAttribute("State", ptr);
694 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
695 currentState = state->GetState();
696 NS_LOG_FUNCTION(this << currentState);
697 NS_TEST_ASSERT_MSG_EQ(currentState,
698 expectedState,
699 "PHY State " << currentState << " does not match expected state "
700 << expectedState << " at " << Simulator::Now());
701}
702
703void
705{
706 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
707 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
708 lossModel->SetFrequency(m_frequency * 1e6);
709 spectrumChannel->AddPropagationLossModel(lossModel);
711 CreateObject<ConstantSpeedPropagationDelayModel>();
712 spectrumChannel->SetPropagationDelayModel(delayModel);
713
714 Ptr<Node> apNode = CreateObject<Node>();
715 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
716 m_phyAp = CreateObject<SpectrumWifiPhy>();
719 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
720 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
721 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
722 m_phyAp->SetErrorRateModel(apErrorModel);
723 m_phyAp->SetDevice(apDev);
724 m_phyAp->SetChannel(spectrumChannel);
725 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
726 m_phyAp->SetMobility(apMobility);
727 apDev->SetPhy(m_phyAp);
728 apNode->AggregateObject(apMobility);
729 apNode->AddDevice(apDev);
730
731 Ptr<Node> sta1Node = CreateObject<Node>();
732 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
733 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
736 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
737 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
738 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
739 m_phySta1->SetErrorRateModel(sta1ErrorModel);
740 m_phySta1->SetDevice(sta1Dev);
741 m_phySta1->SetChannel(spectrumChannel);
745 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
746 m_phySta1->SetMobility(sta1Mobility);
747 sta1Dev->SetPhy(m_phySta1);
748 sta1Node->AggregateObject(sta1Mobility);
749 sta1Node->AddDevice(sta1Dev);
750
751 Ptr<Node> sta2Node = CreateObject<Node>();
752 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
753 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
756 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
757 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
758 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
759 m_phySta2->SetErrorRateModel(sta2ErrorModel);
760 m_phySta2->SetDevice(sta2Dev);
761 m_phySta2->SetChannel(spectrumChannel);
765 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
766 m_phySta2->SetMobility(sta2Mobility);
767 sta2Dev->SetPhy(m_phySta2);
768 sta2Node->AggregateObject(sta2Mobility);
769 sta2Node->AddDevice(sta2Dev);
770
771 Ptr<Node> sta3Node = CreateObject<Node>();
772 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
773 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
776 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
777 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
778 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
779 m_phySta3->SetErrorRateModel(sta3ErrorModel);
780 m_phySta3->SetDevice(sta3Dev);
781 m_phySta3->SetChannel(spectrumChannel);
785 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
786 m_phySta3->SetMobility(sta3Mobility);
787 sta3Dev->SetPhy(m_phySta3);
788 sta3Node->AggregateObject(sta3Mobility);
789 sta3Node->AddDevice(sta3Dev);
790
791 Ptr<Node> interfererNode = CreateObject<Node>();
792 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
793 m_phyInterferer = CreateObject<WaveformGenerator>();
794 m_phyInterferer->SetDevice(interfererDev);
795 m_phyInterferer->SetChannel(spectrumChannel);
797 interfererNode->AddDevice(interfererDev);
798}
799
800void
802{
803 m_phyAp->Dispose();
804 m_phyAp = nullptr;
806 m_phySta1 = nullptr;
808 m_phySta2 = nullptr;
810 m_phySta3 = nullptr;
812 m_phyInterferer = nullptr;
813}
814
815void
817{
818 RngSeedManager::SetSeed(1);
819 RngSeedManager::SetRun(1);
820 int64_t streamNumber = 0;
821 m_phyAp->AssignStreams(streamNumber);
822 m_phySta1->AssignStreams(streamNumber);
823 m_phySta2->AssignStreams(streamNumber);
824 m_phySta3->AssignStreams(streamNumber);
825
826 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
831
840
841 Simulator::Schedule(Seconds(0.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
842
843 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
844 // Each STA should receive its PSDU.
845 Simulator::Schedule(Seconds(1.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
846
847 // Since it takes m_expectedPpduDuration to transmit the PPDU,
848 // all 3 PHYs should be back to IDLE at the same time,
849 // even the PHY that has no PSDU addressed to it.
850 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
852 this,
853 m_phySta1,
855 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
857 this,
858 m_phySta2,
860 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
862 this,
863 m_phySta3,
865 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
867 this,
868 m_phySta1,
870 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
872 this,
873 m_phySta2,
875 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
877 this,
878 m_phySta3,
880
881 // One PSDU of 1000 bytes should have been successfully received by STA 1
882 Simulator::Schedule(Seconds(1.1),
884 this,
885 1,
886 0,
887 1000);
888 // One PSDU of 1500 bytes should have been successfully received by STA 2
889 Simulator::Schedule(Seconds(1.1),
891 this,
892 1,
893 0,
894 1500);
895 // No PSDU should have been received by STA 3
896 Simulator::Schedule(Seconds(1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
897
898 Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
899
900 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
901 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
902 // but should keep its PHY busy during all PPDU duration.
903 Simulator::Schedule(Seconds(2.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 3);
904
905 // Since it takes m_expectedPpduDuration to transmit the PPDU,
906 // all 3 PHYs should be back to IDLE at the same time,
907 // even the PHY that has no PSDU addressed to it.
908 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
910 this,
911 m_phySta1,
913 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
915 this,
916 m_phySta2,
918 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
920 this,
921 m_phySta3,
923 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
925 this,
926 m_phySta1,
928 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
930 this,
931 m_phySta2,
933 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
935 this,
936 m_phySta3,
938
939 // One PSDU of 1000 bytes should have been successfully received by STA 1
940 Simulator::Schedule(Seconds(2.1),
942 this,
943 1,
944 0,
945 1000);
946 // No PSDU should have been received by STA 2
947 Simulator::Schedule(Seconds(2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 0, 0);
948 // One PSDU of 1500 bytes should have been successfully received by STA 3
949 Simulator::Schedule(Seconds(2.1),
951 this,
952 1,
953 0,
954 1500);
955
956 Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
957
958 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
959 Simulator::Schedule(Seconds(3.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
960
961 // A strong non-wifi interference is generated on RU 1 during PSDU reception
962 BandInfo bandInfo;
963 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
964 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
965 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
966 Bands bands;
967 bands.push_back(bandInfo);
968
969 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
970 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
971 double interferencePower = 0.1; // watts
972 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
973
974 Simulator::Schedule(Seconds(3.0) + MicroSeconds(50),
976 this,
977 interferencePsdRu1,
978 MilliSeconds(100));
979
980 // Since it takes m_expectedPpduDuration to transmit the PPDU,
981 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
982 // even the PHY that has no PSDU addressed to it.
983 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
985 this,
986 m_phySta1,
988 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
990 this,
991 m_phySta2,
993 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
995 this,
996 m_phySta3,
998 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1000 this,
1001 m_phySta1,
1003 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1005 this,
1006 m_phySta2,
1008 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1010 this,
1011 m_phySta3,
1013
1014 // One PSDU of 1000 bytes should have been unsuccessfully received by STA 1 (since interference
1015 // occupies RU 1)
1016 Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1017 // One PSDU of 1500 bytes should have been successfully received by STA 2
1018 Simulator::Schedule(Seconds(3.1),
1020 this,
1021 1,
1022 0,
1023 1500);
1024 // No PSDU should have been received by STA3
1025 Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1026
1027 Simulator::Schedule(Seconds(3.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1028
1029 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1030 Simulator::Schedule(Seconds(4.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1031
1032 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1033 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1034 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1035 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1036 bands.clear();
1037 bands.push_back(bandInfo);
1038
1039 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1040 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1041 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1042
1043 Simulator::Schedule(Seconds(4.0) + MicroSeconds(50),
1045 this,
1046 interferencePsdRu2,
1047 MilliSeconds(100));
1048
1049 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1050 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1051 // same time, even the PHY that has no PSDU addressed to it.
1052 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1054 this,
1055 m_phySta1,
1057 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1059 this,
1060 m_phySta2,
1062 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1064 this,
1065 m_phySta3,
1067 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1069 this,
1070 m_phySta1,
1072 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1074 this,
1075 m_phySta2,
1077 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1079 this,
1080 m_phySta3,
1082
1083 // One PSDU of 1000 bytes should have been successfully received by STA 1
1084 Simulator::Schedule(Seconds(4.1),
1086 this,
1087 1,
1088 0,
1089 1000);
1090 // One PSDU of 1500 bytes should have been unsuccessfully received by STA 2 (since interference
1091 // occupies RU 2)
1092 Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1093 // No PSDU should have been received by STA3
1094 Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1095
1096 Simulator::Schedule(Seconds(4.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1097
1098 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1099 Simulator::Schedule(Seconds(5.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1100
1101 // A strong non-wifi interference is generated on the full band during PSDU reception
1102 bandInfo.fc = m_frequency * 1e6;
1103 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1104 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1105 bands.clear();
1106 bands.push_back(bandInfo);
1107
1108 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1109 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1110 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1111
1112 Simulator::Schedule(Seconds(5.0) + MicroSeconds(50),
1114 this,
1115 interferencePsdAll,
1116 MilliSeconds(100));
1117
1118 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1119 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1120 // even the PHY that has no PSDU addressed to it.
1121 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1123 this,
1124 m_phySta1,
1126 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1128 this,
1129 m_phySta2,
1131 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1133 this,
1134 m_phySta3,
1136 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1138 this,
1139 m_phySta1,
1141 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1143 this,
1144 m_phySta2,
1146 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1148 this,
1149 m_phySta3,
1151
1152 // One PSDU of 1000 bytes should have been unsuccessfully received by STA 1 (since interference
1153 // occupies RU 1)
1154 Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1155 // One PSDU of 1500 bytes should have been unsuccessfully received by STA 2 (since interference
1156 // occupies RU 2)
1157 Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1158 // No PSDU should have been received by STA3
1159 Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1160
1161 Simulator::Schedule(Seconds(5.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1162
1163 Simulator::Run();
1164}
1165
1166void
1168{
1169 m_frequency = 5180;
1170 m_channelWidth = 20;
1172 RunOne();
1173
1174 m_frequency = 5190;
1175 m_channelWidth = 40;
1177 RunOne();
1178
1179 m_frequency = 5210;
1180 m_channelWidth = 80;
1182 RunOne();
1183
1184 m_frequency = 5250;
1185 m_channelWidth = 160;
1187 RunOne();
1188
1189 Simulator::Destroy();
1190}
1191
1199{
1200 public:
1202
1203 private:
1204 void DoSetup() override;
1205 void DoTeardown() override;
1206 void DoRun() override;
1207
1216 RxSignalInfo rxSignalInfo,
1217 WifiTxVector txVector,
1218 const std::vector<bool> statusPerMpdu);
1219
1228 RxSignalInfo rxSignalInfo,
1229 WifiTxVector txVector,
1230 std::vector<bool> statusPerMpdu);
1231
1237
1243
1250 void CheckResultsSta1(uint32_t expectedRxSuccess,
1251 uint32_t expectedRxFailure,
1252 uint32_t expectedRxBytes);
1253
1260 void CheckResultsSta2(uint32_t expectedRxSuccess,
1261 uint32_t expectedRxFailure,
1262 uint32_t expectedRxBytes);
1263
1267 void ResetResults();
1268
1276 void SendMuPpdu(uint16_t rxStaId1,
1277 uint16_t rxStaId2,
1278 const std::vector<bool>& puncturedSubchannels);
1279
1285 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1286
1290 void StopInterference();
1291
1295 void RunOne();
1296
1303
1310
1317
1322
1323 uint16_t m_frequency;
1325
1328
1331};
1332
1334 : TestCase("DL-OFDMA PHY puncturing test"),
1335 m_countRxSuccessSta1(0),
1336 m_countRxSuccessSta2(0),
1337 m_countRxFailureSta1(0),
1338 m_countRxFailureSta2(0),
1339 m_countRxBytesSta1(0),
1340 m_countRxBytesSta2(0),
1341 m_frequency(5210),
1342 m_channelWidth(80),
1343 m_indexSubchannel(0),
1344 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1345 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1346{
1347}
1348
1349void
1351{
1358}
1359
1360void
1362 uint16_t rxStaId2,
1363 const std::vector<bool>& puncturedSubchannels)
1364{
1365 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1366 WifiConstPsduMap psdus;
1367 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
1368 0,
1370 800,
1371 1,
1372 1,
1373 0,
1375 false,
1376 false);
1377
1378 HeRu::RuType ruType =
1379 puncturedSubchannels.empty()
1380 ? HeRu::RU_484_TONE
1381 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1382 HeRu::RuSpec ru1(ruType, 1, true);
1383 txVector.SetRu(ru1, rxStaId1);
1384 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1385 txVector.SetNss(1, rxStaId1);
1386
1387 ruType = puncturedSubchannels.empty()
1388 ? HeRu::RU_484_TONE
1389 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1390 HeRu::RuSpec ru2(ruType,
1391 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1392 true);
1393 txVector.SetRu(ru2, rxStaId2);
1394 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1395 txVector.SetNss(1, rxStaId2);
1396
1397 std::vector<uint8_t> ruAlloc;
1398 if (puncturedSubchannels.empty())
1399 {
1400 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1401 }
1402 else
1403 {
1404 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1405 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1406 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1407 : (puncturedSubchannels.at(3) ? 192 : 200));
1408 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1409 : (puncturedSubchannels.at(3) ? 113 : 200));
1410 }
1411
1412 txVector.SetRuAllocation(ruAlloc);
1413 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1414
1415 Ptr<Packet> pkt1 = Create<Packet>(1000);
1416 WifiMacHeader hdr1;
1418 hdr1.SetQosTid(0);
1419 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1420 hdr1.SetSequenceNumber(1);
1421 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1422 psdus.insert(std::make_pair(rxStaId1, psdu1));
1423
1424 Ptr<Packet> pkt2 = Create<Packet>(1500);
1425 WifiMacHeader hdr2;
1427 hdr2.SetQosTid(0);
1428 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1429 hdr2.SetSequenceNumber(2);
1430 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1431 psdus.insert(std::make_pair(rxStaId2, psdu2));
1432
1433 if (!puncturedSubchannels.empty())
1434 {
1435 txVector.SetInactiveSubchannels(puncturedSubchannels);
1436 }
1437
1438 m_phyAp->Send(psdus, txVector);
1439}
1440
1441void
1443{
1444 NS_LOG_FUNCTION(this << duration);
1446 m_phyInterferer->SetPeriod(duration);
1448 Simulator::Schedule(duration, &TestDlOfdmaPhyPuncturing::StopInterference, this);
1449}
1450
1451void
1453{
1454 NS_LOG_FUNCTION(this);
1456}
1457
1458void
1460 RxSignalInfo rxSignalInfo,
1461 WifiTxVector txVector,
1462 std::vector<bool> /*statusPerMpdu*/)
1463{
1464 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1466 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1467}
1468
1469void
1471 RxSignalInfo rxSignalInfo,
1472 WifiTxVector txVector,
1473 std::vector<bool> /*statusPerMpdu*/)
1474{
1475 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1477 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1478}
1479
1480void
1482{
1483 NS_LOG_FUNCTION(this << *psdu);
1485}
1486
1487void
1489{
1490 NS_LOG_FUNCTION(this << *psdu);
1492}
1493
1494void
1496 uint32_t expectedRxFailure,
1497 uint32_t expectedRxBytes)
1498{
1500 expectedRxSuccess,
1501 "The number of successfully received packets by STA 1 is not correct!");
1503 expectedRxFailure,
1504 "The number of unsuccessfully received packets by STA 1 is not correct!");
1506 expectedRxBytes,
1507 "The number of bytes received by STA 1 is not correct!");
1508}
1509
1510void
1512 uint32_t expectedRxFailure,
1513 uint32_t expectedRxBytes)
1514{
1516 expectedRxSuccess,
1517 "The number of successfully received packets by STA 2 is not correct!");
1519 expectedRxFailure,
1520 "The number of unsuccessfully received packets by STA 2 is not correct!");
1522 expectedRxBytes,
1523 "The number of bytes received by STA 2 is not correct!");
1524}
1525
1526void
1528{
1529 // This is needed to make sure PHY state will be checked as the last event if a state change
1530 // occured at the exact same time as the check
1531 Simulator::ScheduleNow(&TestDlOfdmaPhyPuncturing::DoCheckPhyState, this, phy, expectedState);
1532}
1533
1534void
1536{
1537 WifiPhyState currentState;
1538 PointerValue ptr;
1539 phy->GetAttribute("State", ptr);
1540 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1541 currentState = state->GetState();
1542 NS_LOG_FUNCTION(this << currentState);
1543 NS_TEST_ASSERT_MSG_EQ(currentState,
1544 expectedState,
1545 "PHY State " << currentState << " does not match expected state "
1546 << expectedState << " at " << Simulator::Now());
1547}
1548
1549void
1551{
1552 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1553 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1554 lossModel->SetFrequency(m_frequency * 1e6);
1555 spectrumChannel->AddPropagationLossModel(lossModel);
1557 CreateObject<ConstantSpeedPropagationDelayModel>();
1558 spectrumChannel->SetPropagationDelayModel(delayModel);
1559
1560 Ptr<Node> apNode = CreateObject<Node>();
1561 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1562 m_phyAp = CreateObject<SpectrumWifiPhy>();
1565 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1566 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1567 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1568 m_phyAp->SetErrorRateModel(apErrorModel);
1569 m_phyAp->SetDevice(apDev);
1570 m_phyAp->SetChannel(spectrumChannel);
1571 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1572 m_phyAp->SetMobility(apMobility);
1573 apDev->SetPhy(m_phyAp);
1574 apNode->AggregateObject(apMobility);
1575 apNode->AddDevice(apDev);
1576
1577 Ptr<Node> sta1Node = CreateObject<Node>();
1578 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1579 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1582 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1583 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1584 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1585 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1586 m_phySta1->SetDevice(sta1Dev);
1587 m_phySta1->SetChannel(spectrumChannel);
1591 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1592 m_phySta1->SetMobility(sta1Mobility);
1593 sta1Dev->SetPhy(m_phySta1);
1594 sta1Node->AggregateObject(sta1Mobility);
1595 sta1Node->AddDevice(sta1Dev);
1596
1597 Ptr<Node> sta2Node = CreateObject<Node>();
1598 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1599 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1602 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1603 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1604 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1605 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1606 m_phySta2->SetDevice(sta2Dev);
1607 m_phySta2->SetChannel(spectrumChannel);
1611 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1612 m_phySta2->SetMobility(sta2Mobility);
1613 sta2Dev->SetPhy(m_phySta2);
1614 sta2Node->AggregateObject(sta2Mobility);
1615 sta2Node->AddDevice(sta2Dev);
1616
1617 Ptr<Node> interfererNode = CreateObject<Node>();
1618 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1619 m_phyInterferer = CreateObject<WaveformGenerator>();
1620 m_phyInterferer->SetDevice(interfererDev);
1621 m_phyInterferer->SetChannel(spectrumChannel);
1623 interfererNode->AddDevice(interfererDev);
1624}
1625
1626void
1628{
1629 m_phyAp->Dispose();
1630 m_phyAp = nullptr;
1631 m_phySta1->Dispose();
1632 m_phySta1 = nullptr;
1633 m_phySta2->Dispose();
1634 m_phySta2 = nullptr;
1636 m_phyInterferer = nullptr;
1637}
1638
1639void
1641{
1642 RngSeedManager::SetSeed(1);
1643 RngSeedManager::SetRun(1);
1644 int64_t streamNumber = 0;
1645 m_phyAp->AssignStreams(streamNumber);
1646 m_phySta1->AssignStreams(streamNumber);
1647 m_phySta2->AssignStreams(streamNumber);
1648
1649 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1654
1661
1662 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1663 // duration of the test run
1664 BandInfo bandInfo;
1665 bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1666 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1667 // the border of another RU
1668 bandInfo.fl = bandInfo.fc - (5 * 1e6);
1669 bandInfo.fh = bandInfo.fc + (5 * 1e6);
1670 Bands bands;
1671 bands.push_back(bandInfo);
1672
1673 Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1674 Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1675 double interferencePower = 0.1; // watts
1676 *interferencePsd = interferencePower / 10e6;
1677
1678 Simulator::Schedule(Seconds(0.0),
1680 this,
1681 interferencePsd,
1682 Seconds(3));
1683
1684 //---------------------------------------------------------------------------
1685 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1686 Simulator::Schedule(Seconds(1.0),
1688 this,
1689 1,
1690 2,
1691 std::vector<bool>{});
1692
1693 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1694 // both PHYs should be back to IDLE at the same time.
1695 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1697 this,
1698 m_phySta1,
1700 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1702 this,
1703 m_phySta2,
1705 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1707 this,
1708 m_phySta1,
1710 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1712 this,
1713 m_phySta2,
1715
1716 if (m_indexSubchannel < 2) // interference in RU 1
1717 {
1718 // One PSDU of 1000 bytes should have been unsuccessfully received by STA 1
1719 Simulator::Schedule(Seconds(1.1),
1721 this,
1722 0,
1723 1,
1724 0);
1725 // One PSDU of 1500 bytes should have been successfully received by STA 2
1726 Simulator::Schedule(Seconds(1.1),
1728 this,
1729 1,
1730 0,
1731 1500);
1732 }
1733 else // interference in RU 2
1734 {
1735 // One PSDU of 1000 bytes should have been successfully received by STA 1
1736 Simulator::Schedule(Seconds(1.1),
1738 this,
1739 1,
1740 0,
1741 1000);
1742 // One PSDU of 1500 bytes should have been unsuccessfully received by STA 2
1743 Simulator::Schedule(Seconds(1.1),
1745 this,
1746 0,
1747 1,
1748 0);
1749 }
1750
1751 Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1752
1753 //---------------------------------------------------------------------------
1754 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1755 // the punctured 20 MHz subchannel is the one that has interference
1756 std::vector<bool> puncturedSubchannels;
1757 for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1758 {
1759 if (i == m_indexSubchannel)
1760 {
1761 puncturedSubchannels.push_back(true);
1762 }
1763 else
1764 {
1765 puncturedSubchannels.push_back(false);
1766 }
1767 }
1768 Simulator::Schedule(Seconds(2.0),
1770 this,
1771 1,
1772 2,
1773 puncturedSubchannels);
1774
1775 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1776 // both PHYs should be back to IDLE at the same time.
1777 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1779 this,
1780 m_phySta1,
1782 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1784 this,
1785 m_phySta2,
1787 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1789 this,
1790 m_phySta1,
1792 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1794 this,
1795 m_phySta2,
1797
1798 // One PSDU of 1000 bytes should have been successfully received by STA 1
1799 Simulator::Schedule(Seconds(2.1),
1801 this,
1802 1,
1803 0,
1804 1000);
1805 // One PSDU of 1500 bytes should have been successfully received by STA 2
1806 Simulator::Schedule(Seconds(2.1),
1808 this,
1809 1,
1810 0,
1811 1500);
1812
1813 Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1814
1815 Simulator::Run();
1816}
1817
1818void
1820{
1821 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1822 // cannot be punctured
1823 for (auto index : {1, 2, 3})
1824 {
1825 m_indexSubchannel = index;
1826 RunOne();
1827 }
1828 Simulator::Destroy();
1829}
1830
1838{
1839 public:
1841 ~TestUlOfdmaPpduUid() override;
1842
1843 private:
1844 void DoSetup() override;
1845 void DoTeardown() override;
1846 void DoRun() override;
1847
1852 void TxPpduAp(uint64_t uid);
1857 void TxPpduSta1(uint64_t uid);
1862 void TxPpduSta2(uint64_t uid);
1866 void ResetPpduUid();
1867
1871 void SendMuPpdu();
1875 void SendTbPpdu();
1880 void SendSuPpdu(uint16_t txStaId);
1881
1887 void CheckUid(uint16_t staId, uint64_t expectedUid);
1888
1892
1893 uint64_t m_ppduUidAp;
1894 uint64_t m_ppduUidSta1;
1895 uint64_t m_ppduUidSta2;
1896};
1897
1899 : TestCase("UL-OFDMA PPDU UID attribution test"),
1900 m_ppduUidAp(UINT64_MAX),
1901 m_ppduUidSta1(UINT64_MAX),
1902 m_ppduUidSta2(UINT64_MAX)
1903{
1904}
1905
1907{
1908}
1909
1910void
1912{
1913 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1914 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1915 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1916 spectrumChannel->AddPropagationLossModel(lossModel);
1918 CreateObject<ConstantSpeedPropagationDelayModel>();
1919 spectrumChannel->SetPropagationDelayModel(delayModel);
1920
1921 Ptr<Node> apNode = CreateObject<Node>();
1922 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1923 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1926 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1927 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1928 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1929 m_phyAp->SetErrorRateModel(apErrorModel);
1930 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1937 m_phyAp->SetDevice(apDev);
1938 m_phyAp->SetChannel(spectrumChannel);
1941 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1942 m_phyAp->SetMobility(apMobility);
1943 apDev->SetPhy(m_phyAp);
1944 apNode->AggregateObject(apMobility);
1945 apNode->AddDevice(apDev);
1947 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1948
1949 Ptr<Node> sta1Node = CreateObject<Node>();
1950 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1951 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1954 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1955 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1956 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1957 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1960 m_phySta1->SetDevice(sta1Dev);
1961 m_phySta1->SetChannel(spectrumChannel);
1964 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1965 m_phySta1->SetMobility(sta1Mobility);
1966 sta1Dev->SetPhy(m_phySta1);
1967 sta1Node->AggregateObject(sta1Mobility);
1968 sta1Node->AddDevice(sta1Dev);
1969
1970 Ptr<Node> sta2Node = CreateObject<Node>();
1971 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1972 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1975 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1976 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1977 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1978 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1981 m_phySta2->SetDevice(sta2Dev);
1982 m_phySta2->SetChannel(spectrumChannel);
1985 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1986 m_phySta2->SetMobility(sta2Mobility);
1987 sta2Dev->SetPhy(m_phySta2);
1988 sta2Node->AggregateObject(sta2Mobility);
1989 sta2Node->AddDevice(sta2Dev);
1990}
1991
1992void
1994{
1995 m_phyAp->Dispose();
1996 m_phyAp = nullptr;
1997 m_phySta1->Dispose();
1998 m_phySta1 = nullptr;
1999 m_phySta2->Dispose();
2000 m_phySta2 = nullptr;
2001}
2002
2003void
2004TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
2005{
2006 uint64_t uid;
2007 std::string device;
2008 switch (staId)
2009 {
2010 case 0:
2011 uid = m_ppduUidAp;
2012 device = "AP";
2013 break;
2014 case 1:
2015 uid = m_ppduUidSta1;
2016 device = "STA1";
2017 break;
2018 case 2:
2019 uid = m_ppduUidSta2;
2020 device = "STA2";
2021 break;
2022 default:
2023 NS_ABORT_MSG("Unexpected STA-ID");
2024 }
2026 expectedUid,
2027 "UID " << uid << " does not match expected one " << expectedUid << " for "
2028 << device << " at " << Simulator::Now());
2029}
2030
2031void
2033{
2034 NS_LOG_FUNCTION(this << uid);
2035 m_ppduUidAp = uid;
2036}
2037
2038void
2040{
2041 NS_LOG_FUNCTION(this << uid);
2042 m_ppduUidSta1 = uid;
2043}
2044
2045void
2047{
2048 NS_LOG_FUNCTION(this << uid);
2049 m_ppduUidSta2 = uid;
2050}
2051
2052void
2054{
2055 NS_LOG_FUNCTION(this);
2056 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2057}
2058
2059void
2061{
2062 WifiConstPsduMap psdus;
2063 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2064 0,
2066 800,
2067 1,
2068 1,
2069 0,
2071 false,
2072 false);
2073
2074 uint16_t rxStaId1 = 1;
2075 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2076 txVector.SetRu(ru1, rxStaId1);
2077 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2078 txVector.SetNss(1, rxStaId1);
2079
2080 uint16_t rxStaId2 = 2;
2081 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2082 txVector.SetRu(ru2, rxStaId2);
2083 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2084 txVector.SetNss(1, rxStaId2);
2085 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2086 txVector.SetRuAllocation({96});
2087
2088 Ptr<Packet> pkt1 = Create<Packet>(1000);
2089 WifiMacHeader hdr1;
2091 hdr1.SetQosTid(0);
2092 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2093 hdr1.SetSequenceNumber(1);
2094 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2095 psdus.insert(std::make_pair(rxStaId1, psdu1));
2096
2097 Ptr<Packet> pkt2 = Create<Packet>(1500);
2098 WifiMacHeader hdr2;
2100 hdr2.SetQosTid(0);
2101 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2102 hdr2.SetSequenceNumber(2);
2103 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2104 psdus.insert(std::make_pair(rxStaId2, psdu2));
2105
2106 m_phyAp->Send(psdus, txVector);
2107}
2108
2109void
2111{
2112 WifiConstPsduMap psdus1;
2113 WifiConstPsduMap psdus2;
2114 WifiTxVector txVector1 = WifiTxVector(HePhy::GetHeMcs7(),
2115 0,
2117 800,
2118 1,
2119 1,
2120 0,
2122 false,
2123 false);
2124 WifiTxVector txVector2 = txVector1;
2125
2126 uint16_t rxStaId1 = 1;
2127 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2128 txVector1.SetRu(ru1, rxStaId1);
2129 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2130 txVector1.SetNss(1, rxStaId1);
2131
2132 Ptr<Packet> pkt1 = Create<Packet>(1000);
2133 WifiMacHeader hdr1;
2135 hdr1.SetQosTid(0);
2136 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2137 hdr1.SetSequenceNumber(1);
2138 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2139 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2140
2141 uint16_t rxStaId2 = 2;
2142 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2143 txVector2.SetRu(ru2, rxStaId2);
2144 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2145 txVector2.SetNss(1, rxStaId2);
2146
2147 Ptr<Packet> pkt2 = Create<Packet>(1500);
2148 WifiMacHeader hdr2;
2150 hdr2.SetQosTid(0);
2151 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2152 hdr2.SetSequenceNumber(2);
2153 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2154 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2155
2156 Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2157 txVector1,
2159 rxStaId1);
2160 Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2161 txVector2,
2163 rxStaId2);
2164 Time txDuration = std::max(txDuration1, txDuration2);
2165
2166 txVector1.SetLength(
2167 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector1, m_phySta1->GetPhyBand())
2168 .first);
2169 txVector2.SetLength(
2170 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector2, m_phySta2->GetPhyBand())
2171 .first);
2172
2173 m_phySta1->Send(psdus1, txVector1);
2174 m_phySta2->Send(psdus2, txVector2);
2175}
2176
2177void
2179{
2180 WifiConstPsduMap psdus;
2181 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2182 0,
2184 800,
2185 1,
2186 1,
2187 0,
2189 false,
2190 false);
2191
2192 Ptr<Packet> pkt = Create<Packet>(1000);
2193 WifiMacHeader hdr;
2195 hdr.SetQosTid(0);
2196 hdr.SetAddr1(Mac48Address::GetBroadcast());
2197 hdr.SetSequenceNumber(1);
2198 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2199 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2200
2201 switch (txStaId)
2202 {
2203 case 0:
2204 m_phyAp->Send(psdus, txVector);
2205 break;
2206 case 1:
2207 m_phySta1->Send(psdus, txVector);
2208 break;
2209 case 2:
2210 m_phySta2->Send(psdus, txVector);
2211 break;
2212 default:
2213 NS_ABORT_MSG("Unexpected STA-ID");
2214 }
2215}
2216
2217void
2219{
2220 RngSeedManager::SetSeed(1);
2221 RngSeedManager::SetRun(1);
2222 int64_t streamNumber = 0;
2223 m_phyAp->AssignStreams(streamNumber);
2224 m_phySta1->AssignStreams(streamNumber);
2225 m_phySta2->AssignStreams(streamNumber);
2226
2227 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2228 // since global attribute will be changed).
2229 ResetPpduUid();
2230
2231 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2232 // PPDU UID should be equal to 0 (the first counter value).
2233 Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::SendMuPpdu, this);
2234 Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::CheckUid, this, 0, 0);
2235
2236 // Send HE SU PPDU from AP.
2237 // PPDU UID should be incremented since this is a new PPDU.
2238 Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::SendSuPpdu, this, 0);
2239 Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::CheckUid, this, 0, 1);
2240
2241 // Send HE TB PPDU from STAs to AP.
2242 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2243 // preceding correctly received PPDU (which normally contains the trigger frame).
2244 Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::SendTbPpdu, this);
2245 Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 1, 1);
2246 Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 2, 1);
2247
2248 // Send HE SU PPDU from STA1.
2249 // PPDU UID should be incremented since this is a new PPDU.
2250 Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::SendSuPpdu, this, 1);
2251 Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::CheckUid, this, 1, 2);
2252
2253 Simulator::Run();
2254 Simulator::Destroy();
2255}
2256
2264{
2265 public:
2267 ~TestMultipleHeTbPreambles() override;
2268
2269 private:
2270 void DoSetup() override;
2271 void DoTeardown() override;
2272 void DoRun() override;
2273
2283 void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2284
2299
2306
2310 void Reset();
2311
2317 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2318
2323 void CheckBytesDropped(size_t expectedBytesDropped);
2324
2326
2329};
2330
2332 : TestCase("UL-OFDMA multiple RX events test"),
2333 m_totalBytesDropped(0),
2334 m_trigVector(HePhy::GetHeMcs7(),
2335 0,
2337 800,
2338 1,
2339 1,
2340 0,
2342 false,
2343 false)
2344{
2345}
2346
2348{
2349}
2350
2351void
2353{
2354 NS_LOG_FUNCTION(this);
2356 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2357 m_phy->Reset();
2359}
2360
2361void
2363{
2364 NS_LOG_FUNCTION(this << p << reason);
2365 m_totalBytesDropped += (p->GetSize() - 30);
2366}
2367
2368void
2369TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2370{
2371 auto events = m_phy->GetCurrentPreambleEvents();
2372 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2373 for (const auto& uid : uids)
2374 {
2375 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2376 auto it = events.find(pair);
2377 bool found = (it != events.end());
2379 true,
2380 "HE TB PPDU with UID " << uid << " has not been received!");
2381 }
2382}
2383
2384void
2386{
2388 expectedBytesDropped,
2389 "The number of dropped bytes is not correct!");
2390}
2391
2392void
2394 uint16_t staId,
2395 double txPowerWatts,
2396 size_t payloadSize)
2397{
2398 WifiConstPsduMap psdus;
2399 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2400 0,
2402 800,
2403 1,
2404 1,
2405 0,
2407 false,
2408 false);
2409
2410 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2412 txVector.SetRu(ru, staId);
2413 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2414 txVector.SetNss(1, staId);
2415
2416 m_trigVector.SetHeMuUserInfo(staId, {ru, HePhy::GetHeMcs7(), 1});
2417
2418 Ptr<Packet> pkt = Create<Packet>(payloadSize);
2419 WifiMacHeader hdr;
2421 hdr.SetQosTid(0);
2422 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2423 hdr.SetSequenceNumber(1);
2424 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2425 psdus.insert(std::make_pair(staId, psdu));
2426
2427 Time ppduDuration =
2428 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2429 Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2430 txVector,
2432 ppduDuration,
2434 uid,
2435 HePpdu::PSD_NON_HE_PORTION,
2436 0);
2437
2438 // Send non-OFDMA part
2439 Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonOfdmaDurationForHeTb(txVector);
2440 uint32_t centerFrequency =
2441 m_phy->GetHePhy()->GetCenterFrequencyForNonOfdmaPart(txVector, staId);
2442 uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2443 uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2444 Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(
2445 centerFrequency,
2446 channelWidth,
2447 txPowerWatts,
2448 m_phy->GetGuardBandwidth(channelWidth));
2449 Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2450 rxParams->psd = rxPsd;
2451 rxParams->txPhy = nullptr;
2452 rxParams->duration = nonOfdmaDuration;
2453 rxParams->ppdu = ppdu;
2454
2455 uint16_t length;
2456 std::tie(length, ppduDuration) =
2457 HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, txVector, m_phy->GetPhyBand());
2458 txVector.SetLength(length);
2459 m_trigVector.SetLength(length);
2460 auto hePhy = DynamicCast<HePhy>(m_phy->GetPhyEntity(WIFI_MOD_CLASS_HE));
2461 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2462 m_phy->StartRx(rxParams);
2463
2464 // Schedule OFDMA part
2465 Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2466 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2467 WifiSpectrumBand band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2468 Ptr<SpectrumValue> rxPsdOfdma =
2469 WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity(DEFAULT_FREQUENCY,
2471 txPowerWatts,
2473 band);
2474 Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2475 rxParamsOfdma->psd = rxPsd;
2476 rxParamsOfdma->txPhy = nullptr;
2477 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2478 rxParamsOfdma->ppdu = ppduOfdma;
2479 Simulator::Schedule(nonOfdmaDuration,
2481 this,
2482 rxParamsOfdma);
2483}
2484
2485void
2487{
2488 Simulator::ScheduleNow(&TestMultipleHeTbPreambles::DoRxHeTbPpduOfdmaPart, this, rxParamsOfdma);
2489}
2490
2491void
2493{
2494 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2495 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2496 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2497 m_phy->StartRx(rxParamsOfdma);
2498}
2499
2500void
2502{
2503 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2505 m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2507 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2508 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2509 Ptr<ApWifiMac> mac = CreateObject<ApWifiMac>();
2510 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2511 dev->SetMac(mac);
2512 m_phy->SetInterferenceHelper(interferenceHelper);
2513 m_phy->SetErrorRateModel(error);
2517 0});
2518 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2520 m_phy->SetDevice(dev);
2521 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2522 CreateObject<ThresholdPreambleDetectionModel>();
2523 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2524 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2525 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2526 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2527 heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2528 dev->SetHeConfiguration(heConfiguration);
2529}
2530
2531void
2533{
2534 m_phy->Dispose();
2535 m_phy = nullptr;
2536}
2537
2538void
2540{
2541 RngSeedManager::SetSeed(1);
2542 RngSeedManager::SetRun(1);
2543 int64_t streamNumber = 0;
2544 m_phy->AssignStreams(streamNumber);
2545
2546 double txPowerWatts = 0.01;
2547
2548 {
2549 // Verify a single UL MU transmission with two stations belonging to the same BSS
2550 std::vector<uint64_t> uids{0};
2551 Simulator::Schedule(Seconds(1),
2553 this,
2554 uids[0],
2555 1,
2556 txPowerWatts,
2557 1001);
2558 Simulator::Schedule(Seconds(1) + NanoSeconds(100),
2560 this,
2561 uids[0],
2562 2,
2563 txPowerWatts,
2564 1002);
2565 // Check that we received a single UL MU transmission with the corresponding UID
2566 Simulator::Schedule(Seconds(1.0) + MicroSeconds(1),
2568 this,
2569 1,
2570 uids);
2571 Simulator::Schedule(Seconds(1.5), &TestMultipleHeTbPreambles::Reset, this);
2572 }
2573
2574 {
2575 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2576 // the second transmission arrives during the preamble detection window and with half the
2577 // power of the first transmission.
2578 std::vector<uint64_t> uids{1, 2};
2579 Simulator::Schedule(Seconds(2),
2581 this,
2582 uids[0],
2583 1,
2584 txPowerWatts,
2585 1001);
2586 Simulator::Schedule(Seconds(2) + NanoSeconds(100),
2588 this,
2589 uids[0],
2590 2,
2591 txPowerWatts,
2592 1002);
2593 Simulator::Schedule(Seconds(2) + NanoSeconds(200),
2595 this,
2596 uids[1],
2597 1,
2598 txPowerWatts / 2,
2599 1003);
2600 Simulator::Schedule(Seconds(2) + NanoSeconds(300),
2602 this,
2603 uids[1],
2604 2,
2605 txPowerWatts / 2,
2606 1004);
2607 // Check that we received the correct reception of 2 UL MU transmissions with the
2608 // corresponding UIDs
2609 Simulator::Schedule(Seconds(2.0) + MicroSeconds(1),
2611 this,
2612 2,
2613 uids);
2614 Simulator::Schedule(Seconds(2.5), &TestMultipleHeTbPreambles::Reset, this);
2615 // TODO: verify PPDUs from second UL MU transmission are dropped
2616 }
2617
2618 {
2619 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2620 // the second transmission arrives during the preamble detection window and with twice the
2621 // power of the first transmission.
2622 std::vector<uint64_t> uids{3, 4};
2623 Simulator::Schedule(Seconds(3),
2625 this,
2626 uids[0],
2627 1,
2628 txPowerWatts / 2,
2629 1001);
2630 Simulator::Schedule(Seconds(3) + NanoSeconds(100),
2632 this,
2633 uids[0],
2634 2,
2635 txPowerWatts / 2,
2636 1002);
2637 Simulator::Schedule(Seconds(3) + NanoSeconds(200),
2639 this,
2640 uids[1],
2641 1,
2642 txPowerWatts,
2643 1003);
2644 Simulator::Schedule(Seconds(3) + NanoSeconds(300),
2646 this,
2647 uids[1],
2648 2,
2649 txPowerWatts,
2650 1004);
2651 // Check that we received the correct reception of 2 UL MU transmissions with the
2652 // corresponding UIDs
2653 Simulator::Schedule(Seconds(3.0) + MicroSeconds(1),
2655 this,
2656 2,
2657 uids);
2658 Simulator::Schedule(Seconds(3.5), &TestMultipleHeTbPreambles::Reset, this);
2659 // TODO: verify PPDUs from first UL MU transmission are dropped
2660 }
2661
2662 {
2663 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2664 // the second transmission arrives during PHY header reception and with the same power as
2665 // the first transmission.
2666 std::vector<uint64_t> uids{5, 6};
2667 Simulator::Schedule(Seconds(4),
2669 this,
2670 uids[0],
2671 1,
2672 txPowerWatts,
2673 1001);
2674 Simulator::Schedule(Seconds(4) + NanoSeconds(100),
2676 this,
2677 uids[0],
2678 2,
2679 txPowerWatts,
2680 1002);
2681 Simulator::Schedule(Seconds(4) + MicroSeconds(5),
2683 this,
2684 uids[1],
2685 1,
2686 txPowerWatts,
2687 1003);
2688 Simulator::Schedule(Seconds(4) + MicroSeconds(5) + NanoSeconds(100),
2690 this,
2691 uids[1],
2692 2,
2693 txPowerWatts,
2694 1004);
2695 // Check that we received the correct reception of the first UL MU transmission with the
2696 // corresponding UID (second one dropped)
2697 Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2699 this,
2700 1,
2701 std::vector<uint64_t>{uids[0]});
2702 // The packets of the second UL MU transmission should have been dropped
2703 Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2705 this,
2706 1003 + 1004);
2707 Simulator::Schedule(Seconds(4.5), &TestMultipleHeTbPreambles::Reset, this);
2708 }
2709
2710 {
2711 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2712 // BSS, where the second transmission arrives during payload reception and with the same
2713 // power as the first transmission.
2714 std::vector<uint64_t> uids{7, 8};
2715 Simulator::Schedule(Seconds(5),
2717 this,
2718 uids[0],
2719 1,
2720 txPowerWatts,
2721 1001);
2722 Simulator::Schedule(Seconds(5) + NanoSeconds(100),
2724 this,
2725 uids[0],
2726 2,
2727 txPowerWatts,
2728 1002);
2729 Simulator::Schedule(Seconds(5) + MicroSeconds(50),
2731 this,
2732 uids[1],
2733 1,
2734 txPowerWatts,
2735 1003);
2736 Simulator::Schedule(Seconds(5) + MicroSeconds(50) + NanoSeconds(100),
2738 this,
2739 uids[1],
2740 2,
2741 txPowerWatts,
2742 1004);
2743 // Check that we received the correct reception of the first UL MU transmission with the
2744 // corresponding UID (second one dropped)
2745 Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2747 this,
2748 1,
2749 std::vector<uint64_t>{uids[0]});
2750 // The packets of the second UL MU transmission should have been dropped
2751 Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2753 this,
2754 1003 + 1004);
2755 Simulator::Schedule(Seconds(5.5), &TestMultipleHeTbPreambles::Reset, this);
2756 }
2757
2758 {
2759 // Verify the correct reception of a single UL MU transmission with two stations belonging
2760 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2761 // the configured delay spread of 400ns
2762 std::vector<uint64_t> uids{9};
2763 Simulator::Schedule(Seconds(6),
2765 this,
2766 uids[0],
2767 1,
2768 txPowerWatts,
2769 1001);
2770 Simulator::Schedule(Seconds(6) + NanoSeconds(500),
2772 this,
2773 uids[0],
2774 2,
2775 txPowerWatts,
2776 1002);
2777 // Check that we received a single UL MU transmission with the corresponding UID
2778 Simulator::Schedule(Seconds(6.0) + MicroSeconds(1),
2780 this,
2781 1,
2782 uids);
2783 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2784 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2785 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2786 // second packet of 1002 bytes is dropped as well.
2787 Simulator::Schedule(Seconds(6.0) + MicroSeconds(5),
2789 this,
2790 1001 + 1002);
2791 Simulator::Schedule(Seconds(6.5), &TestMultipleHeTbPreambles::Reset, this);
2792 }
2793
2794 Simulator::Run();
2795 Simulator::Destroy();
2796}
2797
2805{
2806 public:
2808
2809 void NotifyRxStart(Time duration) override
2810 {
2811 NS_LOG_FUNCTION(this << duration);
2814 m_lastRxSuccess = false;
2815 }
2816
2817 void NotifyRxEndOk() override
2818 {
2819 NS_LOG_FUNCTION(this);
2821 ++m_notifyRxEnd;
2822 m_lastRxSuccess = true;
2823 }
2824
2825 void NotifyRxEndError() override
2826 {
2827 NS_LOG_FUNCTION(this);
2829 ++m_notifyRxEnd;
2830 m_lastRxSuccess = false;
2831 }
2832
2833 void NotifyTxStart(Time duration, double txPowerDbm) override
2834 {
2835 NS_LOG_FUNCTION(this << duration << txPowerDbm);
2836 }
2837
2839 WifiChannelListType channelType,
2840 const std::vector<Time>& /*per20MhzDurations*/) override
2841 {
2842 NS_LOG_FUNCTION(this << duration << channelType);
2843 }
2844
2845 void NotifySwitchingStart(Time duration) override
2846 {
2847 }
2848
2849 void NotifySleep() override
2850 {
2851 }
2852
2853 void NotifyOff() override
2854 {
2855 }
2856
2857 void NotifyWakeup() override
2858 {
2859 }
2860
2861 void NotifyOn() override
2862 {
2863 }
2864
2868 void Reset()
2869 {
2870 m_notifyRxStart = 0;
2871 m_notifyRxEnd = 0;
2873 m_lastRxEnd = Seconds(0);
2874 m_lastRxSuccess = false;
2875 }
2876
2882 {
2883 return m_notifyRxStart;
2884 }
2885
2891 {
2892 return m_notifyRxEnd;
2893 }
2894
2900 {
2901 return m_lastRxStart;
2902 }
2903
2909 {
2910 return m_lastRxEnd;
2911 }
2912
2917 bool IsLastRxSuccess() const
2918 {
2919 return m_lastRxSuccess;
2920 }
2921
2922 private:
2927 bool m_lastRxSuccess{false};
2928};
2929
2937{
2938 public:
2943 {
2944 NONE = 0,
2949 MCS
2951
2953 ~TestUlOfdmaPhyTransmission() override;
2954
2955 private:
2956 void DoSetup() override;
2957 void DoTeardown() override;
2958 void DoRun() override;
2959
2967 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2968 std::size_t index,
2969 uint8_t bssColor) const;
2976 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2986 void SendHeTbPpdu(uint16_t txStaId,
2987 std::size_t index,
2988 std::size_t payloadSize,
2989 uint64_t uid,
2990 uint8_t bssColor,
2991 bool incrementUid);
2992
3000 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3001
3007 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3008
3014 void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3015
3021 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3025 void StopInterference();
3026
3030 void RunOne();
3031
3038 void CheckRxFromSta1(uint32_t expectedSuccess,
3039 uint32_t expectedFailures,
3040 uint32_t expectedBytes);
3041
3048 void CheckRxFromSta2(uint32_t expectedSuccess,
3049 uint32_t expectedFailures,
3050 uint32_t expectedBytes);
3051
3059 WifiSpectrumBand band,
3060 double expectedRxPower);
3068 WifiSpectrumBand band,
3069 double expectedRxPower);
3070
3074 void VerifyEventsCleared();
3075
3084
3091 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3099 void CheckApRxEnd(uint32_t expectedNotifications,
3100 Time expectedLastNotification,
3101 bool expectedSuccess);
3102
3106 void Reset();
3107
3116 RxSignalInfo rxSignalInfo,
3117 WifiTxVector txVector,
3118 std::vector<bool> statusPerMpdu);
3119
3124 void RxFailure(Ptr<const WifiPsdu> psdu);
3125
3146 void ScheduleTest(Time delay,
3147 bool solicited,
3148 WifiPhyState expectedStateAtEnd,
3149 uint32_t expectedSuccessFromSta1,
3150 uint32_t expectedFailuresFromSta1,
3151 uint32_t expectedBytesFromSta1,
3152 uint32_t expectedSuccessFromSta2,
3153 uint32_t expectedFailuresFromSta2,
3154 uint32_t expectedBytesFromSta2,
3155 bool scheduleTxSta1 = true,
3156 Time ulTimeDifference = Seconds(0),
3157 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3158 TrigVectorInfo error = NONE);
3159
3170 double rxPowerNonOfdmaRu1,
3171 double rxPowerNonOfdmaRu2,
3172 double rxPowerOfdmaRu1,
3173 double rxPowerOfdmaRu2);
3179 void LogScenario(std::string log) const;
3180
3185
3186 std::unique_ptr<OfdmaTestPhyListener>
3188
3190
3197
3198 uint16_t m_frequency;
3201};
3202
3204 : TestCase("UL-OFDMA PHY test"),
3205 m_countRxSuccessFromSta1(0),
3206 m_countRxSuccessFromSta2(0),
3207 m_countRxFailureFromSta1(0),
3208 m_countRxFailureFromSta2(0),
3209 m_countRxBytesFromSta1(0),
3210 m_countRxBytesFromSta2(0),
3211 m_frequency(DEFAULT_FREQUENCY),
3212 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3213 m_expectedPpduDuration(NanoSeconds(271200))
3214{
3215}
3216
3217void
3219 std::size_t payloadSize,
3220 uint64_t uid,
3221 uint8_t bssColor)
3222{
3223 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3224 WifiConstPsduMap psdus;
3225
3226 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3227 0,
3229 800,
3230 1,
3231 1,
3232 0,
3234 false,
3235 false,
3236 false,
3237 bssColor);
3238
3239 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3240 WifiMacHeader hdr;
3242 hdr.SetQosTid(0);
3243 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3244 std::ostringstream addr;
3245 addr << "00:00:00:00:00:0" << txStaId;
3246 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3247 hdr.SetSequenceNumber(1);
3248 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3249 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3250
3252 if (txStaId == 1)
3253 {
3254 phy = m_phySta1;
3255 }
3256 else if (txStaId == 2)
3257 {
3258 phy = m_phySta2;
3259 }
3260 else if (txStaId == 3)
3261 {
3262 phy = m_phySta3;
3263 }
3264 else if (txStaId == 0)
3265 {
3266 phy = m_phyAp;
3267 }
3268 phy->SetPpduUid(uid);
3269 phy->Send(psdus, txVector);
3270}
3271
3274 std::size_t index,
3275 uint8_t bssColor) const
3276{
3277 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3278 0,
3280 800,
3281 1,
3282 1,
3283 0,
3285 false,
3286 false,
3287 false,
3288 bssColor);
3289
3290 HeRu::RuType ruType = HeRu::RU_106_TONE;
3291 if (m_channelWidth == 20)
3292 {
3293 ruType = HeRu::RU_106_TONE;
3294 }
3295 else if (m_channelWidth == 40)
3296 {
3297 ruType = HeRu::RU_242_TONE;
3298 }
3299 else if (m_channelWidth == 80)
3300 {
3301 ruType = HeRu::RU_484_TONE;
3302 }
3303 else if (m_channelWidth == 160)
3304 {
3305 ruType = HeRu::RU_996_TONE;
3306 }
3307 else
3308 {
3309 NS_ASSERT_MSG(false, "Unsupported channel width");
3310 }
3311
3312 bool primary80MHz = true;
3313 if (m_channelWidth == 160 && index == 2)
3314 {
3315 primary80MHz = false;
3316 index = 1;
3317 }
3318 HeRu::RuSpec ru(ruType, index, primary80MHz);
3320 txVector.SetRu(ru, txStaId);
3321 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3322 txVector.SetNss(1, txStaId);
3323 return txVector;
3324}
3325
3326void
3328{
3329 uint16_t channelWidth = m_channelWidth;
3330 if (error == CHANNEL_WIDTH)
3331 {
3332 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3333 }
3334
3335 WifiTxVector txVector(HePhy::GetHeMcs7(),
3336 0,
3338 800,
3339 1,
3340 1,
3341 0,
3342 channelWidth,
3343 false,
3344 false,
3345 false,
3346 bssColor);
3347
3348 HeRu::RuType ruType = HeRu::RU_106_TONE;
3349 if (channelWidth == 20)
3350 {
3351 ruType = (error == RU_TYPE ? HeRu::RU_52_TONE : HeRu::RU_106_TONE);
3352 }
3353 else if (channelWidth == 40)
3354 {
3355 ruType = (error == RU_TYPE ? HeRu::RU_106_TONE : HeRu::RU_242_TONE);
3356 }
3357 else if (channelWidth == 80)
3358 {
3359 ruType = (error == RU_TYPE ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
3360 }
3361 else if (channelWidth == 160)
3362 {
3363 ruType = (error == RU_TYPE ? HeRu::RU_484_TONE : HeRu::RU_996_TONE);
3364 }
3365 else
3366 {
3367 NS_ASSERT_MSG(false, "Unsupported channel width");
3368 }
3369
3370 uint16_t aid1 = (error == AID ? 3 : 1);
3371 uint16_t aid2 = (error == AID ? 4 : 2);
3372
3373 HeRu::RuSpec ru1(ruType, 1, true);
3374 ru1.SetPhyIndex(channelWidth, 0);
3375 txVector.SetRu(ru1, aid1);
3376 txVector.SetMode((error == MCS ? HePhy::GetHeMcs5() : HePhy::GetHeMcs7()), aid1);
3377 txVector.SetNss(1, aid1);
3378
3379 HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth == 160 ? false : true));
3380 ru2.SetPhyIndex(channelWidth, 0);
3381 txVector.SetRu(ru2, aid2);
3382 txVector.SetMode((error == MCS ? HePhy::GetHeMcs5() : HePhy::GetHeMcs7()), aid2);
3383 txVector.SetNss(1, aid2);
3384
3385 uint16_t length;
3386 std::tie(length, m_expectedPpduDuration) =
3387 HePhy::ConvertHeTbPpduDurationToLSigLength(m_expectedPpduDuration,
3388 txVector,
3389 m_phyAp->GetPhyBand());
3390 if (error == UL_LENGTH)
3391 {
3392 ++length;
3393 }
3394 txVector.SetLength(length);
3395 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
3396 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3397}
3398
3399void
3401 std::size_t index,
3402 std::size_t payloadSize,
3403 uint64_t uid,
3404 uint8_t bssColor,
3405 bool incrementUid)
3406{
3407 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3408 WifiConstPsduMap psdus;
3409
3410 if (incrementUid)
3411 {
3412 ++uid;
3413 }
3414
3415 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3416 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3417 WifiMacHeader hdr;
3419 hdr.SetQosTid(0);
3420 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3421 std::ostringstream addr;
3422 addr << "00:00:00:00:00:0" << txStaId;
3423 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3424 hdr.SetSequenceNumber(1);
3425 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3426 psdus.insert(std::make_pair(txStaId, psdu));
3427
3429 if (txStaId == 1)
3430 {
3431 phy = m_phySta1;
3432 }
3433 else if (txStaId == 2)
3434 {
3435 phy = m_phySta2;
3436 }
3437 else if (txStaId == 3)
3438 {
3439 phy = m_phySta3;
3440 }
3441
3442 Time txDuration =
3443 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3444 txVector.SetLength(
3445 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3446
3447 phy->SetPpduUid(uid);
3448 phy->Send(psdus, txVector);
3449}
3450
3451void
3453{
3454 NS_LOG_FUNCTION(this << duration);
3456 m_phyInterferer->SetPeriod(duration);
3458 Simulator::Schedule(duration, &TestUlOfdmaPhyTransmission::StopInterference, this);
3459}
3460
3461void
3463{
3465}
3466
3468{
3469}
3470
3471void
3473 RxSignalInfo rxSignalInfo,
3474 WifiTxVector txVector,
3475 std::vector<bool> /*statusPerMpdu*/)
3476{
3477 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3478 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3479 {
3481 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3482 }
3483 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3484 {
3486 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3487 }
3488}
3489
3490void
3492{
3493 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3494 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3495 {
3497 }
3498 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3499 {
3501 }
3502}
3503
3504void
3506 uint32_t expectedFailures,
3507 uint32_t expectedBytes)
3508{
3510 expectedSuccess,
3511 "The number of successfully received packets from STA 1 is not correct!");
3514 expectedFailures,
3515 "The number of unsuccessfully received packets from STA 1 is not correct!");
3517 expectedBytes,
3518 "The number of bytes received from STA 1 is not correct!");
3519}
3520
3521void
3523 uint32_t expectedFailures,
3524 uint32_t expectedBytes)
3525{
3527 expectedSuccess,
3528 "The number of successfully received packets from STA 2 is not correct!");
3531 expectedFailures,
3532 "The number of unsuccessfully received packets from STA 2 is not correct!");
3534 expectedBytes,
3535 "The number of bytes received from STA 2 is not correct!");
3536}
3537
3538void
3540 WifiSpectrumBand band,
3541 double expectedRxPower)
3542{
3543 Ptr<Event> event = phy->GetCurrentEvent();
3544 NS_ASSERT(event);
3545 double rxPower = event->GetRxPowerW(band);
3546 NS_LOG_FUNCTION(this << band.first << band.second << expectedRxPower << rxPower);
3547 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3549 expectedRxPower,
3550 5e-3,
3551 "RX power " << rxPower << " over (" << band.first << ", "
3552 << band.second << ") does not match expected power "
3553 << expectedRxPower << " at " << Simulator::Now());
3554}
3555
3556void
3558 WifiSpectrumBand band,
3559 double expectedRxPower)
3560{
3566 NS_LOG_FUNCTION(this << band.first << band.second << expectedRxPower);
3567 double step = 5e-3;
3568 if (expectedRxPower > 0.0)
3569 {
3571 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3572 true,
3573 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3574 << ", " << band.second << ") at " << Simulator::Now());
3576 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3577 false,
3578 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3579 << ", " << band.second << ") at " << Simulator::Now());
3580 }
3581 else
3582 {
3584 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3585 false,
3586 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3587 << ", " << band.second << ") at " << Simulator::Now());
3588 }
3589}
3590
3591void
3593{
3595 nullptr,
3596 "m_currentEvent for AP was not cleared");
3598 nullptr,
3599 "m_currentEvent for STA 1 was not cleared");
3601 nullptr,
3602 "m_currentEvent for STA 2 was not cleared");
3603}
3604
3605void
3607{
3608 // This is needed to make sure PHY state will be checked as the last event if a state change
3609 // occurred at the exact same time as the check
3610 Simulator::ScheduleNow(&TestUlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
3611}
3612
3613void
3615 WifiPhyState expectedState)
3616{
3617 WifiPhyState currentState;
3618 PointerValue ptr;
3619 phy->GetAttribute("State", ptr);
3620 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3621 currentState = state->GetState();
3622 NS_LOG_FUNCTION(this << currentState);
3623 NS_TEST_ASSERT_MSG_EQ(currentState,
3624 expectedState,
3625 "PHY State " << currentState << " does not match expected state "
3626 << expectedState << " at " << Simulator::Now());
3627}
3628
3629void
3631 Time expectedLastNotification)
3632{
3633 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3634 expectedNotifications,
3635 "Number of RX start notifications "
3636 << m_apPhyStateListener->GetNumRxStartNotifications()
3637 << " does not match expected count " << expectedNotifications
3638 << " for AP at " << Simulator::Now());
3639 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3640 expectedLastNotification,
3641 "Last time RX start notification has been received "
3642 << m_apPhyStateListener->GetLastRxStartNotification()
3643 << " does not match expected time " << expectedLastNotification
3644 << " for AP at " << Simulator::Now());
3645}
3646
3647void
3649 Time expectedLastNotification,
3650 bool expectedSuccess)
3651{
3652 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3653 expectedNotifications,
3654 "Number of RX end notifications "
3655 << m_apPhyStateListener->GetNumRxEndNotifications()
3656 << " does not match expected count " << expectedNotifications
3657 << " for AP at " << Simulator::Now());
3658 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3659 expectedLastNotification,
3660 "Last time RX end notification has been received "
3661 << m_apPhyStateListener->GetLastRxEndNotification()
3662 << " does not match expected time " << expectedLastNotification
3663 << " for AP at " << Simulator::Now());
3665 expectedSuccess,
3666 "Last time RX end notification indicated a "
3667 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3668 << " but expected a " << (expectedSuccess ? "success" : "failure")
3669 << " for AP at " << Simulator::Now());
3670}
3671
3672void
3674{
3684 SetBssColor(m_phyAp, 0);
3685 m_apPhyStateListener->Reset();
3686}
3687
3688void
3690{
3691 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3692 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3693 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3694}
3695
3696void
3698{
3699 NS_LOG_FUNCTION(this << phy << psdLimit);
3700 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3701}
3702
3703void
3705{
3706 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3707 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3708 lossModel->SetFrequency(m_frequency);
3709 spectrumChannel->AddPropagationLossModel(lossModel);
3711 CreateObject<ConstantSpeedPropagationDelayModel>();
3712 spectrumChannel->SetPropagationDelayModel(delayModel);
3713
3714 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3715 CreateObject<ThresholdPreambleDetectionModel>();
3716 preambleDetectionModel->SetAttribute(
3717 "MinimumRssi",
3719 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3720 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3721
3722 Ptr<Node> apNode = CreateObject<Node>();
3723 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3725 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
3726 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3727 apDev->SetMac(apMac);
3728 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3731 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3732 apDev->SetHeConfiguration(heConfiguration);
3733 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3734 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3735 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3736 m_phyAp->SetErrorRateModel(apErrorModel);
3737 m_phyAp->SetDevice(apDev);
3738 m_phyAp->SetChannel(spectrumChannel);
3741 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3742 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3743 m_phyAp->SetMobility(apMobility);
3744 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3746 apDev->SetPhy(m_phyAp);
3747 apMac->SetWifiPhys({m_phyAp});
3748 apNode->AggregateObject(apMobility);
3749 apNode->AddDevice(apDev);
3750
3751 Ptr<Node> sta1Node = CreateObject<Node>();
3752 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3754 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3755 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3758 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3759 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3760 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3761 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3762 m_phySta1->SetDevice(sta1Dev);
3763 m_phySta1->SetChannel(spectrumChannel);
3764 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3765 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3766 m_phySta1->SetMobility(sta1Mobility);
3767 sta1Dev->SetPhy(m_phySta1);
3768 sta1Node->AggregateObject(sta1Mobility);
3769 sta1Node->AddDevice(sta1Dev);
3770
3771 Ptr<Node> sta2Node = CreateObject<Node>();
3772 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3774 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3775 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3778 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3779 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3780 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3781 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3782 m_phySta2->SetDevice(sta2Dev);
3783 m_phySta2->SetChannel(spectrumChannel);
3784 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3785 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3786 m_phySta2->SetMobility(sta2Mobility);
3787 sta2Dev->SetPhy(m_phySta2);
3788 sta2Node->AggregateObject(sta2Mobility);
3789 sta2Node->AddDevice(sta2Dev);
3790
3791 Ptr<Node> sta3Node = CreateObject<Node>();
3792 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3794 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3795 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3798 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3799 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3800 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3801 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3802 m_phySta3->SetDevice(sta3Dev);
3803 m_phySta3->SetChannel(spectrumChannel);
3804 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3805 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3806 m_phySta3->SetMobility(sta3Mobility);
3807 sta3Dev->SetPhy(m_phySta3);
3808 sta3Node->AggregateObject(sta3Mobility);
3809 sta3Node->AddDevice(sta3Dev);
3810
3811 Ptr<Node> interfererNode = CreateObject<Node>();
3812 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3813 m_phyInterferer = CreateObject<WaveformGenerator>();
3814 m_phyInterferer->SetDevice(interfererDev);
3815 m_phyInterferer->SetChannel(spectrumChannel);
3817 interfererNode->AddDevice(interfererDev);
3818
3819 // Configure power attributes of all wifi devices
3820 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3821 for (auto& phy : phys)
3822 {
3823 phy->SetAttribute("TxGain", DoubleValue(1.0));
3824 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3825 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3826 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3827 phy->SetAttribute("RxGain", DoubleValue(2.0));
3828 // test assumes no rejection power for simplicity
3829 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3830 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3831 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3832 }
3833}
3834
3835void
3837{
3838 m_phyAp->Dispose();
3839 m_phyAp = nullptr;
3840 m_phySta1->Dispose();
3841 m_phySta1 = nullptr;
3842 m_phySta2->Dispose();
3843 m_phySta2 = nullptr;
3844 m_phySta3->Dispose();
3845 m_phySta3 = nullptr;
3847 m_phyInterferer = nullptr;
3848}
3849
3850void
3852{
3853 NS_LOG_INFO(log);
3854}
3855
3856void
3858 bool solicited,
3859 WifiPhyState expectedStateAtEnd,
3860 uint32_t expectedSuccessFromSta1,
3861 uint32_t expectedFailuresFromSta1,
3862 uint32_t expectedBytesFromSta1,
3863 uint32_t expectedSuccessFromSta2,
3864 uint32_t expectedFailuresFromSta2,
3865 uint32_t expectedBytesFromSta2,
3866 bool scheduleTxSta1,
3867 Time ulTimeDifference,
3868 WifiPhyState expectedStateBeforeEnd,
3869 TrigVectorInfo error)
3870{
3871 static uint64_t uid = 0;
3872
3873 // AP sends an SU packet preceding HE TB PPDUs
3874 Simulator::Schedule(delay - MilliSeconds(10),
3876 this,
3877 0,
3878 50,
3879 ++uid,
3880 0);
3881 if (!solicited)
3882 {
3883 // UID of TB PPDUs will be different than the one of the preceeding frame
3884 ++uid;
3885 }
3886 else
3887 {
3888 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetTrigVector, this, 0, error);
3889 }
3890 // STA1 and STA2 send MU UL PPDUs addressed to AP
3891 Simulator::Schedule(delay - MilliSeconds(1),
3893 m_apPhyStateListener.get());
3894 if (scheduleTxSta1)
3895 {
3896 Simulator::Schedule(delay,
3898 this,
3899 1,
3900 1,
3901 1000,
3902 uid,
3903 0,
3904 false);
3905 }
3906 Simulator::Schedule(delay + ulTimeDifference,
3908 this,
3909 2,
3910 2,
3911 1001,
3912 uid,
3913 0,
3914 false);
3915
3916 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3917 Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
3919 this,
3920 m_phyAp,
3921 expectedStateBeforeEnd);
3922 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3924 this,
3925 m_phyAp,
3926 expectedStateAtEnd);
3927 // TODO: add checks on TX stop for STAs
3928
3929 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3930 expectedFailuresFromSta2 >
3931 0)
3932 {
3933 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3934 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3935 // The expected time at which the reception is started corresponds to the time at which the
3936 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3937 const Time expectedPayloadStart = delay + MicroSeconds(48);
3938 // The expected time at which the reception is terminated corresponds to the time at which
3939 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3940 // received HE TB PPDU and the last received HE TB PPDU.
3941 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3942 // At the end of the transmission, verify that a single RX start notification shall have
3943 // been notified when the reception of the first HE RB PPDU starts.
3944 Simulator::Schedule(expectedPayloadEnd,
3946 this,
3947 1,
3948 Simulator::Now() + expectedPayloadStart);
3949 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3950 // notification shall have been notified when the reception of the last HE RB PPDU ends
3951 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3953 this,
3954 1,
3955 Simulator::Now() + expectedPayloadEnd,
3956 isSuccess);
3957 }
3958
3959 delay += MilliSeconds(100);
3960 // Check reception state from STA 1
3961 Simulator::Schedule(delay,
3963 this,
3964 expectedSuccessFromSta1,
3965 expectedFailuresFromSta1,
3966 expectedBytesFromSta1);
3967 // Check reception state from STA 2
3968 Simulator::Schedule(delay,
3970 this,
3971 expectedSuccessFromSta2,
3972 expectedFailuresFromSta2,
3973 expectedBytesFromSta2);
3974 // Verify events data have been cleared
3975 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
3976
3977 delay += MilliSeconds(100);
3978 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
3979}
3980
3981void
3983 double rxPowerNonOfdmaRu1,
3984 double rxPowerNonOfdmaRu2,
3985 double rxPowerOfdmaRu1,
3986 double rxPowerOfdmaRu2)
3987{
3988 Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3989 WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3990 WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3992 Time nonOfdmaDuration = hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta2);
3993 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta1));
3994
3995 std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3996 std::vector<WifiSpectrumBand> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3997 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3998 std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3999 std::vector<WifiSpectrumBand> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
4000 hePhy->GetRuBandForRx(txVectorSta2, 2)};
4001
4002 for (uint8_t i = 0; i < 2; ++i)
4003 {
4007 // Check received power on non-OFDMA portion
4008 Simulator::Schedule(
4009 delay + detectionDuration +
4010 NanoSeconds(1), // just after beginning of portion (once event is stored)
4012 this,
4013 m_phyAp,
4014 nonOfdmaBand[i],
4015 rxPowerNonOfdma[i]);
4016 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4018 this,
4019 m_phyAp,
4020 nonOfdmaBand[i],
4021 rxPowerNonOfdma[i]);
4022 // Check received power on OFDMA portion
4023 Simulator::Schedule(delay + nonOfdmaDuration +
4024 NanoSeconds(1), // just after beginning of portion
4026 this,
4027 m_phyAp,
4028 ofdmaBand[i],
4029 rxPowerOfdma[i]);
4030 Simulator::Schedule(delay + m_expectedPpduDuration -
4031 NanoSeconds(1), // just before end of portion
4033 this,
4034 m_phyAp,
4035 ofdmaBand[i],
4036 rxPowerOfdma[i]);
4037
4043 // Check received power on non-OFDMA portion
4044 Simulator::Schedule(
4045 delay + detectionDuration +
4046 NanoSeconds(1), // just after beginning of portion (once event is stored)
4048 this,
4049 m_phySta3,
4050 nonOfdmaBand[i],
4051 rxPowerNonOfdma[i]);
4052 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4054 this,
4055 m_phySta3,
4056 nonOfdmaBand[i],
4057 rxPowerNonOfdma[i]);
4058 // Check received power on OFDMA portion
4059 Simulator::Schedule(delay + nonOfdmaDuration +
4060 NanoSeconds(1), // just after beginning of portion
4062 this,
4063 m_phySta3,
4064 ofdmaBand[i],
4065 rxPowerOfdma[i]);
4066 Simulator::Schedule(delay + m_expectedPpduDuration -
4067 NanoSeconds(1), // just before end of portion
4069 this,
4070 m_phySta3,
4071 ofdmaBand[i],
4072 rxPowerOfdma[i]);
4073 }
4074
4075 if (rxPowerOfdmaRu1 != 0.0)
4076 {
4082 double rxPowerNonOfdmaSta1Only =
4083 (m_channelWidth >= 40)
4084 ? rxPowerNonOfdma[0]
4085 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4086 // Check received power on non-OFDMA portion
4087 Simulator::Schedule(
4088 delay + detectionDuration +
4089 NanoSeconds(1), // just after beginning of portion (once event is stored)
4091 this,
4092 m_phySta2,
4093 nonOfdmaBand[0],
4094 rxPowerNonOfdmaSta1Only);
4095 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4097 this,
4098 m_phySta2,
4099 nonOfdmaBand[0],
4100 rxPowerNonOfdmaSta1Only);
4101 // Check received power on OFDMA portion
4102 Simulator::Schedule(delay + nonOfdmaDuration +
4103 NanoSeconds(1), // just after beginning of portion
4105 this,
4106 m_phySta2,
4107 ofdmaBand[0],
4108 rxPowerOfdma[0]);
4109 Simulator::Schedule(delay + m_expectedPpduDuration -
4110 NanoSeconds(1), // just before end of portion
4112 this,
4113 m_phySta2,
4114 ofdmaBand[0],
4115 rxPowerOfdma[0]);
4116 }
4117}
4118
4119void
4121{
4122 RngSeedManager::SetSeed(1);
4123 RngSeedManager::SetRun(1);
4124 int64_t streamNumber = 0;
4125 m_phyAp->AssignStreams(streamNumber);
4126 m_phySta1->AssignStreams(streamNumber);
4127 m_phySta2->AssignStreams(streamNumber);
4128 m_phySta3->AssignStreams(streamNumber);
4129
4130 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4135
4144
4145 Time delay = Seconds(0.0);
4146 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
4147 delay += Seconds(1.0);
4148
4157 //---------------------------------------------------------------------------
4158 // Verify that both solicited HE TB PPDUs have been corrected received
4159 Simulator::Schedule(delay,
4161 this,
4162 "Reception of solicited HE TB PPDUs");
4163 ScheduleTest(delay,
4164 true,
4166 1,
4167 0,
4168 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4169 1,
4170 0,
4171 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4172 delay += Seconds(1.0);
4173
4174 //---------------------------------------------------------------------------
4175 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4176 // corrected received
4177 Simulator::Schedule(
4178 delay,
4180 this,
4181 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4182 ScheduleTest(delay,
4183 true,
4185 1,
4186 0,
4187 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4188 1,
4189 0,
4190 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4191 true,
4192 NanoSeconds(100));
4193 delay += Seconds(1.0);
4194
4195 //---------------------------------------------------------------------------
4196 // Verify that no unsolicited HE TB PPDU is received
4197 Simulator::Schedule(delay,
4199 this,
4200 "Dropping of unsolicited HE TB PPDUs");
4201 ScheduleTest(delay,
4202 false,
4204 0,
4205 0,
4206 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4207 0,
4208 0,
4209 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4210 true,
4211 Seconds(0),
4213 delay += Seconds(1.0);
4214
4215 //---------------------------------------------------------------------------
4216 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4217 Simulator::Schedule(delay,
4219 this,
4220 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4221 ScheduleTest(delay,
4222 true,
4224 0,
4225 0,
4226 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4227 0,
4228 0,
4229 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4230 true,
4231 Seconds(0),
4234 delay += Seconds(1.0);
4235
4236 //---------------------------------------------------------------------------
4237 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4238 Simulator::Schedule(delay,
4240 this,
4241 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4242 ScheduleTest(delay,
4243 true,
4245 0,
4246 0,
4247 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4248 0,
4249 0,
4250 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4251 true,
4252 Seconds(0),
4254 UL_LENGTH);
4255 delay += Seconds(1.0);
4256
4257 //---------------------------------------------------------------------------
4258 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4259 Simulator::Schedule(delay,
4261 this,
4262 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4263 ScheduleTest(delay,
4264 true,
4266 0,
4267 0,
4268 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4269 0,
4270 0,
4271 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4272 true,
4273 Seconds(0),
4275 AID);
4276 delay += Seconds(1.0);
4277
4278 //---------------------------------------------------------------------------
4279 // Verify that HE TB PPDUs with RU type differing from TRIGVECTOR are discarded
4280 Simulator::Schedule(delay,
4282 this,
4283 "Dropping of HE TB PPDUs with RU type differing from TRIGVECTOR");
4284 ScheduleTest(delay,
4285 true,
4287 0,
4288 0,
4289 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4290 0,
4291 0,
4292 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4293 true,
4294 Seconds(0),
4296 RU_TYPE);
4297 delay += Seconds(1.0);
4298
4299 //---------------------------------------------------------------------------
4300 // Verify that HE TB PPDUs with MCS differing from TRIGVECTOR are discarded
4301 Simulator::Schedule(delay,
4303 this,
4304 "Dropping of HE TB PPDUs with MCS differing from TRIGVECTOR");
4305 ScheduleTest(delay,
4306 true,
4308 0,
4309 0,
4310 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4311 0,
4312 0,
4313 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4314 true,
4315 Seconds(0),
4317 MCS);
4318 delay += Seconds(1.0);
4319
4320 //---------------------------------------------------------------------------
4321 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4322 // impacted
4323 Simulator::Schedule(
4324 delay,
4326 this,
4327 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4328 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4329 BandInfo bandInfo;
4330 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4331 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4332 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4333 Bands bands;
4334 bands.push_back(bandInfo);
4335
4336 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4337 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4338 double interferencePower = 0.1; // watts
4339 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4340
4341 Simulator::Schedule(delay + MicroSeconds(50),
4343 this,
4344 interferencePsdRu1,
4345 MilliSeconds(100));
4347 delay,
4348 true,
4349 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4350 // interference
4351 0,
4352 1,
4353 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4354 1,
4355 0,
4356 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4357 delay += Seconds(1.0);
4358
4359 //---------------------------------------------------------------------------
4360 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4361 // impacted
4362 Simulator::Schedule(
4363 delay,
4365 this,
4366 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4367 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4368 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4369 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4370 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4371 bands.clear();
4372 bands.push_back(bandInfo);
4373
4374 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4375 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4376 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4377
4378 Simulator::Schedule(delay + MicroSeconds(50),
4380 this,
4381 interferencePsdRu2,
4382 MilliSeconds(100));
4383 ScheduleTest(delay,
4384 true,
4385 (m_channelWidth >= 40)
4387 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4388 // generated in its primary channel
4389 1,
4390 0,
4391 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4392 0,
4393 1,
4394 0); // Reception of the PSDU from STA 2 should have failed (since interference
4395 // occupies RU 2)
4396 delay += Seconds(1.0);
4397
4398 //---------------------------------------------------------------------------
4399 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4400 // been impacted
4401 Simulator::Schedule(delay,
4403 this,
4404 "Reception of solicited HE TB PPDUs with interference on the full band "
4405 "during PSDU reception");
4406 // A strong non-wifi interference is generated on the full band during PSDU reception
4407 bandInfo.fc = m_frequency * 1e6;
4408 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4409 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4410 bands.clear();
4411 bands.push_back(bandInfo);
4412
4413 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4414 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4415 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4416
4417 Simulator::Schedule(delay + MicroSeconds(50),
4419 this,
4420 interferencePsdAll,
4421 MilliSeconds(100));
4423 delay,
4424 true,
4425 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4426 // interference
4427 0,
4428 1,
4429 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4430 0,
4431 1,
4432 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4433 // 2)
4434 delay += Seconds(1.0);
4435
4436 //---------------------------------------------------------------------------
4437 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4438 // solicited HE TB PPDUs have been impacted if they are on the same
4439 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4440 Simulator::Schedule(delay,
4442 this,
4443 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4444 "1 during PSDU reception");
4445 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4446 Simulator::Schedule(delay + MicroSeconds(50),
4448 this,
4449 3,
4450 1,
4451 1002,
4452 1,
4453 0,
4454 false);
4455 // Expected figures from STA 2
4456 uint32_t succ;
4457 uint32_t fail;
4458 uint32_t bytes;
4459 if (m_channelWidth > 20)
4460 {
4461 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4462 // interference from STA 3 on distinct 20 MHz channel)
4463 succ = 1;
4464 fail = 0;
4465 bytes = 1001;
4466 }
4467 else
4468 {
4469 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4470 // same 20 MHz channel)
4471 succ = 0;
4472 fail = 1;
4473 bytes = 0;
4474 }
4475 ScheduleTest(delay,
4476 true,
4477 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4478 // interference on measurement channel width
4479 0,
4480 1,
4481 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4482 // STA 3 on same 20 MHz channel)
4483 succ,
4484 fail,
4485 bytes);
4486 delay += Seconds(1.0);
4487
4488 //---------------------------------------------------------------------------
4489 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4490 // solicited HE TB PPDUs have been impacted if they are on the same
4491 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4492 Simulator::Schedule(delay,
4494 this,
4495 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4496 "2 during PSDU reception");
4497 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4498 Simulator::Schedule(delay + MicroSeconds(50),
4500 this,
4501 3,
4502 2,
4503 1002,
4504 1,
4505 0,
4506 false);
4507 // Expected figures from STA 1
4508 if (m_channelWidth > 20)
4509 {
4510 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4511 // interference from STA 3 on distinct 20 MHz channel)
4512 succ = 1;
4513 fail = 0;
4514 bytes = 1000;
4515 }
4516 else
4517 {
4518 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4519 // same 20 MHz channel)
4520 succ = 0;
4521 fail = 1;
4522 bytes = 0;
4523 }
4524 ScheduleTest(delay,
4525 true,
4526 (m_channelWidth >= 40)
4528 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4529 // TB PPDU on primary channel
4530 succ,
4531 fail,
4532 bytes,
4533 0,
4534 1,
4535 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4536 // STA 3 on same 20 MHz channel)
4537 delay += Seconds(1.0);
4538
4539 //---------------------------------------------------------------------------
4540 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4541 // impacted
4542 Simulator::Schedule(
4543 delay,
4545 this,
4546 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4547 // One HE SU arrives at AP during the 400ns window
4548 Simulator::Schedule(delay + NanoSeconds(300),
4550 this,
4551 3,
4552 1002,
4553 1,
4554 0);
4556 delay,
4557 true,
4559 0,
4560 1,
4561 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4562 0,
4563 1,
4564 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4565 delay += Seconds(1.0);
4566
4567 //---------------------------------------------------------------------------
4568 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4569 // received
4570 Simulator::Schedule(delay,
4572 this,
4573 "Reception of solicited HE TB PPDU only on RU 2");
4574 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4575 // otherwise
4576 Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
4578 this,
4579 m_phySta3,
4580 (m_channelWidth >= 40)
4582 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4583 // IDLE if HE TB PPDU on primary channel
4584 ScheduleTest(delay,
4585 true,
4587 0,
4588 0,
4589 0, // No transmission scheduled for STA 1
4590 1,
4591 0,
4592 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4593 false,
4594 Seconds(0),
4595 WifiPhyState::RX); // Measurement channel is total channel width
4596 delay += Seconds(1.0);
4597
4598 //---------------------------------------------------------------------------
4599 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4600 Simulator::Schedule(delay,
4602 this,
4603 "Measure power for reception of HE TB PPDU only on RU 2");
4604 double rxPower =
4605 DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4607 (m_channelWidth >= 40) ? 0.0 : rxPower,
4608 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4609 0.0,
4610 rxPower);
4611 ScheduleTest(delay,
4612 true,
4614 0,
4615 0,
4616 0, // No transmission scheduled for STA 1
4617 1,
4618 0,
4619 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4620 false,
4621 Seconds(0),
4622 WifiPhyState::RX); // Measurement channel is total channel width
4623 delay += Seconds(1.0);
4624
4625 //---------------------------------------------------------------------------
4626 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4627 // limitation enforced
4628 Simulator::Schedule(
4629 delay,
4631 this,
4632 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4633 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4634 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4635 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4637 this,
4638 m_phySta2,
4639 3.0);
4640
4641 rxPower = (m_channelWidth > 40)
4642 ? DbmToW(19)
4643 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4644 // transmitted only on one 20 MHz channel
4645 double rxPowerOfdma = rxPower;
4646 if (m_channelWidth <= 40)
4647 {
4648 rxPowerOfdma = (m_channelWidth == 20)
4649 ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4650 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4651 }
4653 (m_channelWidth >= 40) ? 0.0 : rxPower,
4654 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4655 0.0,
4656 rxPowerOfdma);
4657
4658 // Reset PSD limitation once HE TB has been sent
4659 Simulator::Schedule(delay + m_expectedPpduDuration,
4661 this,
4662 m_phySta2,
4663 100.0);
4664 ScheduleTest(delay,
4665 true,
4667 0,
4668 0,
4669 0, // No transmission scheduled for STA 1
4670 1,
4671 0,
4672 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4673 false,
4674 Seconds(0),
4675 WifiPhyState::RX); // Measurement channel is total channel width
4676 delay += Seconds(1.0);
4677
4678 //---------------------------------------------------------------------------
4679 // Measure the power of 2 solicited HE TB PPDU from both STAs
4680 Simulator::Schedule(delay,
4682 this,
4683 "Measure power for reception of HE TB PPDU on both RUs");
4684 rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4685 double rxPowerNonOfdma = (m_channelWidth >= 40)
4686 ? rxPower
4687 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4688 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4689 ScheduleTest(delay,
4690 true,
4692 1,
4693 0,
4694 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4695 1,
4696 0,
4697 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4698 delay += Seconds(1.0);
4699
4700 //---------------------------------------------------------------------------
4701 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4702 // ongoing)
4703 Simulator::Schedule(delay,
4705 this,
4706 "Reception of an HE TB PPDU from another BSS");
4707 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4708 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4709 Simulator::Schedule(delay + MilliSeconds(100),
4711 this,
4712 3,
4713 1,
4714 1002,
4715 1,
4716 2,
4717 false);
4718
4719 // Verify events data have been cleared
4720 Simulator::Schedule(delay + MilliSeconds(200),
4722 this);
4723
4724 Simulator::Schedule(delay + MilliSeconds(500), &TestUlOfdmaPhyTransmission::Reset, this);
4725 delay += Seconds(1.0);
4726
4727 //---------------------------------------------------------------------------
4728 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4729 // corrected received
4730 Simulator::Schedule(
4731 delay,
4733 this,
4734 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4735 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4736 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4737 Simulator::Schedule(delay + m_expectedPpduDuration + NanoSeconds(100),
4739 this,
4740 3,
4741 1,
4742 1002,
4743 1,
4744 2,
4745 true);
4746 ScheduleTest(delay,
4747 true,
4749 1,
4750 0,
4751 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4752 1,
4753 0,
4754 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4755 true,
4756 NanoSeconds(200));
4757 delay += Seconds(1.0);
4758
4759 Simulator::Run();
4760}
4761
4762void
4764{
4765 m_frequency = 5180;
4766 m_channelWidth = 20;
4768 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4769 RunOne();
4770
4771 m_frequency = 5190;
4772 m_channelWidth = 40;
4774 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4775 RunOne();
4776
4777 m_frequency = 5210;
4778 m_channelWidth = 80;
4780 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4781 RunOne();
4782
4783 m_frequency = 5250;
4784 m_channelWidth = 160;
4786 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4787 RunOne();
4788
4789 Simulator::Destroy();
4790}
4791
4799{
4800 public:
4802 ~TestPhyPaddingExclusion() override;
4803
4804 private:
4805 void DoSetup() override;
4806 void DoTeardown() override;
4807 void DoRun() override;
4808
4816 void SendHeTbPpdu(uint16_t txStaId,
4817 std::size_t index,
4818 std::size_t payloadSize,
4819 Time txDuration);
4825 void SetTrigVector(Time ppduDuration);
4826
4832 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4836 void StopInterference();
4837
4841 void RunOne();
4842
4849 void CheckRxFromSta1(uint32_t expectedSuccess,
4850 uint32_t expectedFailures,
4851 uint32_t expectedBytes);
4852
4859 void CheckRxFromSta2(uint32_t expectedSuccess,
4860 uint32_t expectedFailures,
4861 uint32_t expectedBytes);
4862
4866 void VerifyEventsCleared();
4867
4876
4880 void Reset();
4881
4890 RxSignalInfo rxSignalInfo,
4891 WifiTxVector txVector,
4892 std::vector<bool> statusPerMpdu);
4893
4898 void RxFailure(Ptr<const WifiPsdu> psdu);
4899
4903
4905
4912};
4913
4915 : TestCase("PHY padding exclusion test"),
4916 m_countRxSuccessFromSta1(0),
4917 m_countRxSuccessFromSta2(0),
4918 m_countRxFailureFromSta1(0),
4919 m_countRxFailureFromSta2(0),
4920 m_countRxBytesFromSta1(0),
4921 m_countRxBytesFromSta2(0)
4922{
4923}
4924
4925void
4927 std::size_t index,
4928 std::size_t payloadSize,
4929 Time txDuration)
4930{
4931 WifiConstPsduMap psdus;
4932
4933 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
4934 0,
4936 800,
4937 1,
4938 1,
4939 0,
4941 false,
4942 false,
4943 1);
4944
4945 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4946 txVector.SetRu(ru, txStaId);
4947 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4948 txVector.SetNss(1, txStaId);
4949
4950 Ptr<Packet> pkt = Create<Packet>(payloadSize);
4951 WifiMacHeader hdr;
4953 hdr.SetQosTid(0);
4954 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4955 std::ostringstream addr;
4956 addr << "00:00:00:00:00:0" << txStaId;
4957 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4958 hdr.SetSequenceNumber(1);
4959 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4960 psdus.insert(std::make_pair(txStaId, psdu));
4961
4963 if (txStaId == 1)
4964 {
4965 phy = m_phySta1;
4966 }
4967 else if (txStaId == 2)
4968 {
4969 phy = m_phySta2;
4970 }
4971
4972 txVector.SetLength(
4973 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4974
4975 phy->SetPpduUid(0);
4976 phy->Send(psdus, txVector);
4977}
4978
4979void
4981{
4983 m_phyInterferer->SetPeriod(duration);
4985 Simulator::Schedule(duration, &TestPhyPaddingExclusion::StopInterference, this);
4986}
4987
4988void
4990{
4992}
4993
4995{
4996}
4997
4998void
5000 RxSignalInfo rxSignalInfo,
5001 WifiTxVector txVector,
5002 std::vector<bool> /*statusPerMpdu*/)
5003{
5004 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
5005 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
5006 {
5008 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
5009 }
5010 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
5011 {
5013 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
5014 }
5015}
5016
5017void
5019{
5020 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
5021 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
5022 {
5024 }
5025 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
5026 {
5028 }
5029}
5030
5031void
5033 uint32_t expectedFailures,
5034 uint32_t expectedBytes)
5035{
5037 expectedSuccess,
5038 "The number of successfully received packets from STA 1 is not correct!");
5041 expectedFailures,
5042 "The number of unsuccessfully received packets from STA 1 is not correct!");
5044 expectedBytes,
5045 "The number of bytes received from STA 1 is not correct!");
5046}
5047
5048void
5050 uint32_t expectedFailures,
5051 uint32_t expectedBytes)
5052{
5054 expectedSuccess,
5055 "The number of successfully received packets from STA 2 is not correct!");
5058 expectedFailures,
5059 "The number of unsuccessfully received packets from STA 2 is not correct!");
5061 expectedBytes,
5062 "The number of bytes received from STA 2 is not correct!");
5063}
5064
5065void
5067{
5069 nullptr,
5070 "m_currentEvent for AP was not cleared");
5072 nullptr,
5073 "m_currentEvent for STA 1 was not cleared");
5075 nullptr,
5076 "m_currentEvent for STA 2 was not cleared");
5077}
5078
5079void
5081{
5082 // This is needed to make sure PHY state will be checked as the last event if a state change
5083 // occurred at the exact same time as the check
5084 Simulator::ScheduleNow(&TestPhyPaddingExclusion::DoCheckPhyState, this, phy, expectedState);
5085}
5086
5087void
5089{
5090 WifiPhyState currentState = phy->GetState()->GetState();
5091 NS_LOG_FUNCTION(this << currentState);
5092 NS_TEST_ASSERT_MSG_EQ(currentState,
5093 expectedState,
5094 "PHY State " << currentState << " does not match expected state "
5095 << expectedState << " at " << Simulator::Now());
5096}
5097
5098void
5100{
5110}
5111
5112void
5114{
5115 RngSeedManager::SetSeed(1);
5116 RngSeedManager::SetRun(1);
5117 int64_t streamNumber = 0;
5118
5119 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5120 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5121 lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5122 spectrumChannel->AddPropagationLossModel(lossModel);
5124 CreateObject<ConstantSpeedPropagationDelayModel>();
5125 spectrumChannel->SetPropagationDelayModel(delayModel);
5126
5127 Ptr<Node> apNode = CreateObject<Node>();
5128 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5129 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
5130 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5131 apDev->SetMac(apMac);
5132 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5135 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5136 apDev->SetHeConfiguration(heConfiguration);
5137 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5138 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5139 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5140 m_phyAp->SetErrorRateModel(apErrorModel);
5141 m_phyAp->SetDevice(apDev);
5142 m_phyAp->SetChannel(spectrumChannel);
5143 m_phyAp->AssignStreams(streamNumber);
5144 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5149
5154 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5155 m_phyAp->SetMobility(apMobility);
5156 apDev->SetPhy(m_phyAp);
5158 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5159 apMac->SetWifiPhys({m_phyAp});
5160 apNode->AggregateObject(apMobility);
5161 apNode->AddDevice(apDev);
5162
5163 Ptr<Node> sta1Node = CreateObject<Node>();
5164 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5165 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5168 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5169 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5170 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5171 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5172 m_phySta1->SetDevice(sta1Dev);
5173 m_phySta1->SetChannel(spectrumChannel);
5174 m_phySta1->AssignStreams(streamNumber);
5177 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5178 m_phySta1->SetMobility(sta1Mobility);
5179 sta1Dev->SetPhy(m_phySta1);
5181 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5182 sta1Node->AggregateObject(sta1Mobility);
5183 sta1Node->AddDevice(sta1Dev);
5184
5185 Ptr<Node> sta2Node = CreateObject<Node>();
5186 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5187 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5190 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5191 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5192 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5193 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5194 m_phySta2->SetDevice(sta2Dev);
5195 m_phySta2->SetChannel(spectrumChannel);
5196 m_phySta2->AssignStreams(streamNumber);
5199 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5200 m_phySta2->SetMobility(sta2Mobility);
5201 sta2Dev->SetPhy(m_phySta2);
5203 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5204 sta2Node->AggregateObject(sta2Mobility);
5205 sta2Node->AddDevice(sta2Dev);
5206
5207 Ptr<Node> interfererNode = CreateObject<Node>();
5208 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5209 m_phyInterferer = CreateObject<WaveformGenerator>();
5210 m_phyInterferer->SetDevice(interfererDev);
5211 m_phyInterferer->SetChannel(spectrumChannel);
5213 interfererNode->AddDevice(interfererDev);
5214}
5215
5216void
5218{
5219 m_phyAp->Dispose();
5220 m_phyAp = nullptr;
5221 m_phySta1->Dispose();
5222 m_phySta1 = nullptr;
5223 m_phySta2->Dispose();
5224 m_phySta2 = nullptr;
5226 m_phyInterferer = nullptr;
5227}
5228
5229void
5231{
5232 WifiTxVector trigVector(HePhy::GetHeMcs7(),
5233 0,
5235 800,
5236 1,
5237 1,
5238 0,
5240 false,
5241 false,
5242 1);
5243 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5244 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5245 trigVector.SetNss(1, 1);
5246 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5247 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5248 trigVector.SetNss(1, 2);
5249 uint16_t length;
5250 std::tie(length, ppduDuration) =
5251 HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, trigVector, m_phyAp->GetPhyBand());
5252 trigVector.SetLength(length);
5253 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
5254 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5255}
5256
5257void
5259{
5260 Time expectedPpduDuration = NanoSeconds(279200);
5261 Time ppduWithPaddingDuration =
5262 expectedPpduDuration + 10 * NanoSeconds(12800 + 800 /* GI */); // add 10 extra OFDM symbols
5263
5264 Simulator::Schedule(Seconds(0.0), &TestPhyPaddingExclusion::Reset, this);
5265
5266 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5267 Simulator::Schedule(Seconds(1.0),
5269 this,
5270 1,
5271 1,
5272 1000,
5273 ppduWithPaddingDuration);
5274 Simulator::Schedule(Seconds(1.0),
5276 this,
5277 2,
5278 2,
5279 1001,
5280 ppduWithPaddingDuration);
5281
5282 // Set TRIGVECTOR on AP
5283 Simulator::Schedule(Seconds(1.0),
5285 this,
5286 ppduWithPaddingDuration);
5287
5288 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5289 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5291 this,
5292 m_phyAp,
5294 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5296 this,
5297 m_phyAp,
5299
5300 // One PSDU of 1000 bytes should have been successfully received from STA 1
5301 Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5302 // One PSDU of 1001 bytes should have been successfully received from STA 2
5303 Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5304 // Verify events data have been cleared
5305 Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5306
5307 Simulator::Schedule(Seconds(1.5), &TestPhyPaddingExclusion::Reset, this);
5308
5309 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5310 Simulator::Schedule(Seconds(2.0),
5312 this,
5313 1,
5314 1,
5315 1000,
5316 ppduWithPaddingDuration);
5317 Simulator::Schedule(Seconds(2.0),
5319 this,
5320 2,
5321 2,
5322 1001,
5323 ppduWithPaddingDuration);
5324
5325 // Set TRIGVECTOR on AP
5326 Simulator::Schedule(Seconds(2.0),
5328 this,
5329 ppduWithPaddingDuration);
5330
5331 // A strong non-wifi interference is generated on RU 1 during padding reception
5332 BandInfo bandInfo;
5333 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5334 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5335 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5336 Bands bands;
5337 bands.push_back(bandInfo);
5338
5339 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5340 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5341 double interferencePower = 0.1; // watts
5342 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5343
5344 Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5346 this,
5347 interferencePsdRu1,
5348 MilliSeconds(100));
5349
5350 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5351 // CCA_BUSY instead of IDLE due to the interference)
5352 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5354 this,
5355 m_phyAp,
5357 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5359 this,
5360 m_phyAp,
5362
5363 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5364 // occupies RU 1 after payload, during PHY padding)
5365 Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5366 // One PSDU of 1001 bytes should have been successfully received from STA 2
5367 Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5368 // Verify events data have been cleared
5369 Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5370
5371 Simulator::Schedule(Seconds(2.5), &TestPhyPaddingExclusion::Reset, this);
5372
5373 Simulator::Run();
5374
5375 Simulator::Destroy();
5376}
5377
5385{
5386 public:
5388 ~TestUlOfdmaPowerControl() override;
5389
5390 private:
5391 void DoSetup() override;
5392 void DoTeardown() override;
5393 void DoRun() override;
5394
5400 void SendMuBar(std::vector<uint16_t> staIds);
5401
5408 void SetupBa(Address destination);
5409
5416 void RunOne(bool setupBa);
5417
5423
5434 RxSignalInfo rxSignalInfo,
5435 WifiTxVector txVector,
5436 std::vector<bool> statusPerMpdu);
5437
5438 uint8_t m_bssColor;
5439
5443
5445
5450
5453
5454 double m_rssiSta1;
5455 double m_rssiSta2;
5456
5457 double m_tol;
5458};
5459
5461 : TestCase("UL-OFDMA power control test"),
5462 m_bssColor(1),
5463 m_txPowerAp(0),
5464 m_txPowerStart(0),
5465 m_txPowerEnd(0),
5466 m_txPowerLevels(0),
5467 m_requestedRssiSta1(0),
5468 m_requestedRssiSta2(0),
5469 m_rssiSta1(0),
5470 m_rssiSta2(0),
5471 m_tol(0.1)
5472{
5473}
5474
5476{
5477 m_phyAp = nullptr;
5478 m_apDev = nullptr;
5479 m_sta1Dev = nullptr;
5480 m_sta2Dev = nullptr;
5481}
5482
5483void
5485{
5486 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5487 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5488 m_apDev->Send(pkt, destination, 0);
5489}
5490
5491void
5492TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5493{
5494 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5495
5496 // Build MU-BAR trigger frame
5497 CtrlTriggerHeader muBar;
5498 muBar.SetType(MU_BAR_TRIGGER);
5499 muBar.SetMoreTF(true);
5500 muBar.SetCsRequired(true);
5502 muBar.SetGiAndLtfType(1600, 2);
5503 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5504 muBar.SetUlSpatialReuse(60500);
5505
5506 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5507 std::size_t index = 1;
5508 int8_t ulTargetRssi = -40; // will be overwritten
5509 for (const auto& staId : staIds)
5510 {
5512 ui.SetAid12(staId);
5513 ui.SetRuAllocation({ru, index, true});
5514 ui.SetUlFecCodingType(true);
5515 ui.SetUlMcs(7);
5516 ui.SetUlDcm(false);
5517 ui.SetSsAllocation(1, 1);
5518 if (staId == 1)
5519 {
5520 ulTargetRssi = m_requestedRssiSta1;
5521 }
5522 else if (staId == 2)
5523 {
5524 ulTargetRssi = m_requestedRssiSta2;
5525 }
5526 else
5527 {
5528 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5529 }
5530 ui.SetUlTargetRssi(ulTargetRssi);
5531
5533 bar.SetType(BlockAckReqType::COMPRESSED);
5534 bar.SetTidInfo(0);
5535 bar.SetStartingSequence(4095);
5537
5538 ++index;
5539 }
5540
5541 WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5542 muBar.SetUlLength(HePhy::ConvertHeTbPpduDurationToLSigLength(MicroSeconds(128),
5543 tbTxVector,
5545 .first);
5546
5547 WifiConstPsduMap psdus;
5548 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
5549 0,
5551 800,
5552 1,
5553 1,
5554 0,
5556 false,
5557 false,
5558 false,
5559 m_bssColor);
5560
5561 Ptr<Packet> bar = Create<Packet>();
5562 bar->AddHeader(muBar);
5563
5564 Mac48Address receiver = Mac48Address::GetBroadcast();
5565 if (staIds.size() == 1)
5566 {
5567 uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5568 if (staIds.front() == aidSta1)
5569 {
5570 receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5571 }
5572 else
5573 {
5574 NS_ASSERT(staIds.front() ==
5575 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5576 receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5577 }
5578 }
5579
5580 WifiMacHeader hdr;
5582 hdr.SetAddr1(receiver);
5583 hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5584 hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5585 hdr.SetDsNotTo();
5586 hdr.SetDsFrom();
5587 hdr.SetNoRetry();
5588 hdr.SetNoMoreFragments();
5589 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5590
5591 Time nav = m_apDev->GetPhy()->GetSifs();
5592 uint16_t staId = staIds.front(); // either will do
5593 nav += m_phyAp->CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5594 tbTxVector,
5596 staId);
5597 psdu->SetDuration(nav);
5598 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5599
5600 m_phyAp->Send(psdus, txVector);
5601}
5602
5603void
5605 RxSignalInfo rxSignalInfo,
5606 WifiTxVector txVector,
5607 std::vector<bool> /*statusPerMpdu*/)
5608{
5609 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5610 double rssi = rxSignalInfo.rssi;
5611 NS_ASSERT(psdu->GetNMpdus() == 1);
5612 WifiMacHeader hdr = psdu->GetHeader(0);
5613 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5614 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5615 {
5617 rssi,
5618 m_rssiSta1,
5619 m_tol,
5620 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5621 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5622 }
5623 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5624 {
5626 rssi,
5627 m_rssiSta2,
5628 m_tol,
5629 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5630 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5631 }
5632 else
5633 {
5634 NS_ABORT_MSG("The receiver address is unknown");
5635 }
5636}
5637
5638void
5640{
5641 // Now that BA session has been established we can plug our method
5644}
5645
5646void
5648{
5649 Ptr<Node> apNode = CreateObject<Node>();
5650 NodeContainer staNodes;
5651 staNodes.Create(2);
5652
5653 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5654 Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5655 spectrumChannel->AddPropagationLossModel(lossModel);
5657 CreateObject<ConstantSpeedPropagationDelayModel>();
5658 spectrumChannel->SetPropagationDelayModel(delayModel);
5659
5660 SpectrumWifiPhyHelper spectrumPhy;
5661 spectrumPhy.SetChannel(spectrumChannel);
5662 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5663 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5664
5666 wifi.SetStandard(WIFI_STANDARD_80211ax);
5667 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5668 "DataMode",
5669 StringValue("HeMcs7"),
5670 "ControlMode",
5671 StringValue("HeMcs7"));
5672
5674 mac.SetType("ns3::StaWifiMac");
5675 NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5676 wifi.AssignStreams(staDevs, 0);
5677 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5679 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5681
5682 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5683 // beacon generation is disabled during the actual tests. Having such a long interval also
5684 // avoids bloating logs with beacons during the set up phase.
5685 mac.SetType("ns3::ApWifiMac",
5686 "BeaconGeneration",
5687 BooleanValue(true),
5688 "BeaconInterval",
5689 TimeValue(MicroSeconds(1024 * 600)));
5690 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5692 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5693 m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5695 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5696 // set up for both STAs
5697
5699 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5700 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5701 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5702 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5703 positionAlloc->Add(
5704 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5705 mobility.SetPositionAllocator(positionAlloc);
5706
5707 mobility.Install(apNode);
5708 mobility.Install(staNodes);
5709
5710 lossModel->SetDefaultLoss(50.0);
5711 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5712 staNodes.Get(1)->GetObject<MobilityModel>(),
5713 56.0,
5714 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5715}
5716
5717void
5719{
5720 m_phyAp->Dispose();
5721 m_phyAp = nullptr;
5722 m_apDev->Dispose();
5723 m_apDev = nullptr;
5724 m_sta1Dev->Dispose();
5725 m_sta1Dev = nullptr;
5726 m_sta2Dev->Dispose();
5727 m_sta2Dev = nullptr;
5728}
5729
5730void
5732{
5733 RngSeedManager::SetSeed(1);
5734 RngSeedManager::SetRun(1);
5735 int64_t streamNumber = 0;
5736
5737 Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5738 Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5739
5740 m_phyAp->AssignStreams(streamNumber);
5741 phySta1->AssignStreams(streamNumber);
5742 phySta2->AssignStreams(streamNumber);
5743
5744 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5746 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5747
5748 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5749 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5750 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5751
5752 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5753 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5754 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5755
5756 Time relativeStart = MilliSeconds(0);
5757 if (setupBa)
5758 {
5759 // Set up BA for each station once the association phase has ended
5760 // so that a BA session is established when the MU-BAR is received.
5761 Simulator::Schedule(MilliSeconds(800),
5763 this,
5765 Simulator::Schedule(MilliSeconds(850),
5767 this,
5769 relativeStart = MilliSeconds(1000);
5770 }
5771 else
5772 {
5773 Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5774 NS_ASSERT(apMac);
5775 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5776 }
5777
5778 Simulator::Schedule(relativeStart,
5780 this);
5781
5782 {
5783 // Verify that the RSSI from STA 1 is consistent with what was requested
5784 std::vector<uint16_t> staIds{1};
5785 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5786 }
5787
5788 {
5789 // Verify that the RSSI from STA 2 is consistent with what was requested
5790 std::vector<uint16_t> staIds{2};
5791 Simulator::Schedule(relativeStart + MilliSeconds(20),
5793 this,
5794 staIds);
5795 }
5796
5797 {
5798 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5799 std::vector<uint16_t> staIds{1, 2};
5800 Simulator::Schedule(relativeStart + MilliSeconds(40),
5802 this,
5803 staIds);
5804 }
5805
5806 Simulator::Stop(relativeStart + MilliSeconds(100));
5807 Simulator::Run();
5808}
5809
5810void
5812{
5813 // Power configurations
5814 m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5815 // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5816 m_txPowerStart = 15; // dBm
5817
5818 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5819 m_requestedRssiSta1 = -30.0;
5820 m_requestedRssiSta2 = -36.0;
5821
5822 // Test single power level
5823 {
5824 // STA power configurations: 15 dBm only
5825 m_txPowerEnd = 15;
5826 m_txPowerLevels = 1;
5827
5828 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5829 // regardless of the estimated path loss.
5830 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5831 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5832
5833 RunOne(true);
5834 }
5835
5836 // Test 2 dBm granularity
5837 {
5838 // STA power configurations: [15:2:25] dBm
5839 m_txPowerEnd = 25;
5840 m_txPowerLevels = 6;
5841
5842 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5843 // requested
5844 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5845 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5846
5847 RunOne(false);
5848 }
5849
5850 // Test 1 dBm granularity
5851 {
5852 // STA power configurations: [15:1:25] dBm
5853 m_txPowerEnd = 25;
5854 m_txPowerLevels = 11;
5855
5856 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5857 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5858 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5859
5860 RunOne(false);
5861 }
5862
5863 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5864 {
5865 // STA power configurations: [15:1:25] dBm
5866 m_txPowerEnd = 25;
5867 m_txPowerLevels = 11;
5868
5869 // Requested UL RSSIs
5870 m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5871 m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5872
5873 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5874 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5875 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5876
5877 RunOne(false);
5878 }
5879
5880 Simulator::Destroy();
5881}
5882
5890{
5891 public:
5893};
5894
5896 : TestSuite("wifi-phy-ofdma", UNIT)
5897{
5898 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::QUICK);
5899 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::QUICK);
5900 AddTestCase(new TestUlOfdmaPpduUid, TestCase::QUICK);
5901 AddTestCase(new TestMultipleHeTbPreambles, TestCase::QUICK);
5902 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::QUICK);
5903 AddTestCase(new TestPhyPaddingExclusion, TestCase::QUICK);
5904 AddTestCase(new TestUlOfdmaPowerControl, TestCase::QUICK);
5905}
5906
#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.
Ptr< const HePhy > GetHePhy() const
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
static TypeId GetTypeId()
Get the type ID.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents()
Ptr< OfdmaTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for OFDMA test.
Ptr< Event > GetCurrentEvent()
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
void StartTx(Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector) override
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
void DoInitialize() override
Initialize() implementation.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy.
OfdmaTestHePhy(uint16_t staId)
Constructor.
~OfdmaTestHePhy() override
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.
PHY listener for OFDMA tests.
OfdmaTestPhyListener()=default
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, double txPowerDbm) override
bool m_lastRxSuccess
flag whether last RX has been successfull
void NotifyRxStart(Time duration) override
Time GetLastRxStartNotification() const
Return the time at which the last RX start notification has been received.
void NotifySwitchingStart(Time duration) override
void NotifyWakeup() override
Notify listeners that we woke up.
uint32_t m_notifyRxStart
count number of RX start notifications
void Reset()
Reset function.
Time m_lastRxEnd
last time a RX end notification has been received
Time m_lastRxStart
last time a RX start notification has been received
Time GetLastRxEndNotification() const
Return the time at which the last RX end notification has been received.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
uint32_t m_notifyRxEnd
count number of RX end notifications
bool IsLastRxSuccess() const
Return whether last RX has been successfull.
void NotifySleep() override
Notify listeners that we went to sleep.
uint32_t GetNumRxEndNotifications() const
Return the number of RX end notifications that has been received since the last reset.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
uint32_t GetNumRxStartNotifications() const
Return the number of RX start notifications that has been received since the last reset.
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyOn() override
Notify listeners that we went to switch on.
DL-OFDMA PHY puncturing test.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoRun() override
Implementation to actually run this TestCase.
Time m_expectedPpduDuration20Mhz
expected duration to send MU PPDU on 20 MHz RU
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void RunOne()
Run one function.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2, const std::vector< bool > &puncturedSubchannels)
Send MU-PPDU function.
uint16_t m_frequency
frequency in MHz
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta1
count RX failure for STA 1
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void StopInterference()
Stop interference function.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, const std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
uint16_t m_frequency
frequency in MHz
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint16_t m_channelWidth
channel width in MHz
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void DoRun() override
Implementation to actually run 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 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 RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function 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.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for 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 RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
void StopInterference()
Stop interference function.
void ResetResults()
Reset the results.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
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 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 RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize)
Receive HE TB PPDU function.
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
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()
Verify all events are cleared at end of TX or RX.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
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 DoRun() override
Implementation to actually run this TestCase.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
Ptr< OfdmaSpectrumWifiPhy > m_phyAp
PHY of AP.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
void RxSuccess(Ptr< const 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 StopInterference()
Stop interference function.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
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 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, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
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 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
std::unique_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification)
Check the the number of RX start notifications at the AP as well as the last time a RX start has been...
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.
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 SendHeTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor, bool incrementUid)
Send HE TB PPDU function.
void SetPsdLimit(Ptr< WifiPhy > phy, double psdLimit)
Set the PSD limit.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void StopInterference()
Stop interference function.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoTeardown() 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 RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
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 RunOne()
Run one function.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
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 VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
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
void DoRun() override
Implementation to actually run this TestCase.
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
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
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive OK callback function at AP.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
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
double m_txPowerAp
transmit power (in dBm) of AP
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
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 TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
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.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
Ptr< OfdmaSpectrumWifiPhy > m_phySta1
PHY of STA 1.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
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:92
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAckRequest.
Definition: ctrl-headers.h:51
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()
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:579
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:42
PHY entity for HE (11ax)
Definition: he-phy.h:64
RU Specification.
Definition: he-ru.h:66
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:435
void SetPhyIndex(uint16_t bw, uint8_t p20Index)
Set the RU PHY index.
Definition: he-ru.cc:456
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
an EUI-48 address
Definition: mac48-address.h:46
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:138
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:369
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:258
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition: object.cc:259
void Dispose()
Dispose of this Object.
Definition: object.cc:219
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:89
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:966
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:205
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
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:42
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1425
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
void SetDevice(Ptr< NetDevice > d) override
Set the associated NetDevice instance.
void SetChannel(Ptr< SpectrumChannel > c) override
Set the channel attached to this device.
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:325
Implements the IEEE 802.11 MAC header.
WifiMacType GetType() const
Return the type (enum WifiMacType)
void SetNoMoreFragments()
Un-set the More Fragment bit in the Frame Control Field.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
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.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
void SetDsFrom()
Set the From DS bit in the Frame Control field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
void SetNoRetry()
Un-set the Retry bit in the Frame Control field.
create MAC layers for a ns3::WifiNetDevice.
virtual void SetWifiPhys(const std::vector< Ptr< WifiPhy > > &phys)
Definition: wifi-mac.cc:920
void SetMac(const Ptr< WifiMac > mac)
void SetHeConfiguration(Ptr< HeConfiguration > heConfiguration)
Ptr< WifiMac > GetMac() const
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Ptr< HeConfiguration > GetHeConfiguration() const
void SetStandard(WifiStandard standard)
Set the Wifi standard.
Ptr< WifiPhy > GetPhy() const
void SetPhy(const Ptr< WifiPhy > phy)
Address GetAddress() const override
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
Definition: wifi-helper.h:536
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:606
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:1635
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:614
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:1188
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:728
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:423
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:895
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1422
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1211
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:1004
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:950
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1186
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:685
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1191
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:575
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:634
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:587
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:429
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1173
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:417
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1745
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:869
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:2124
receive notifications about PHY events.
This objects implements the PHY state machine of the Wifi device.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition: wifi-psdu.cc:269
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Definition: wifi-psdu.cc:128
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition: wifi-psdu.cc:263
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition: wifi-psdu.cc:158
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:317
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetInactiveSubchannels(const std::vector< bool > &inactiveSubchannels)
Set the 20 MHz subchannels that are punctured.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by 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.
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
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:66
#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:86
void Reset()
Reset the initial value of every attribute as well as the value of every global to what they were bef...
Definition: config.cc:856
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#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:275
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#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:144
#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:337
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1374
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
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
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ 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:562
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.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:691
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:40
@ 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:66
mac
Definition: third.py:85
wifi
Definition: third.py:88
mobility
Definition: third.py:96
phy
Definition: third.py:82
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
double rssi
RSSI in dBm.
Definition: phy-entity.h:72
#define SU_STA_ID
Definition: wifi-mode.h:34
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.