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 void StartTx(Ptr<const WifiPpdu> ppdu) override;
153
159 typedef void (*TxPpduUidCallback)(uint64_t uid);
160
166 void SetPpduUid(uint64_t uid);
167
173 void SetTriggerFrameUid(uint64_t uid);
174
178 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
183
194 Time GetEnergyDuration(double energyW, WifiSpectrumBand band);
195
200
201 private:
205}; // class OfdmaSpectrumWifiPhy
206
207TypeId
209{
210 static TypeId tid =
211 TypeId("ns3::OfdmaSpectrumWifiPhy")
213 .SetGroupName("Wifi")
214 .AddTraceSource("TxPpduUid",
215 "UID of the PPDU to be transmitted",
217 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
218 return tid;
219}
220
223{
224 m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
226}
227
229{
230}
231
232void
234{
235 // Replace HE PHY instance with test instance
237 SpectrumWifiPhy::DoInitialize();
238}
239
240void
242{
243 m_ofdmTestHePhy = nullptr;
244 SpectrumWifiPhy::DoDispose();
245}
246
247void
249{
252}
253
254void
256{
258}
259
260void
262{
263 m_phyTxPpduUidTrace(ppdu->GetUid());
264 SpectrumWifiPhy::StartTx(ppdu);
265}
266
267std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
269{
271}
272
275{
276 return m_currentEvent;
277}
278
279Time
281{
282 return m_interference->GetEnergyDuration(energyW, band);
283}
284
287{
288 return DynamicCast<const HePhy>(GetLatestPhyEntity());
289}
290
298{
299 public:
302
303 private:
304 void DoSetup() override;
305 void DoTeardown() override;
306 void DoRun() override;
307
316 RxSignalInfo rxSignalInfo,
317 WifiTxVector txVector,
318 std::vector<bool> statusPerMpdu);
327 RxSignalInfo rxSignalInfo,
328 WifiTxVector txVector,
329 std::vector<bool> statusPerMpdu);
338 RxSignalInfo rxSignalInfo,
339 WifiTxVector txVector,
340 std::vector<bool> statusPerMpdu);
341
357
364 void CheckResultsSta1(uint32_t expectedRxSuccess,
365 uint32_t expectedRxFailure,
366 uint32_t expectedRxBytes);
373 void CheckResultsSta2(uint32_t expectedRxSuccess,
374 uint32_t expectedRxFailure,
375 uint32_t expectedRxBytes);
382 void CheckResultsSta3(uint32_t expectedRxSuccess,
383 uint32_t expectedRxFailure,
384 uint32_t expectedRxBytes);
385
389 void ResetResults();
390
396 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
397
403 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
407 void StopInterference();
408
412 void RunOne();
413
426
436
442
443 uint16_t m_frequency;
444 uint16_t m_channelWidth;
446};
447
449 : TestCase("DL-OFDMA PHY test"),
450 m_countRxSuccessSta1(0),
451 m_countRxSuccessSta2(0),
452 m_countRxSuccessSta3(0),
453 m_countRxFailureSta1(0),
454 m_countRxFailureSta2(0),
455 m_countRxFailureSta3(0),
456 m_countRxBytesSta1(0),
457 m_countRxBytesSta2(0),
458 m_countRxBytesSta3(0),
459 m_frequency(DEFAULT_FREQUENCY),
460 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
461 m_expectedPpduDuration(NanoSeconds(306400))
462{
463}
464
465void
467{
477}
478
479void
480TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
481{
482 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
483 WifiConstPsduMap psdus;
484 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
485 0,
487 800,
488 1,
489 1,
490 0,
492 false,
493 false);
494 HeRu::RuType ruType = HeRu::RU_106_TONE;
495 if (m_channelWidth == 20)
496 {
497 ruType = HeRu::RU_106_TONE;
498 txVector.SetRuAllocation({96});
499 }
500 else if (m_channelWidth == 40)
501 {
502 ruType = HeRu::RU_242_TONE;
503 txVector.SetRuAllocation({192, 192});
504 }
505 else if (m_channelWidth == 80)
506 {
507 ruType = HeRu::RU_484_TONE;
508 txVector.SetRuAllocation({200, 200, 200, 200});
509 }
510 else if (m_channelWidth == 160)
511 {
512 ruType = HeRu::RU_996_TONE;
513 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208});
514 }
515 else
516 {
517 NS_ASSERT_MSG(false, "Unsupported channel width");
518 }
519
520 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
521
522 HeRu::RuSpec ru1(ruType, 1, true);
523 txVector.SetRu(ru1, rxStaId1);
524 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
525 txVector.SetNss(1, rxStaId1);
526
527 HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
528 txVector.SetRu(ru2, rxStaId2);
529 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
530 txVector.SetNss(1, rxStaId2);
531
532 Ptr<Packet> pkt1 = Create<Packet>(1000);
533 WifiMacHeader hdr1;
535 hdr1.SetQosTid(0);
536 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
537 hdr1.SetSequenceNumber(1);
538 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
539 psdus.insert(std::make_pair(rxStaId1, psdu1));
540
541 Ptr<Packet> pkt2 = Create<Packet>(1500);
542 WifiMacHeader hdr2;
544 hdr2.SetQosTid(0);
545 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
546 hdr2.SetSequenceNumber(2);
547 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
548 psdus.insert(std::make_pair(rxStaId2, psdu2));
549
550 m_phyAp->Send(psdus, txVector);
551}
552
553void
555{
557 m_phyInterferer->SetPeriod(duration);
559 Simulator::Schedule(duration, &TestDlOfdmaPhyTransmission::StopInterference, this);
560}
561
562void
564{
566}
567
569{
570}
571
572void
574 RxSignalInfo rxSignalInfo,
575 WifiTxVector txVector,
576 std::vector<bool> /*statusPerMpdu*/)
577{
578 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
580 m_countRxBytesSta1 += (psdu->GetSize() - 30);
581}
582
583void
585 RxSignalInfo rxSignalInfo,
586 WifiTxVector txVector,
587 std::vector<bool> /*statusPerMpdu*/)
588{
589 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
591 m_countRxBytesSta2 += (psdu->GetSize() - 30);
592}
593
594void
596 RxSignalInfo rxSignalInfo,
597 WifiTxVector txVector,
598 std::vector<bool> /*statusPerMpdu*/)
599{
600 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
602 m_countRxBytesSta3 += (psdu->GetSize() - 30);
603}
604
605void
607{
608 NS_LOG_FUNCTION(this << *psdu);
610}
611
612void
614{
615 NS_LOG_FUNCTION(this << *psdu);
617}
618
619void
621{
622 NS_LOG_FUNCTION(this << *psdu);
624}
625
626void
628 uint32_t expectedRxFailure,
629 uint32_t expectedRxBytes)
630{
632 expectedRxSuccess,
633 "The number of successfully received packets by STA 1 is not correct!");
635 expectedRxFailure,
636 "The number of unsuccessfuly received packets by STA 1 is not correct!");
638 expectedRxBytes,
639 "The number of bytes received by STA 1 is not correct!");
640}
641
642void
644 uint32_t expectedRxFailure,
645 uint32_t expectedRxBytes)
646{
648 expectedRxSuccess,
649 "The number of successfully received packets by STA 2 is not correct!");
651 expectedRxFailure,
652 "The number of unsuccessfuly received packets by STA 2 is not correct!");
654 expectedRxBytes,
655 "The number of bytes received by STA 2 is not correct!");
656}
657
658void
660 uint32_t expectedRxFailure,
661 uint32_t expectedRxBytes)
662{
664 expectedRxSuccess,
665 "The number of successfully received packets by STA 3 is not correct!");
667 expectedRxFailure,
668 "The number of unsuccessfuly received packets by STA 3 is not correct!");
670 expectedRxBytes,
671 "The number of bytes received by STA 3 is not correct!");
672}
673
674void
676{
677 // This is needed to make sure PHY state will be checked as the last event if a state change
678 // occurred at the exact same time as the check
679 Simulator::ScheduleNow(&TestDlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
680}
681
682void
684 WifiPhyState expectedState)
685{
686 WifiPhyState currentState;
687 PointerValue ptr;
688 phy->GetAttribute("State", ptr);
689 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
690 currentState = state->GetState();
691 NS_LOG_FUNCTION(this << currentState);
692 NS_TEST_ASSERT_MSG_EQ(currentState,
693 expectedState,
694 "PHY State " << currentState << " does not match expected state "
695 << expectedState << " at " << Simulator::Now());
696}
697
698void
700{
701 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
702 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
703 lossModel->SetFrequency(m_frequency * 1e6);
704 spectrumChannel->AddPropagationLossModel(lossModel);
706 CreateObject<ConstantSpeedPropagationDelayModel>();
707 spectrumChannel->SetPropagationDelayModel(delayModel);
708
709 Ptr<Node> apNode = CreateObject<Node>();
710 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
711 m_phyAp = CreateObject<SpectrumWifiPhy>();
714 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
715 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
716 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
717 m_phyAp->SetErrorRateModel(apErrorModel);
718 m_phyAp->SetDevice(apDev);
719 m_phyAp->SetChannel(spectrumChannel);
720 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
721 m_phyAp->SetMobility(apMobility);
722 apDev->SetPhy(m_phyAp);
723 apNode->AggregateObject(apMobility);
724 apNode->AddDevice(apDev);
725
726 Ptr<Node> sta1Node = CreateObject<Node>();
727 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
728 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
731 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
732 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
733 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
734 m_phySta1->SetErrorRateModel(sta1ErrorModel);
735 m_phySta1->SetDevice(sta1Dev);
736 m_phySta1->SetChannel(spectrumChannel);
740 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
741 m_phySta1->SetMobility(sta1Mobility);
742 sta1Dev->SetPhy(m_phySta1);
743 sta1Node->AggregateObject(sta1Mobility);
744 sta1Node->AddDevice(sta1Dev);
745
746 Ptr<Node> sta2Node = CreateObject<Node>();
747 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
748 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
751 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
752 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
753 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
754 m_phySta2->SetErrorRateModel(sta2ErrorModel);
755 m_phySta2->SetDevice(sta2Dev);
756 m_phySta2->SetChannel(spectrumChannel);
760 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
761 m_phySta2->SetMobility(sta2Mobility);
762 sta2Dev->SetPhy(m_phySta2);
763 sta2Node->AggregateObject(sta2Mobility);
764 sta2Node->AddDevice(sta2Dev);
765
766 Ptr<Node> sta3Node = CreateObject<Node>();
767 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
768 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
771 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
772 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
773 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
774 m_phySta3->SetErrorRateModel(sta3ErrorModel);
775 m_phySta3->SetDevice(sta3Dev);
776 m_phySta3->SetChannel(spectrumChannel);
780 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
781 m_phySta3->SetMobility(sta3Mobility);
782 sta3Dev->SetPhy(m_phySta3);
783 sta3Node->AggregateObject(sta3Mobility);
784 sta3Node->AddDevice(sta3Dev);
785
786 Ptr<Node> interfererNode = CreateObject<Node>();
787 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
788 m_phyInterferer = CreateObject<WaveformGenerator>();
789 m_phyInterferer->SetDevice(interfererDev);
790 m_phyInterferer->SetChannel(spectrumChannel);
792 interfererNode->AddDevice(interfererDev);
793}
794
795void
797{
798 m_phyAp->Dispose();
799 m_phyAp = nullptr;
801 m_phySta1 = nullptr;
803 m_phySta2 = nullptr;
805 m_phySta3 = nullptr;
807 m_phyInterferer = nullptr;
808}
809
810void
812{
813 RngSeedManager::SetSeed(1);
814 RngSeedManager::SetRun(1);
815 int64_t streamNumber = 0;
816 m_phyAp->AssignStreams(streamNumber);
817 m_phySta1->AssignStreams(streamNumber);
818 m_phySta2->AssignStreams(streamNumber);
819 m_phySta3->AssignStreams(streamNumber);
820
821 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
826
835
836 Simulator::Schedule(Seconds(0.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
837
838 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
839 // Each STA should receive its PSDU.
840 Simulator::Schedule(Seconds(1.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
841
842 // Since it takes m_expectedPpduDuration to transmit the PPDU,
843 // all 3 PHYs should be back to IDLE at the same time,
844 // even the PHY that has no PSDU addressed to it.
845 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
847 this,
848 m_phySta1,
850 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
852 this,
853 m_phySta2,
855 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration - NanoSeconds(1),
857 this,
858 m_phySta3,
860 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
862 this,
863 m_phySta1,
865 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
867 this,
868 m_phySta2,
870 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration,
872 this,
873 m_phySta3,
875
876 // One PSDU of 1000 bytes should have been successfully received by STA 1
877 Simulator::Schedule(Seconds(1.1),
879 this,
880 1,
881 0,
882 1000);
883 // One PSDU of 1500 bytes should have been successfully received by STA 2
884 Simulator::Schedule(Seconds(1.1),
886 this,
887 1,
888 0,
889 1500);
890 // No PSDU should have been received by STA 3
891 Simulator::Schedule(Seconds(1.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
892
893 Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
894
895 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
896 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
897 // but should keep its PHY busy during all PPDU duration.
898 Simulator::Schedule(Seconds(2.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 3);
899
900 // Since it takes m_expectedPpduDuration to transmit the PPDU,
901 // all 3 PHYs should be back to IDLE at the same time,
902 // even the PHY that has no PSDU addressed to it.
903 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
905 this,
906 m_phySta1,
908 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
910 this,
911 m_phySta2,
913 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration - NanoSeconds(1),
915 this,
916 m_phySta3,
918 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
920 this,
921 m_phySta1,
923 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
925 this,
926 m_phySta2,
928 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration,
930 this,
931 m_phySta3,
933
934 // One PSDU of 1000 bytes should have been successfully received by STA 1
935 Simulator::Schedule(Seconds(2.1),
937 this,
938 1,
939 0,
940 1000);
941 // No PSDU should have been received by STA 2
942 Simulator::Schedule(Seconds(2.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 0, 0);
943 // One PSDU of 1500 bytes should have been successfully received by STA 3
944 Simulator::Schedule(Seconds(2.1),
946 this,
947 1,
948 0,
949 1500);
950
951 Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
952
953 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
954 Simulator::Schedule(Seconds(3.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
955
956 // A strong non-wifi interference is generated on RU 1 during PSDU reception
957 BandInfo bandInfo;
958 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
959 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
960 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
961 Bands bands;
962 bands.push_back(bandInfo);
963
964 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
965 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
966 double interferencePower = 0.1; // watts
967 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
968
969 Simulator::Schedule(Seconds(3.0) + MicroSeconds(50),
971 this,
972 interferencePsdRu1,
973 MilliSeconds(100));
974
975 // Since it takes m_expectedPpduDuration to transmit the PPDU,
976 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
977 // even the PHY that has no PSDU addressed to it.
978 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
980 this,
981 m_phySta1,
983 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
985 this,
986 m_phySta2,
988 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration - NanoSeconds(1),
990 this,
991 m_phySta3,
993 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
995 this,
996 m_phySta1,
998 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1000 this,
1001 m_phySta2,
1003 Simulator::Schedule(Seconds(3.0) + m_expectedPpduDuration,
1005 this,
1006 m_phySta3,
1008
1009 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1010 // occupies RU 1)
1011 Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1012 // One PSDU of 1500 bytes should have been successfully received by STA 2
1013 Simulator::Schedule(Seconds(3.1),
1015 this,
1016 1,
1017 0,
1018 1500);
1019 // No PSDU should have been received by STA3
1020 Simulator::Schedule(Seconds(3.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1021
1022 Simulator::Schedule(Seconds(3.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1023
1024 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1025 Simulator::Schedule(Seconds(4.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1026
1027 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1028 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1029 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1030 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1031 bands.clear();
1032 bands.push_back(bandInfo);
1033
1034 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1035 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1036 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1037
1038 Simulator::Schedule(Seconds(4.0) + MicroSeconds(50),
1040 this,
1041 interferencePsdRu2,
1042 MilliSeconds(100));
1043
1044 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1045 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1046 // same time, even the PHY that has no PSDU addressed to it.
1047 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1049 this,
1050 m_phySta1,
1052 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1054 this,
1055 m_phySta2,
1057 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration - NanoSeconds(1),
1059 this,
1060 m_phySta3,
1062 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1064 this,
1065 m_phySta1,
1067 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1069 this,
1070 m_phySta2,
1072 Simulator::Schedule(Seconds(4.0) + m_expectedPpduDuration,
1074 this,
1075 m_phySta3,
1077
1078 // One PSDU of 1000 bytes should have been successfully received by STA 1
1079 Simulator::Schedule(Seconds(4.1),
1081 this,
1082 1,
1083 0,
1084 1000);
1085 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1086 // occupies RU 2)
1087 Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1088 // No PSDU should have been received by STA3
1089 Simulator::Schedule(Seconds(4.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1090
1091 Simulator::Schedule(Seconds(4.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1092
1093 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1094 Simulator::Schedule(Seconds(5.0), &TestDlOfdmaPhyTransmission::SendMuPpdu, this, 1, 2);
1095
1096 // A strong non-wifi interference is generated on the full band during PSDU reception
1097 bandInfo.fc = m_frequency * 1e6;
1098 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1099 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1100 bands.clear();
1101 bands.push_back(bandInfo);
1102
1103 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1104 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1105 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1106
1107 Simulator::Schedule(Seconds(5.0) + MicroSeconds(50),
1109 this,
1110 interferencePsdAll,
1111 MilliSeconds(100));
1112
1113 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1114 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1115 // even the PHY that has no PSDU addressed to it.
1116 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1118 this,
1119 m_phySta1,
1121 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1123 this,
1124 m_phySta2,
1126 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration - NanoSeconds(1),
1128 this,
1129 m_phySta3,
1131 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1133 this,
1134 m_phySta1,
1136 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1138 this,
1139 m_phySta2,
1141 Simulator::Schedule(Seconds(5.0) + m_expectedPpduDuration,
1143 this,
1144 m_phySta3,
1146
1147 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1148 // occupies RU 1)
1149 Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta1, this, 0, 1, 0);
1150 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1151 // occupies RU 2)
1152 Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta2, this, 0, 1, 0);
1153 // No PSDU should have been received by STA3
1154 Simulator::Schedule(Seconds(5.1), &TestDlOfdmaPhyTransmission::CheckResultsSta3, this, 0, 0, 0);
1155
1156 Simulator::Schedule(Seconds(5.5), &TestDlOfdmaPhyTransmission::ResetResults, this);
1157
1158 Simulator::Run();
1159}
1160
1161void
1163{
1164 m_frequency = 5180;
1165 m_channelWidth = 20;
1167 RunOne();
1168
1169 m_frequency = 5190;
1170 m_channelWidth = 40;
1172 RunOne();
1173
1174 m_frequency = 5210;
1175 m_channelWidth = 80;
1177 RunOne();
1178
1179 m_frequency = 5250;
1180 m_channelWidth = 160;
1182 RunOne();
1183
1184 Simulator::Destroy();
1185}
1186
1194{
1195 public:
1197
1198 private:
1199 void DoSetup() override;
1200 void DoTeardown() override;
1201 void DoRun() override;
1202
1211 RxSignalInfo rxSignalInfo,
1212 WifiTxVector txVector,
1213 const std::vector<bool> statusPerMpdu);
1214
1223 RxSignalInfo rxSignalInfo,
1224 WifiTxVector txVector,
1225 std::vector<bool> statusPerMpdu);
1226
1232
1238
1245 void CheckResultsSta1(uint32_t expectedRxSuccess,
1246 uint32_t expectedRxFailure,
1247 uint32_t expectedRxBytes);
1248
1255 void CheckResultsSta2(uint32_t expectedRxSuccess,
1256 uint32_t expectedRxFailure,
1257 uint32_t expectedRxBytes);
1258
1262 void ResetResults();
1263
1271 void SendMuPpdu(uint16_t rxStaId1,
1272 uint16_t rxStaId2,
1273 const std::vector<bool>& puncturedSubchannels);
1274
1280 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1281
1285 void StopInterference();
1286
1290 void RunOne();
1291
1298
1305
1312
1317
1318 uint16_t m_frequency;
1320
1323
1326};
1327
1329 : TestCase("DL-OFDMA PHY puncturing test"),
1330 m_countRxSuccessSta1(0),
1331 m_countRxSuccessSta2(0),
1332 m_countRxFailureSta1(0),
1333 m_countRxFailureSta2(0),
1334 m_countRxBytesSta1(0),
1335 m_countRxBytesSta2(0),
1336 m_frequency(5210),
1337 m_channelWidth(80),
1338 m_indexSubchannel(0),
1339 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1340 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1341{
1342}
1343
1344void
1346{
1353}
1354
1355void
1357 uint16_t rxStaId2,
1358 const std::vector<bool>& puncturedSubchannels)
1359{
1360 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1361 WifiConstPsduMap psdus;
1362 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
1363 0,
1365 800,
1366 1,
1367 1,
1368 0,
1370 false,
1371 false);
1372
1373 HeRu::RuType ruType =
1374 puncturedSubchannels.empty()
1375 ? HeRu::RU_484_TONE
1376 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1377 HeRu::RuSpec ru1(ruType, 1, true);
1378 txVector.SetRu(ru1, rxStaId1);
1379 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1380 txVector.SetNss(1, rxStaId1);
1381
1382 ruType = puncturedSubchannels.empty()
1383 ? HeRu::RU_484_TONE
1384 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1385 HeRu::RuSpec ru2(ruType,
1386 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1387 true);
1388 txVector.SetRu(ru2, rxStaId2);
1389 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1390 txVector.SetNss(1, rxStaId2);
1391
1392 std::vector<uint8_t> ruAlloc;
1393 if (puncturedSubchannels.empty())
1394 {
1395 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1396 }
1397 else
1398 {
1399 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1400 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1401 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1402 : (puncturedSubchannels.at(3) ? 192 : 200));
1403 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1404 : (puncturedSubchannels.at(3) ? 113 : 200));
1405 }
1406
1407 txVector.SetRuAllocation(ruAlloc);
1408 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1409
1410 Ptr<Packet> pkt1 = Create<Packet>(1000);
1411 WifiMacHeader hdr1;
1413 hdr1.SetQosTid(0);
1414 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1415 hdr1.SetSequenceNumber(1);
1416 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1417 psdus.insert(std::make_pair(rxStaId1, psdu1));
1418
1419 Ptr<Packet> pkt2 = Create<Packet>(1500);
1420 WifiMacHeader hdr2;
1422 hdr2.SetQosTid(0);
1423 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1424 hdr2.SetSequenceNumber(2);
1425 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1426 psdus.insert(std::make_pair(rxStaId2, psdu2));
1427
1428 if (!puncturedSubchannels.empty())
1429 {
1430 txVector.SetInactiveSubchannels(puncturedSubchannels);
1431 }
1432
1433 m_phyAp->Send(psdus, txVector);
1434}
1435
1436void
1438{
1439 NS_LOG_FUNCTION(this << duration);
1441 m_phyInterferer->SetPeriod(duration);
1443 Simulator::Schedule(duration, &TestDlOfdmaPhyPuncturing::StopInterference, this);
1444}
1445
1446void
1448{
1449 NS_LOG_FUNCTION(this);
1451}
1452
1453void
1455 RxSignalInfo rxSignalInfo,
1456 WifiTxVector txVector,
1457 std::vector<bool> /*statusPerMpdu*/)
1458{
1459 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1461 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1462}
1463
1464void
1466 RxSignalInfo rxSignalInfo,
1467 WifiTxVector txVector,
1468 std::vector<bool> /*statusPerMpdu*/)
1469{
1470 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1472 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1473}
1474
1475void
1477{
1478 NS_LOG_FUNCTION(this << *psdu);
1480}
1481
1482void
1484{
1485 NS_LOG_FUNCTION(this << *psdu);
1487}
1488
1489void
1491 uint32_t expectedRxFailure,
1492 uint32_t expectedRxBytes)
1493{
1495 expectedRxSuccess,
1496 "The number of successfully received packets by STA 1 is not correct!");
1498 expectedRxFailure,
1499 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1501 expectedRxBytes,
1502 "The number of bytes received by STA 1 is not correct!");
1503}
1504
1505void
1507 uint32_t expectedRxFailure,
1508 uint32_t expectedRxBytes)
1509{
1511 expectedRxSuccess,
1512 "The number of successfully received packets by STA 2 is not correct!");
1514 expectedRxFailure,
1515 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1517 expectedRxBytes,
1518 "The number of bytes received by STA 2 is not correct!");
1519}
1520
1521void
1523{
1524 // This is needed to make sure PHY state will be checked as the last event if a state change
1525 // occurred at the exact same time as the check
1526 Simulator::ScheduleNow(&TestDlOfdmaPhyPuncturing::DoCheckPhyState, this, phy, expectedState);
1527}
1528
1529void
1531{
1532 WifiPhyState currentState;
1533 PointerValue ptr;
1534 phy->GetAttribute("State", ptr);
1535 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1536 currentState = state->GetState();
1537 NS_LOG_FUNCTION(this << currentState);
1538 NS_TEST_ASSERT_MSG_EQ(currentState,
1539 expectedState,
1540 "PHY State " << currentState << " does not match expected state "
1541 << expectedState << " at " << Simulator::Now());
1542}
1543
1544void
1546{
1547 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1548 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1549 lossModel->SetFrequency(m_frequency * 1e6);
1550 spectrumChannel->AddPropagationLossModel(lossModel);
1552 CreateObject<ConstantSpeedPropagationDelayModel>();
1553 spectrumChannel->SetPropagationDelayModel(delayModel);
1554
1555 Ptr<Node> apNode = CreateObject<Node>();
1556 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1557 m_phyAp = CreateObject<SpectrumWifiPhy>();
1560 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1561 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1562 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1563 m_phyAp->SetErrorRateModel(apErrorModel);
1564 m_phyAp->SetDevice(apDev);
1565 m_phyAp->SetChannel(spectrumChannel);
1566 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1567 m_phyAp->SetMobility(apMobility);
1568 apDev->SetPhy(m_phyAp);
1569 apNode->AggregateObject(apMobility);
1570 apNode->AddDevice(apDev);
1571
1572 Ptr<Node> sta1Node = CreateObject<Node>();
1573 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1574 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1577 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1578 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1579 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1580 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1581 m_phySta1->SetDevice(sta1Dev);
1582 m_phySta1->SetChannel(spectrumChannel);
1586 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1587 m_phySta1->SetMobility(sta1Mobility);
1588 sta1Dev->SetPhy(m_phySta1);
1589 sta1Node->AggregateObject(sta1Mobility);
1590 sta1Node->AddDevice(sta1Dev);
1591
1592 Ptr<Node> sta2Node = CreateObject<Node>();
1593 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1594 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1597 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1598 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1599 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1600 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1601 m_phySta2->SetDevice(sta2Dev);
1602 m_phySta2->SetChannel(spectrumChannel);
1606 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1607 m_phySta2->SetMobility(sta2Mobility);
1608 sta2Dev->SetPhy(m_phySta2);
1609 sta2Node->AggregateObject(sta2Mobility);
1610 sta2Node->AddDevice(sta2Dev);
1611
1612 Ptr<Node> interfererNode = CreateObject<Node>();
1613 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1614 m_phyInterferer = CreateObject<WaveformGenerator>();
1615 m_phyInterferer->SetDevice(interfererDev);
1616 m_phyInterferer->SetChannel(spectrumChannel);
1618 interfererNode->AddDevice(interfererDev);
1619}
1620
1621void
1623{
1624 m_phyAp->Dispose();
1625 m_phyAp = nullptr;
1626 m_phySta1->Dispose();
1627 m_phySta1 = nullptr;
1628 m_phySta2->Dispose();
1629 m_phySta2 = nullptr;
1631 m_phyInterferer = nullptr;
1632}
1633
1634void
1636{
1637 RngSeedManager::SetSeed(1);
1638 RngSeedManager::SetRun(1);
1639 int64_t streamNumber = 0;
1640 m_phyAp->AssignStreams(streamNumber);
1641 m_phySta1->AssignStreams(streamNumber);
1642 m_phySta2->AssignStreams(streamNumber);
1643
1644 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1649
1656
1657 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1658 // duration of the test run
1659 BandInfo bandInfo;
1660 bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1661 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1662 // the border of another RU
1663 bandInfo.fl = bandInfo.fc - (5 * 1e6);
1664 bandInfo.fh = bandInfo.fc + (5 * 1e6);
1665 Bands bands;
1666 bands.push_back(bandInfo);
1667
1668 Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1669 Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1670 double interferencePower = 0.1; // watts
1671 *interferencePsd = interferencePower / 10e6;
1672
1673 Simulator::Schedule(Seconds(0.0),
1675 this,
1676 interferencePsd,
1677 Seconds(3));
1678
1679 //---------------------------------------------------------------------------
1680 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1681 Simulator::Schedule(Seconds(1.0),
1683 this,
1684 1,
1685 2,
1686 std::vector<bool>{});
1687
1688 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1689 // both PHYs should be back to IDLE at the same time.
1690 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1692 this,
1693 m_phySta1,
1695 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz - NanoSeconds(1),
1697 this,
1698 m_phySta2,
1700 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1702 this,
1703 m_phySta1,
1705 Simulator::Schedule(Seconds(1.0) + m_expectedPpduDuration40Mhz,
1707 this,
1708 m_phySta2,
1710
1711 if (m_indexSubchannel < 2) // interference in RU 1
1712 {
1713 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1714 Simulator::Schedule(Seconds(1.1),
1716 this,
1717 0,
1718 1,
1719 0);
1720 // One PSDU of 1500 bytes should have been successfully received by STA 2
1721 Simulator::Schedule(Seconds(1.1),
1723 this,
1724 1,
1725 0,
1726 1500);
1727 }
1728 else // interference in RU 2
1729 {
1730 // One PSDU of 1000 bytes should have been successfully received by STA 1
1731 Simulator::Schedule(Seconds(1.1),
1733 this,
1734 1,
1735 0,
1736 1000);
1737 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1738 Simulator::Schedule(Seconds(1.1),
1740 this,
1741 0,
1742 1,
1743 0);
1744 }
1745
1746 Simulator::Schedule(Seconds(1.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1747
1748 //---------------------------------------------------------------------------
1749 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1750 // the punctured 20 MHz subchannel is the one that has interference
1751 std::vector<bool> puncturedSubchannels;
1752 for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1753 {
1754 if (i == m_indexSubchannel)
1755 {
1756 puncturedSubchannels.push_back(true);
1757 }
1758 else
1759 {
1760 puncturedSubchannels.push_back(false);
1761 }
1762 }
1763 Simulator::Schedule(Seconds(2.0),
1765 this,
1766 1,
1767 2,
1768 puncturedSubchannels);
1769
1770 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1771 // both PHYs should be back to IDLE at the same time.
1772 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1774 this,
1775 m_phySta1,
1777 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz - NanoSeconds(1),
1779 this,
1780 m_phySta2,
1782 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1784 this,
1785 m_phySta1,
1787 Simulator::Schedule(Seconds(2.0) + m_expectedPpduDuration20Mhz,
1789 this,
1790 m_phySta2,
1792
1793 // One PSDU of 1000 bytes should have been successfully received by STA 1
1794 Simulator::Schedule(Seconds(2.1),
1796 this,
1797 1,
1798 0,
1799 1000);
1800 // One PSDU of 1500 bytes should have been successfully received by STA 2
1801 Simulator::Schedule(Seconds(2.1),
1803 this,
1804 1,
1805 0,
1806 1500);
1807
1808 Simulator::Schedule(Seconds(2.5), &TestDlOfdmaPhyPuncturing::ResetResults, this);
1809
1810 Simulator::Run();
1811}
1812
1813void
1815{
1816 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1817 // cannot be punctured
1818 for (auto index : {1, 2, 3})
1819 {
1820 m_indexSubchannel = index;
1821 RunOne();
1822 }
1823 Simulator::Destroy();
1824}
1825
1833{
1834 public:
1836 ~TestUlOfdmaPpduUid() override;
1837
1838 private:
1839 void DoSetup() override;
1840 void DoTeardown() override;
1841 void DoRun() override;
1842
1847 void TxPpduAp(uint64_t uid);
1852 void TxPpduSta1(uint64_t uid);
1857 void TxPpduSta2(uint64_t uid);
1861 void ResetPpduUid();
1862
1866 void SendMuPpdu();
1870 void SendTbPpdu();
1875 void SendSuPpdu(uint16_t txStaId);
1876
1882 void CheckUid(uint16_t staId, uint64_t expectedUid);
1883
1887
1888 uint64_t m_ppduUidAp;
1889 uint64_t m_ppduUidSta1;
1890 uint64_t m_ppduUidSta2;
1891};
1892
1894 : TestCase("UL-OFDMA PPDU UID attribution test"),
1895 m_ppduUidAp(UINT64_MAX),
1896 m_ppduUidSta1(UINT64_MAX),
1897 m_ppduUidSta2(UINT64_MAX)
1898{
1899}
1900
1902{
1903}
1904
1905void
1907{
1908 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1909 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1910 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1911 spectrumChannel->AddPropagationLossModel(lossModel);
1913 CreateObject<ConstantSpeedPropagationDelayModel>();
1914 spectrumChannel->SetPropagationDelayModel(delayModel);
1915
1916 Ptr<Node> apNode = CreateObject<Node>();
1917 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1918 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1921 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1922 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1923 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1924 m_phyAp->SetErrorRateModel(apErrorModel);
1925 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1932 m_phyAp->SetDevice(apDev);
1933 m_phyAp->SetChannel(spectrumChannel);
1936 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1937 m_phyAp->SetMobility(apMobility);
1938 apDev->SetPhy(m_phyAp);
1939 apNode->AggregateObject(apMobility);
1940 apNode->AddDevice(apDev);
1942 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1943
1944 Ptr<Node> sta1Node = CreateObject<Node>();
1945 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1946 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1949 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1950 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1951 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1952 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1955 m_phySta1->SetDevice(sta1Dev);
1956 m_phySta1->SetChannel(spectrumChannel);
1959 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1960 m_phySta1->SetMobility(sta1Mobility);
1961 sta1Dev->SetPhy(m_phySta1);
1962 sta1Node->AggregateObject(sta1Mobility);
1963 sta1Node->AddDevice(sta1Dev);
1964
1965 Ptr<Node> sta2Node = CreateObject<Node>();
1966 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1967 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1970 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1971 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1972 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1973 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1976 m_phySta2->SetDevice(sta2Dev);
1977 m_phySta2->SetChannel(spectrumChannel);
1980 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1981 m_phySta2->SetMobility(sta2Mobility);
1982 sta2Dev->SetPhy(m_phySta2);
1983 sta2Node->AggregateObject(sta2Mobility);
1984 sta2Node->AddDevice(sta2Dev);
1985}
1986
1987void
1989{
1990 m_phyAp->Dispose();
1991 m_phyAp = nullptr;
1992 m_phySta1->Dispose();
1993 m_phySta1 = nullptr;
1994 m_phySta2->Dispose();
1995 m_phySta2 = nullptr;
1996}
1997
1998void
1999TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
2000{
2001 uint64_t uid;
2002 std::string device;
2003 switch (staId)
2004 {
2005 case 0:
2006 uid = m_ppduUidAp;
2007 device = "AP";
2008 break;
2009 case 1:
2010 uid = m_ppduUidSta1;
2011 device = "STA1";
2012 break;
2013 case 2:
2014 uid = m_ppduUidSta2;
2015 device = "STA2";
2016 break;
2017 default:
2018 NS_ABORT_MSG("Unexpected STA-ID");
2019 }
2021 expectedUid,
2022 "UID " << uid << " does not match expected one " << expectedUid << " for "
2023 << device << " at " << Simulator::Now());
2024}
2025
2026void
2028{
2029 NS_LOG_FUNCTION(this << uid);
2030 m_ppduUidAp = uid;
2031}
2032
2033void
2035{
2036 NS_LOG_FUNCTION(this << uid);
2037 m_ppduUidSta1 = uid;
2038}
2039
2040void
2042{
2043 NS_LOG_FUNCTION(this << uid);
2044 m_ppduUidSta2 = uid;
2045}
2046
2047void
2049{
2050 NS_LOG_FUNCTION(this);
2051 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2052}
2053
2054void
2056{
2057 WifiConstPsduMap psdus;
2058 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2059 0,
2061 800,
2062 1,
2063 1,
2064 0,
2066 false,
2067 false);
2068
2069 uint16_t rxStaId1 = 1;
2070 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2071 txVector.SetRu(ru1, rxStaId1);
2072 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2073 txVector.SetNss(1, rxStaId1);
2074
2075 uint16_t rxStaId2 = 2;
2076 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2077 txVector.SetRu(ru2, rxStaId2);
2078 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2079 txVector.SetNss(1, rxStaId2);
2080 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2081 txVector.SetRuAllocation({96});
2082
2083 Ptr<Packet> pkt1 = Create<Packet>(1000);
2084 WifiMacHeader hdr1;
2086 hdr1.SetQosTid(0);
2087 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2088 hdr1.SetSequenceNumber(1);
2089 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2090 psdus.insert(std::make_pair(rxStaId1, psdu1));
2091
2092 Ptr<Packet> pkt2 = Create<Packet>(1500);
2093 WifiMacHeader hdr2;
2095 hdr2.SetQosTid(0);
2096 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2097 hdr2.SetSequenceNumber(2);
2098 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2099 psdus.insert(std::make_pair(rxStaId2, psdu2));
2100
2101 m_phyAp->Send(psdus, txVector);
2102}
2103
2104void
2106{
2107 WifiConstPsduMap psdus1;
2108 WifiConstPsduMap psdus2;
2109
2110 WifiTxVector txVector1 = WifiTxVector(HePhy::GetHeMcs7(),
2111 0,
2113 1600,
2114 1,
2115 1,
2116 0,
2118 false,
2119 false);
2120 WifiTxVector txVector2 = txVector1;
2121 WifiTxVector trigVector = txVector2;
2122
2123 uint16_t rxStaId1 = 1;
2124 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2125 txVector1.SetRu(ru1, rxStaId1);
2126 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2127 txVector1.SetNss(1, rxStaId1);
2128 trigVector.SetRu(ru1, rxStaId1);
2129 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2130 trigVector.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 trigVector.SetRu(ru2, rxStaId2);
2147 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2148 trigVector.SetNss(1, rxStaId2);
2149
2150 Ptr<Packet> pkt2 = Create<Packet>(1500);
2151 WifiMacHeader hdr2;
2153 hdr2.SetQosTid(0);
2154 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2155 hdr2.SetSequenceNumber(2);
2156 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2157 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2158
2159 Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2160 txVector1,
2162 rxStaId1);
2163 Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2164 txVector2,
2166 rxStaId2);
2167 Time txDuration = std::max(txDuration1, txDuration2);
2168
2169 txVector1.SetLength(
2170 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector1, m_phySta1->GetPhyBand())
2171 .first);
2172 txVector2.SetLength(
2173 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector2, m_phySta2->GetPhyBand())
2174 .first);
2175
2176 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
2177 hePhyAp->SetTrigVector(trigVector, txDuration);
2178
2179 m_phySta1->Send(psdus1, txVector1);
2180 m_phySta2->Send(psdus2, txVector2);
2181}
2182
2183void
2185{
2186 WifiConstPsduMap psdus;
2187 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2188 0,
2190 800,
2191 1,
2192 1,
2193 0,
2195 false,
2196 false);
2197
2198 Ptr<Packet> pkt = Create<Packet>(1000);
2199 WifiMacHeader hdr;
2201 hdr.SetQosTid(0);
2202 hdr.SetAddr1(Mac48Address::GetBroadcast());
2203 hdr.SetSequenceNumber(1);
2204 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2205 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2206
2207 switch (txStaId)
2208 {
2209 case 0:
2210 m_phyAp->Send(psdus, txVector);
2211 break;
2212 case 1:
2213 m_phySta1->Send(psdus, txVector);
2214 break;
2215 case 2:
2216 m_phySta2->Send(psdus, txVector);
2217 break;
2218 default:
2219 NS_ABORT_MSG("Unexpected STA-ID");
2220 }
2221}
2222
2223void
2225{
2226 RngSeedManager::SetSeed(1);
2227 RngSeedManager::SetRun(1);
2228 int64_t streamNumber = 0;
2229 m_phyAp->AssignStreams(streamNumber);
2230 m_phySta1->AssignStreams(streamNumber);
2231 m_phySta2->AssignStreams(streamNumber);
2232
2233 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2234 // since global attribute will be changed).
2235 ResetPpduUid();
2236
2237 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2238 // PPDU UID should be equal to 0 (the first counter value).
2239 Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::SendMuPpdu, this);
2240 Simulator::Schedule(Seconds(1.0), &TestUlOfdmaPpduUid::CheckUid, this, 0, 0);
2241
2242 // Send HE SU PPDU from AP.
2243 // PPDU UID should be incremented since this is a new PPDU.
2244 Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::SendSuPpdu, this, 0);
2245 Simulator::Schedule(Seconds(1.1), &TestUlOfdmaPpduUid::CheckUid, this, 0, 1);
2246
2247 // Send HE TB PPDU from STAs to AP.
2248 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2249 // preceding correctly received PPDU (which normally contains the trigger frame).
2250 Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::SendTbPpdu, this);
2251 Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 1, 1);
2252 Simulator::Schedule(Seconds(1.15), &TestUlOfdmaPpduUid::CheckUid, this, 2, 1);
2253
2254 // Send HE SU PPDU from STA1.
2255 // PPDU UID should be incremented since this is a new PPDU.
2256 Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::SendSuPpdu, this, 1);
2257 Simulator::Schedule(Seconds(1.2), &TestUlOfdmaPpduUid::CheckUid, this, 1, 2);
2258
2259 Simulator::Run();
2260 Simulator::Destroy();
2261}
2262
2270{
2271 public:
2273 ~TestMultipleHeTbPreambles() override;
2274
2275 private:
2276 void DoSetup() override;
2277 void DoTeardown() override;
2278 void DoRun() override;
2279
2289 void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2290
2305
2312
2316 void Reset();
2317
2323 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2324
2329 void CheckBytesDropped(size_t expectedBytesDropped);
2330
2332
2335};
2336
2338 : TestCase("UL-OFDMA multiple RX events test"),
2339 m_totalBytesDropped(0),
2340 m_trigVector(HePhy::GetHeMcs7(),
2341 0,
2343 1600,
2344 1,
2345 1,
2346 0,
2348 false,
2349 false)
2350{
2351}
2352
2354{
2355}
2356
2357void
2359{
2360 NS_LOG_FUNCTION(this);
2362 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2363 m_phy->Reset();
2365}
2366
2367void
2369{
2370 NS_LOG_FUNCTION(this << p << reason);
2371 m_totalBytesDropped += (p->GetSize() - 30);
2372}
2373
2374void
2375TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2376{
2377 auto events = m_phy->GetCurrentPreambleEvents();
2378 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2379 for (const auto& uid : uids)
2380 {
2381 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2382 auto it = events.find(pair);
2383 bool found = (it != events.end());
2385 true,
2386 "HE TB PPDU with UID " << uid << " has not been received!");
2387 }
2388}
2389
2390void
2392{
2394 expectedBytesDropped,
2395 "The number of dropped bytes is not correct!");
2396}
2397
2398void
2400 uint16_t staId,
2401 double txPowerWatts,
2402 size_t payloadSize)
2403{
2404 WifiConstPsduMap psdus;
2405 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
2406 0,
2408 1600,
2409 1,
2410 1,
2411 0,
2413 false,
2414 false);
2415
2416 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2417 txVector.SetRu(ru, staId);
2418 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2419 txVector.SetNss(1, staId);
2420
2421 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2422
2423 Ptr<Packet> pkt = Create<Packet>(payloadSize);
2424 WifiMacHeader hdr;
2426 hdr.SetQosTid(0);
2427 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2428 hdr.SetSequenceNumber(1);
2429 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2430 psdus.insert(std::make_pair(staId, psdu));
2431
2432 Time ppduDuration =
2433 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2434 Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2435 txVector,
2437 ppduDuration,
2439 uid,
2440 HePpdu::PSD_NON_HE_PORTION);
2441
2442 // Send non-OFDMA part
2443 Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonOfdmaDurationForHeTb(txVector);
2444 uint32_t centerFrequency =
2445 m_phy->GetHePhy()->GetCenterFrequencyForNonOfdmaPart(txVector, staId);
2446 uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2447 uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2448 Ptr<SpectrumValue> rxPsd = WifiSpectrumValueHelper::CreateHeOfdmTxPowerSpectralDensity(
2449 centerFrequency,
2450 channelWidth,
2451 txPowerWatts,
2452 m_phy->GetGuardBandwidth(channelWidth));
2453 Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2454 rxParams->psd = rxPsd;
2455 rxParams->txPhy = nullptr;
2456 rxParams->duration = nonOfdmaDuration;
2457 rxParams->ppdu = ppdu;
2458 rxParams->txWidth = channelWidth;
2459
2460 uint16_t length;
2461 std::tie(length, ppduDuration) =
2462 HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, txVector, m_phy->GetPhyBand());
2463 txVector.SetLength(length);
2464 m_trigVector.SetLength(length);
2465 auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
2466 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2467 ppdu->ResetTxVector();
2468 m_phy->StartRx(rxParams);
2469
2470 // Schedule OFDMA part
2471 Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2472 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2473 WifiSpectrumBand band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2474 Ptr<SpectrumValue> rxPsdOfdma =
2475 WifiSpectrumValueHelper::CreateHeMuOfdmTxPowerSpectralDensity(DEFAULT_FREQUENCY,
2477 txPowerWatts,
2479 band);
2480 Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2481 rxParamsOfdma->psd = rxPsd;
2482 rxParamsOfdma->txPhy = nullptr;
2483 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2484 rxParamsOfdma->ppdu = ppduOfdma;
2485 rxParamsOfdma->txWidth = DEFAULT_CHANNEL_WIDTH;
2486 Simulator::Schedule(nonOfdmaDuration,
2488 this,
2489 rxParamsOfdma);
2490}
2491
2492void
2494{
2495 Simulator::ScheduleNow(&TestMultipleHeTbPreambles::DoRxHeTbPpduOfdmaPart, this, rxParamsOfdma);
2496}
2497
2498void
2500{
2501 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2502 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2503 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2504 m_phy->StartRx(rxParamsOfdma);
2505}
2506
2507void
2509{
2510 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2512 m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2514 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2515 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2516 Ptr<ApWifiMac> mac = CreateObject<ApWifiMac>();
2517 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2518 dev->SetMac(mac);
2519 m_phy->SetInterferenceHelper(interferenceHelper);
2520 m_phy->SetErrorRateModel(error);
2524 0});
2525 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2527 m_phy->SetDevice(dev);
2528 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2529 CreateObject<ThresholdPreambleDetectionModel>();
2530 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2531 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2532 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2533 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2534 heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2535 dev->SetHeConfiguration(heConfiguration);
2536}
2537
2538void
2540{
2541 m_phy->Dispose();
2542 m_phy = nullptr;
2543}
2544
2545void
2547{
2548 RngSeedManager::SetSeed(1);
2549 RngSeedManager::SetRun(1);
2550 int64_t streamNumber = 0;
2551 m_phy->AssignStreams(streamNumber);
2552
2553 double txPowerWatts = 0.01;
2554
2555 {
2556 // Verify a single UL MU transmission with two stations belonging to the same BSS
2557 std::vector<uint64_t> uids{0};
2558 Simulator::Schedule(Seconds(1),
2560 this,
2561 uids[0],
2562 1,
2563 txPowerWatts,
2564 1001);
2565 Simulator::Schedule(Seconds(1) + NanoSeconds(100),
2567 this,
2568 uids[0],
2569 2,
2570 txPowerWatts,
2571 1002);
2572 // Check that we received a single UL MU transmission with the corresponding UID
2573 Simulator::Schedule(Seconds(1.0) + MicroSeconds(1),
2575 this,
2576 1,
2577 uids);
2578 Simulator::Schedule(Seconds(1.5), &TestMultipleHeTbPreambles::Reset, this);
2579 }
2580
2581 {
2582 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2583 // the second transmission arrives during the preamble detection window and with half the
2584 // power of the first transmission.
2585 std::vector<uint64_t> uids{1, 2};
2586 Simulator::Schedule(Seconds(2),
2588 this,
2589 uids[0],
2590 1,
2591 txPowerWatts,
2592 1001);
2593 Simulator::Schedule(Seconds(2) + NanoSeconds(100),
2595 this,
2596 uids[0],
2597 2,
2598 txPowerWatts,
2599 1002);
2600 Simulator::Schedule(Seconds(2) + NanoSeconds(200),
2602 this,
2603 uids[1],
2604 1,
2605 txPowerWatts / 2,
2606 1003);
2607 Simulator::Schedule(Seconds(2) + NanoSeconds(300),
2609 this,
2610 uids[1],
2611 2,
2612 txPowerWatts / 2,
2613 1004);
2614 // Check that we received the correct reception of 2 UL MU transmissions with the
2615 // corresponding UIDs
2616 Simulator::Schedule(Seconds(2.0) + MicroSeconds(1),
2618 this,
2619 2,
2620 uids);
2621 Simulator::Schedule(Seconds(2.5), &TestMultipleHeTbPreambles::Reset, this);
2622 // TODO: verify PPDUs from second UL MU transmission are dropped
2623 }
2624
2625 {
2626 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2627 // the second transmission arrives during the preamble detection window and with twice the
2628 // power of the first transmission.
2629 std::vector<uint64_t> uids{3, 4};
2630 Simulator::Schedule(Seconds(3),
2632 this,
2633 uids[0],
2634 1,
2635 txPowerWatts / 2,
2636 1001);
2637 Simulator::Schedule(Seconds(3) + NanoSeconds(100),
2639 this,
2640 uids[0],
2641 2,
2642 txPowerWatts / 2,
2643 1002);
2644 Simulator::Schedule(Seconds(3) + NanoSeconds(200),
2646 this,
2647 uids[1],
2648 1,
2649 txPowerWatts,
2650 1003);
2651 Simulator::Schedule(Seconds(3) + NanoSeconds(300),
2653 this,
2654 uids[1],
2655 2,
2656 txPowerWatts,
2657 1004);
2658 // Check that we received the correct reception of 2 UL MU transmissions with the
2659 // corresponding UIDs
2660 Simulator::Schedule(Seconds(3.0) + MicroSeconds(1),
2662 this,
2663 2,
2664 uids);
2665 Simulator::Schedule(Seconds(3.5), &TestMultipleHeTbPreambles::Reset, this);
2666 // TODO: verify PPDUs from first UL MU transmission are dropped
2667 }
2668
2669 {
2670 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2671 // the second transmission arrives during PHY header reception and with the same power as
2672 // the first transmission.
2673 std::vector<uint64_t> uids{5, 6};
2674 Simulator::Schedule(Seconds(4),
2676 this,
2677 uids[0],
2678 1,
2679 txPowerWatts,
2680 1001);
2681 Simulator::Schedule(Seconds(4) + NanoSeconds(100),
2683 this,
2684 uids[0],
2685 2,
2686 txPowerWatts,
2687 1002);
2688 Simulator::Schedule(Seconds(4) + MicroSeconds(5),
2690 this,
2691 uids[1],
2692 1,
2693 txPowerWatts,
2694 1003);
2695 Simulator::Schedule(Seconds(4) + MicroSeconds(5) + NanoSeconds(100),
2697 this,
2698 uids[1],
2699 2,
2700 txPowerWatts,
2701 1004);
2702 // Check that we received the correct reception of the first UL MU transmission with the
2703 // corresponding UID (second one dropped)
2704 Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2706 this,
2707 1,
2708 std::vector<uint64_t>{uids[0]});
2709 // The packets of the second UL MU transmission should have been dropped
2710 Simulator::Schedule(Seconds(4.0) + MicroSeconds(10),
2712 this,
2713 1003 + 1004);
2714 Simulator::Schedule(Seconds(4.5), &TestMultipleHeTbPreambles::Reset, this);
2715 }
2716
2717 {
2718 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2719 // BSS, where the second transmission arrives during payload reception and with the same
2720 // power as the first transmission.
2721 std::vector<uint64_t> uids{7, 8};
2722 Simulator::Schedule(Seconds(5),
2724 this,
2725 uids[0],
2726 1,
2727 txPowerWatts,
2728 1001);
2729 Simulator::Schedule(Seconds(5) + NanoSeconds(100),
2731 this,
2732 uids[0],
2733 2,
2734 txPowerWatts,
2735 1002);
2736 Simulator::Schedule(Seconds(5) + MicroSeconds(50),
2738 this,
2739 uids[1],
2740 1,
2741 txPowerWatts,
2742 1003);
2743 Simulator::Schedule(Seconds(5) + MicroSeconds(50) + NanoSeconds(100),
2745 this,
2746 uids[1],
2747 2,
2748 txPowerWatts,
2749 1004);
2750 // Check that we received the correct reception of the first UL MU transmission with the
2751 // corresponding UID (second one dropped)
2752 Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2754 this,
2755 1,
2756 std::vector<uint64_t>{uids[0]});
2757 // The packets of the second UL MU transmission should have been dropped
2758 Simulator::Schedule(Seconds(5.0) + MicroSeconds(100),
2760 this,
2761 1003 + 1004);
2762 Simulator::Schedule(Seconds(5.5), &TestMultipleHeTbPreambles::Reset, this);
2763 }
2764
2765 {
2766 // Verify the correct reception of a single UL MU transmission with two stations belonging
2767 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2768 // the configured delay spread of 400ns
2769 std::vector<uint64_t> uids{9};
2770 Simulator::Schedule(Seconds(6),
2772 this,
2773 uids[0],
2774 1,
2775 txPowerWatts,
2776 1001);
2777 Simulator::Schedule(Seconds(6) + NanoSeconds(500),
2779 this,
2780 uids[0],
2781 2,
2782 txPowerWatts,
2783 1002);
2784 // Check that we received a single UL MU transmission with the corresponding UID
2785 Simulator::Schedule(Seconds(6.0) + MicroSeconds(1),
2787 this,
2788 1,
2789 uids);
2790 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2791 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2792 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2793 // second packet of 1002 bytes is dropped as well.
2794 Simulator::Schedule(Seconds(6.0) + MicroSeconds(5),
2796 this,
2797 1001 + 1002);
2798 Simulator::Schedule(Seconds(6.5), &TestMultipleHeTbPreambles::Reset, this);
2799 }
2800
2801 Simulator::Run();
2802 Simulator::Destroy();
2803}
2804
2812{
2813 public:
2815
2816 void NotifyRxStart(Time duration) override
2817 {
2818 NS_LOG_FUNCTION(this << duration);
2821 m_lastRxSuccess = false;
2822 }
2823
2824 void NotifyRxEndOk() override
2825 {
2826 NS_LOG_FUNCTION(this);
2828 ++m_notifyRxEnd;
2829 m_lastRxSuccess = true;
2830 }
2831
2832 void NotifyRxEndError() override
2833 {
2834 NS_LOG_FUNCTION(this);
2836 ++m_notifyRxEnd;
2837 m_lastRxSuccess = false;
2838 }
2839
2840 void NotifyTxStart(Time duration, double txPowerDbm) override
2841 {
2842 NS_LOG_FUNCTION(this << duration << txPowerDbm);
2843 }
2844
2846 WifiChannelListType channelType,
2847 const std::vector<Time>& /*per20MhzDurations*/) override
2848 {
2849 NS_LOG_FUNCTION(this << duration << channelType);
2850 }
2851
2852 void NotifySwitchingStart(Time duration) override
2853 {
2854 }
2855
2856 void NotifySleep() override
2857 {
2858 }
2859
2860 void NotifyOff() override
2861 {
2862 }
2863
2864 void NotifyWakeup() override
2865 {
2866 }
2867
2868 void NotifyOn() override
2869 {
2870 }
2871
2875 void Reset()
2876 {
2877 m_notifyRxStart = 0;
2878 m_notifyRxEnd = 0;
2880 m_lastRxEnd = Seconds(0);
2881 m_lastRxSuccess = false;
2882 }
2883
2889 {
2890 return m_notifyRxStart;
2891 }
2892
2898 {
2899 return m_notifyRxEnd;
2900 }
2901
2907 {
2908 return m_lastRxStart;
2909 }
2910
2916 {
2917 return m_lastRxEnd;
2918 }
2919
2924 bool IsLastRxSuccess() const
2925 {
2926 return m_lastRxSuccess;
2927 }
2928
2929 private:
2934 bool m_lastRxSuccess{false};
2935};
2936
2944{
2945 public:
2950 {
2951 NONE = 0,
2955 };
2956
2958 ~TestUlOfdmaPhyTransmission() override;
2959
2960 private:
2961 void DoSetup() override;
2962 void DoTeardown() override;
2963 void DoRun() override;
2964
2972 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2973 std::size_t index,
2974 uint8_t bssColor) const;
2981 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2991 void SendHeTbPpdu(uint16_t txStaId,
2992 std::size_t index,
2993 std::size_t payloadSize,
2994 uint64_t uid,
2995 uint8_t bssColor,
2996 bool incrementUid);
2997
3005 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3006
3012 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3013
3019 void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3020
3026 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3030 void StopInterference();
3031
3035 void RunOne();
3036
3043 void CheckRxFromSta1(uint32_t expectedSuccess,
3044 uint32_t expectedFailures,
3045 uint32_t expectedBytes);
3046
3053 void CheckRxFromSta2(uint32_t expectedSuccess,
3054 uint32_t expectedFailures,
3055 uint32_t expectedBytes);
3056
3064 WifiSpectrumBand band,
3065 double expectedRxPower);
3073 WifiSpectrumBand band,
3074 double expectedRxPower);
3075
3079 void VerifyEventsCleared();
3080
3089
3096 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3104 void CheckApRxEnd(uint32_t expectedNotifications,
3105 Time expectedLastNotification,
3106 bool expectedSuccess);
3107
3111 void Reset();
3112
3121 RxSignalInfo rxSignalInfo,
3122 WifiTxVector txVector,
3123 std::vector<bool> statusPerMpdu);
3124
3129 void RxFailure(Ptr<const WifiPsdu> psdu);
3130
3151 void ScheduleTest(Time delay,
3152 bool solicited,
3153 WifiPhyState expectedStateAtEnd,
3154 uint32_t expectedSuccessFromSta1,
3155 uint32_t expectedFailuresFromSta1,
3156 uint32_t expectedBytesFromSta1,
3157 uint32_t expectedSuccessFromSta2,
3158 uint32_t expectedFailuresFromSta2,
3159 uint32_t expectedBytesFromSta2,
3160 bool scheduleTxSta1 = true,
3161 Time ulTimeDifference = Seconds(0),
3162 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3163 TrigVectorInfo error = NONE);
3164
3175 double rxPowerNonOfdmaRu1,
3176 double rxPowerNonOfdmaRu2,
3177 double rxPowerOfdmaRu1,
3178 double rxPowerOfdmaRu2);
3184 void LogScenario(std::string log) const;
3185
3190
3191 std::unique_ptr<OfdmaTestPhyListener>
3193
3195
3202
3203 uint16_t m_frequency;
3206};
3207
3209 : TestCase("UL-OFDMA PHY test"),
3210 m_countRxSuccessFromSta1(0),
3211 m_countRxSuccessFromSta2(0),
3212 m_countRxFailureFromSta1(0),
3213 m_countRxFailureFromSta2(0),
3214 m_countRxBytesFromSta1(0),
3215 m_countRxBytesFromSta2(0),
3216 m_frequency(DEFAULT_FREQUENCY),
3217 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3218 m_expectedPpduDuration(NanoSeconds(271200))
3219{
3220}
3221
3222void
3224 std::size_t payloadSize,
3225 uint64_t uid,
3226 uint8_t bssColor)
3227{
3228 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3229 WifiConstPsduMap psdus;
3230
3231 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3232 0,
3234 800,
3235 1,
3236 1,
3237 0,
3239 false,
3240 false,
3241 false,
3242 bssColor);
3243
3244 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3245 WifiMacHeader hdr;
3247 hdr.SetQosTid(0);
3248 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3249 std::ostringstream addr;
3250 addr << "00:00:00:00:00:0" << txStaId;
3251 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3252 hdr.SetSequenceNumber(1);
3253 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3254 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3255
3257 if (txStaId == 1)
3258 {
3259 phy = m_phySta1;
3260 }
3261 else if (txStaId == 2)
3262 {
3263 phy = m_phySta2;
3264 }
3265 else if (txStaId == 3)
3266 {
3267 phy = m_phySta3;
3268 }
3269 else if (txStaId == 0)
3270 {
3271 phy = m_phyAp;
3272 }
3273 phy->SetPpduUid(uid);
3274 phy->Send(psdus, txVector);
3275}
3276
3279 std::size_t index,
3280 uint8_t bssColor) const
3281{
3282 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
3283 0,
3285 1600,
3286 1,
3287 1,
3288 0,
3290 false,
3291 false,
3292 false,
3293 bssColor);
3294
3295 HeRu::RuType ruType = HeRu::RU_106_TONE;
3296 if (m_channelWidth == 20)
3297 {
3298 ruType = HeRu::RU_106_TONE;
3299 }
3300 else if (m_channelWidth == 40)
3301 {
3302 ruType = HeRu::RU_242_TONE;
3303 }
3304 else if (m_channelWidth == 80)
3305 {
3306 ruType = HeRu::RU_484_TONE;
3307 }
3308 else if (m_channelWidth == 160)
3309 {
3310 ruType = HeRu::RU_996_TONE;
3311 }
3312 else
3313 {
3314 NS_ASSERT_MSG(false, "Unsupported channel width");
3315 }
3316
3317 bool primary80MHz = true;
3318 if (m_channelWidth == 160 && index == 2)
3319 {
3320 primary80MHz = false;
3321 index = 1;
3322 }
3323 HeRu::RuSpec ru(ruType, index, primary80MHz);
3324 txVector.SetRu(ru, txStaId);
3325 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3326 txVector.SetNss(1, txStaId);
3327 return txVector;
3328}
3329
3330void
3332{
3333 uint16_t channelWidth = m_channelWidth;
3334 if (error == CHANNEL_WIDTH)
3335 {
3336 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3337 }
3338
3339 WifiTxVector txVector(HePhy::GetHeMcs7(),
3340 0,
3342 1600,
3343 1,
3344 1,
3345 0,
3346 channelWidth,
3347 false,
3348 false,
3349 false,
3350 bssColor);
3351
3352 HeRu::RuType ruType = HeRu::RU_106_TONE;
3353 if (channelWidth == 20)
3354 {
3355 ruType = HeRu::RU_106_TONE;
3356 }
3357 else if (channelWidth == 40)
3358 {
3359 ruType = HeRu::RU_242_TONE;
3360 }
3361 else if (channelWidth == 80)
3362 {
3363 ruType = HeRu::RU_484_TONE;
3364 }
3365 else if (channelWidth == 160)
3366 {
3367 ruType = HeRu::RU_996_TONE;
3368 }
3369 else
3370 {
3371 NS_ASSERT_MSG(false, "Unsupported channel width");
3372 }
3373
3374 uint16_t aid1 = (error == AID ? 3 : 1);
3375 uint16_t aid2 = (error == AID ? 4 : 2);
3376
3377 HeRu::RuSpec ru1(ruType, 1, true);
3378 txVector.SetRu(ru1, aid1);
3379 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3380 txVector.SetNss(1, aid1);
3381
3382 HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth == 160 ? false : true));
3383 txVector.SetRu(ru2, aid2);
3384 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3385 txVector.SetNss(1, aid2);
3386
3387 uint16_t length;
3388 std::tie(length, m_expectedPpduDuration) =
3389 HePhy::ConvertHeTbPpduDurationToLSigLength(m_expectedPpduDuration,
3390 txVector,
3391 m_phyAp->GetPhyBand());
3392 if (error == UL_LENGTH)
3393 {
3394 ++length;
3395 }
3396 txVector.SetLength(length);
3397 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
3398 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3399}
3400
3401void
3403 std::size_t index,
3404 std::size_t payloadSize,
3405 uint64_t uid,
3406 uint8_t bssColor,
3407 bool incrementUid)
3408{
3409 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3410 WifiConstPsduMap psdus;
3411
3412 if (incrementUid)
3413 {
3414 ++uid;
3415 }
3416
3417 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3418 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3419 WifiMacHeader hdr;
3421 hdr.SetQosTid(0);
3422 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3423 std::ostringstream addr;
3424 addr << "00:00:00:00:00:0" << txStaId;
3425 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3426 hdr.SetSequenceNumber(1);
3427 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3428 psdus.insert(std::make_pair(txStaId, psdu));
3429
3431 if (txStaId == 1)
3432 {
3433 phy = m_phySta1;
3434 }
3435 else if (txStaId == 2)
3436 {
3437 phy = m_phySta2;
3438 }
3439 else if (txStaId == 3)
3440 {
3441 phy = m_phySta3;
3442 }
3443
3444 Time txDuration =
3445 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3446 txVector.SetLength(
3447 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3448
3449 phy->SetPpduUid(uid);
3450 phy->Send(psdus, txVector);
3451}
3452
3453void
3455{
3456 NS_LOG_FUNCTION(this << duration);
3458 m_phyInterferer->SetPeriod(duration);
3460 Simulator::Schedule(duration, &TestUlOfdmaPhyTransmission::StopInterference, this);
3461}
3462
3463void
3465{
3467}
3468
3470{
3471}
3472
3473void
3475 RxSignalInfo rxSignalInfo,
3476 WifiTxVector txVector,
3477 std::vector<bool> /*statusPerMpdu*/)
3478{
3479 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3480 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3481 {
3483 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3484 }
3485 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3486 {
3488 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3489 }
3490}
3491
3492void
3494{
3495 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3496 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3497 {
3499 }
3500 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3501 {
3503 }
3504}
3505
3506void
3508 uint32_t expectedFailures,
3509 uint32_t expectedBytes)
3510{
3512 expectedSuccess,
3513 "The number of successfully received packets from STA 1 is not correct!");
3516 expectedFailures,
3517 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3519 expectedBytes,
3520 "The number of bytes received from STA 1 is not correct!");
3521}
3522
3523void
3525 uint32_t expectedFailures,
3526 uint32_t expectedBytes)
3527{
3529 expectedSuccess,
3530 "The number of successfully received packets from STA 2 is not correct!");
3533 expectedFailures,
3534 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3536 expectedBytes,
3537 "The number of bytes received from STA 2 is not correct!");
3538}
3539
3540void
3542 WifiSpectrumBand band,
3543 double expectedRxPower)
3544{
3545 Ptr<Event> event = phy->GetCurrentEvent();
3546 NS_ASSERT(event);
3547 double rxPower = event->GetRxPowerW(band);
3548 NS_LOG_FUNCTION(this << band.first << band.second << expectedRxPower << rxPower);
3549 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3551 expectedRxPower,
3552 5e-3,
3553 "RX power " << rxPower << " over (" << band.first << ", "
3554 << band.second << ") does not match expected power "
3555 << expectedRxPower << " at " << Simulator::Now());
3556}
3557
3558void
3560 WifiSpectrumBand band,
3561 double expectedRxPower)
3562{
3568 NS_LOG_FUNCTION(this << band.first << band.second << expectedRxPower);
3569 double step = 5e-3;
3570 if (expectedRxPower > 0.0)
3571 {
3573 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3574 true,
3575 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3576 << ", " << band.second << ") at " << Simulator::Now());
3578 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3579 false,
3580 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3581 << ", " << band.second << ") at " << Simulator::Now());
3582 }
3583 else
3584 {
3586 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3587 false,
3588 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band.first
3589 << ", " << band.second << ") at " << Simulator::Now());
3590 }
3591}
3592
3593void
3595{
3597 nullptr,
3598 "m_currentEvent for AP was not cleared");
3600 nullptr,
3601 "m_currentEvent for STA 1 was not cleared");
3603 nullptr,
3604 "m_currentEvent for STA 2 was not cleared");
3605}
3606
3607void
3609{
3610 // This is needed to make sure PHY state will be checked as the last event if a state change
3611 // occurred at the exact same time as the check
3612 Simulator::ScheduleNow(&TestUlOfdmaPhyTransmission::DoCheckPhyState, this, phy, expectedState);
3613}
3614
3615void
3617 WifiPhyState expectedState)
3618{
3619 WifiPhyState currentState;
3620 PointerValue ptr;
3621 phy->GetAttribute("State", ptr);
3622 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3623 currentState = state->GetState();
3624 NS_LOG_FUNCTION(this << currentState);
3625 NS_TEST_ASSERT_MSG_EQ(currentState,
3626 expectedState,
3627 "PHY State " << currentState << " does not match expected state "
3628 << expectedState << " at " << Simulator::Now());
3629}
3630
3631void
3633 Time expectedLastNotification)
3634{
3635 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3636 expectedNotifications,
3637 "Number of RX start notifications "
3638 << m_apPhyStateListener->GetNumRxStartNotifications()
3639 << " does not match expected count " << expectedNotifications
3640 << " for AP at " << Simulator::Now());
3641 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3642 expectedLastNotification,
3643 "Last time RX start notification has been received "
3644 << m_apPhyStateListener->GetLastRxStartNotification()
3645 << " does not match expected time " << expectedLastNotification
3646 << " for AP at " << Simulator::Now());
3647}
3648
3649void
3651 Time expectedLastNotification,
3652 bool expectedSuccess)
3653{
3654 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3655 expectedNotifications,
3656 "Number of RX end notifications "
3657 << m_apPhyStateListener->GetNumRxEndNotifications()
3658 << " does not match expected count " << expectedNotifications
3659 << " for AP at " << Simulator::Now());
3660 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3661 expectedLastNotification,
3662 "Last time RX end notification has been received "
3663 << m_apPhyStateListener->GetLastRxEndNotification()
3664 << " does not match expected time " << expectedLastNotification
3665 << " for AP at " << Simulator::Now());
3667 expectedSuccess,
3668 "Last time RX end notification indicated a "
3669 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3670 << " but expected a " << (expectedSuccess ? "success" : "failure")
3671 << " for AP at " << Simulator::Now());
3672}
3673
3674void
3676{
3686 SetBssColor(m_phyAp, 0);
3687 m_apPhyStateListener->Reset();
3688}
3689
3690void
3692{
3693 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3694 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3695 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3696}
3697
3698void
3700{
3701 NS_LOG_FUNCTION(this << phy << psdLimit);
3702 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3703}
3704
3705void
3707{
3708 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3709 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3710 lossModel->SetFrequency(m_frequency);
3711 spectrumChannel->AddPropagationLossModel(lossModel);
3713 CreateObject<ConstantSpeedPropagationDelayModel>();
3714 spectrumChannel->SetPropagationDelayModel(delayModel);
3715
3716 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3717 CreateObject<ThresholdPreambleDetectionModel>();
3718 preambleDetectionModel->SetAttribute(
3719 "MinimumRssi",
3721 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3722 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3723
3724 Ptr<Node> apNode = CreateObject<Node>();
3725 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3727 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
3728 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3729 apDev->SetMac(apMac);
3730 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3733 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3734 apDev->SetHeConfiguration(heConfiguration);
3735 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3736 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3737 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3738 m_phyAp->SetErrorRateModel(apErrorModel);
3739 m_phyAp->SetDevice(apDev);
3740 m_phyAp->SetChannel(spectrumChannel);
3743 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3744 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3745 m_phyAp->SetMobility(apMobility);
3746 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3748 apDev->SetPhy(m_phyAp);
3749 apMac->SetWifiPhys({m_phyAp});
3750 apNode->AggregateObject(apMobility);
3751 apNode->AddDevice(apDev);
3752
3753 Ptr<Node> sta1Node = CreateObject<Node>();
3754 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3756 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3757 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3760 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3761 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3762 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3763 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3764 m_phySta1->SetDevice(sta1Dev);
3765 m_phySta1->SetChannel(spectrumChannel);
3766 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3767 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3768 m_phySta1->SetMobility(sta1Mobility);
3769 sta1Dev->SetPhy(m_phySta1);
3770 sta1Node->AggregateObject(sta1Mobility);
3771 sta1Node->AddDevice(sta1Dev);
3772
3773 Ptr<Node> sta2Node = CreateObject<Node>();
3774 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3776 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3777 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3780 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3781 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3782 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3783 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3784 m_phySta2->SetDevice(sta2Dev);
3785 m_phySta2->SetChannel(spectrumChannel);
3786 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3787 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3788 m_phySta2->SetMobility(sta2Mobility);
3789 sta2Dev->SetPhy(m_phySta2);
3790 sta2Node->AggregateObject(sta2Mobility);
3791 sta2Node->AddDevice(sta2Dev);
3792
3793 Ptr<Node> sta3Node = CreateObject<Node>();
3794 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3796 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3797 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3800 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3801 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3802 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3803 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3804 m_phySta3->SetDevice(sta3Dev);
3805 m_phySta3->SetChannel(spectrumChannel);
3806 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3807 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3808 m_phySta3->SetMobility(sta3Mobility);
3809 sta3Dev->SetPhy(m_phySta3);
3810 sta3Node->AggregateObject(sta3Mobility);
3811 sta3Node->AddDevice(sta3Dev);
3812
3813 Ptr<Node> interfererNode = CreateObject<Node>();
3814 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3815 m_phyInterferer = CreateObject<WaveformGenerator>();
3816 m_phyInterferer->SetDevice(interfererDev);
3817 m_phyInterferer->SetChannel(spectrumChannel);
3819 interfererNode->AddDevice(interfererDev);
3820
3821 // Configure power attributes of all wifi devices
3822 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3823 for (auto& phy : phys)
3824 {
3825 phy->SetAttribute("TxGain", DoubleValue(1.0));
3826 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3827 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3828 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3829 phy->SetAttribute("RxGain", DoubleValue(2.0));
3830 // test assumes no rejection power for simplicity
3831 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3832 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3833 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3834 }
3835}
3836
3837void
3839{
3840 m_phyAp->Dispose();
3841 m_phyAp = nullptr;
3842 m_phySta1->Dispose();
3843 m_phySta1 = nullptr;
3844 m_phySta2->Dispose();
3845 m_phySta2 = nullptr;
3846 m_phySta3->Dispose();
3847 m_phySta3 = nullptr;
3849 m_phyInterferer = nullptr;
3850}
3851
3852void
3854{
3855 NS_LOG_INFO(log);
3856}
3857
3858void
3860 bool solicited,
3861 WifiPhyState expectedStateAtEnd,
3862 uint32_t expectedSuccessFromSta1,
3863 uint32_t expectedFailuresFromSta1,
3864 uint32_t expectedBytesFromSta1,
3865 uint32_t expectedSuccessFromSta2,
3866 uint32_t expectedFailuresFromSta2,
3867 uint32_t expectedBytesFromSta2,
3868 bool scheduleTxSta1,
3869 Time ulTimeDifference,
3870 WifiPhyState expectedStateBeforeEnd,
3871 TrigVectorInfo error)
3872{
3873 static uint64_t uid = 0;
3874
3875 // AP sends an SU packet preceding HE TB PPDUs
3876 Simulator::Schedule(delay - MilliSeconds(10),
3878 this,
3879 0,
3880 50,
3881 ++uid,
3882 0);
3883 if (!solicited)
3884 {
3885 // UID of TB PPDUs will be different than the one of the preceding frame
3886 ++uid;
3887 }
3888 else
3889 {
3890 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetTrigVector, this, 0, error);
3891 }
3892 // STA1 and STA2 send MU UL PPDUs addressed to AP
3893 Simulator::Schedule(delay - MilliSeconds(1),
3895 m_apPhyStateListener.get());
3896 if (scheduleTxSta1)
3897 {
3898 Simulator::Schedule(delay,
3900 this,
3901 1,
3902 1,
3903 1000,
3904 uid,
3905 0,
3906 false);
3907 }
3908 Simulator::Schedule(delay + ulTimeDifference,
3910 this,
3911 2,
3912 2,
3913 1001,
3914 uid,
3915 0,
3916 false);
3917
3918 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3919 Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
3921 this,
3922 m_phyAp,
3923 expectedStateBeforeEnd);
3924 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3926 this,
3927 m_phyAp,
3928 expectedStateAtEnd);
3929 // TODO: add checks on TX stop for STAs
3930
3931 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3932 expectedFailuresFromSta2 >
3933 0)
3934 {
3935 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3936 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3937 // The expected time at which the reception is started corresponds to the time at which the
3938 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3939 const Time expectedPayloadStart = delay + MicroSeconds(48);
3940 // The expected time at which the reception is terminated corresponds to the time at which
3941 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3942 // received HE TB PPDU and the last received HE TB PPDU.
3943 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3944 // At the end of the transmission, verify that a single RX start notification shall have
3945 // been notified when the reception of the first HE RB PPDU starts.
3946 Simulator::Schedule(expectedPayloadEnd,
3948 this,
3949 1,
3950 Simulator::Now() + expectedPayloadStart);
3951 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3952 // notification shall have been notified when the reception of the last HE RB PPDU ends
3953 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3955 this,
3956 1,
3957 Simulator::Now() + expectedPayloadEnd,
3958 isSuccess);
3959 }
3960
3961 delay += MilliSeconds(100);
3962 // Check reception state from STA 1
3963 Simulator::Schedule(delay,
3965 this,
3966 expectedSuccessFromSta1,
3967 expectedFailuresFromSta1,
3968 expectedBytesFromSta1);
3969 // Check reception state from STA 2
3970 Simulator::Schedule(delay,
3972 this,
3973 expectedSuccessFromSta2,
3974 expectedFailuresFromSta2,
3975 expectedBytesFromSta2);
3976 // Verify events data have been cleared
3977 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::VerifyEventsCleared, this);
3978
3979 delay += MilliSeconds(100);
3980 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
3981}
3982
3983void
3985 double rxPowerNonOfdmaRu1,
3986 double rxPowerNonOfdmaRu2,
3987 double rxPowerOfdmaRu1,
3988 double rxPowerOfdmaRu2)
3989{
3990 Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3991 WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3992 WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3994 Time nonOfdmaDuration = hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta2);
3995 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta1));
3996
3997 std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3998 std::vector<WifiSpectrumBand> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3999 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
4000 std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
4001 std::vector<WifiSpectrumBand> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
4002 hePhy->GetRuBandForRx(txVectorSta2, 2)};
4003
4004 for (uint8_t i = 0; i < 2; ++i)
4005 {
4009 // Check received power on non-OFDMA portion
4010 Simulator::Schedule(
4011 delay + detectionDuration +
4012 NanoSeconds(1), // just after beginning of portion (once event is stored)
4014 this,
4015 m_phyAp,
4016 nonOfdmaBand[i],
4017 rxPowerNonOfdma[i]);
4018 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4020 this,
4021 m_phyAp,
4022 nonOfdmaBand[i],
4023 rxPowerNonOfdma[i]);
4024 // Check received power on OFDMA portion
4025 Simulator::Schedule(delay + nonOfdmaDuration +
4026 NanoSeconds(1), // just after beginning of portion
4028 this,
4029 m_phyAp,
4030 ofdmaBand[i],
4031 rxPowerOfdma[i]);
4032 Simulator::Schedule(delay + m_expectedPpduDuration -
4033 NanoSeconds(1), // just before end of portion
4035 this,
4036 m_phyAp,
4037 ofdmaBand[i],
4038 rxPowerOfdma[i]);
4039
4045 // Check received power on non-OFDMA portion
4046 Simulator::Schedule(
4047 delay + detectionDuration +
4048 NanoSeconds(1), // just after beginning of portion (once event is stored)
4050 this,
4051 m_phySta3,
4052 nonOfdmaBand[i],
4053 rxPowerNonOfdma[i]);
4054 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4056 this,
4057 m_phySta3,
4058 nonOfdmaBand[i],
4059 rxPowerNonOfdma[i]);
4060 // Check received power on OFDMA portion
4061 Simulator::Schedule(delay + nonOfdmaDuration +
4062 NanoSeconds(1), // just after beginning of portion
4064 this,
4065 m_phySta3,
4066 ofdmaBand[i],
4067 rxPowerOfdma[i]);
4068 Simulator::Schedule(delay + m_expectedPpduDuration -
4069 NanoSeconds(1), // just before end of portion
4071 this,
4072 m_phySta3,
4073 ofdmaBand[i],
4074 rxPowerOfdma[i]);
4075 }
4076
4077 if (rxPowerOfdmaRu1 != 0.0)
4078 {
4084 double rxPowerNonOfdmaSta1Only =
4085 (m_channelWidth >= 40)
4086 ? rxPowerNonOfdma[0]
4087 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4088 // Check received power on non-OFDMA portion
4089 Simulator::Schedule(
4090 delay + detectionDuration +
4091 NanoSeconds(1), // just after beginning of portion (once event is stored)
4093 this,
4094 m_phySta2,
4095 nonOfdmaBand[0],
4096 rxPowerNonOfdmaSta1Only);
4097 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4099 this,
4100 m_phySta2,
4101 nonOfdmaBand[0],
4102 rxPowerNonOfdmaSta1Only);
4103 // Check received power on OFDMA portion
4104 Simulator::Schedule(delay + nonOfdmaDuration +
4105 NanoSeconds(1), // just after beginning of portion
4107 this,
4108 m_phySta2,
4109 ofdmaBand[0],
4110 rxPowerOfdma[0]);
4111 Simulator::Schedule(delay + m_expectedPpduDuration -
4112 NanoSeconds(1), // just before end of portion
4114 this,
4115 m_phySta2,
4116 ofdmaBand[0],
4117 rxPowerOfdma[0]);
4118 }
4119}
4120
4121void
4123{
4124 RngSeedManager::SetSeed(1);
4125 RngSeedManager::SetRun(1);
4126 int64_t streamNumber = 0;
4127 m_phyAp->AssignStreams(streamNumber);
4128 m_phySta1->AssignStreams(streamNumber);
4129 m_phySta2->AssignStreams(streamNumber);
4130 m_phySta3->AssignStreams(streamNumber);
4131
4132 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4137
4146
4147 Time delay = Seconds(0.0);
4148 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::Reset, this);
4149 delay += Seconds(1.0);
4150
4159 //---------------------------------------------------------------------------
4160 // Verify that both solicited HE TB PPDUs have been corrected received
4161 Simulator::Schedule(delay,
4163 this,
4164 "Reception of solicited HE TB PPDUs");
4165 ScheduleTest(delay,
4166 true,
4168 1,
4169 0,
4170 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4171 1,
4172 0,
4173 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4174 delay += Seconds(1.0);
4175
4176 //---------------------------------------------------------------------------
4177 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4178 // corrected received
4179 Simulator::Schedule(
4180 delay,
4182 this,
4183 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4184 ScheduleTest(delay,
4185 true,
4187 1,
4188 0,
4189 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4190 1,
4191 0,
4192 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4193 true,
4194 NanoSeconds(100));
4195 delay += Seconds(1.0);
4196
4197 //---------------------------------------------------------------------------
4198 // Verify that no unsolicited HE TB PPDU is received
4199 Simulator::Schedule(delay,
4201 this,
4202 "Dropping of unsolicited HE TB PPDUs");
4203 ScheduleTest(delay,
4204 false,
4206 0,
4207 0,
4208 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4209 0,
4210 0,
4211 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4212 true,
4213 Seconds(0),
4215 delay += Seconds(1.0);
4216
4217 //---------------------------------------------------------------------------
4218 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4219 Simulator::Schedule(delay,
4221 this,
4222 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4223 ScheduleTest(delay,
4224 true,
4226 0,
4227 0,
4228 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4229 0,
4230 0,
4231 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4232 true,
4233 Seconds(0),
4236 delay += Seconds(1.0);
4237
4238 //---------------------------------------------------------------------------
4239 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4240 Simulator::Schedule(delay,
4242 this,
4243 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4244 ScheduleTest(delay,
4245 true,
4247 0,
4248 0,
4249 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4250 0,
4251 0,
4252 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4253 true,
4254 Seconds(0),
4256 UL_LENGTH);
4257 delay += Seconds(1.0);
4258
4259 //---------------------------------------------------------------------------
4260 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4261 Simulator::Schedule(delay,
4263 this,
4264 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4265 ScheduleTest(delay,
4266 true,
4268 0,
4269 0,
4270 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4271 0,
4272 0,
4273 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4274 true,
4275 Seconds(0),
4277 AID);
4278 delay += Seconds(1.0);
4279
4280 //---------------------------------------------------------------------------
4281 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4282 // impacted
4283 Simulator::Schedule(
4284 delay,
4286 this,
4287 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4288 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4289 BandInfo bandInfo;
4290 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4291 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4292 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4293 Bands bands;
4294 bands.push_back(bandInfo);
4295
4296 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4297 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4298 double interferencePower = 0.1; // watts
4299 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4300
4301 Simulator::Schedule(delay + MicroSeconds(50),
4303 this,
4304 interferencePsdRu1,
4305 MilliSeconds(100));
4307 delay,
4308 true,
4309 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4310 // interference
4311 0,
4312 1,
4313 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4314 1,
4315 0,
4316 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4317 delay += Seconds(1.0);
4318
4319 //---------------------------------------------------------------------------
4320 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4321 // impacted
4322 Simulator::Schedule(
4323 delay,
4325 this,
4326 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4327 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4328 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4329 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4330 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4331 bands.clear();
4332 bands.push_back(bandInfo);
4333
4334 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4335 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4336 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4337
4338 Simulator::Schedule(delay + MicroSeconds(50),
4340 this,
4341 interferencePsdRu2,
4342 MilliSeconds(100));
4343 ScheduleTest(delay,
4344 true,
4345 (m_channelWidth >= 40)
4347 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4348 // generated in its primary channel
4349 1,
4350 0,
4351 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4352 0,
4353 1,
4354 0); // Reception of the PSDU from STA 2 should have failed (since interference
4355 // occupies RU 2)
4356 delay += Seconds(1.0);
4357
4358 //---------------------------------------------------------------------------
4359 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4360 // been impacted
4361 Simulator::Schedule(delay,
4363 this,
4364 "Reception of solicited HE TB PPDUs with interference on the full band "
4365 "during PSDU reception");
4366 // A strong non-wifi interference is generated on the full band during PSDU reception
4367 bandInfo.fc = m_frequency * 1e6;
4368 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4369 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4370 bands.clear();
4371 bands.push_back(bandInfo);
4372
4373 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4374 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4375 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4376
4377 Simulator::Schedule(delay + MicroSeconds(50),
4379 this,
4380 interferencePsdAll,
4381 MilliSeconds(100));
4383 delay,
4384 true,
4385 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4386 // interference
4387 0,
4388 1,
4389 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4390 0,
4391 1,
4392 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4393 // 2)
4394 delay += Seconds(1.0);
4395
4396 //---------------------------------------------------------------------------
4397 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4398 // solicited HE TB PPDUs have been impacted if they are on the same
4399 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4400 Simulator::Schedule(delay,
4402 this,
4403 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4404 "1 during PSDU reception");
4405 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4406 Simulator::Schedule(delay + MicroSeconds(50),
4408 this,
4409 3,
4410 1,
4411 1002,
4412 1,
4413 0,
4414 false);
4415 // Expected figures from STA 2
4416 uint32_t succ;
4417 uint32_t fail;
4418 uint32_t bytes;
4419 if (m_channelWidth > 20)
4420 {
4421 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4422 // interference from STA 3 on distinct 20 MHz channel)
4423 succ = 1;
4424 fail = 0;
4425 bytes = 1001;
4426 }
4427 else
4428 {
4429 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4430 // same 20 MHz channel)
4431 succ = 0;
4432 fail = 1;
4433 bytes = 0;
4434 }
4435 ScheduleTest(delay,
4436 true,
4437 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4438 // interference on measurement channel width
4439 0,
4440 1,
4441 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4442 // STA 3 on same 20 MHz channel)
4443 succ,
4444 fail,
4445 bytes);
4446 delay += Seconds(1.0);
4447
4448 //---------------------------------------------------------------------------
4449 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4450 // solicited HE TB PPDUs have been impacted if they are on the same
4451 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4452 Simulator::Schedule(delay,
4454 this,
4455 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4456 "2 during PSDU reception");
4457 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4458 Simulator::Schedule(delay + MicroSeconds(50),
4460 this,
4461 3,
4462 2,
4463 1002,
4464 1,
4465 0,
4466 false);
4467 // Expected figures from STA 1
4468 if (m_channelWidth > 20)
4469 {
4470 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4471 // interference from STA 3 on distinct 20 MHz channel)
4472 succ = 1;
4473 fail = 0;
4474 bytes = 1000;
4475 }
4476 else
4477 {
4478 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4479 // same 20 MHz channel)
4480 succ = 0;
4481 fail = 1;
4482 bytes = 0;
4483 }
4484 ScheduleTest(delay,
4485 true,
4486 (m_channelWidth >= 40)
4488 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4489 // TB PPDU on primary channel
4490 succ,
4491 fail,
4492 bytes,
4493 0,
4494 1,
4495 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4496 // STA 3 on same 20 MHz channel)
4497 delay += Seconds(1.0);
4498
4499 //---------------------------------------------------------------------------
4500 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4501 // impacted
4502 Simulator::Schedule(
4503 delay,
4505 this,
4506 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4507 // One HE SU arrives at AP during the 400ns window
4508 Simulator::Schedule(delay + NanoSeconds(300),
4510 this,
4511 3,
4512 1002,
4513 1,
4514 0);
4516 delay,
4517 true,
4519 0,
4520 1,
4521 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4522 0,
4523 1,
4524 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4525 delay += Seconds(1.0);
4526
4527 //---------------------------------------------------------------------------
4528 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4529 // received
4530 Simulator::Schedule(delay,
4532 this,
4533 "Reception of solicited HE TB PPDU only on RU 2");
4534 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4535 // otherwise
4536 Simulator::Schedule(delay + m_expectedPpduDuration - NanoSeconds(1),
4538 this,
4539 m_phySta3,
4540 (m_channelWidth >= 40)
4542 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4543 // IDLE if HE TB PPDU on primary channel
4544 ScheduleTest(delay,
4545 true,
4547 0,
4548 0,
4549 0, // No transmission scheduled for STA 1
4550 1,
4551 0,
4552 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4553 false,
4554 Seconds(0),
4555 WifiPhyState::RX); // Measurement channel is total channel width
4556 delay += Seconds(1.0);
4557
4558 //---------------------------------------------------------------------------
4559 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4560 Simulator::Schedule(delay,
4562 this,
4563 "Measure power for reception of HE TB PPDU only on RU 2");
4564 double rxPower =
4565 DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4567 (m_channelWidth >= 40) ? 0.0 : rxPower,
4568 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4569 0.0,
4570 rxPower);
4571 ScheduleTest(delay,
4572 true,
4574 0,
4575 0,
4576 0, // No transmission scheduled for STA 1
4577 1,
4578 0,
4579 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4580 false,
4581 Seconds(0),
4582 WifiPhyState::RX); // Measurement channel is total channel width
4583 delay += Seconds(1.0);
4584
4585 //---------------------------------------------------------------------------
4586 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4587 // limitation enforced
4588 Simulator::Schedule(
4589 delay,
4591 this,
4592 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4593 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4594 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4595 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4597 this,
4598 m_phySta2,
4599 3.0);
4600
4601 rxPower = (m_channelWidth > 40)
4602 ? DbmToW(19)
4603 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4604 // transmitted only on one 20 MHz channel
4605 double rxPowerOfdma = rxPower;
4606 if (m_channelWidth <= 40)
4607 {
4608 rxPowerOfdma = (m_channelWidth == 20)
4609 ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4610 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4611 }
4613 (m_channelWidth >= 40) ? 0.0 : rxPower,
4614 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4615 0.0,
4616 rxPowerOfdma);
4617
4618 // Reset PSD limitation once HE TB has been sent
4619 Simulator::Schedule(delay + m_expectedPpduDuration,
4621 this,
4622 m_phySta2,
4623 100.0);
4624 ScheduleTest(delay,
4625 true,
4627 0,
4628 0,
4629 0, // No transmission scheduled for STA 1
4630 1,
4631 0,
4632 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4633 false,
4634 Seconds(0),
4635 WifiPhyState::RX); // Measurement channel is total channel width
4636 delay += Seconds(1.0);
4637
4638 //---------------------------------------------------------------------------
4639 // Measure the power of 2 solicited HE TB PPDU from both STAs
4640 Simulator::Schedule(delay,
4642 this,
4643 "Measure power for reception of HE TB PPDU on both RUs");
4644 rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4645 double rxPowerNonOfdma = (m_channelWidth >= 40)
4646 ? rxPower
4647 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4648 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4649 ScheduleTest(delay,
4650 true,
4652 1,
4653 0,
4654 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4655 1,
4656 0,
4657 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4658 delay += Seconds(1.0);
4659
4660 //---------------------------------------------------------------------------
4661 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4662 // ongoing)
4663 Simulator::Schedule(delay,
4665 this,
4666 "Reception of an HE TB PPDU from another BSS");
4667 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4668 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4669 Simulator::Schedule(delay + MilliSeconds(100),
4671 this,
4672 3,
4673 1,
4674 1002,
4675 1,
4676 2,
4677 false);
4678
4679 // Verify events data have been cleared
4680 Simulator::Schedule(delay + MilliSeconds(200),
4682 this);
4683
4684 Simulator::Schedule(delay + MilliSeconds(500), &TestUlOfdmaPhyTransmission::Reset, this);
4685 delay += Seconds(1.0);
4686
4687 //---------------------------------------------------------------------------
4688 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4689 // corrected received
4690 Simulator::Schedule(
4691 delay,
4693 this,
4694 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4695 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4696 Simulator::Schedule(delay, &TestUlOfdmaPhyTransmission::SetBssColor, this, m_phyAp, 1);
4697 Simulator::Schedule(delay + m_expectedPpduDuration + NanoSeconds(100),
4699 this,
4700 3,
4701 1,
4702 1002,
4703 1,
4704 2,
4705 true);
4706 ScheduleTest(delay,
4707 true,
4709 1,
4710 0,
4711 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4712 1,
4713 0,
4714 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4715 true,
4716 NanoSeconds(200));
4717 delay += Seconds(1.0);
4718
4719 Simulator::Run();
4720}
4721
4722void
4724{
4725 m_frequency = 5180;
4726 m_channelWidth = 20;
4728 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4729 RunOne();
4730
4731 m_frequency = 5190;
4732 m_channelWidth = 40;
4734 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4735 RunOne();
4736
4737 m_frequency = 5210;
4738 m_channelWidth = 80;
4740 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4741 RunOne();
4742
4743 m_frequency = 5250;
4744 m_channelWidth = 160;
4746 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4747 RunOne();
4748
4749 Simulator::Destroy();
4750}
4751
4759{
4760 public:
4762 ~TestPhyPaddingExclusion() override;
4763
4764 private:
4765 void DoSetup() override;
4766 void DoTeardown() override;
4767 void DoRun() override;
4768
4776 void SendHeTbPpdu(uint16_t txStaId,
4777 std::size_t index,
4778 std::size_t payloadSize,
4779 Time txDuration);
4785 void SetTrigVector(Time ppduDuration);
4786
4792 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4796 void StopInterference();
4797
4801 void RunOne();
4802
4809 void CheckRxFromSta1(uint32_t expectedSuccess,
4810 uint32_t expectedFailures,
4811 uint32_t expectedBytes);
4812
4819 void CheckRxFromSta2(uint32_t expectedSuccess,
4820 uint32_t expectedFailures,
4821 uint32_t expectedBytes);
4822
4826 void VerifyEventsCleared();
4827
4836
4840 void Reset();
4841
4850 RxSignalInfo rxSignalInfo,
4851 WifiTxVector txVector,
4852 std::vector<bool> statusPerMpdu);
4853
4858 void RxFailure(Ptr<const WifiPsdu> psdu);
4859
4863
4865
4872};
4873
4875 : TestCase("PHY padding exclusion test"),
4876 m_countRxSuccessFromSta1(0),
4877 m_countRxSuccessFromSta2(0),
4878 m_countRxFailureFromSta1(0),
4879 m_countRxFailureFromSta2(0),
4880 m_countRxBytesFromSta1(0),
4881 m_countRxBytesFromSta2(0)
4882{
4883}
4884
4885void
4887 std::size_t index,
4888 std::size_t payloadSize,
4889 Time txDuration)
4890{
4891 WifiConstPsduMap psdus;
4892
4893 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
4894 0,
4896 1600,
4897 1,
4898 1,
4899 0,
4901 false,
4902 false,
4903 1);
4904
4905 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4906 txVector.SetRu(ru, txStaId);
4907 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4908 txVector.SetNss(1, txStaId);
4909
4910 Ptr<Packet> pkt = Create<Packet>(payloadSize);
4911 WifiMacHeader hdr;
4913 hdr.SetQosTid(0);
4914 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4915 std::ostringstream addr;
4916 addr << "00:00:00:00:00:0" << txStaId;
4917 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4918 hdr.SetSequenceNumber(1);
4919 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4920 psdus.insert(std::make_pair(txStaId, psdu));
4921
4923 if (txStaId == 1)
4924 {
4925 phy = m_phySta1;
4926 }
4927 else if (txStaId == 2)
4928 {
4929 phy = m_phySta2;
4930 }
4931
4932 txVector.SetLength(
4933 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4934
4935 phy->SetPpduUid(0);
4936 phy->Send(psdus, txVector);
4937}
4938
4939void
4941{
4943 m_phyInterferer->SetPeriod(duration);
4945 Simulator::Schedule(duration, &TestPhyPaddingExclusion::StopInterference, this);
4946}
4947
4948void
4950{
4952}
4953
4955{
4956}
4957
4958void
4960 RxSignalInfo rxSignalInfo,
4961 WifiTxVector txVector,
4962 std::vector<bool> /*statusPerMpdu*/)
4963{
4964 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4965 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4966 {
4968 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4969 }
4970 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4971 {
4973 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4974 }
4975}
4976
4977void
4979{
4980 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4981 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4982 {
4984 }
4985 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4986 {
4988 }
4989}
4990
4991void
4993 uint32_t expectedFailures,
4994 uint32_t expectedBytes)
4995{
4997 expectedSuccess,
4998 "The number of successfully received packets from STA 1 is not correct!");
5001 expectedFailures,
5002 "The number of unsuccessfuly received packets from STA 1 is not correct!");
5004 expectedBytes,
5005 "The number of bytes received from STA 1 is not correct!");
5006}
5007
5008void
5010 uint32_t expectedFailures,
5011 uint32_t expectedBytes)
5012{
5014 expectedSuccess,
5015 "The number of successfully received packets from STA 2 is not correct!");
5018 expectedFailures,
5019 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5021 expectedBytes,
5022 "The number of bytes received from STA 2 is not correct!");
5023}
5024
5025void
5027{
5029 nullptr,
5030 "m_currentEvent for AP was not cleared");
5032 nullptr,
5033 "m_currentEvent for STA 1 was not cleared");
5035 nullptr,
5036 "m_currentEvent for STA 2 was not cleared");
5037}
5038
5039void
5041{
5042 // This is needed to make sure PHY state will be checked as the last event if a state change
5043 // occurred at the exact same time as the check
5044 Simulator::ScheduleNow(&TestPhyPaddingExclusion::DoCheckPhyState, this, phy, expectedState);
5045}
5046
5047void
5049{
5050 WifiPhyState currentState = phy->GetState()->GetState();
5051 NS_LOG_FUNCTION(this << currentState);
5052 NS_TEST_ASSERT_MSG_EQ(currentState,
5053 expectedState,
5054 "PHY State " << currentState << " does not match expected state "
5055 << expectedState << " at " << Simulator::Now());
5056}
5057
5058void
5060{
5070}
5071
5072void
5074{
5075 RngSeedManager::SetSeed(1);
5076 RngSeedManager::SetRun(1);
5077 int64_t streamNumber = 0;
5078
5079 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5080 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5081 lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5082 spectrumChannel->AddPropagationLossModel(lossModel);
5084 CreateObject<ConstantSpeedPropagationDelayModel>();
5085 spectrumChannel->SetPropagationDelayModel(delayModel);
5086
5087 Ptr<Node> apNode = CreateObject<Node>();
5088 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5089 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
5090 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5091 apDev->SetMac(apMac);
5092 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5095 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5096 apDev->SetHeConfiguration(heConfiguration);
5097 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5098 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5099 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5100 m_phyAp->SetErrorRateModel(apErrorModel);
5101 m_phyAp->SetDevice(apDev);
5102 m_phyAp->SetChannel(spectrumChannel);
5103 m_phyAp->AssignStreams(streamNumber);
5104 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5109
5114 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5115 m_phyAp->SetMobility(apMobility);
5116 apDev->SetPhy(m_phyAp);
5118 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5119 apMac->SetWifiPhys({m_phyAp});
5120 apNode->AggregateObject(apMobility);
5121 apNode->AddDevice(apDev);
5122
5123 Ptr<Node> sta1Node = CreateObject<Node>();
5124 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5125 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5128 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5129 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5130 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5131 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5132 m_phySta1->SetDevice(sta1Dev);
5133 m_phySta1->SetChannel(spectrumChannel);
5134 m_phySta1->AssignStreams(streamNumber);
5137 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5138 m_phySta1->SetMobility(sta1Mobility);
5139 sta1Dev->SetPhy(m_phySta1);
5141 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5142 sta1Node->AggregateObject(sta1Mobility);
5143 sta1Node->AddDevice(sta1Dev);
5144
5145 Ptr<Node> sta2Node = CreateObject<Node>();
5146 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5147 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5150 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5151 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5152 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5153 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5154 m_phySta2->SetDevice(sta2Dev);
5155 m_phySta2->SetChannel(spectrumChannel);
5156 m_phySta2->AssignStreams(streamNumber);
5159 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5160 m_phySta2->SetMobility(sta2Mobility);
5161 sta2Dev->SetPhy(m_phySta2);
5163 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5164 sta2Node->AggregateObject(sta2Mobility);
5165 sta2Node->AddDevice(sta2Dev);
5166
5167 Ptr<Node> interfererNode = CreateObject<Node>();
5168 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5169 m_phyInterferer = CreateObject<WaveformGenerator>();
5170 m_phyInterferer->SetDevice(interfererDev);
5171 m_phyInterferer->SetChannel(spectrumChannel);
5173 interfererNode->AddDevice(interfererDev);
5174}
5175
5176void
5178{
5179 m_phyAp->Dispose();
5180 m_phyAp = nullptr;
5181 m_phySta1->Dispose();
5182 m_phySta1 = nullptr;
5183 m_phySta2->Dispose();
5184 m_phySta2 = nullptr;
5186 m_phyInterferer = nullptr;
5187}
5188
5189void
5191{
5192 WifiTxVector trigVector(HePhy::GetHeMcs7(),
5193 0,
5195 1600,
5196 1,
5197 1,
5198 0,
5200 false,
5201 false,
5202 1);
5203 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5204 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5205 trigVector.SetNss(1, 1);
5206 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5207 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5208 trigVector.SetNss(1, 2);
5209 uint16_t length;
5210 std::tie(length, ppduDuration) =
5211 HePhy::ConvertHeTbPpduDurationToLSigLength(ppduDuration, trigVector, m_phyAp->GetPhyBand());
5212 trigVector.SetLength(length);
5213 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
5214 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5215}
5216
5217void
5219{
5220 Time expectedPpduDuration = NanoSeconds(292800);
5221 Time ppduWithPaddingDuration =
5222 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5223
5224 Simulator::Schedule(Seconds(0.0), &TestPhyPaddingExclusion::Reset, this);
5225
5226 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5227 Simulator::Schedule(Seconds(1.0),
5229 this,
5230 1,
5231 1,
5232 1000,
5233 ppduWithPaddingDuration);
5234 Simulator::Schedule(Seconds(1.0),
5236 this,
5237 2,
5238 2,
5239 1001,
5240 ppduWithPaddingDuration);
5241
5242 // Set TRIGVECTOR on AP
5243 Simulator::Schedule(Seconds(1.0),
5245 this,
5246 ppduWithPaddingDuration);
5247
5248 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5249 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5251 this,
5252 m_phyAp,
5254 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5256 this,
5257 m_phyAp,
5259
5260 // One PSDU of 1000 bytes should have been successfully received from STA 1
5261 Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5262 // One PSDU of 1001 bytes should have been successfully received from STA 2
5263 Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5264 // Verify events data have been cleared
5265 Simulator::Schedule(Seconds(1.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5266
5267 Simulator::Schedule(Seconds(1.5), &TestPhyPaddingExclusion::Reset, this);
5268
5269 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5270 Simulator::Schedule(Seconds(2.0),
5272 this,
5273 1,
5274 1,
5275 1000,
5276 ppduWithPaddingDuration);
5277 Simulator::Schedule(Seconds(2.0),
5279 this,
5280 2,
5281 2,
5282 1001,
5283 ppduWithPaddingDuration);
5284
5285 // Set TRIGVECTOR on AP
5286 Simulator::Schedule(Seconds(2.0),
5288 this,
5289 ppduWithPaddingDuration);
5290
5291 // A strong non-wifi interference is generated on RU 1 during padding reception
5292 BandInfo bandInfo;
5293 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5294 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5295 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5296 Bands bands;
5297 bands.push_back(bandInfo);
5298
5299 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5300 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5301 double interferencePower = 0.1; // watts
5302 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5303
5304 Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5306 this,
5307 interferencePsdRu1,
5308 MilliSeconds(100));
5309
5310 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5311 // CCA_BUSY instead of IDLE due to the interference)
5312 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5314 this,
5315 m_phyAp,
5317 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5319 this,
5320 m_phyAp,
5322
5323 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5324 // occupies RU 1 after payload, during PHY padding)
5325 Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta1, this, 1, 0, 1000);
5326 // One PSDU of 1001 bytes should have been successfully received from STA 2
5327 Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::CheckRxFromSta2, this, 1, 0, 1001);
5328 // Verify events data have been cleared
5329 Simulator::Schedule(Seconds(2.1), &TestPhyPaddingExclusion::VerifyEventsCleared, this);
5330
5331 Simulator::Schedule(Seconds(2.5), &TestPhyPaddingExclusion::Reset, this);
5332
5333 Simulator::Run();
5334
5335 Simulator::Destroy();
5336}
5337
5345{
5346 public:
5348 ~TestUlOfdmaPowerControl() override;
5349
5350 private:
5351 void DoSetup() override;
5352 void DoTeardown() override;
5353 void DoRun() override;
5354
5360 void SendMuBar(std::vector<uint16_t> staIds);
5361
5368 void SetupBa(Address destination);
5369
5376 void RunOne(bool setupBa);
5377
5383
5394 RxSignalInfo rxSignalInfo,
5395 WifiTxVector txVector,
5396 std::vector<bool> statusPerMpdu);
5397
5398 uint8_t m_bssColor;
5399
5403
5405
5410
5413
5414 double m_rssiSta1;
5415 double m_rssiSta2;
5416
5417 double m_tol;
5418};
5419
5421 : TestCase("UL-OFDMA power control test"),
5422 m_bssColor(1),
5423 m_txPowerAp(0),
5424 m_txPowerStart(0),
5425 m_txPowerEnd(0),
5426 m_txPowerLevels(0),
5427 m_requestedRssiSta1(0),
5428 m_requestedRssiSta2(0),
5429 m_rssiSta1(0),
5430 m_rssiSta2(0),
5431 m_tol(0.1)
5432{
5433}
5434
5436{
5437 m_phyAp = nullptr;
5438 m_apDev = nullptr;
5439 m_sta1Dev = nullptr;
5440 m_sta2Dev = nullptr;
5441}
5442
5443void
5445{
5446 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5447 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5448 m_apDev->Send(pkt, destination, 0);
5449}
5450
5451void
5452TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5453{
5454 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5455
5456 // Build MU-BAR trigger frame
5457 CtrlTriggerHeader muBar;
5458 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5459 muBar.SetMoreTF(true);
5460 muBar.SetCsRequired(true);
5462 muBar.SetGiAndLtfType(1600, 2);
5463 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5464 muBar.SetUlSpatialReuse(60500);
5465
5466 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5467 std::size_t index = 1;
5468 int8_t ulTargetRssi = -40; // will be overwritten
5469 for (const auto& staId : staIds)
5470 {
5472 ui.SetAid12(staId);
5473 ui.SetRuAllocation({ru, index, true});
5474 ui.SetUlFecCodingType(true);
5475 ui.SetUlMcs(7);
5476 ui.SetUlDcm(false);
5477 ui.SetSsAllocation(1, 1);
5478 if (staId == 1)
5479 {
5480 ulTargetRssi = m_requestedRssiSta1;
5481 }
5482 else if (staId == 2)
5483 {
5484 ulTargetRssi = m_requestedRssiSta2;
5485 }
5486 else
5487 {
5488 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5489 }
5490 ui.SetUlTargetRssi(ulTargetRssi);
5491
5493 bar.SetType(BlockAckReqType::COMPRESSED);
5494 bar.SetTidInfo(0);
5495 bar.SetStartingSequence(4095);
5497
5498 ++index;
5499 }
5500
5501 WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5502 muBar.SetUlLength(HePhy::ConvertHeTbPpduDurationToLSigLength(MicroSeconds(128),
5503 tbTxVector,
5505 .first);
5506
5507 WifiConstPsduMap psdus;
5508 WifiTxVector txVector = WifiTxVector(HePhy::GetHeMcs7(),
5509 0,
5511 800,
5512 1,
5513 1,
5514 0,
5516 false,
5517 false,
5518 false,
5519 m_bssColor);
5520
5521 Ptr<Packet> bar = Create<Packet>();
5522 bar->AddHeader(muBar);
5523
5524 Mac48Address receiver = Mac48Address::GetBroadcast();
5525 if (staIds.size() == 1)
5526 {
5527 uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5528 if (staIds.front() == aidSta1)
5529 {
5530 receiver = Mac48Address::ConvertFrom(m_sta1Dev->GetAddress());
5531 }
5532 else
5533 {
5534 NS_ASSERT(staIds.front() ==
5535 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5536 receiver = Mac48Address::ConvertFrom(m_sta2Dev->GetAddress());
5537 }
5538 }
5539
5540 WifiMacHeader hdr;
5542 hdr.SetAddr1(receiver);
5543 hdr.SetAddr2(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5544 hdr.SetAddr3(Mac48Address::ConvertFrom(m_apDev->GetAddress()));
5545 hdr.SetDsNotTo();
5546 hdr.SetDsFrom();
5547 hdr.SetNoRetry();
5548 hdr.SetNoMoreFragments();
5549 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5550
5551 Time nav = m_apDev->GetPhy()->GetSifs();
5552 uint16_t staId = staIds.front(); // either will do
5553 nav += m_phyAp->CalculateTxDuration(GetBlockAckSize(BlockAckType::COMPRESSED),
5554 tbTxVector,
5556 staId);
5557 psdu->SetDuration(nav);
5558 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5559
5560 m_phyAp->Send(psdus, txVector);
5561}
5562
5563void
5565 RxSignalInfo rxSignalInfo,
5566 WifiTxVector txVector,
5567 std::vector<bool> /*statusPerMpdu*/)
5568{
5569 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5570 double rssi = rxSignalInfo.rssi;
5571 NS_ASSERT(psdu->GetNMpdus() == 1);
5572 WifiMacHeader hdr = psdu->GetHeader(0);
5573 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5574 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5575 {
5577 rssi,
5578 m_rssiSta1,
5579 m_tol,
5580 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5581 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5582 }
5583 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5584 {
5586 rssi,
5587 m_rssiSta2,
5588 m_tol,
5589 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5590 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5591 }
5592 else
5593 {
5594 NS_ABORT_MSG("The receiver address is unknown");
5595 }
5596}
5597
5598void
5600{
5601 // Now that BA session has been established we can plug our method
5604}
5605
5606void
5608{
5609 Ptr<Node> apNode = CreateObject<Node>();
5610 NodeContainer staNodes;
5611 staNodes.Create(2);
5612
5613 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5614 Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5615 spectrumChannel->AddPropagationLossModel(lossModel);
5617 CreateObject<ConstantSpeedPropagationDelayModel>();
5618 spectrumChannel->SetPropagationDelayModel(delayModel);
5619
5620 SpectrumWifiPhyHelper spectrumPhy;
5621 spectrumPhy.SetChannel(spectrumChannel);
5622 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5623 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5624
5626 wifi.SetStandard(WIFI_STANDARD_80211ax);
5627 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5628 "DataMode",
5629 StringValue("HeMcs7"),
5630 "ControlMode",
5631 StringValue("HeMcs7"));
5632
5634 mac.SetType("ns3::StaWifiMac");
5635 NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5636 wifi.AssignStreams(staDevs, 0);
5637 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5639 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5641
5642 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5643 // beacon generation is disabled during the actual tests. Having such a long interval also
5644 // avoids bloating logs with beacons during the set up phase.
5645 mac.SetType("ns3::ApWifiMac",
5646 "BeaconGeneration",
5647 BooleanValue(true),
5648 "BeaconInterval",
5649 TimeValue(MicroSeconds(1024 * 600)));
5650 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5652 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5653 m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5655 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5656 // set up for both STAs
5657
5659 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5660 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5661 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5662 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5663 positionAlloc->Add(
5664 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5665 mobility.SetPositionAllocator(positionAlloc);
5666
5667 mobility.Install(apNode);
5668 mobility.Install(staNodes);
5669
5670 lossModel->SetDefaultLoss(50.0);
5671 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5672 staNodes.Get(1)->GetObject<MobilityModel>(),
5673 56.0,
5674 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5675}
5676
5677void
5679{
5680 m_phyAp->Dispose();
5681 m_phyAp = nullptr;
5682 m_apDev->Dispose();
5683 m_apDev = nullptr;
5684 m_sta1Dev->Dispose();
5685 m_sta1Dev = nullptr;
5686 m_sta2Dev->Dispose();
5687 m_sta2Dev = nullptr;
5688}
5689
5690void
5692{
5693 RngSeedManager::SetSeed(1);
5694 RngSeedManager::SetRun(1);
5695 int64_t streamNumber = 0;
5696
5697 Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5698 Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5699
5700 m_phyAp->AssignStreams(streamNumber);
5701 phySta1->AssignStreams(streamNumber);
5702 phySta2->AssignStreams(streamNumber);
5703
5704 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5706 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5707
5708 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5709 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5710 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5711
5712 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5713 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5714 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5715
5716 Time relativeStart = MilliSeconds(0);
5717 if (setupBa)
5718 {
5719 // Set up BA for each station once the association phase has ended
5720 // so that a BA session is established when the MU-BAR is received.
5721 Simulator::Schedule(MilliSeconds(800),
5723 this,
5725 Simulator::Schedule(MilliSeconds(850),
5727 this,
5729 relativeStart = MilliSeconds(1000);
5730 }
5731 else
5732 {
5733 Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5734 NS_ASSERT(apMac);
5735 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5736 }
5737
5738 Simulator::Schedule(relativeStart,
5740 this);
5741
5742 {
5743 // Verify that the RSSI from STA 1 is consistent with what was requested
5744 std::vector<uint16_t> staIds{1};
5745 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5746 }
5747
5748 {
5749 // Verify that the RSSI from STA 2 is consistent with what was requested
5750 std::vector<uint16_t> staIds{2};
5751 Simulator::Schedule(relativeStart + MilliSeconds(20),
5753 this,
5754 staIds);
5755 }
5756
5757 {
5758 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5759 std::vector<uint16_t> staIds{1, 2};
5760 Simulator::Schedule(relativeStart + MilliSeconds(40),
5762 this,
5763 staIds);
5764 }
5765
5766 Simulator::Stop(relativeStart + MilliSeconds(100));
5767 Simulator::Run();
5768}
5769
5770void
5772{
5773 // Power configurations
5774 m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5775 // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5776 m_txPowerStart = 15; // dBm
5777
5778 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5779 m_requestedRssiSta1 = -30.0;
5780 m_requestedRssiSta2 = -36.0;
5781
5782 // Test single power level
5783 {
5784 // STA power configurations: 15 dBm only
5785 m_txPowerEnd = 15;
5786 m_txPowerLevels = 1;
5787
5788 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5789 // regardless of the estimated path loss.
5790 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5791 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5792
5793 RunOne(true);
5794 }
5795
5796 // Test 2 dBm granularity
5797 {
5798 // STA power configurations: [15:2:25] dBm
5799 m_txPowerEnd = 25;
5800 m_txPowerLevels = 6;
5801
5802 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5803 // requested
5804 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5805 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5806
5807 RunOne(false);
5808 }
5809
5810 // Test 1 dBm granularity
5811 {
5812 // STA power configurations: [15:1:25] dBm
5813 m_txPowerEnd = 25;
5814 m_txPowerLevels = 11;
5815
5816 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5817 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5818 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5819
5820 RunOne(false);
5821 }
5822
5823 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5824 {
5825 // STA power configurations: [15:1:25] dBm
5826 m_txPowerEnd = 25;
5827 m_txPowerLevels = 11;
5828
5829 // Requested UL RSSIs
5830 m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5831 m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5832
5833 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5834 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5835 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5836
5837 RunOne(false);
5838 }
5839
5840 Simulator::Destroy();
5841}
5842
5850{
5851 public:
5853};
5854
5856 : TestSuite("wifi-phy-ofdma", UNIT)
5857{
5858 AddTestCase(new TestDlOfdmaPhyTransmission, TestCase::QUICK);
5859 AddTestCase(new TestDlOfdmaPhyPuncturing, TestCase::QUICK);
5860 AddTestCase(new TestUlOfdmaPpduUid, TestCase::QUICK);
5861 AddTestCase(new TestMultipleHeTbPreambles, TestCase::QUICK);
5862 AddTestCase(new TestUlOfdmaPhyTransmission, TestCase::QUICK);
5863 AddTestCase(new TestPhyPaddingExclusion, TestCase::QUICK);
5864 AddTestCase(new TestUlOfdmaPowerControl, TestCase::QUICK);
5865}
5866
#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 StartTx(Ptr< const WifiPpdu > ppdu) override
void DoDispose() override
Destructor implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
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 successful
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 successful.
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:100
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
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:945
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:590
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:68
RU Specification.
Definition: he-ru.h:66
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:435
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:311
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:200
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:862
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:987
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:206
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:56
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:1423
a unique identifier for an interface.
Definition: type-id.h:59
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:324
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:925
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:550
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:624
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:1693
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:632
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:1221
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:774
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:448
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:941
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1480
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1244
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:1062
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1219
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:704
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1224
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-phy.cc:600
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:652
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:612
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:454
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1206
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:442
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1804
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:870
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:719
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:2184
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:279
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:273
void SetDuration(Time duration)
Set the Duration/ID field on all the MPDUs.
Definition: wifi-psdu.cc:168
std::size_t GetNMpdus() const
Return the number of MPDUs constituting the PSDU.
Definition: wifi-psdu.cc:327
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:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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)
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:707
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.