A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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-phy-interface.h"
50#include "ns3/wifi-spectrum-signal-parameters.h"
51#include "ns3/wifi-spectrum-value-helper.h"
52#include "ns3/wifi-utils.h"
53
54#include <algorithm>
55#include <iterator>
56#include <memory>
57
58using namespace ns3;
59
60NS_LOG_COMPONENT_DEFINE("WifiPhyOfdmaTest");
61
62static const uint8_t DEFAULT_CHANNEL_NUMBER = 36;
63static const uint32_t DEFAULT_FREQUENCY = 5180; // MHz
65static const uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
66static const uint16_t DEFAULT_GUARD_WIDTH =
67 DEFAULT_CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
68
73class OfdmaTestHePhy : public HePhy
74{
75 public:
81 OfdmaTestHePhy(uint16_t staId);
82 ~OfdmaTestHePhy() override;
83
91 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
92
98 void SetGlobalPpduUid(uint64_t uid);
99
100 private:
101 uint16_t m_staId;
102}; // class OfdmaTestHePhy
103
105 : HePhy(),
106 m_staId(staId)
107{
108}
109
111{
112}
113
114uint16_t
116{
117 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
118 {
119 return m_staId;
120 }
121 return HePhy::GetStaId(ppdu);
122}
123
124void
126{
127 m_globalPpduUid = uid;
128}
129
134{
135 public:
140 static TypeId GetTypeId();
146 OfdmaSpectrumWifiPhy(uint16_t staId);
147 ~OfdmaSpectrumWifiPhy() override;
148
149 void DoInitialize() override;
150 void DoDispose() override;
151
152 using WifiPhy::Reset;
153 void StartTx(Ptr<const WifiPpdu> ppdu) override;
154
160 typedef void (*TxPpduUidCallback)(uint64_t uid);
161
167 void SetPpduUid(uint64_t uid);
168
174 void SetTriggerFrameUid(uint64_t uid);
175
179 std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>& GetCurrentPreambleEvents();
184
195 Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band);
196
201
202 private:
206}; // class OfdmaSpectrumWifiPhy
207
208TypeId
210{
211 static TypeId tid =
212 TypeId("ns3::OfdmaSpectrumWifiPhy")
214 .SetGroupName("Wifi")
215 .AddTraceSource("TxPpduUid",
216 "UID of the PPDU to be transmitted",
218 "ns3::OfdmaSpectrumWifiPhy::TxPpduUidCallback");
219 return tid;
220}
221
224{
225 m_ofdmTestHePhy = Create<OfdmaTestHePhy>(staId);
227}
228
230{
231}
232
233void
235{
236 // Replace HE PHY instance with test instance
239}
240
241void
243{
244 m_ofdmTestHePhy = nullptr;
246}
247
248void
250{
253}
254
255void
257{
259}
260
261void
263{
264 m_phyTxPpduUidTrace(ppdu->GetUid());
266}
267
268std::map<std::pair<uint64_t, WifiPreamble>, Ptr<Event>>&
270{
272}
273
276{
277 return m_currentEvent;
278}
279
280Time
282{
283 return m_interference->GetEnergyDuration(energyW, band);
284}
285
288{
289 return DynamicCast<const HePhy>(GetLatestPhyEntity());
290}
291
299{
300 public:
303
304 private:
305 void DoSetup() override;
306 void DoTeardown() override;
307 void DoRun() override;
308
317 RxSignalInfo rxSignalInfo,
318 WifiTxVector txVector,
319 std::vector<bool> statusPerMpdu);
328 RxSignalInfo rxSignalInfo,
329 WifiTxVector txVector,
330 std::vector<bool> statusPerMpdu);
339 RxSignalInfo rxSignalInfo,
340 WifiTxVector txVector,
341 std::vector<bool> statusPerMpdu);
342
358
365 void CheckResultsSta1(uint32_t expectedRxSuccess,
366 uint32_t expectedRxFailure,
367 uint32_t expectedRxBytes);
374 void CheckResultsSta2(uint32_t expectedRxSuccess,
375 uint32_t expectedRxFailure,
376 uint32_t expectedRxBytes);
383 void CheckResultsSta3(uint32_t expectedRxSuccess,
384 uint32_t expectedRxFailure,
385 uint32_t expectedRxBytes);
386
390 void ResetResults();
391
397 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
398
404 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
408 void StopInterference();
409
413 void RunOne();
414
427
437
443
444 uint16_t m_frequency;
445 uint16_t m_channelWidth;
447};
448
450 : TestCase("DL-OFDMA PHY test"),
451 m_countRxSuccessSta1(0),
452 m_countRxSuccessSta2(0),
453 m_countRxSuccessSta3(0),
454 m_countRxFailureSta1(0),
455 m_countRxFailureSta2(0),
456 m_countRxFailureSta3(0),
457 m_countRxBytesSta1(0),
458 m_countRxBytesSta2(0),
459 m_countRxBytesSta3(0),
460 m_frequency(DEFAULT_FREQUENCY),
461 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
462 m_expectedPpduDuration(NanoSeconds(306400))
463{
464}
465
466void
468{
478}
479
480void
481TestDlOfdmaPhyTransmission::SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
482{
483 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
484 WifiConstPsduMap psdus;
486 0,
488 800,
489 1,
490 1,
491 0,
493 false,
494 false);
496 if (m_channelWidth == 20)
497 {
498 ruType = HeRu::RU_106_TONE;
499 txVector.SetRuAllocation({96}, 0);
500 }
501 else if (m_channelWidth == 40)
502 {
503 ruType = HeRu::RU_242_TONE;
504 txVector.SetRuAllocation({192, 192}, 0);
505 }
506 else if (m_channelWidth == 80)
507 {
508 ruType = HeRu::RU_484_TONE;
509 txVector.SetRuAllocation({200, 200, 200, 200}, 0);
510 }
511 else if (m_channelWidth == 160)
512 {
513 ruType = HeRu::RU_996_TONE;
514 txVector.SetRuAllocation({208, 208, 208, 208, 208, 208, 208, 208}, 0);
515 }
516 else
517 {
518 NS_ASSERT_MSG(false, "Unsupported channel width");
519 }
520
522
523 HeRu::RuSpec ru1(ruType, 1, true);
524 txVector.SetRu(ru1, rxStaId1);
525 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
526 txVector.SetNss(1, rxStaId1);
527
528 HeRu::RuSpec ru2(ruType, (m_channelWidth == 160 ? 1 : 2), m_channelWidth != 160);
529 txVector.SetRu(ru2, rxStaId2);
530 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
531 txVector.SetNss(1, rxStaId2);
532
533 Ptr<Packet> pkt1 = Create<Packet>(1000);
534 WifiMacHeader hdr1;
536 hdr1.SetQosTid(0);
537 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
538 hdr1.SetSequenceNumber(1);
539 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
540 psdus.insert(std::make_pair(rxStaId1, psdu1));
541
542 Ptr<Packet> pkt2 = Create<Packet>(1500);
543 WifiMacHeader hdr2;
545 hdr2.SetQosTid(0);
546 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
547 hdr2.SetSequenceNumber(2);
548 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
549 psdus.insert(std::make_pair(rxStaId2, psdu2));
550
551 m_phyAp->Send(psdus, txVector);
552}
553
554void
556{
558 m_phyInterferer->SetPeriod(duration);
561}
562
563void
565{
567}
568
570{
571}
572
573void
575 RxSignalInfo rxSignalInfo,
576 WifiTxVector txVector,
577 std::vector<bool> /*statusPerMpdu*/)
578{
579 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
581 m_countRxBytesSta1 += (psdu->GetSize() - 30);
582}
583
584void
586 RxSignalInfo rxSignalInfo,
587 WifiTxVector txVector,
588 std::vector<bool> /*statusPerMpdu*/)
589{
590 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
592 m_countRxBytesSta2 += (psdu->GetSize() - 30);
593}
594
595void
597 RxSignalInfo rxSignalInfo,
598 WifiTxVector txVector,
599 std::vector<bool> /*statusPerMpdu*/)
600{
601 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
603 m_countRxBytesSta3 += (psdu->GetSize() - 30);
604}
605
606void
608{
609 NS_LOG_FUNCTION(this << *psdu);
611}
612
613void
615{
616 NS_LOG_FUNCTION(this << *psdu);
618}
619
620void
622{
623 NS_LOG_FUNCTION(this << *psdu);
625}
626
627void
629 uint32_t expectedRxFailure,
630 uint32_t expectedRxBytes)
631{
633 expectedRxSuccess,
634 "The number of successfully received packets by STA 1 is not correct!");
636 expectedRxFailure,
637 "The number of unsuccessfuly received packets by STA 1 is not correct!");
639 expectedRxBytes,
640 "The number of bytes received by STA 1 is not correct!");
641}
642
643void
645 uint32_t expectedRxFailure,
646 uint32_t expectedRxBytes)
647{
649 expectedRxSuccess,
650 "The number of successfully received packets by STA 2 is not correct!");
652 expectedRxFailure,
653 "The number of unsuccessfuly received packets by STA 2 is not correct!");
655 expectedRxBytes,
656 "The number of bytes received by STA 2 is not correct!");
657}
658
659void
661 uint32_t expectedRxFailure,
662 uint32_t expectedRxBytes)
663{
665 expectedRxSuccess,
666 "The number of successfully received packets by STA 3 is not correct!");
668 expectedRxFailure,
669 "The number of unsuccessfuly received packets by STA 3 is not correct!");
671 expectedRxBytes,
672 "The number of bytes received by STA 3 is not correct!");
673}
674
675void
677{
678 // This is needed to make sure PHY state will be checked as the last event if a state change
679 // occurred at the exact same time as the check
681}
682
683void
685 WifiPhyState expectedState)
686{
687 WifiPhyState currentState;
688 PointerValue ptr;
689 phy->GetAttribute("State", ptr);
690 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
691 currentState = state->GetState();
692 NS_LOG_FUNCTION(this << currentState);
693 NS_TEST_ASSERT_MSG_EQ(currentState,
694 expectedState,
695 "PHY State " << currentState << " does not match expected state "
696 << expectedState << " at " << Simulator::Now());
697}
698
699void
701{
702 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
703 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
704 lossModel->SetFrequency(m_frequency * 1e6);
705 spectrumChannel->AddPropagationLossModel(lossModel);
707 CreateObject<ConstantSpeedPropagationDelayModel>();
708 spectrumChannel->SetPropagationDelayModel(delayModel);
709
710 Ptr<Node> apNode = CreateObject<Node>();
711 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
712 m_phyAp = CreateObject<SpectrumWifiPhy>();
713 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
714 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
715 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
716 m_phyAp->SetErrorRateModel(apErrorModel);
717 m_phyAp->SetDevice(apDev);
718 m_phyAp->AddChannel(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);
729 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
730 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
731 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
732 m_phySta1->SetErrorRateModel(sta1ErrorModel);
733 m_phySta1->SetDevice(sta1Dev);
734 m_phySta1->AddChannel(spectrumChannel);
739 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
740 m_phySta1->SetMobility(sta1Mobility);
741 sta1Dev->SetPhy(m_phySta1);
742 sta1Node->AggregateObject(sta1Mobility);
743 sta1Node->AddDevice(sta1Dev);
744
745 Ptr<Node> sta2Node = CreateObject<Node>();
746 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
747 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
748 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
749 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
750 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
751 m_phySta2->SetErrorRateModel(sta2ErrorModel);
752 m_phySta2->SetDevice(sta2Dev);
753 m_phySta2->AddChannel(spectrumChannel);
758 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
759 m_phySta2->SetMobility(sta2Mobility);
760 sta2Dev->SetPhy(m_phySta2);
761 sta2Node->AggregateObject(sta2Mobility);
762 sta2Node->AddDevice(sta2Dev);
763
764 Ptr<Node> sta3Node = CreateObject<Node>();
765 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
766 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
767 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
768 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
769 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
770 m_phySta3->SetErrorRateModel(sta3ErrorModel);
771 m_phySta3->SetDevice(sta3Dev);
772 m_phySta3->AddChannel(spectrumChannel);
777 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
778 m_phySta3->SetMobility(sta3Mobility);
779 sta3Dev->SetPhy(m_phySta3);
780 sta3Node->AggregateObject(sta3Mobility);
781 sta3Node->AddDevice(sta3Dev);
782
783 Ptr<Node> interfererNode = CreateObject<Node>();
784 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
785 m_phyInterferer = CreateObject<WaveformGenerator>();
786 m_phyInterferer->SetDevice(interfererDev);
787 m_phyInterferer->SetChannel(spectrumChannel);
789 interfererNode->AddDevice(interfererDev);
790}
791
792void
794{
795 m_phyAp->Dispose();
796 m_phyAp = nullptr;
798 m_phySta1 = nullptr;
800 m_phySta2 = nullptr;
802 m_phySta3 = nullptr;
804 m_phyInterferer = nullptr;
805}
806
807void
809{
812 int64_t streamNumber = 0;
813 m_phyAp->AssignStreams(streamNumber);
814 m_phySta1->AssignStreams(streamNumber);
815 m_phySta2->AssignStreams(streamNumber);
816 m_phySta3->AssignStreams(streamNumber);
817
818 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
823
832
834
835 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
836 // Each STA should receive its PSDU.
838
839 // Since it takes m_expectedPpduDuration to transmit the PPDU,
840 // all 3 PHYs should be back to IDLE at the same time,
841 // even the PHY that has no PSDU addressed to it.
844 this,
845 m_phySta1,
846 WifiPhyState::RX);
849 this,
850 m_phySta2,
851 WifiPhyState::RX);
854 this,
855 m_phySta3,
856 WifiPhyState::CCA_BUSY);
859 this,
860 m_phySta1,
861 WifiPhyState::IDLE);
864 this,
865 m_phySta2,
866 WifiPhyState::IDLE);
869 this,
870 m_phySta3,
871 WifiPhyState::IDLE);
872
873 // One PSDU of 1000 bytes should have been successfully received by STA 1
876 this,
877 1,
878 0,
879 1000);
880 // One PSDU of 1500 bytes should have been successfully received by STA 2
883 this,
884 1,
885 0,
886 1500);
887 // No PSDU should have been received by STA 3
889
891
892 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
893 // STA 1 should receive its PSDU, whereas STA 2 should not receive any PSDU
894 // but should keep its PHY busy during all PPDU duration.
896
897 // Since it takes m_expectedPpduDuration to transmit the PPDU,
898 // all 3 PHYs should be back to IDLE at the same time,
899 // even the PHY that has no PSDU addressed to it.
902 this,
903 m_phySta1,
904 WifiPhyState::RX);
907 this,
908 m_phySta2,
909 WifiPhyState::CCA_BUSY);
912 this,
913 m_phySta3,
914 WifiPhyState::RX);
917 this,
918 m_phySta1,
919 WifiPhyState::IDLE);
922 this,
923 m_phySta2,
924 WifiPhyState::IDLE);
927 this,
928 m_phySta3,
929 WifiPhyState::IDLE);
930
931 // One PSDU of 1000 bytes should have been successfully received by STA 1
934 this,
935 1,
936 0,
937 1000);
938 // No PSDU should have been received by STA 2
940 // One PSDU of 1500 bytes should have been successfully received by STA 3
943 this,
944 1,
945 0,
946 1500);
947
949
950 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
952
953 // A strong non-wifi interference is generated on RU 1 during PSDU reception
954 BandInfo bandInfo;
955 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
956 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
957 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
958 Bands bands;
959 bands.push_back(bandInfo);
960
961 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
962 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
963 double interferencePower = 0.1; // watts
964 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
965
968 this,
969 interferencePsdRu1,
970 MilliSeconds(100));
971
972 // Since it takes m_expectedPpduDuration to transmit the PPDU,
973 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
974 // even the PHY that has no PSDU addressed to it.
977 this,
978 m_phySta1,
979 WifiPhyState::RX);
982 this,
983 m_phySta2,
984 WifiPhyState::RX);
987 this,
988 m_phySta3,
989 WifiPhyState::CCA_BUSY);
992 this,
993 m_phySta1,
994 WifiPhyState::CCA_BUSY);
997 this,
998 m_phySta2,
999 WifiPhyState::CCA_BUSY);
1002 this,
1003 m_phySta3,
1004 WifiPhyState::CCA_BUSY);
1005
1006 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1007 // occupies RU 1)
1009 // One PSDU of 1500 bytes should have been successfully received by STA 2
1012 this,
1013 1,
1014 0,
1015 1500);
1016 // No PSDU should have been received by STA3
1018
1020
1021 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1023
1024 // A strong non-wifi interference is generated on RU 2 during PSDU reception
1025 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
1026 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
1027 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
1028 bands.clear();
1029 bands.push_back(bandInfo);
1030
1031 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
1032 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
1033 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
1034
1037 this,
1038 interferencePsdRu2,
1039 MilliSeconds(100));
1040
1041 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1042 // both PHYs should be back to IDLE (or CCA_BUSY if interference on the primary 20 MHz) at the
1043 // same time, even the PHY that has no PSDU addressed to it.
1046 this,
1047 m_phySta1,
1048 WifiPhyState::RX);
1051 this,
1052 m_phySta2,
1053 WifiPhyState::RX);
1056 this,
1057 m_phySta3,
1058 WifiPhyState::CCA_BUSY);
1061 this,
1062 m_phySta1,
1063 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1066 this,
1067 m_phySta2,
1068 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1071 this,
1072 m_phySta3,
1073 (m_channelWidth >= 40) ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
1074
1075 // One PSDU of 1000 bytes should have been successfully received by STA 1
1078 this,
1079 1,
1080 0,
1081 1000);
1082 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1083 // occupies RU 2)
1085 // No PSDU should have been received by STA3
1087
1089
1090 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
1092
1093 // A strong non-wifi interference is generated on the full band during PSDU reception
1094 bandInfo.fc = m_frequency * 1e6;
1095 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
1096 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
1097 bands.clear();
1098 bands.push_back(bandInfo);
1099
1100 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
1101 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
1102 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
1103
1106 this,
1107 interferencePsdAll,
1108 MilliSeconds(100));
1109
1110 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1111 // both PHYs should be back to CCA_BUSY (due to the interference) at the same time,
1112 // even the PHY that has no PSDU addressed to it.
1115 this,
1116 m_phySta1,
1117 WifiPhyState::RX);
1120 this,
1121 m_phySta2,
1122 WifiPhyState::RX);
1125 this,
1126 m_phySta3,
1127 WifiPhyState::CCA_BUSY);
1130 this,
1131 m_phySta1,
1132 WifiPhyState::CCA_BUSY);
1135 this,
1136 m_phySta2,
1137 WifiPhyState::CCA_BUSY);
1140 this,
1141 m_phySta3,
1142 WifiPhyState::CCA_BUSY);
1143
1144 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1 (since interference
1145 // occupies RU 1)
1147 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2 (since interference
1148 // occupies RU 2)
1150 // No PSDU should have been received by STA3
1152
1154
1156}
1157
1158void
1160{
1161 m_frequency = 5180;
1162 m_channelWidth = 20;
1164 RunOne();
1165
1166 m_frequency = 5190;
1167 m_channelWidth = 40;
1169 RunOne();
1170
1171 m_frequency = 5210;
1172 m_channelWidth = 80;
1174 RunOne();
1175
1176 m_frequency = 5250;
1177 m_channelWidth = 160;
1179 RunOne();
1180
1182}
1183
1191{
1192 public:
1194
1195 private:
1196 void DoSetup() override;
1197 void DoTeardown() override;
1198 void DoRun() override;
1199
1208 RxSignalInfo rxSignalInfo,
1209 WifiTxVector txVector,
1210 const std::vector<bool> statusPerMpdu);
1211
1220 RxSignalInfo rxSignalInfo,
1221 WifiTxVector txVector,
1222 std::vector<bool> statusPerMpdu);
1223
1229
1235
1242 void CheckResultsSta1(uint32_t expectedRxSuccess,
1243 uint32_t expectedRxFailure,
1244 uint32_t expectedRxBytes);
1245
1252 void CheckResultsSta2(uint32_t expectedRxSuccess,
1253 uint32_t expectedRxFailure,
1254 uint32_t expectedRxBytes);
1255
1259 void ResetResults();
1260
1268 void SendMuPpdu(uint16_t rxStaId1,
1269 uint16_t rxStaId2,
1270 const std::vector<bool>& puncturedSubchannels);
1271
1277 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
1278
1282 void StopInterference();
1283
1287 void RunOne();
1288
1294 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
1295
1302
1309
1314
1315 uint16_t m_frequency;
1317
1320
1323};
1324
1326 : TestCase("DL-OFDMA PHY puncturing test"),
1327 m_countRxSuccessSta1(0),
1328 m_countRxSuccessSta2(0),
1329 m_countRxFailureSta1(0),
1330 m_countRxFailureSta2(0),
1331 m_countRxBytesSta1(0),
1332 m_countRxBytesSta2(0),
1333 m_frequency(5210),
1334 m_channelWidth(80),
1335 m_indexSubchannel(0),
1336 m_expectedPpduDuration20Mhz(NanoSeconds(156800)),
1337 m_expectedPpduDuration40Mhz(NanoSeconds(102400))
1338{
1339}
1340
1341void
1343{
1350}
1351
1352void
1354 uint16_t rxStaId2,
1355 const std::vector<bool>& puncturedSubchannels)
1356{
1357 NS_LOG_FUNCTION(this << rxStaId1 << rxStaId2);
1358 WifiConstPsduMap psdus;
1360 0,
1362 800,
1363 1,
1364 1,
1365 0,
1367 false,
1368 false);
1369
1370 HeRu::RuType ruType =
1371 puncturedSubchannels.empty()
1373 : (puncturedSubchannels.at(1) ? HeRu::RU_242_TONE : HeRu::RU_484_TONE);
1374 HeRu::RuSpec ru1(ruType, 1, true);
1375 txVector.SetRu(ru1, rxStaId1);
1376 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
1377 txVector.SetNss(1, rxStaId1);
1378
1379 ruType = puncturedSubchannels.empty()
1381 : (puncturedSubchannels.at(1) ? HeRu::RU_484_TONE : HeRu::RU_242_TONE);
1382 HeRu::RuSpec ru2(ruType,
1383 ruType == HeRu::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1384 true);
1385 txVector.SetRu(ru2, rxStaId2);
1386 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
1387 txVector.SetNss(1, rxStaId2);
1388
1389 std::vector<uint8_t> ruAlloc;
1390 if (puncturedSubchannels.empty())
1391 {
1392 std::fill_n(std::back_inserter(ruAlloc), 4, 200);
1393 }
1394 else
1395 {
1396 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1397 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 200);
1398 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1399 : (puncturedSubchannels.at(3) ? 192 : 200));
1400 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1401 : (puncturedSubchannels.at(3) ? 113 : 200));
1402 }
1403
1404 txVector.SetRuAllocation(ruAlloc, 0);
1405 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1406
1407 Ptr<Packet> pkt1 = Create<Packet>(1000);
1408 WifiMacHeader hdr1;
1410 hdr1.SetQosTid(0);
1411 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
1412 hdr1.SetSequenceNumber(1);
1413 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
1414 psdus.insert(std::make_pair(rxStaId1, psdu1));
1415
1416 Ptr<Packet> pkt2 = Create<Packet>(1500);
1417 WifiMacHeader hdr2;
1419 hdr2.SetQosTid(0);
1420 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
1421 hdr2.SetSequenceNumber(2);
1422 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
1423 psdus.insert(std::make_pair(rxStaId2, psdu2));
1424
1425 if (!puncturedSubchannels.empty())
1426 {
1427 txVector.SetInactiveSubchannels(puncturedSubchannels);
1428 }
1429
1430 m_phyAp->Send(psdus, txVector);
1431}
1432
1433void
1435{
1436 NS_LOG_FUNCTION(this << duration);
1438 m_phyInterferer->SetPeriod(duration);
1441}
1442
1443void
1445{
1446 NS_LOG_FUNCTION(this);
1448}
1449
1450void
1452 RxSignalInfo rxSignalInfo,
1453 WifiTxVector txVector,
1454 std::vector<bool> /*statusPerMpdu*/)
1455{
1456 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1458 m_countRxBytesSta1 += (psdu->GetSize() - 30);
1459}
1460
1461void
1463 RxSignalInfo rxSignalInfo,
1464 WifiTxVector txVector,
1465 std::vector<bool> /*statusPerMpdu*/)
1466{
1467 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
1469 m_countRxBytesSta2 += (psdu->GetSize() - 30);
1470}
1471
1472void
1474{
1475 NS_LOG_FUNCTION(this << *psdu);
1477}
1478
1479void
1481{
1482 NS_LOG_FUNCTION(this << *psdu);
1484}
1485
1486void
1488 uint32_t expectedRxFailure,
1489 uint32_t expectedRxBytes)
1490{
1492 expectedRxSuccess,
1493 "The number of successfully received packets by STA 1 is not correct!");
1495 expectedRxFailure,
1496 "The number of unsuccessfuly received packets by STA 1 is not correct!");
1498 expectedRxBytes,
1499 "The number of bytes received by STA 1 is not correct!");
1500}
1501
1502void
1504 uint32_t expectedRxFailure,
1505 uint32_t expectedRxBytes)
1506{
1508 expectedRxSuccess,
1509 "The number of successfully received packets by STA 2 is not correct!");
1511 expectedRxFailure,
1512 "The number of unsuccessfuly received packets by STA 2 is not correct!");
1514 expectedRxBytes,
1515 "The number of bytes received by STA 2 is not correct!");
1516}
1517
1518void
1520{
1521 // This is needed to make sure PHY state will be checked as the last event if a state change
1522 // occurred at the exact same time as the check
1524}
1525
1526void
1528{
1529 WifiPhyState currentState;
1530 PointerValue ptr;
1531 phy->GetAttribute("State", ptr);
1532 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1533 currentState = state->GetState();
1534 NS_LOG_FUNCTION(this << currentState);
1535 NS_TEST_ASSERT_MSG_EQ(currentState,
1536 expectedState,
1537 "PHY State " << currentState << " does not match expected state "
1538 << expectedState << " at " << Simulator::Now());
1539}
1540
1541void
1543{
1544 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1545 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1546 lossModel->SetFrequency(m_frequency * 1e6);
1547 spectrumChannel->AddPropagationLossModel(lossModel);
1549 CreateObject<ConstantSpeedPropagationDelayModel>();
1550 spectrumChannel->SetPropagationDelayModel(delayModel);
1551
1552 Ptr<Node> apNode = CreateObject<Node>();
1553 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1554 m_phyAp = CreateObject<SpectrumWifiPhy>();
1555 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1556 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1557 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1558 m_phyAp->SetErrorRateModel(apErrorModel);
1559 m_phyAp->SetDevice(apDev);
1560 m_phyAp->AddChannel(spectrumChannel);
1562 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1563 m_phyAp->SetMobility(apMobility);
1564 apDev->SetPhy(m_phyAp);
1565 apNode->AggregateObject(apMobility);
1566 apNode->AddDevice(apDev);
1567
1568 Ptr<Node> sta1Node = CreateObject<Node>();
1569 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1570 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1571 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1572 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1573 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1574 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1575 m_phySta1->SetDevice(sta1Dev);
1576 m_phySta1->AddChannel(spectrumChannel);
1581 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1582 m_phySta1->SetMobility(sta1Mobility);
1583 sta1Dev->SetPhy(m_phySta1);
1584 sta1Node->AggregateObject(sta1Mobility);
1585 sta1Node->AddDevice(sta1Dev);
1586
1587 Ptr<Node> sta2Node = CreateObject<Node>();
1588 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1589 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1590 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1591 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1592 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1593 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1594 m_phySta2->SetDevice(sta2Dev);
1595 m_phySta2->AddChannel(spectrumChannel);
1600 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1601 m_phySta2->SetMobility(sta2Mobility);
1602 sta2Dev->SetPhy(m_phySta2);
1603 sta2Node->AggregateObject(sta2Mobility);
1604 sta2Node->AddDevice(sta2Dev);
1605
1606 Ptr<Node> interfererNode = CreateObject<Node>();
1607 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
1608 m_phyInterferer = CreateObject<WaveformGenerator>();
1609 m_phyInterferer->SetDevice(interfererDev);
1610 m_phyInterferer->SetChannel(spectrumChannel);
1612 interfererNode->AddDevice(interfererDev);
1613}
1614
1615void
1617{
1618 m_phyAp->Dispose();
1619 m_phyAp = nullptr;
1620 m_phySta1->Dispose();
1621 m_phySta1 = nullptr;
1622 m_phySta2->Dispose();
1623 m_phySta2 = nullptr;
1625 m_phyInterferer = nullptr;
1626}
1627
1628void
1630{
1633 int64_t streamNumber = 0;
1634 m_phyAp->AssignStreams(streamNumber);
1635 m_phySta1->AssignStreams(streamNumber);
1636 m_phySta2->AssignStreams(streamNumber);
1637
1638 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1643
1650
1651 // A strong non-wifi interference is generated on selected 20 MHz subchannel for the whole
1652 // duration of the test run
1653 BandInfo bandInfo;
1654 bandInfo.fc = (m_frequency - (m_channelWidth / 2) + 10 + (m_indexSubchannel * 20)) * 1e6;
1655 // Occupy half of the RU to make sure we do not have some power allocated to the subcarriers on
1656 // the border of another RU
1657 bandInfo.fl = bandInfo.fc - (5 * 1e6);
1658 bandInfo.fh = bandInfo.fc + (5 * 1e6);
1659 Bands bands;
1660 bands.push_back(bandInfo);
1661
1662 Ptr<SpectrumModel> spectrumInterference = Create<SpectrumModel>(bands);
1663 Ptr<SpectrumValue> interferencePsd = Create<SpectrumValue>(spectrumInterference);
1664 double interferencePower = 0.1; // watts
1665 *interferencePsd = interferencePower / 10e6;
1666
1669 this,
1670 interferencePsd,
1671 Seconds(3));
1672
1673 //---------------------------------------------------------------------------
1674 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 without preamble puncturing:
1677 this,
1678 1,
1679 2,
1680 std::vector<bool>{});
1681
1682 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1683 // both PHYs should be back to IDLE at the same time.
1686 this,
1687 m_phySta1,
1688 WifiPhyState::RX);
1691 this,
1692 m_phySta2,
1693 WifiPhyState::RX);
1696 this,
1697 m_phySta1,
1698 WifiPhyState::IDLE);
1701 this,
1702 m_phySta2,
1703 WifiPhyState::IDLE);
1704
1705 if (m_indexSubchannel < 2) // interference in RU 1
1706 {
1707 // One PSDU of 1000 bytes should have been unsuccessfuly received by STA 1
1710 this,
1711 0,
1712 1,
1713 0);
1714 // One PSDU of 1500 bytes should have been successfully received by STA 2
1717 this,
1718 1,
1719 0,
1720 1500);
1721 }
1722 else // interference in RU 2
1723 {
1724 // One PSDU of 1000 bytes should have been successfully received by STA 1
1727 this,
1728 1,
1729 0,
1730 1000);
1731 // One PSDU of 1500 bytes should have been unsuccessfuly received by STA 2
1734 this,
1735 0,
1736 1,
1737 0);
1738 }
1739
1741
1742 //---------------------------------------------------------------------------
1743 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2 with preamble puncturing:
1744 // the punctured 20 MHz subchannel is the one that has interference
1745 std::vector<bool> puncturedSubchannels;
1746 for (std::size_t i = 0; i < (m_channelWidth / 20); ++i)
1747 {
1748 if (i == m_indexSubchannel)
1749 {
1750 puncturedSubchannels.push_back(true);
1751 }
1752 else
1753 {
1754 puncturedSubchannels.push_back(false);
1755 }
1756 }
1759 this,
1760 1,
1761 2,
1762 puncturedSubchannels);
1763
1764 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1765 // both PHYs should be back to IDLE at the same time.
1768 this,
1769 m_phySta1,
1770 WifiPhyState::RX);
1773 this,
1774 m_phySta2,
1775 WifiPhyState::RX);
1778 this,
1779 m_phySta1,
1780 WifiPhyState::IDLE);
1783 this,
1784 m_phySta2,
1785 WifiPhyState::IDLE);
1786
1787 // One PSDU of 1000 bytes should have been successfully received by STA 1
1790 this,
1791 1,
1792 0,
1793 1000);
1794 // One PSDU of 1500 bytes should have been successfully received by STA 2
1797 this,
1798 1,
1799 0,
1800 1500);
1801
1803
1805}
1806
1807void
1809{
1810 // test all 20 MHz subchannels in the 80 MHz operation channel except the primary one which
1811 // cannot be punctured
1812 for (auto index : {1, 2, 3})
1813 {
1814 m_indexSubchannel = index;
1815 RunOne();
1816 }
1818}
1819
1827{
1828 public:
1830 ~TestUlOfdmaPpduUid() override;
1831
1832 private:
1833 void DoSetup() override;
1834 void DoTeardown() override;
1835 void DoRun() override;
1836
1841 void TxPpduAp(uint64_t uid);
1846 void TxPpduSta1(uint64_t uid);
1851 void TxPpduSta2(uint64_t uid);
1855 void ResetPpduUid();
1856
1860 void SendMuPpdu();
1864 void SendTbPpdu();
1869 void SendSuPpdu(uint16_t txStaId);
1870
1876 void CheckUid(uint16_t staId, uint64_t expectedUid);
1877
1881
1882 uint64_t m_ppduUidAp;
1883 uint64_t m_ppduUidSta1;
1884 uint64_t m_ppduUidSta2;
1885};
1886
1888 : TestCase("UL-OFDMA PPDU UID attribution test"),
1889 m_ppduUidAp(UINT64_MAX),
1890 m_ppduUidSta1(UINT64_MAX),
1891 m_ppduUidSta2(UINT64_MAX)
1892{
1893}
1894
1896{
1897}
1898
1899void
1901{
1902 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1903 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1904 lossModel->SetFrequency(DEFAULT_FREQUENCY);
1905 spectrumChannel->AddPropagationLossModel(lossModel);
1907 CreateObject<ConstantSpeedPropagationDelayModel>();
1908 spectrumChannel->SetPropagationDelayModel(delayModel);
1909
1910 Ptr<Node> apNode = CreateObject<Node>();
1911 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1912 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
1913 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1914 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1915 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1916 m_phyAp->SetErrorRateModel(apErrorModel);
1917 m_phyAp->AddChannel(spectrumChannel);
1919 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1926 m_phyAp->SetDevice(apDev);
1929 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
1930 m_phyAp->SetMobility(apMobility);
1931 apDev->SetPhy(m_phyAp);
1932 apNode->AggregateObject(apMobility);
1933 apNode->AddDevice(apDev);
1934 apDev->SetStandard(WIFI_STANDARD_80211ax);
1935 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1936
1937 Ptr<Node> sta1Node = CreateObject<Node>();
1938 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
1939 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
1940 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
1941 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1942 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
1943 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1944 m_phySta1->AddChannel(spectrumChannel);
1948 m_phySta1->SetDevice(sta1Dev);
1951 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
1952 m_phySta1->SetMobility(sta1Mobility);
1953 sta1Dev->SetPhy(m_phySta1);
1954 sta1Node->AggregateObject(sta1Mobility);
1955 sta1Node->AddDevice(sta1Dev);
1956
1957 Ptr<Node> sta2Node = CreateObject<Node>();
1958 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
1959 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
1960 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
1961 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1962 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
1963 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1964 m_phySta2->AddChannel(spectrumChannel);
1968 m_phySta2->SetDevice(sta2Dev);
1971 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
1972 m_phySta2->SetMobility(sta2Mobility);
1973 sta2Dev->SetPhy(m_phySta2);
1974 sta2Node->AggregateObject(sta2Mobility);
1975 sta2Node->AddDevice(sta2Dev);
1976}
1977
1978void
1980{
1981 m_phyAp->Dispose();
1982 m_phyAp = nullptr;
1983 m_phySta1->Dispose();
1984 m_phySta1 = nullptr;
1985 m_phySta2->Dispose();
1986 m_phySta2 = nullptr;
1987}
1988
1989void
1990TestUlOfdmaPpduUid::CheckUid(uint16_t staId, uint64_t expectedUid)
1991{
1992 uint64_t uid;
1993 std::string device;
1994 switch (staId)
1995 {
1996 case 0:
1997 uid = m_ppduUidAp;
1998 device = "AP";
1999 break;
2000 case 1:
2001 uid = m_ppduUidSta1;
2002 device = "STA1";
2003 break;
2004 case 2:
2005 uid = m_ppduUidSta2;
2006 device = "STA2";
2007 break;
2008 default:
2009 NS_ABORT_MSG("Unexpected STA-ID");
2010 }
2012 expectedUid,
2013 "UID " << uid << " does not match expected one " << expectedUid << " for "
2014 << device << " at " << Simulator::Now());
2015}
2016
2017void
2019{
2020 NS_LOG_FUNCTION(this << uid);
2021 m_ppduUidAp = uid;
2022}
2023
2024void
2026{
2027 NS_LOG_FUNCTION(this << uid);
2028 m_ppduUidSta1 = uid;
2029}
2030
2031void
2033{
2034 NS_LOG_FUNCTION(this << uid);
2035 m_ppduUidSta2 = uid;
2036}
2037
2038void
2040{
2041 NS_LOG_FUNCTION(this);
2042 m_phyAp->SetPpduUid(0); // one is enough since it's a global attribute
2043}
2044
2045void
2047{
2048 WifiConstPsduMap psdus;
2050 0,
2052 800,
2053 1,
2054 1,
2055 0,
2057 false,
2058 false);
2059
2060 uint16_t rxStaId1 = 1;
2061 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, true);
2062 txVector.SetRu(ru1, rxStaId1);
2063 txVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2064 txVector.SetNss(1, rxStaId1);
2065
2066 uint16_t rxStaId2 = 2;
2067 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, true);
2068 txVector.SetRu(ru2, rxStaId2);
2069 txVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2070 txVector.SetNss(1, rxStaId2);
2071 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
2072 txVector.SetRuAllocation({96}, 0);
2073
2074 Ptr<Packet> pkt1 = Create<Packet>(1000);
2075 WifiMacHeader hdr1;
2077 hdr1.SetQosTid(0);
2078 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:01"));
2079 hdr1.SetSequenceNumber(1);
2080 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2081 psdus.insert(std::make_pair(rxStaId1, psdu1));
2082
2083 Ptr<Packet> pkt2 = Create<Packet>(1500);
2084 WifiMacHeader hdr2;
2086 hdr2.SetQosTid(0);
2087 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:02"));
2088 hdr2.SetSequenceNumber(2);
2089 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2090 psdus.insert(std::make_pair(rxStaId2, psdu2));
2091
2092 m_phyAp->Send(psdus, txVector);
2093}
2094
2095void
2097{
2098 WifiConstPsduMap psdus1;
2099 WifiConstPsduMap psdus2;
2100
2102 0,
2104 1600,
2105 1,
2106 1,
2107 0,
2109 false,
2110 false);
2111 WifiTxVector txVector2 = txVector1;
2112 WifiTxVector trigVector = txVector2;
2113
2114 uint16_t rxStaId1 = 1;
2115 HeRu::RuSpec ru1(HeRu::RU_106_TONE, 1, false);
2116 txVector1.SetRu(ru1, rxStaId1);
2117 txVector1.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2118 txVector1.SetNss(1, rxStaId1);
2119 trigVector.SetRu(ru1, rxStaId1);
2120 trigVector.SetMode(HePhy::GetHeMcs7(), rxStaId1);
2121 trigVector.SetNss(1, rxStaId1);
2122
2123 Ptr<Packet> pkt1 = Create<Packet>(1000);
2124 WifiMacHeader hdr1;
2126 hdr1.SetQosTid(0);
2127 hdr1.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2128 hdr1.SetSequenceNumber(1);
2129 Ptr<WifiPsdu> psdu1 = Create<WifiPsdu>(pkt1, hdr1);
2130 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2131
2132 uint16_t rxStaId2 = 2;
2133 HeRu::RuSpec ru2(HeRu::RU_106_TONE, 2, false);
2134 txVector2.SetRu(ru2, rxStaId2);
2135 txVector2.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2136 txVector2.SetNss(1, rxStaId2);
2137 trigVector.SetRu(ru2, rxStaId2);
2138 trigVector.SetMode(HePhy::GetHeMcs9(), rxStaId2);
2139 trigVector.SetNss(1, rxStaId2);
2140
2141 Ptr<Packet> pkt2 = Create<Packet>(1500);
2142 WifiMacHeader hdr2;
2144 hdr2.SetQosTid(0);
2145 hdr2.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2146 hdr2.SetSequenceNumber(2);
2147 Ptr<WifiPsdu> psdu2 = Create<WifiPsdu>(pkt2, hdr2);
2148 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2149
2150 Time txDuration1 = m_phySta1->CalculateTxDuration(psdu1->GetSize(),
2151 txVector1,
2153 rxStaId1);
2154 Time txDuration2 = m_phySta2->CalculateTxDuration(psdu2->GetSize(),
2155 txVector2,
2157 rxStaId2);
2158 Time txDuration = std::max(txDuration1, txDuration2);
2159
2160 txVector1.SetLength(
2162 .first);
2163 txVector2.SetLength(
2165 .first);
2166
2167 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
2168 hePhyAp->SetTrigVector(trigVector, txDuration);
2169
2170 m_phySta1->Send(psdus1, txVector1);
2171 m_phySta2->Send(psdus2, txVector2);
2172}
2173
2174void
2176{
2177 WifiConstPsduMap psdus;
2179 0,
2181 800,
2182 1,
2183 1,
2184 0,
2186 false,
2187 false);
2188
2189 Ptr<Packet> pkt = Create<Packet>(1000);
2190 WifiMacHeader hdr;
2192 hdr.SetQosTid(0);
2194 hdr.SetSequenceNumber(1);
2195 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2196 psdus.insert(std::make_pair(SU_STA_ID, psdu));
2197
2198 switch (txStaId)
2199 {
2200 case 0:
2201 m_phyAp->Send(psdus, txVector);
2202 break;
2203 case 1:
2204 m_phySta1->Send(psdus, txVector);
2205 break;
2206 case 2:
2207 m_phySta2->Send(psdus, txVector);
2208 break;
2209 default:
2210 NS_ABORT_MSG("Unexpected STA-ID");
2211 }
2212}
2213
2214void
2216{
2219 int64_t streamNumber = 0;
2220 m_phyAp->AssignStreams(streamNumber);
2221 m_phySta1->AssignStreams(streamNumber);
2222 m_phySta2->AssignStreams(streamNumber);
2223
2224 // Reset PPDU UID so as not to be dependent on previously executed test cases,
2225 // since global attribute will be changed).
2226 ResetPpduUid();
2227
2228 // Send HE MU PPDU with two PSDUs addressed to STA 1 and STA 2.
2229 // PPDU UID should be equal to 0 (the first counter value).
2232
2233 // Send HE SU PPDU from AP.
2234 // PPDU UID should be incremented since this is a new PPDU.
2237
2238 // Send HE TB PPDU from STAs to AP.
2239 // PPDU UID should NOT be incremented since HE TB PPDUs reuse the UID of the immediately
2240 // preceding correctly received PPDU (which normally contains the trigger frame).
2244
2245 // Send HE SU PPDU from STA1.
2246 // PPDU UID should be incremented since this is a new PPDU.
2249
2252}
2253
2261{
2262 public:
2264 ~TestMultipleHeTbPreambles() override;
2265
2266 private:
2267 void DoSetup() override;
2268 void DoTeardown() override;
2269 void DoRun() override;
2270
2280 void RxHeTbPpdu(uint64_t uid, uint16_t staId, double txPowerWatts, size_t payloadSize);
2281
2296
2303
2307 void Reset();
2308
2314 void CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids);
2315
2320 void CheckBytesDropped(size_t expectedBytesDropped);
2321
2323
2326};
2327
2329 : TestCase("UL-OFDMA multiple RX events test"),
2330 m_totalBytesDropped(0),
2331 m_trigVector(HePhy::GetHeMcs7(),
2332 0,
2334 1600,
2335 1,
2336 1,
2337 0,
2339 false,
2340 false)
2341{
2342}
2343
2345{
2346}
2347
2348void
2350{
2351 NS_LOG_FUNCTION(this);
2353 // We have to reset PHY here since we do not trigger OFDMA payload RX event in this test
2354 m_phy->Reset();
2356}
2357
2358void
2360{
2361 NS_LOG_FUNCTION(this << p << reason);
2362 m_totalBytesDropped += (p->GetSize() - 30);
2363}
2364
2365void
2366TestMultipleHeTbPreambles::CheckHeTbPreambles(size_t nEvents, std::vector<uint64_t> uids)
2367{
2368 auto events = m_phy->GetCurrentPreambleEvents();
2369 NS_TEST_ASSERT_MSG_EQ(events.size(), nEvents, "The number of UL MU events is not correct!");
2370 for (const auto& uid : uids)
2371 {
2372 auto pair = std::make_pair(uid, WIFI_PREAMBLE_HE_TB);
2373 auto it = events.find(pair);
2374 bool found = (it != events.end());
2376 true,
2377 "HE TB PPDU with UID " << uid << " has not been received!");
2378 }
2379}
2380
2381void
2383{
2385 expectedBytesDropped,
2386 "The number of dropped bytes is not correct!");
2387}
2388
2389void
2391 uint16_t staId,
2392 double txPowerWatts,
2393 size_t payloadSize)
2394{
2395 WifiConstPsduMap psdus;
2397 0,
2399 1600,
2400 1,
2401 1,
2402 0,
2404 false,
2405 false);
2406
2407 HeRu::RuSpec ru(HeRu::RU_106_TONE, staId, false);
2408 txVector.SetRu(ru, staId);
2409 txVector.SetMode(HePhy::GetHeMcs7(), staId);
2410 txVector.SetNss(1, staId);
2411
2412 m_trigVector.SetHeMuUserInfo(staId, {ru, 7, 1});
2413
2414 Ptr<Packet> pkt = Create<Packet>(payloadSize);
2415 WifiMacHeader hdr;
2417 hdr.SetQosTid(0);
2418 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
2419 hdr.SetSequenceNumber(1);
2420 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
2421 psdus.insert(std::make_pair(staId, psdu));
2422
2423 Time ppduDuration =
2424 m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand(), staId);
2425 Ptr<HePpdu> ppdu = Create<HePpdu>(psdus,
2426 txVector,
2428 ppduDuration,
2429 uid,
2431
2432 // Send non-OFDMA part
2433 Time nonOfdmaDuration = m_phy->GetHePhy()->CalculateNonOfdmaDurationForHeTb(txVector);
2434 uint32_t centerFrequency =
2435 m_phy->GetHePhy()->GetCenterFrequencyForNonOfdmaPart(txVector, staId);
2436 uint16_t ruWidth = HeRu::GetBandwidth(txVector.GetRu(staId).GetRuType());
2437 uint16_t channelWidth = ruWidth < 20 ? 20 : ruWidth;
2439 centerFrequency,
2440 channelWidth,
2441 txPowerWatts,
2442 m_phy->GetGuardBandwidth(channelWidth));
2443 Ptr<WifiSpectrumSignalParameters> rxParams = Create<WifiSpectrumSignalParameters>();
2444 rxParams->psd = rxPsd;
2445 rxParams->txPhy = nullptr;
2446 rxParams->duration = nonOfdmaDuration;
2447 rxParams->ppdu = ppdu;
2448 rxParams->txWidth = channelWidth;
2449
2450 uint16_t length;
2451 std::tie(length, ppduDuration) =
2453 txVector.SetLength(length);
2454 m_trigVector.SetLength(length);
2455 auto hePhy = DynamicCast<HePhy>(m_phy->GetLatestPhyEntity());
2456 hePhy->SetTrigVector(m_trigVector, ppduDuration);
2457 ppdu->ResetTxVector();
2458 m_phy->StartRx(rxParams, nullptr);
2459
2460 // Schedule OFDMA part
2461 Ptr<HePpdu> ppduOfdma = DynamicCast<HePpdu>(ppdu->Copy()); // since flag will be modified
2462 ppduOfdma->SetTxPsdFlag(HePpdu::PSD_HE_PORTION);
2463 const auto band = m_phy->GetHePhy()->GetRuBandForRx(txVector, staId);
2464 Ptr<SpectrumValue> rxPsdOfdma =
2467 txPowerWatts,
2469 band.indices);
2470 Ptr<WifiSpectrumSignalParameters> rxParamsOfdma = Create<WifiSpectrumSignalParameters>();
2471 rxParamsOfdma->psd = rxPsd;
2472 rxParamsOfdma->txPhy = nullptr;
2473 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2474 rxParamsOfdma->ppdu = ppduOfdma;
2475 rxParamsOfdma->txWidth = DEFAULT_CHANNEL_WIDTH;
2476 Simulator::Schedule(nonOfdmaDuration,
2478 this,
2479 rxParamsOfdma);
2480}
2481
2482void
2484{
2486}
2487
2488void
2490{
2491 // This is needed to make sure the OFDMA part is started as the last event since HE-SIG-A should
2492 // end at the exact same time as the start For normal WifiNetDevices, this the reception of the
2493 // OFDMA part is scheduled after end of HE-SIG-A decoding.
2494 m_phy->StartRx(rxParamsOfdma, nullptr);
2495}
2496
2497void
2499{
2500 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
2501 Ptr<Node> node = CreateObject<Node>();
2502 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
2503 dev->SetStandard(WIFI_STANDARD_80211ax);
2504 m_phy = CreateObject<OfdmaSpectrumWifiPhy>(0);
2505 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
2506 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
2507 Ptr<ApWifiMac> mac = CreateObject<ApWifiMac>();
2508 mac->SetAttribute("BeaconGeneration", BooleanValue(false));
2509 dev->SetMac(mac);
2510 m_phy->SetInterferenceHelper(interferenceHelper);
2511 m_phy->SetErrorRateModel(error);
2512 m_phy->AddChannel(spectrumChannel);
2517 0});
2518 m_phy->TraceConnectWithoutContext("PhyRxDrop",
2520 m_phy->SetDevice(dev);
2521 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
2522 CreateObject<ThresholdPreambleDetectionModel>();
2523 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(4));
2524 preambleDetectionModel->SetAttribute("MinimumRssi", DoubleValue(-82));
2525 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2526 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
2527 heConfiguration->SetMaxTbPpduDelay(NanoSeconds(400));
2528 dev->SetHeConfiguration(heConfiguration);
2529 dev->SetPhy(m_phy);
2530 node->AddDevice(dev);
2531}
2532
2533void
2535{
2536 m_phy->Dispose();
2537 m_phy = nullptr;
2538}
2539
2540void
2542{
2545 int64_t streamNumber = 0;
2546 m_phy->AssignStreams(streamNumber);
2547
2548 double txPowerWatts = 0.01;
2549
2550 {
2551 // Verify a single UL MU transmission with two stations belonging to the same BSS
2552 std::vector<uint64_t> uids{0};
2555 this,
2556 uids[0],
2557 1,
2558 txPowerWatts,
2559 1001);
2562 this,
2563 uids[0],
2564 2,
2565 txPowerWatts,
2566 1002);
2567 // Check that we received a single UL MU transmission with the corresponding UID
2570 this,
2571 1,
2572 uids);
2574 }
2575
2576 {
2577 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2578 // the second transmission arrives during the preamble detection window and with half the
2579 // power of the first transmission.
2580 std::vector<uint64_t> uids{1, 2};
2583 this,
2584 uids[0],
2585 1,
2586 txPowerWatts,
2587 1001);
2590 this,
2591 uids[0],
2592 2,
2593 txPowerWatts,
2594 1002);
2597 this,
2598 uids[1],
2599 1,
2600 txPowerWatts / 2,
2601 1003);
2604 this,
2605 uids[1],
2606 2,
2607 txPowerWatts / 2,
2608 1004);
2609 // Check that we received the correct reception of 2 UL MU transmissions with the
2610 // corresponding UIDs
2613 this,
2614 2,
2615 uids);
2617 // TODO: verify PPDUs from second UL MU transmission are dropped
2618 }
2619
2620 {
2621 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2622 // the second transmission arrives during the preamble detection window and with twice the
2623 // power of the first transmission.
2624 std::vector<uint64_t> uids{3, 4};
2627 this,
2628 uids[0],
2629 1,
2630 txPowerWatts / 2,
2631 1001);
2634 this,
2635 uids[0],
2636 2,
2637 txPowerWatts / 2,
2638 1002);
2641 this,
2642 uids[1],
2643 1,
2644 txPowerWatts,
2645 1003);
2648 this,
2649 uids[1],
2650 2,
2651 txPowerWatts,
2652 1004);
2653 // Check that we received the correct reception of 2 UL MU transmissions with the
2654 // corresponding UIDs
2657 this,
2658 2,
2659 uids);
2661 // TODO: verify PPDUs from first UL MU transmission are dropped
2662 }
2663
2664 {
2665 // Verify the correct reception of 2 UL MU transmissions with two stations per BSS, where
2666 // the second transmission arrives during PHY header reception and with the same power as
2667 // the first transmission.
2668 std::vector<uint64_t> uids{5, 6};
2671 this,
2672 uids[0],
2673 1,
2674 txPowerWatts,
2675 1001);
2678 this,
2679 uids[0],
2680 2,
2681 txPowerWatts,
2682 1002);
2685 this,
2686 uids[1],
2687 1,
2688 txPowerWatts,
2689 1003);
2692 this,
2693 uids[1],
2694 2,
2695 txPowerWatts,
2696 1004);
2697 // Check that we received the correct reception of the first UL MU transmission with the
2698 // corresponding UID (second one dropped)
2701 this,
2702 1,
2703 std::vector<uint64_t>{uids[0]});
2704 // The packets of the second UL MU transmission should have been dropped
2707 this,
2708 1003 + 1004);
2710 }
2711
2712 {
2713 // Verify the correct reception of one UL MU transmission out of 2 with two stations per
2714 // BSS, where the second transmission arrives during payload reception and with the same
2715 // power as the first transmission.
2716 std::vector<uint64_t> uids{7, 8};
2719 this,
2720 uids[0],
2721 1,
2722 txPowerWatts,
2723 1001);
2726 this,
2727 uids[0],
2728 2,
2729 txPowerWatts,
2730 1002);
2733 this,
2734 uids[1],
2735 1,
2736 txPowerWatts,
2737 1003);
2740 this,
2741 uids[1],
2742 2,
2743 txPowerWatts,
2744 1004);
2745 // Check that we received the correct reception of the first UL MU transmission with the
2746 // corresponding UID (second one dropped)
2749 this,
2750 1,
2751 std::vector<uint64_t>{uids[0]});
2752 // The packets of the second UL MU transmission should have been dropped
2755 this,
2756 1003 + 1004);
2758 }
2759
2760 {
2761 // Verify the correct reception of a single UL MU transmission with two stations belonging
2762 // to the same BSS, and the second PPDU arrives 500ns after the first PPDU, i.e. it exceeds
2763 // the configured delay spread of 400ns
2764 std::vector<uint64_t> uids{9};
2767 this,
2768 uids[0],
2769 1,
2770 txPowerWatts,
2771 1001);
2774 this,
2775 uids[0],
2776 2,
2777 txPowerWatts,
2778 1002);
2779 // Check that we received a single UL MU transmission with the corresponding UID
2782 this,
2783 1,
2784 uids);
2785 // The first packet of 1001 bytes should be dropped because preamble is not detected after
2786 // 4us (because the PPDU that arrived at 500ns is interfering): the second HE TB PPDU is
2787 // acting as interference since it arrived after the maximum allowed 400ns. Obviously, that
2788 // second packet of 1002 bytes is dropped as well.
2791 this,
2792 1001 + 1002);
2794 }
2795
2798}
2799
2807{
2808 public:
2810
2811 void NotifyRxStart(Time duration) override
2812 {
2813 NS_LOG_FUNCTION(this << duration);
2816 m_lastRxSuccess = false;
2817 }
2818
2819 void NotifyRxEndOk() override
2820 {
2821 NS_LOG_FUNCTION(this);
2823 ++m_notifyRxEnd;
2824 m_lastRxSuccess = true;
2825 }
2826
2827 void NotifyRxEndError() override
2828 {
2829 NS_LOG_FUNCTION(this);
2831 ++m_notifyRxEnd;
2832 m_lastRxSuccess = false;
2833 }
2834
2835 void NotifyTxStart(Time duration, double txPowerDbm) override
2836 {
2837 NS_LOG_FUNCTION(this << duration << txPowerDbm);
2838 }
2839
2841 WifiChannelListType channelType,
2842 const std::vector<Time>& /*per20MhzDurations*/) override
2843 {
2844 NS_LOG_FUNCTION(this << duration << channelType);
2845 }
2846
2847 void NotifySwitchingStart(Time duration) override
2848 {
2849 }
2850
2851 void NotifySleep() override
2852 {
2853 }
2854
2855 void NotifyOff() override
2856 {
2857 }
2858
2859 void NotifyWakeup() override
2860 {
2861 }
2862
2863 void NotifyOn() override
2864 {
2865 }
2866
2870 void Reset()
2871 {
2872 m_notifyRxStart = 0;
2873 m_notifyRxEnd = 0;
2875 m_lastRxEnd = Seconds(0);
2876 m_lastRxSuccess = false;
2877 }
2878
2884 {
2885 return m_notifyRxStart;
2886 }
2887
2893 {
2894 return m_notifyRxEnd;
2895 }
2896
2902 {
2903 return m_lastRxStart;
2904 }
2905
2911 {
2912 return m_lastRxEnd;
2913 }
2914
2919 bool IsLastRxSuccess() const
2920 {
2921 return m_lastRxSuccess;
2922 }
2923
2924 private:
2929 bool m_lastRxSuccess{false};
2930};
2931
2939{
2940 public:
2945 {
2946 NONE = 0,
2950 };
2951
2953 ~TestUlOfdmaPhyTransmission() override;
2954
2955 private:
2956 void DoSetup() override;
2957 void DoTeardown() override;
2958 void DoRun() override;
2959
2967 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId,
2968 std::size_t index,
2969 uint8_t bssColor) const;
2976 void SetTrigVector(uint8_t bssColor, TrigVectorInfo error);
2986 void SendHeTbPpdu(uint16_t txStaId,
2987 std::size_t index,
2988 std::size_t payloadSize,
2989 uint64_t uid,
2990 uint8_t bssColor,
2991 bool incrementUid);
2992
3000 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3001
3007 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
3008
3014 void SetPsdLimit(Ptr<WifiPhy> phy, double psdLimit);
3015
3021 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
3025 void StopInterference();
3026
3030 void RunOne();
3031
3038 void CheckRxFromSta1(uint32_t expectedSuccess,
3039 uint32_t expectedFailures,
3040 uint32_t expectedBytes);
3041
3048 void CheckRxFromSta2(uint32_t expectedSuccess,
3049 uint32_t expectedFailures,
3050 uint32_t expectedBytes);
3051
3060 double expectedRxPower);
3069 double expectedRxPower);
3070
3074 void VerifyEventsCleared();
3075
3081 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
3084
3091 void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification);
3099 void CheckApRxEnd(uint32_t expectedNotifications,
3100 Time expectedLastNotification,
3101 bool expectedSuccess);
3102
3106 void Reset();
3107
3116 RxSignalInfo rxSignalInfo,
3117 WifiTxVector txVector,
3118 std::vector<bool> statusPerMpdu);
3119
3124 void RxFailure(Ptr<const WifiPsdu> psdu);
3125
3146 void ScheduleTest(Time delay,
3147 bool solicited,
3148 WifiPhyState expectedStateAtEnd,
3149 uint32_t expectedSuccessFromSta1,
3150 uint32_t expectedFailuresFromSta1,
3151 uint32_t expectedBytesFromSta1,
3152 uint32_t expectedSuccessFromSta2,
3153 uint32_t expectedFailuresFromSta2,
3154 uint32_t expectedBytesFromSta2,
3155 bool scheduleTxSta1 = true,
3156 Time ulTimeDifference = Seconds(0),
3157 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3158 TrigVectorInfo error = NONE);
3159
3170 double rxPowerNonOfdmaRu1,
3171 double rxPowerNonOfdmaRu2,
3172 double rxPowerOfdmaRu1,
3173 double rxPowerOfdmaRu2);
3179 void LogScenario(std::string log) const;
3180
3185
3186 std::unique_ptr<OfdmaTestPhyListener>
3188
3190
3197
3198 uint16_t m_frequency;
3201};
3202
3204 : TestCase("UL-OFDMA PHY test"),
3205 m_countRxSuccessFromSta1(0),
3206 m_countRxSuccessFromSta2(0),
3207 m_countRxFailureFromSta1(0),
3208 m_countRxFailureFromSta2(0),
3209 m_countRxBytesFromSta1(0),
3210 m_countRxBytesFromSta2(0),
3211 m_frequency(DEFAULT_FREQUENCY),
3212 m_channelWidth(DEFAULT_CHANNEL_WIDTH),
3213 m_expectedPpduDuration(NanoSeconds(271200))
3214{
3215}
3216
3217void
3219 std::size_t payloadSize,
3220 uint64_t uid,
3221 uint8_t bssColor)
3222{
3223 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
3224 WifiConstPsduMap psdus;
3225
3227 0,
3229 800,
3230 1,
3231 1,
3232 0,
3234 false,
3235 false,
3236 false,
3237 bssColor);
3238
3239 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3240 WifiMacHeader hdr;
3242 hdr.SetQosTid(0);
3243 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3244 std::ostringstream addr;
3245 addr << "00:00:00:00:00:0" << txStaId;
3246 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3247 hdr.SetSequenceNumber(1);
3248 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3249 psdus.insert(std::make_pair(SU_STA_ID, psdu));
3250
3252 if (txStaId == 1)
3253 {
3254 phy = m_phySta1;
3255 }
3256 else if (txStaId == 2)
3257 {
3258 phy = m_phySta2;
3259 }
3260 else if (txStaId == 3)
3261 {
3262 phy = m_phySta3;
3263 }
3264 else if (txStaId == 0)
3265 {
3266 phy = m_phyAp;
3267 }
3268 phy->SetPpduUid(uid);
3269 phy->Send(psdus, txVector);
3270}
3271
3274 std::size_t index,
3275 uint8_t bssColor) const
3276{
3278 0,
3280 1600,
3281 1,
3282 1,
3283 0,
3285 false,
3286 false,
3287 false,
3288 bssColor);
3289
3291 if (m_channelWidth == 20)
3292 {
3293 ruType = HeRu::RU_106_TONE;
3294 }
3295 else if (m_channelWidth == 40)
3296 {
3297 ruType = HeRu::RU_242_TONE;
3298 }
3299 else if (m_channelWidth == 80)
3300 {
3301 ruType = HeRu::RU_484_TONE;
3302 }
3303 else if (m_channelWidth == 160)
3304 {
3305 ruType = HeRu::RU_996_TONE;
3306 }
3307 else
3308 {
3309 NS_ASSERT_MSG(false, "Unsupported channel width");
3310 }
3311
3312 bool primary80MHz = true;
3313 if (m_channelWidth == 160 && index == 2)
3314 {
3315 primary80MHz = false;
3316 index = 1;
3317 }
3318 HeRu::RuSpec ru(ruType, index, primary80MHz);
3319 txVector.SetRu(ru, txStaId);
3320 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
3321 txVector.SetNss(1, txStaId);
3322 return txVector;
3323}
3324
3325void
3327{
3328 uint16_t channelWidth = m_channelWidth;
3329 if (error == CHANNEL_WIDTH)
3330 {
3331 channelWidth = (channelWidth == 160 ? 20 : channelWidth * 2);
3332 }
3333
3334 WifiTxVector txVector(HePhy::GetHeMcs7(),
3335 0,
3337 1600,
3338 1,
3339 1,
3340 0,
3341 channelWidth,
3342 false,
3343 false,
3344 false,
3345 bssColor);
3346
3348 if (channelWidth == 20)
3349 {
3350 ruType = HeRu::RU_106_TONE;
3351 }
3352 else if (channelWidth == 40)
3353 {
3354 ruType = HeRu::RU_242_TONE;
3355 }
3356 else if (channelWidth == 80)
3357 {
3358 ruType = HeRu::RU_484_TONE;
3359 }
3360 else if (channelWidth == 160)
3361 {
3362 ruType = HeRu::RU_996_TONE;
3363 }
3364 else
3365 {
3366 NS_ASSERT_MSG(false, "Unsupported channel width");
3367 }
3368
3369 uint16_t aid1 = (error == AID ? 3 : 1);
3370 uint16_t aid2 = (error == AID ? 4 : 2);
3371
3372 HeRu::RuSpec ru1(ruType, 1, true);
3373 txVector.SetRu(ru1, aid1);
3374 txVector.SetMode(HePhy::GetHeMcs7(), aid1);
3375 txVector.SetNss(1, aid1);
3376
3377 HeRu::RuSpec ru2(ruType, (channelWidth == 160 ? 1 : 2), (channelWidth != 160));
3378 txVector.SetRu(ru2, aid2);
3379 txVector.SetMode(HePhy::GetHeMcs7(), aid2);
3380 txVector.SetNss(1, aid2);
3381
3382 uint16_t length;
3383 std::tie(length, m_expectedPpduDuration) =
3385 txVector,
3386 m_phyAp->GetPhyBand());
3387 if (error == UL_LENGTH)
3388 {
3389 ++length;
3390 }
3391 txVector.SetLength(length);
3392 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
3393 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3394}
3395
3396void
3398 std::size_t index,
3399 std::size_t payloadSize,
3400 uint64_t uid,
3401 uint8_t bssColor,
3402 bool incrementUid)
3403{
3404 NS_LOG_FUNCTION(this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3405 WifiConstPsduMap psdus;
3406
3407 if (incrementUid)
3408 {
3409 ++uid;
3410 }
3411
3412 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, index, bssColor);
3413 Ptr<Packet> pkt = Create<Packet>(payloadSize);
3414 WifiMacHeader hdr;
3416 hdr.SetQosTid(0);
3417 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
3418 std::ostringstream addr;
3419 addr << "00:00:00:00:00:0" << txStaId;
3420 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
3421 hdr.SetSequenceNumber(1);
3422 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
3423 psdus.insert(std::make_pair(txStaId, psdu));
3424
3426 if (txStaId == 1)
3427 {
3428 phy = m_phySta1;
3429 }
3430 else if (txStaId == 2)
3431 {
3432 phy = m_phySta2;
3433 }
3434 else if (txStaId == 3)
3435 {
3436 phy = m_phySta3;
3437 }
3438
3439 Time txDuration =
3440 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
3441 txVector.SetLength(
3442 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
3443
3444 phy->SetPpduUid(uid);
3445 phy->Send(psdus, txVector);
3446}
3447
3448void
3450{
3451 NS_LOG_FUNCTION(this << duration);
3453 m_phyInterferer->SetPeriod(duration);
3456}
3457
3458void
3460{
3462}
3463
3465{
3466}
3467
3468void
3470 RxSignalInfo rxSignalInfo,
3471 WifiTxVector txVector,
3472 std::vector<bool> /*statusPerMpdu*/)
3473{
3474 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3475 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3476 {
3478 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3479 }
3480 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3481 {
3483 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3484 }
3485}
3486
3487void
3489{
3490 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
3491 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
3492 {
3494 }
3495 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
3496 {
3498 }
3499}
3500
3501void
3503 uint32_t expectedFailures,
3504 uint32_t expectedBytes)
3505{
3507 expectedSuccess,
3508 "The number of successfully received packets from STA 1 is not correct!");
3511 expectedFailures,
3512 "The number of unsuccessfuly received packets from STA 1 is not correct!");
3514 expectedBytes,
3515 "The number of bytes received from STA 1 is not correct!");
3516}
3517
3518void
3520 uint32_t expectedFailures,
3521 uint32_t expectedBytes)
3522{
3524 expectedSuccess,
3525 "The number of successfully received packets from STA 2 is not correct!");
3528 expectedFailures,
3529 "The number of unsuccessfuly received packets from STA 2 is not correct!");
3531 expectedBytes,
3532 "The number of bytes received from STA 2 is not correct!");
3533}
3534
3535void
3538 double expectedRxPower)
3539{
3540 Ptr<Event> event = phy->GetCurrentEvent();
3541 NS_ASSERT(event);
3542 auto rxPower = event->GetRxPowerW(band);
3543 NS_LOG_FUNCTION(this << band << expectedRxPower << rxPower);
3544 // Since there is out of band emission due to spectrum mask, the tolerance cannot be very low
3546 expectedRxPower,
3547 5e-3,
3548 "RX power " << rxPower << " over (" << band
3549 << ") does not match expected power " << expectedRxPower
3550 << " at " << Simulator::Now());
3551}
3552
3553void
3556 double expectedRxPower)
3557{
3563 NS_LOG_FUNCTION(this << band << expectedRxPower);
3564 double step = 5e-3;
3565 if (expectedRxPower > 0.0)
3566 {
3568 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3569 true,
3570 "At least " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3571 << Simulator::Now());
3573 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3574 false,
3575 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3576 << Simulator::Now());
3577 }
3578 else
3579 {
3581 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3582 false,
3583 "At most " << expectedRxPower << " W expected for OFDMA part over (" << band << ") at "
3584 << Simulator::Now());
3585 }
3586}
3587
3588void
3590{
3592 nullptr,
3593 "m_currentEvent for AP was not cleared");
3595 nullptr,
3596 "m_currentEvent for STA 1 was not cleared");
3598 nullptr,
3599 "m_currentEvent for STA 2 was not cleared");
3600}
3601
3602void
3604{
3605 // This is needed to make sure PHY state will be checked as the last event if a state change
3606 // occurred at the exact same time as the check
3608}
3609
3610void
3612 WifiPhyState expectedState)
3613{
3614 WifiPhyState currentState;
3615 PointerValue ptr;
3616 phy->GetAttribute("State", ptr);
3617 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
3618 currentState = state->GetState();
3619 NS_LOG_FUNCTION(this << currentState);
3620 NS_TEST_ASSERT_MSG_EQ(currentState,
3621 expectedState,
3622 "PHY State " << currentState << " does not match expected state "
3623 << expectedState << " at " << Simulator::Now());
3624}
3625
3626void
3628 Time expectedLastNotification)
3629{
3630 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxStartNotifications(),
3631 expectedNotifications,
3632 "Number of RX start notifications "
3633 << m_apPhyStateListener->GetNumRxStartNotifications()
3634 << " does not match expected count " << expectedNotifications
3635 << " for AP at " << Simulator::Now());
3636 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxStartNotification(),
3637 expectedLastNotification,
3638 "Last time RX start notification has been received "
3639 << m_apPhyStateListener->GetLastRxStartNotification()
3640 << " does not match expected time " << expectedLastNotification
3641 << " for AP at " << Simulator::Now());
3642}
3643
3644void
3646 Time expectedLastNotification,
3647 bool expectedSuccess)
3648{
3649 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetNumRxEndNotifications(),
3650 expectedNotifications,
3651 "Number of RX end notifications "
3652 << m_apPhyStateListener->GetNumRxEndNotifications()
3653 << " does not match expected count " << expectedNotifications
3654 << " for AP at " << Simulator::Now());
3655 NS_TEST_ASSERT_MSG_EQ(m_apPhyStateListener->GetLastRxEndNotification(),
3656 expectedLastNotification,
3657 "Last time RX end notification has been received "
3658 << m_apPhyStateListener->GetLastRxEndNotification()
3659 << " does not match expected time " << expectedLastNotification
3660 << " for AP at " << Simulator::Now());
3662 expectedSuccess,
3663 "Last time RX end notification indicated a "
3664 << (m_apPhyStateListener->IsLastRxSuccess() ? "success" : "failure")
3665 << " but expected a " << (expectedSuccess ? "success" : "failure")
3666 << " for AP at " << Simulator::Now());
3667}
3668
3669void
3671{
3681 SetBssColor(m_phyAp, 0);
3682 m_apPhyStateListener->Reset();
3683}
3684
3685void
3687{
3688 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
3689 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
3690 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
3691}
3692
3693void
3695{
3696 NS_LOG_FUNCTION(this << phy << psdLimit);
3697 phy->SetAttribute("PowerDensityLimit", DoubleValue(psdLimit));
3698}
3699
3700void
3702{
3703 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
3704 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
3705 lossModel->SetFrequency(m_frequency);
3706 spectrumChannel->AddPropagationLossModel(lossModel);
3708 CreateObject<ConstantSpeedPropagationDelayModel>();
3709 spectrumChannel->SetPropagationDelayModel(delayModel);
3710
3711 Ptr<ThresholdPreambleDetectionModel> preambleDetectionModel =
3712 CreateObject<ThresholdPreambleDetectionModel>();
3713 preambleDetectionModel->SetAttribute(
3714 "MinimumRssi",
3716 -8)); // to ensure that transmission in neighboring channel is ignored (16 dBm baseline)
3717 preambleDetectionModel->SetAttribute("Threshold", DoubleValue(-100)); // no limit on SNR
3718
3719 Ptr<Node> apNode = CreateObject<Node>();
3720 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
3721 apDev->SetStandard(WIFI_STANDARD_80211ax);
3722 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
3723 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
3724 apDev->SetMac(apMac);
3725 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
3726 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
3727 apDev->SetHeConfiguration(heConfiguration);
3728 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
3729 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
3730 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
3731 m_phyAp->SetErrorRateModel(apErrorModel);
3732 m_phyAp->SetDevice(apDev);
3733 m_phyAp->AddChannel(spectrumChannel);
3737 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
3738 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
3739 m_phyAp->SetMobility(apMobility);
3740 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
3742 apDev->SetPhy(m_phyAp);
3743 apMac->SetWifiPhys({m_phyAp});
3744 apNode->AggregateObject(apMobility);
3745 apNode->AddDevice(apDev);
3746
3747 Ptr<Node> sta1Node = CreateObject<Node>();
3748 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
3749 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
3750 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3751 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
3752 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
3753 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
3754 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
3755 m_phySta1->SetErrorRateModel(sta1ErrorModel);
3756 m_phySta1->SetDevice(sta1Dev);
3757 m_phySta1->AddChannel(spectrumChannel);
3759 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
3760 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
3761 m_phySta1->SetMobility(sta1Mobility);
3762 sta1Dev->SetPhy(m_phySta1);
3763 sta1Node->AggregateObject(sta1Mobility);
3764 sta1Node->AddDevice(sta1Dev);
3765
3766 Ptr<Node> sta2Node = CreateObject<Node>();
3767 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
3768 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
3769 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3770 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
3771 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
3772 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
3773 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
3774 m_phySta2->SetErrorRateModel(sta2ErrorModel);
3775 m_phySta2->SetDevice(sta2Dev);
3776 m_phySta2->AddChannel(spectrumChannel);
3778 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
3779 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
3780 m_phySta2->SetMobility(sta2Mobility);
3781 sta2Dev->SetPhy(m_phySta2);
3782 sta2Node->AggregateObject(sta2Mobility);
3783 sta2Node->AddDevice(sta2Dev);
3784
3785 Ptr<Node> sta3Node = CreateObject<Node>();
3786 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
3787 sta3Dev->SetStandard(WIFI_STANDARD_80211ax);
3788 sta3Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
3789 m_phySta3 = CreateObject<OfdmaSpectrumWifiPhy>(3);
3790 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
3791 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
3792 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
3793 m_phySta3->SetErrorRateModel(sta3ErrorModel);
3794 m_phySta3->SetDevice(sta3Dev);
3795 m_phySta3->AddChannel(spectrumChannel);
3797 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
3798 Ptr<ConstantPositionMobilityModel> sta3Mobility = CreateObject<ConstantPositionMobilityModel>();
3799 m_phySta3->SetMobility(sta3Mobility);
3800 sta3Dev->SetPhy(m_phySta3);
3801 sta3Node->AggregateObject(sta3Mobility);
3802 sta3Node->AddDevice(sta3Dev);
3803
3804 Ptr<Node> interfererNode = CreateObject<Node>();
3805 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
3806 m_phyInterferer = CreateObject<WaveformGenerator>();
3807 m_phyInterferer->SetDevice(interfererDev);
3808 m_phyInterferer->SetChannel(spectrumChannel);
3810 interfererNode->AddDevice(interfererDev);
3811
3812 // Configure power attributes of all wifi devices
3813 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
3814 for (auto& phy : phys)
3815 {
3816 phy->SetAttribute("TxGain", DoubleValue(1.0));
3817 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
3818 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
3819 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
3820 phy->SetAttribute("RxGain", DoubleValue(2.0));
3821 // test assumes no rejection power for simplicity
3822 phy->SetAttribute("TxMaskInnerBandMinimumRejection", DoubleValue(-100.0));
3823 phy->SetAttribute("TxMaskOuterBandMinimumRejection", DoubleValue(-100.0));
3824 phy->SetAttribute("TxMaskOuterBandMaximumRejection", DoubleValue(-100.0));
3825 }
3826}
3827
3828void
3830{
3831 m_phyAp->Dispose();
3832 m_phyAp = nullptr;
3833 m_phySta1->Dispose();
3834 m_phySta1 = nullptr;
3835 m_phySta2->Dispose();
3836 m_phySta2 = nullptr;
3837 m_phySta3->Dispose();
3838 m_phySta3 = nullptr;
3840 m_phyInterferer = nullptr;
3841}
3842
3843void
3845{
3846 NS_LOG_INFO(log);
3847}
3848
3849void
3851 bool solicited,
3852 WifiPhyState expectedStateAtEnd,
3853 uint32_t expectedSuccessFromSta1,
3854 uint32_t expectedFailuresFromSta1,
3855 uint32_t expectedBytesFromSta1,
3856 uint32_t expectedSuccessFromSta2,
3857 uint32_t expectedFailuresFromSta2,
3858 uint32_t expectedBytesFromSta2,
3859 bool scheduleTxSta1,
3860 Time ulTimeDifference,
3861 WifiPhyState expectedStateBeforeEnd,
3862 TrigVectorInfo error)
3863{
3864 static uint64_t uid = 0;
3865
3866 // AP sends an SU packet preceding HE TB PPDUs
3869 this,
3870 0,
3871 50,
3872 ++uid,
3873 0);
3874 if (!solicited)
3875 {
3876 // UID of TB PPDUs will be different than the one of the preceding frame
3877 ++uid;
3878 }
3879 else
3880 {
3882 }
3883 // STA1 and STA2 send MU UL PPDUs addressed to AP
3886 m_apPhyStateListener.get());
3887 if (scheduleTxSta1)
3888 {
3889 Simulator::Schedule(delay,
3891 this,
3892 1,
3893 1,
3894 1000,
3895 uid,
3896 0,
3897 false);
3898 }
3899 Simulator::Schedule(delay + ulTimeDifference,
3901 this,
3902 2,
3903 2,
3904 1001,
3905 uid,
3906 0,
3907 false);
3908
3909 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
3912 this,
3913 m_phyAp,
3914 expectedStateBeforeEnd);
3915 Simulator::Schedule(delay + m_expectedPpduDuration + ulTimeDifference,
3917 this,
3918 m_phyAp,
3919 expectedStateAtEnd);
3920 // TODO: add checks on TX stop for STAs
3921
3922 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
3923 expectedFailuresFromSta2 >
3924 0)
3925 {
3926 // RxEndOk if at least one HE TB PPDU has been successfully received, RxEndError otherwise
3927 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
3928 // The expected time at which the reception is started corresponds to the time at which the
3929 // test is started, plus the time to transmit the PHY preamble and the PHY headers.
3930 const Time expectedPayloadStart = delay + MicroSeconds(48);
3931 // The expected time at which the reception is terminated corresponds to the time at which
3932 // the test is started, plus the time to transmit the PPDU, plus the delay between the first
3933 // received HE TB PPDU and the last received HE TB PPDU.
3934 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
3935 // At the end of the transmission, verify that a single RX start notification shall have
3936 // been notified when the reception of the first HE RB PPDU starts.
3937 Simulator::Schedule(expectedPayloadEnd,
3939 this,
3940 1,
3941 Simulator::Now() + expectedPayloadStart);
3942 // After the reception (hence we add 1ns to expectedPayloadEnd), a single RX end
3943 // notification shall have been notified when the reception of the last HE RB PPDU ends
3944 Simulator::Schedule(expectedPayloadEnd + NanoSeconds(1),
3946 this,
3947 1,
3948 Simulator::Now() + expectedPayloadEnd,
3949 isSuccess);
3950 }
3951
3952 delay += MilliSeconds(100);
3953 // Check reception state from STA 1
3954 Simulator::Schedule(delay,
3956 this,
3957 expectedSuccessFromSta1,
3958 expectedFailuresFromSta1,
3959 expectedBytesFromSta1);
3960 // Check reception state from STA 2
3961 Simulator::Schedule(delay,
3963 this,
3964 expectedSuccessFromSta2,
3965 expectedFailuresFromSta2,
3966 expectedBytesFromSta2);
3967 // Verify events data have been cleared
3969
3970 delay += MilliSeconds(100);
3972}
3973
3974void
3976 double rxPowerNonOfdmaRu1,
3977 double rxPowerNonOfdmaRu2,
3978 double rxPowerOfdmaRu1,
3979 double rxPowerOfdmaRu2)
3980{
3981 Time detectionDuration = WifiPhy::GetPreambleDetectionDuration();
3982 WifiTxVector txVectorSta1 = GetTxVectorForHeTbPpdu(1, 1, 0);
3983 WifiTxVector txVectorSta2 = GetTxVectorForHeTbPpdu(2, 2, 0);
3985 Time nonOfdmaDuration = hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta2);
3986 NS_ASSERT(nonOfdmaDuration == hePhy->CalculateNonOfdmaDurationForHeTb(txVectorSta1));
3987
3988 std::vector<double> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
3989 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{hePhy->GetNonOfdmaBand(txVectorSta1, 1),
3990 hePhy->GetNonOfdmaBand(txVectorSta2, 2)};
3991 std::vector<double> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
3992 std::vector<WifiSpectrumBandInfo> ofdmaBand{hePhy->GetRuBandForRx(txVectorSta1, 1),
3993 hePhy->GetRuBandForRx(txVectorSta2, 2)};
3994
3995 for (uint8_t i = 0; i < 2; ++i)
3996 {
4000 // Check received power on non-OFDMA portion
4002 delay + detectionDuration +
4003 NanoSeconds(1), // just after beginning of portion (once event is stored)
4005 this,
4006 m_phyAp,
4007 nonOfdmaBand[i],
4008 rxPowerNonOfdma[i]);
4009 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4011 this,
4012 m_phyAp,
4013 nonOfdmaBand[i],
4014 rxPowerNonOfdma[i]);
4015 // Check received power on OFDMA portion
4016 Simulator::Schedule(delay + nonOfdmaDuration +
4017 NanoSeconds(1), // just after beginning of portion
4019 this,
4020 m_phyAp,
4021 ofdmaBand[i],
4022 rxPowerOfdma[i]);
4024 NanoSeconds(1), // just before end of portion
4026 this,
4027 m_phyAp,
4028 ofdmaBand[i],
4029 rxPowerOfdma[i]);
4030
4036 // Check received power on non-OFDMA portion
4038 delay + detectionDuration +
4039 NanoSeconds(1), // just after beginning of portion (once event is stored)
4041 this,
4042 m_phySta3,
4043 nonOfdmaBand[i],
4044 rxPowerNonOfdma[i]);
4045 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4047 this,
4048 m_phySta3,
4049 nonOfdmaBand[i],
4050 rxPowerNonOfdma[i]);
4051 // Check received power on OFDMA portion
4052 Simulator::Schedule(delay + nonOfdmaDuration +
4053 NanoSeconds(1), // just after beginning of portion
4055 this,
4056 m_phySta3,
4057 ofdmaBand[i],
4058 rxPowerOfdma[i]);
4060 NanoSeconds(1), // just before end of portion
4062 this,
4063 m_phySta3,
4064 ofdmaBand[i],
4065 rxPowerOfdma[i]);
4066 }
4067
4068 if (rxPowerOfdmaRu1 != 0.0)
4069 {
4075 double rxPowerNonOfdmaSta1Only =
4076 (m_channelWidth >= 40)
4077 ? rxPowerNonOfdma[0]
4078 : rxPowerNonOfdma[0] / 2; // both STAs transmit over the same 20 MHz channel
4079 // Check received power on non-OFDMA portion
4081 delay + detectionDuration +
4082 NanoSeconds(1), // just after beginning of portion (once event is stored)
4084 this,
4085 m_phySta2,
4086 nonOfdmaBand[0],
4087 rxPowerNonOfdmaSta1Only);
4088 Simulator::Schedule(delay + nonOfdmaDuration - NanoSeconds(1), // just before end of portion
4090 this,
4091 m_phySta2,
4092 nonOfdmaBand[0],
4093 rxPowerNonOfdmaSta1Only);
4094 // Check received power on OFDMA portion
4095 Simulator::Schedule(delay + nonOfdmaDuration +
4096 NanoSeconds(1), // just after beginning of portion
4098 this,
4099 m_phySta2,
4100 ofdmaBand[0],
4101 rxPowerOfdma[0]);
4103 NanoSeconds(1), // just before end of portion
4105 this,
4106 m_phySta2,
4107 ofdmaBand[0],
4108 rxPowerOfdma[0]);
4109 }
4110}
4111
4112void
4114{
4117 int64_t streamNumber = 0;
4118 m_phyAp->AssignStreams(streamNumber);
4119 m_phySta1->AssignStreams(streamNumber);
4120 m_phySta2->AssignStreams(streamNumber);
4121 m_phySta3->AssignStreams(streamNumber);
4122
4123 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
4128
4137
4138 Time delay = Seconds(0.0);
4140 delay += Seconds(1.0);
4141
4150 //---------------------------------------------------------------------------
4151 // Verify that both solicited HE TB PPDUs have been corrected received
4152 Simulator::Schedule(delay,
4154 this,
4155 "Reception of solicited HE TB PPDUs");
4156 ScheduleTest(delay,
4157 true,
4158 WifiPhyState::IDLE,
4159 1,
4160 0,
4161 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4162 1,
4163 0,
4164 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4165 delay += Seconds(1.0);
4166
4167 //---------------------------------------------------------------------------
4168 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4169 // corrected received
4171 delay,
4173 this,
4174 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4175 ScheduleTest(delay,
4176 true,
4177 WifiPhyState::IDLE,
4178 1,
4179 0,
4180 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4181 1,
4182 0,
4183 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4184 true,
4185 NanoSeconds(100));
4186 delay += Seconds(1.0);
4187
4188 //---------------------------------------------------------------------------
4189 // Verify that no unsolicited HE TB PPDU is received
4190 Simulator::Schedule(delay,
4192 this,
4193 "Dropping of unsolicited HE TB PPDUs");
4194 ScheduleTest(delay,
4195 false,
4196 WifiPhyState::IDLE,
4197 0,
4198 0,
4199 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4200 0,
4201 0,
4202 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4203 true,
4204 Seconds(0),
4205 WifiPhyState::CCA_BUSY);
4206 delay += Seconds(1.0);
4207
4208 //---------------------------------------------------------------------------
4209 // Verify that HE TB PPDUs with channel width differing from TRIGVECTOR are discarded
4210 Simulator::Schedule(delay,
4212 this,
4213 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4214 ScheduleTest(delay,
4215 true,
4216 WifiPhyState::IDLE,
4217 0,
4218 0,
4219 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4220 0,
4221 0,
4222 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4223 true,
4224 Seconds(0),
4225 WifiPhyState::CCA_BUSY,
4227 delay += Seconds(1.0);
4228
4229 //---------------------------------------------------------------------------
4230 // Verify that HE TB PPDUs with UL Length differing from TRIGVECTOR are discarded
4231 Simulator::Schedule(delay,
4233 this,
4234 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4235 ScheduleTest(delay,
4236 true,
4237 WifiPhyState::IDLE,
4238 0,
4239 0,
4240 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4241 0,
4242 0,
4243 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4244 true,
4245 Seconds(0),
4246 WifiPhyState::CCA_BUSY,
4247 UL_LENGTH);
4248 delay += Seconds(1.0);
4249
4250 //---------------------------------------------------------------------------
4251 // Verify that HE TB PPDUs with AIDs differing from TRIGVECTOR are discarded
4252 Simulator::Schedule(delay,
4254 this,
4255 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4256 ScheduleTest(delay,
4257 true,
4258 WifiPhyState::IDLE,
4259 0,
4260 0,
4261 0, // PSDU from STA 1 is not received (no TRIGVECTOR)
4262 0,
4263 0,
4264 0, // PSDU from STA 2 is not received (no TRIGVECTOR)
4265 true,
4266 Seconds(0),
4267 WifiPhyState::CCA_BUSY,
4268 AID);
4269 delay += Seconds(1.0);
4270
4271 //---------------------------------------------------------------------------
4272 // Generate an interference on RU 1 and verify that only STA 1's solicited HE TB PPDU has been
4273 // impacted
4275 delay,
4277 this,
4278 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4279 // A strong non-wifi interference is generated on RU 1 during PSDU reception
4280 BandInfo bandInfo;
4281 bandInfo.fc = (m_frequency - (m_channelWidth / 4)) * 1e6;
4282 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4283 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4284 Bands bands;
4285 bands.push_back(bandInfo);
4286
4287 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
4288 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
4289 double interferencePower = 0.1; // watts
4290 *interferencePsdRu1 = interferencePower / ((m_channelWidth / 2) * 20e6);
4291
4294 this,
4295 interferencePsdRu1,
4296 MilliSeconds(100));
4298 delay,
4299 true,
4300 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4301 // interference
4302 0,
4303 1,
4304 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4305 1,
4306 0,
4307 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4308 delay += Seconds(1.0);
4309
4310 //---------------------------------------------------------------------------
4311 // Generate an interference on RU 2 and verify that only STA 2's solicited HE TB PPDU has been
4312 // impacted
4314 delay,
4316 this,
4317 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4318 // A strong non-wifi interference is generated on RU 2 during PSDU reception
4319 bandInfo.fc = (m_frequency + (m_channelWidth / 4)) * 1e6;
4320 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 4) * 1e6);
4321 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 4) * 1e6);
4322 bands.clear();
4323 bands.push_back(bandInfo);
4324
4325 Ptr<SpectrumModel> SpectrumInterferenceRu2 = Create<SpectrumModel>(bands);
4326 Ptr<SpectrumValue> interferencePsdRu2 = Create<SpectrumValue>(SpectrumInterferenceRu2);
4327 *interferencePsdRu2 = interferencePower / ((m_channelWidth / 2) * 20e6);
4328
4331 this,
4332 interferencePsdRu2,
4333 MilliSeconds(100));
4334 ScheduleTest(delay,
4335 true,
4336 (m_channelWidth >= 40)
4337 ? WifiPhyState::IDLE
4338 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY if interference is
4339 // generated in its primary channel
4340 1,
4341 0,
4342 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4343 0,
4344 1,
4345 0); // Reception of the PSDU from STA 2 should have failed (since interference
4346 // occupies RU 2)
4347 delay += Seconds(1.0);
4348
4349 //---------------------------------------------------------------------------
4350 // Generate an interference on the full band and verify that both solicited HE TB PPDUs have
4351 // been impacted
4352 Simulator::Schedule(delay,
4354 this,
4355 "Reception of solicited HE TB PPDUs with interference on the full band "
4356 "during PSDU reception");
4357 // A strong non-wifi interference is generated on the full band during PSDU reception
4358 bandInfo.fc = m_frequency * 1e6;
4359 bandInfo.fl = bandInfo.fc - ((m_channelWidth / 2) * 1e6);
4360 bandInfo.fh = bandInfo.fc + ((m_channelWidth / 2) * 1e6);
4361 bands.clear();
4362 bands.push_back(bandInfo);
4363
4364 Ptr<SpectrumModel> SpectrumInterferenceAll = Create<SpectrumModel>(bands);
4365 Ptr<SpectrumValue> interferencePsdAll = Create<SpectrumValue>(SpectrumInterferenceAll);
4366 *interferencePsdAll = interferencePower / (m_channelWidth * 20e6);
4367
4370 this,
4371 interferencePsdAll,
4372 MilliSeconds(100));
4374 delay,
4375 true,
4376 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4377 // interference
4378 0,
4379 1,
4380 0, // Reception of the PSDU from STA 1 should have failed (since interference occupies RU 1)
4381 0,
4382 1,
4383 0); // Reception of the PSDU from STA 2 should have failed (since interference occupies RU
4384 // 2)
4385 delay += Seconds(1.0);
4386
4387 //---------------------------------------------------------------------------
4388 // Send another HE TB PPDU (of another UL MU transmission) on RU 1 and verify that both
4389 // solicited HE TB PPDUs have been impacted if they are on the same
4390 // 20 MHz channel. Only STA 1's solicited HE TB PPDU is impacted otherwise.
4391 Simulator::Schedule(delay,
4393 this,
4394 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4395 "1 during PSDU reception");
4396 // Another HE TB PPDU arrives at AP on the same RU as STA 1 during PSDU reception
4399 this,
4400 3,
4401 1,
4402 1002,
4403 1,
4404 0,
4405 false);
4406 // Expected figures from STA 2
4407 uint32_t succ;
4408 uint32_t fail;
4409 uint32_t bytes;
4410 if (m_channelWidth > 20)
4411 {
4412 // One PSDU of 1001 bytes should have been successfully received from STA 2 (since
4413 // interference from STA 3 on distinct 20 MHz channel)
4414 succ = 1;
4415 fail = 0;
4416 bytes = 1001;
4417 }
4418 else
4419 {
4420 // Reception of the PSDU from STA 2 should have failed (since interference from STA 3 on
4421 // same 20 MHz channel)
4422 succ = 0;
4423 fail = 1;
4424 bytes = 0;
4425 }
4426 ScheduleTest(delay,
4427 true,
4428 WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE due to the
4429 // interference on measurement channel width
4430 0,
4431 1,
4432 0, // Reception of the PSDU from STA 1 should have failed (since interference from
4433 // STA 3 on same 20 MHz channel)
4434 succ,
4435 fail,
4436 bytes);
4437 delay += Seconds(1.0);
4438
4439 //---------------------------------------------------------------------------
4440 // Send another HE TB PPDU (of another UL MU transmission) on RU 2 and verify that both
4441 // solicited HE TB PPDUs have been impacted if they are on the same
4442 // 20 MHz channel. Only STA 2's solicited HE TB PPDU is impacted otherwise.
4443 Simulator::Schedule(delay,
4445 this,
4446 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4447 "2 during PSDU reception");
4448 // Another HE TB PPDU arrives at AP on the same RU as STA 2 during PSDU reception
4451 this,
4452 3,
4453 2,
4454 1002,
4455 1,
4456 0,
4457 false);
4458 // Expected figures from STA 1
4459 if (m_channelWidth > 20)
4460 {
4461 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since
4462 // interference from STA 3 on distinct 20 MHz channel)
4463 succ = 1;
4464 fail = 0;
4465 bytes = 1000;
4466 }
4467 else
4468 {
4469 // Reception of the PSDU from STA 1 should have failed (since interference from STA 3 on
4470 // same 20 MHz channel)
4471 succ = 0;
4472 fail = 1;
4473 bytes = 0;
4474 }
4475 ScheduleTest(delay,
4476 true,
4477 (m_channelWidth >= 40)
4478 ? WifiPhyState::IDLE
4479 : WifiPhyState::CCA_BUSY, // PHY should move to CCA_BUSY instead of IDLE if HE
4480 // TB PPDU on primary channel
4481 succ,
4482 fail,
4483 bytes,
4484 0,
4485 1,
4486 0); // Reception of the PSDU from STA 2 should have failed (since interference from
4487 // STA 3 on same 20 MHz channel)
4488 delay += Seconds(1.0);
4489
4490 //---------------------------------------------------------------------------
4491 // Send an HE SU PPDU during 400 ns window and verify that both solicited HE TB PPDUs have been
4492 // impacted
4494 delay,
4496 this,
4497 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4498 // One HE SU arrives at AP during the 400ns window
4499 Simulator::Schedule(delay + NanoSeconds(300),
4501 this,
4502 3,
4503 1002,
4504 1,
4505 0);
4507 delay,
4508 true,
4509 WifiPhyState::IDLE,
4510 0,
4511 1,
4512 0, // Reception of the PSDU from STA 1 should have failed (since interference from STA 3)
4513 0,
4514 1,
4515 0); // Reception of the PSDU from STA 2 should have failed (since interference from STA 3)
4516 delay += Seconds(1.0);
4517
4518 //---------------------------------------------------------------------------
4519 // Only send a solicited HE TB PPDU from STA 2 on RU 2 and verify that it has been correctly
4520 // received
4521 Simulator::Schedule(delay,
4523 this,
4524 "Reception of solicited HE TB PPDU only on RU 2");
4525 // Check that STA3 will correctly set its state to CCA_BUSY if in measurement channel or IDLE
4526 // otherwise
4529 this,
4530 m_phySta3,
4531 (m_channelWidth >= 40)
4532 ? WifiPhyState::IDLE
4533 : WifiPhyState::CCA_BUSY); // PHY should move to CCA_BUSY instead of
4534 // IDLE if HE TB PPDU on primary channel
4535 ScheduleTest(delay,
4536 true,
4537 WifiPhyState::IDLE,
4538 0,
4539 0,
4540 0, // No transmission scheduled for STA 1
4541 1,
4542 0,
4543 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4544 false,
4545 Seconds(0),
4546 WifiPhyState::RX); // Measurement channel is total channel width
4547 delay += Seconds(1.0);
4548
4549 //---------------------------------------------------------------------------
4550 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2
4551 Simulator::Schedule(delay,
4553 this,
4554 "Measure power for reception of HE TB PPDU only on RU 2");
4555 double rxPower =
4556 DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4558 (m_channelWidth >= 40) ? 0.0 : rxPower,
4559 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4560 0.0,
4561 rxPower);
4562 ScheduleTest(delay,
4563 true,
4564 WifiPhyState::IDLE,
4565 0,
4566 0,
4567 0, // No transmission scheduled for STA 1
4568 1,
4569 0,
4570 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4571 false,
4572 Seconds(0),
4573 WifiPhyState::RX); // Measurement channel is total channel width
4574 delay += Seconds(1.0);
4575
4576 //---------------------------------------------------------------------------
4577 // Measure the power of a solicited HE TB PPDU from STA 2 on RU 2 with power spectrum density
4578 // limitation enforced
4580 delay,
4582 this,
4583 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4584 // Configure PSD limitation at 3 dBm/MHz -> 3+13.0103=16.0103 dBm max for 20 MHz,
4585 // 3+9.0309=12.0309 dBm max for 106-tone RU, no impact for 40 MHz and above
4586 Simulator::Schedule(delay - NanoSeconds(1), // just before sending HE TB
4588 this,
4589 m_phySta2,
4590 3.0);
4591
4592 rxPower = (m_channelWidth > 40)
4593 ? DbmToW(19)
4594 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP for non-OFDMA
4595 // transmitted only on one 20 MHz channel
4596 double rxPowerOfdma = rxPower;
4597 if (m_channelWidth <= 40)
4598 {
4599 rxPowerOfdma = (m_channelWidth == 20)
4600 ? DbmToW(14.0309) // 11.0309+1 dBm at STA and +2 at AP if 106-tone RU
4601 : DbmToW(18.0103); // 15.0103+1 dBm at STA 2 and +2 at AP if 242-tone RU
4602 }
4604 (m_channelWidth >= 40) ? 0.0 : rxPower,
4605 rxPower, // power detected on RU1 only if same 20 MHz as RU 2
4606 0.0,
4607 rxPowerOfdma);
4608
4609 // Reset PSD limitation once HE TB has been sent
4612 this,
4613 m_phySta2,
4614 100.0);
4615 ScheduleTest(delay,
4616 true,
4617 WifiPhyState::IDLE,
4618 0,
4619 0,
4620 0, // No transmission scheduled for STA 1
4621 1,
4622 0,
4623 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4624 false,
4625 Seconds(0),
4626 WifiPhyState::RX); // Measurement channel is total channel width
4627 delay += Seconds(1.0);
4628
4629 //---------------------------------------------------------------------------
4630 // Measure the power of 2 solicited HE TB PPDU from both STAs
4631 Simulator::Schedule(delay,
4633 this,
4634 "Measure power for reception of HE TB PPDU on both RUs");
4635 rxPower = DbmToW(19); // 16+1 dBm at STAs and +2 at AP (no loss since all devices are colocated)
4636 double rxPowerNonOfdma = (m_channelWidth >= 40)
4637 ? rxPower
4638 : rxPower * 2; // both STAs transmit over the same 20 MHz channel
4639 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
4640 ScheduleTest(delay,
4641 true,
4642 WifiPhyState::IDLE,
4643 1,
4644 0,
4645 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4646 1,
4647 0,
4648 1001); // One PSDU of 1001 bytes should have been successfully received from STA 2
4649 delay += Seconds(1.0);
4650
4651 //---------------------------------------------------------------------------
4652 // Verify that an HE TB PPDU from another BSS has been correctly received (no UL MU transmission
4653 // ongoing)
4654 Simulator::Schedule(delay,
4656 this,
4657 "Reception of an HE TB PPDU from another BSS");
4658 // One HE TB from another BSS (BSS color 2) arrives at AP (BSS color 1)
4660 Simulator::Schedule(delay + MilliSeconds(100),
4662 this,
4663 3,
4664 1,
4665 1002,
4666 1,
4667 2,
4668 false);
4669
4670 // Verify events data have been cleared
4671 Simulator::Schedule(delay + MilliSeconds(200),
4673 this);
4674
4676 delay += Seconds(1.0);
4677
4678 //---------------------------------------------------------------------------
4679 // Verify that two solicited HE TB PPDUs with delay (< 400ns) between the two signals have been
4680 // corrected received
4682 delay,
4684 this,
4685 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
4686 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
4690 this,
4691 3,
4692 1,
4693 1002,
4694 1,
4695 2,
4696 true);
4697 ScheduleTest(delay,
4698 true,
4699 WifiPhyState::CCA_BUSY,
4700 1,
4701 0,
4702 1000, // One PSDU of 1000 bytes should have been successfully received from STA 1
4703 1,
4704 0,
4705 1001, // One PSDU of 1001 bytes should have been successfully received from STA 2
4706 true,
4707 NanoSeconds(200));
4708 delay += Seconds(1.0);
4709
4711}
4712
4713void
4715{
4716 m_frequency = 5180;
4717 m_channelWidth = 20;
4719 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4720 RunOne();
4721
4722 m_frequency = 5190;
4723 m_channelWidth = 40;
4725 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4726 RunOne();
4727
4728 m_frequency = 5210;
4729 m_channelWidth = 80;
4731 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4732 RunOne();
4733
4734 m_frequency = 5250;
4735 m_channelWidth = 160;
4737 NS_LOG_DEBUG("Run UL OFDMA PHY transmission test for " << m_channelWidth << " MHz");
4738 RunOne();
4739
4741}
4742
4750{
4751 public:
4753 ~TestPhyPaddingExclusion() override;
4754
4755 private:
4756 void DoSetup() override;
4757 void DoTeardown() override;
4758 void DoRun() override;
4759
4767 void SendHeTbPpdu(uint16_t txStaId,
4768 std::size_t index,
4769 std::size_t payloadSize,
4770 Time txDuration);
4776 void SetTrigVector(Time ppduDuration);
4777
4783 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
4787 void StopInterference();
4788
4792 void RunOne();
4793
4800 void CheckRxFromSta1(uint32_t expectedSuccess,
4801 uint32_t expectedFailures,
4802 uint32_t expectedBytes);
4803
4810 void CheckRxFromSta2(uint32_t expectedSuccess,
4811 uint32_t expectedFailures,
4812 uint32_t expectedBytes);
4813
4817 void VerifyEventsCleared();
4818
4824 void CheckPhyState(Ptr<OfdmaSpectrumWifiPhy> phy, WifiPhyState expectedState);
4827
4831 void Reset();
4832
4841 RxSignalInfo rxSignalInfo,
4842 WifiTxVector txVector,
4843 std::vector<bool> statusPerMpdu);
4844
4849 void RxFailure(Ptr<const WifiPsdu> psdu);
4850
4854
4856
4863};
4864
4866 : TestCase("PHY padding exclusion test"),
4867 m_countRxSuccessFromSta1(0),
4868 m_countRxSuccessFromSta2(0),
4869 m_countRxFailureFromSta1(0),
4870 m_countRxFailureFromSta2(0),
4871 m_countRxBytesFromSta1(0),
4872 m_countRxBytesFromSta2(0)
4873{
4874}
4875
4876void
4878 std::size_t index,
4879 std::size_t payloadSize,
4880 Time txDuration)
4881{
4882 WifiConstPsduMap psdus;
4883
4885 0,
4887 1600,
4888 1,
4889 1,
4890 0,
4892 false,
4893 false,
4894 1);
4895
4896 HeRu::RuSpec ru(HeRu::RU_106_TONE, index, false);
4897 txVector.SetRu(ru, txStaId);
4898 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
4899 txVector.SetNss(1, txStaId);
4900
4901 Ptr<Packet> pkt = Create<Packet>(payloadSize);
4902 WifiMacHeader hdr;
4904 hdr.SetQosTid(0);
4905 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
4906 std::ostringstream addr;
4907 addr << "00:00:00:00:00:0" << txStaId;
4908 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
4909 hdr.SetSequenceNumber(1);
4910 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
4911 psdus.insert(std::make_pair(txStaId, psdu));
4912
4914 if (txStaId == 1)
4915 {
4916 phy = m_phySta1;
4917 }
4918 else if (txStaId == 2)
4919 {
4920 phy = m_phySta2;
4921 }
4922
4923 txVector.SetLength(
4924 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
4925
4926 phy->SetPpduUid(0);
4927 phy->Send(psdus, txVector);
4928}
4929
4930void
4932{
4934 m_phyInterferer->SetPeriod(duration);
4937}
4938
4939void
4941{
4943}
4944
4946{
4947}
4948
4949void
4951 RxSignalInfo rxSignalInfo,
4952 WifiTxVector txVector,
4953 std::vector<bool> /*statusPerMpdu*/)
4954{
4955 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
4956 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4957 {
4959 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
4960 }
4961 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4962 {
4964 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
4965 }
4966}
4967
4968void
4970{
4971 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
4972 if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:01"))
4973 {
4975 }
4976 else if (psdu->GetAddr2() == Mac48Address("00:00:00:00:00:02"))
4977 {
4979 }
4980}
4981
4982void
4984 uint32_t expectedFailures,
4985 uint32_t expectedBytes)
4986{
4988 expectedSuccess,
4989 "The number of successfully received packets from STA 1 is not correct!");
4992 expectedFailures,
4993 "The number of unsuccessfuly received packets from STA 1 is not correct!");
4995 expectedBytes,
4996 "The number of bytes received from STA 1 is not correct!");
4997}
4998
4999void
5001 uint32_t expectedFailures,
5002 uint32_t expectedBytes)
5003{
5005 expectedSuccess,
5006 "The number of successfully received packets from STA 2 is not correct!");
5009 expectedFailures,
5010 "The number of unsuccessfuly received packets from STA 2 is not correct!");
5012 expectedBytes,
5013 "The number of bytes received from STA 2 is not correct!");
5014}
5015
5016void
5018{
5020 nullptr,
5021 "m_currentEvent for AP was not cleared");
5023 nullptr,
5024 "m_currentEvent for STA 1 was not cleared");
5026 nullptr,
5027 "m_currentEvent for STA 2 was not cleared");
5028}
5029
5030void
5032{
5033 // This is needed to make sure PHY state will be checked as the last event if a state change
5034 // occurred at the exact same time as the check
5036}
5037
5038void
5040{
5041 WifiPhyState currentState = phy->GetState()->GetState();
5042 NS_LOG_FUNCTION(this << currentState);
5043 NS_TEST_ASSERT_MSG_EQ(currentState,
5044 expectedState,
5045 "PHY State " << currentState << " does not match expected state "
5046 << expectedState << " at " << Simulator::Now());
5047}
5048
5049void
5051{
5061}
5062
5063void
5065{
5068 int64_t streamNumber = 0;
5069
5070 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5071 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
5072 lossModel->SetFrequency(DEFAULT_FREQUENCY * 1e6);
5073 spectrumChannel->AddPropagationLossModel(lossModel);
5075 CreateObject<ConstantSpeedPropagationDelayModel>();
5076 spectrumChannel->SetPropagationDelayModel(delayModel);
5077
5078 Ptr<Node> apNode = CreateObject<Node>();
5079 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
5080 Ptr<ApWifiMac> apMac = CreateObject<ApWifiMac>();
5081 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5082 apDev->SetMac(apMac);
5083 m_phyAp = CreateObject<OfdmaSpectrumWifiPhy>(0);
5084 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
5085 apDev->SetHeConfiguration(heConfiguration);
5086 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
5087 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5088 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
5089 m_phyAp->SetErrorRateModel(apErrorModel);
5090 m_phyAp->SetDevice(apDev);
5091 m_phyAp->AddChannel(spectrumChannel);
5093 m_phyAp->AssignStreams(streamNumber);
5094 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
5099
5104 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
5105 m_phyAp->SetMobility(apMobility);
5106 apDev->SetPhy(m_phyAp);
5107 apDev->SetStandard(WIFI_STANDARD_80211ax);
5108 apDev->SetHeConfiguration(CreateObject<HeConfiguration>());
5109 apMac->SetWifiPhys({m_phyAp});
5110 apNode->AggregateObject(apMobility);
5111 apNode->AddDevice(apDev);
5112
5113 Ptr<Node> sta1Node = CreateObject<Node>();
5114 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
5115 m_phySta1 = CreateObject<OfdmaSpectrumWifiPhy>(1);
5116 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
5117 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5118 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
5119 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5120 m_phySta1->SetDevice(sta1Dev);
5121 m_phySta1->AddChannel(spectrumChannel);
5123 m_phySta1->AssignStreams(streamNumber);
5126 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
5127 m_phySta1->SetMobility(sta1Mobility);
5128 sta1Dev->SetPhy(m_phySta1);
5129 sta1Dev->SetStandard(WIFI_STANDARD_80211ax);
5130 sta1Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5131 sta1Node->AggregateObject(sta1Mobility);
5132 sta1Node->AddDevice(sta1Dev);
5133
5134 Ptr<Node> sta2Node = CreateObject<Node>();
5135 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
5136 m_phySta2 = CreateObject<OfdmaSpectrumWifiPhy>(2);
5137 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
5138 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5139 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
5140 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5141 m_phySta2->SetDevice(sta2Dev);
5142 m_phySta2->AddChannel(spectrumChannel);
5144 m_phySta2->AssignStreams(streamNumber);
5147 Ptr<ConstantPositionMobilityModel> sta2Mobility = CreateObject<ConstantPositionMobilityModel>();
5148 m_phySta2->SetMobility(sta2Mobility);
5149 sta2Dev->SetPhy(m_phySta2);
5150 sta2Dev->SetStandard(WIFI_STANDARD_80211ax);
5151 sta2Dev->SetHeConfiguration(CreateObject<HeConfiguration>());
5152 sta2Node->AggregateObject(sta2Mobility);
5153 sta2Node->AddDevice(sta2Dev);
5154
5155 Ptr<Node> interfererNode = CreateObject<Node>();
5156 Ptr<NonCommunicatingNetDevice> interfererDev = CreateObject<NonCommunicatingNetDevice>();
5157 m_phyInterferer = CreateObject<WaveformGenerator>();
5158 m_phyInterferer->SetDevice(interfererDev);
5159 m_phyInterferer->SetChannel(spectrumChannel);
5161 interfererNode->AddDevice(interfererDev);
5162}
5163
5164void
5166{
5167 m_phyAp->Dispose();
5168 m_phyAp = nullptr;
5169 m_phySta1->Dispose();
5170 m_phySta1 = nullptr;
5171 m_phySta2->Dispose();
5172 m_phySta2 = nullptr;
5174 m_phyInterferer = nullptr;
5175}
5176
5177void
5179{
5180 WifiTxVector trigVector(HePhy::GetHeMcs7(),
5181 0,
5183 1600,
5184 1,
5185 1,
5186 0,
5188 false,
5189 false,
5190 1);
5191 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 1, false), 1);
5192 trigVector.SetMode(HePhy::GetHeMcs7(), 1);
5193 trigVector.SetNss(1, 1);
5194 trigVector.SetRu(HeRu::RuSpec(HeRu::RU_106_TONE, 2, false), 2);
5195 trigVector.SetMode(HePhy::GetHeMcs7(), 2);
5196 trigVector.SetNss(1, 2);
5197 uint16_t length;
5198 std::tie(length, ppduDuration) =
5200 trigVector.SetLength(length);
5201 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetLatestPhyEntity());
5202 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5203}
5204
5205void
5207{
5208 Time expectedPpduDuration = NanoSeconds(292800);
5209 Time ppduWithPaddingDuration =
5210 expectedPpduDuration + 10 * NanoSeconds(12800 + 1600 /* GI */); // add 10 extra OFDM symbols
5211
5213
5214 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5217 this,
5218 1,
5219 1,
5220 1000,
5221 ppduWithPaddingDuration);
5224 this,
5225 2,
5226 2,
5227 1001,
5228 ppduWithPaddingDuration);
5229
5230 // Set TRIGVECTOR on AP
5233 this,
5234 ppduWithPaddingDuration);
5235
5236 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs
5237 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration - NanoSeconds(1),
5239 this,
5240 m_phyAp,
5241 WifiPhyState::RX);
5242 Simulator::Schedule(Seconds(1.0) + ppduWithPaddingDuration,
5244 this,
5245 m_phyAp,
5246 WifiPhyState::IDLE);
5247
5248 // One PSDU of 1000 bytes should have been successfully received from STA 1
5250 // One PSDU of 1001 bytes should have been successfully received from STA 2
5252 // Verify events data have been cleared
5254
5256
5257 // STA1 and STA2 send MU UL PPDUs addressed to AP:
5260 this,
5261 1,
5262 1,
5263 1000,
5264 ppduWithPaddingDuration);
5267 this,
5268 2,
5269 2,
5270 1001,
5271 ppduWithPaddingDuration);
5272
5273 // Set TRIGVECTOR on AP
5276 this,
5277 ppduWithPaddingDuration);
5278
5279 // A strong non-wifi interference is generated on RU 1 during padding reception
5280 BandInfo bandInfo;
5281 bandInfo.fc = (DEFAULT_FREQUENCY - (DEFAULT_CHANNEL_WIDTH / 4)) * 1e6;
5282 bandInfo.fl = bandInfo.fc - ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5283 bandInfo.fh = bandInfo.fc + ((DEFAULT_CHANNEL_WIDTH / 4) * 1e6);
5284 Bands bands;
5285 bands.push_back(bandInfo);
5286
5287 Ptr<SpectrumModel> SpectrumInterferenceRu1 = Create<SpectrumModel>(bands);
5288 Ptr<SpectrumValue> interferencePsdRu1 = Create<SpectrumValue>(SpectrumInterferenceRu1);
5289 double interferencePower = 0.1; // watts
5290 *interferencePsdRu1 = interferencePower / ((DEFAULT_CHANNEL_WIDTH / 2) * 20e6);
5291
5292 Simulator::Schedule(Seconds(2.0) + MicroSeconds(50) + expectedPpduDuration,
5294 this,
5295 interferencePsdRu1,
5296 MilliSeconds(100));
5297
5298 // Verify it takes expectedPpduDuration + padding to transmit the PPDUs (PHY should move to
5299 // CCA_BUSY instead of IDLE due to the interference)
5300 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration - NanoSeconds(1),
5302 this,
5303 m_phyAp,
5304 WifiPhyState::RX);
5305 Simulator::Schedule(Seconds(2.0) + ppduWithPaddingDuration,
5307 this,
5308 m_phyAp,
5309 WifiPhyState::CCA_BUSY);
5310
5311 // One PSDU of 1000 bytes should have been successfully received from STA 1 (since interference
5312 // occupies RU 1 after payload, during PHY padding)
5314 // One PSDU of 1001 bytes should have been successfully received from STA 2
5316 // Verify events data have been cleared
5318
5320
5322
5324}
5325
5333{
5334 public:
5336 ~TestUlOfdmaPowerControl() override;
5337
5338 private:
5339 void DoSetup() override;
5340 void DoTeardown() override;
5341 void DoRun() override;
5342
5348 void SendMuBar(std::vector<uint16_t> staIds);
5349
5356 void SetupBa(Address destination);
5357
5364 void RunOne(bool setupBa);
5365
5371
5382 RxSignalInfo rxSignalInfo,
5383 WifiTxVector txVector,
5384 std::vector<bool> statusPerMpdu);
5385
5386 uint8_t m_bssColor;
5387
5391
5393
5398
5401
5402 double m_rssiSta1;
5403 double m_rssiSta2;
5404
5405 double m_tol;
5406};
5407
5409 : TestCase("UL-OFDMA power control test"),
5410 m_bssColor(1),
5411 m_txPowerAp(0),
5412 m_txPowerStart(0),
5413 m_txPowerEnd(0),
5414 m_txPowerLevels(0),
5415 m_requestedRssiSta1(0),
5416 m_requestedRssiSta2(0),
5417 m_rssiSta1(0),
5418 m_rssiSta2(0),
5419 m_tol(0.1)
5420{
5421}
5422
5424{
5425 m_phyAp = nullptr;
5426 m_apDev = nullptr;
5427 m_sta1Dev = nullptr;
5428 m_sta2Dev = nullptr;
5429}
5430
5431void
5433{
5434 // Only one packet is sufficient to set up BA since AP and STAs are HE capable
5435 Ptr<Packet> pkt = Create<Packet>(100); // 100 dummy bytes of data
5436 m_apDev->Send(pkt, destination, 0);
5437}
5438
5439void
5440TestUlOfdmaPowerControl::SendMuBar(std::vector<uint16_t> staIds)
5441{
5442 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5443
5444 // Build MU-BAR trigger frame
5445 CtrlTriggerHeader muBar;
5446 muBar.SetType(TriggerFrameType::MU_BAR_TRIGGER);
5447 muBar.SetMoreTF(true);
5448 muBar.SetCsRequired(true);
5450 muBar.SetGiAndLtfType(1600, 2);
5451 muBar.SetApTxPower(static_cast<int8_t>(m_txPowerAp));
5452 muBar.SetUlSpatialReuse(60500);
5453
5454 HeRu::RuType ru = (staIds.size() == 1) ? HeRu::RU_242_TONE : HeRu::RU_106_TONE;
5455 std::size_t index = 1;
5456 int8_t ulTargetRssi = -40; // will be overwritten
5457 for (const auto& staId : staIds)
5458 {
5460 ui.SetAid12(staId);
5461 ui.SetRuAllocation({ru, index, true});
5462 ui.SetUlFecCodingType(true);
5463 ui.SetUlMcs(7);
5464 ui.SetUlDcm(false);
5465 ui.SetSsAllocation(1, 1);
5466 if (staId == 1)
5467 {
5468 ulTargetRssi = m_requestedRssiSta1;
5469 }
5470 else if (staId == 2)
5471 {
5472 ulTargetRssi = m_requestedRssiSta2;
5473 }
5474 else
5475 {
5476 NS_ABORT_MSG("Unknown STA-ID (" << staId << ")");
5477 }
5478 ui.SetUlTargetRssi(ulTargetRssi);
5479
5482 bar.SetTidInfo(0);
5483 bar.SetStartingSequence(4095);
5485
5486 ++index;
5487 }
5488
5489 WifiTxVector tbTxVector = muBar.GetHeTbTxVector(staIds.front());
5491 tbTxVector,
5493 .first);
5494
5495 WifiConstPsduMap psdus;
5497 0,
5499 800,
5500 1,
5501 1,
5502 0,
5504 false,
5505 false,
5506 false,
5507 m_bssColor);
5508
5509 Ptr<Packet> bar = Create<Packet>();
5510 bar->AddHeader(muBar);
5511
5513 if (staIds.size() == 1)
5514 {
5515 uint16_t aidSta1 = DynamicCast<StaWifiMac>(m_sta1Dev->GetMac())->GetAssociationId();
5516 if (staIds.front() == aidSta1)
5517 {
5519 }
5520 else
5521 {
5522 NS_ASSERT(staIds.front() ==
5523 DynamicCast<StaWifiMac>(m_sta2Dev->GetMac())->GetAssociationId());
5525 }
5526 }
5527
5528 WifiMacHeader hdr;
5530 hdr.SetAddr1(receiver);
5533 hdr.SetDsNotTo();
5534 hdr.SetDsFrom();
5535 hdr.SetNoRetry();
5536 hdr.SetNoMoreFragments();
5537 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(bar, hdr);
5538
5539 Time nav = m_apDev->GetPhy()->GetSifs();
5540 uint16_t staId = staIds.front(); // either will do
5542 tbTxVector,
5544 staId);
5545 psdu->SetDuration(nav);
5546 psdus.insert(std::make_pair(SU_STA_ID, psdu));
5547
5548 m_phyAp->Send(psdus, txVector);
5549}
5550
5551void
5553 RxSignalInfo rxSignalInfo,
5554 WifiTxVector txVector,
5555 std::vector<bool> /*statusPerMpdu*/)
5556{
5557 NS_TEST_ASSERT_MSG_EQ(txVector.GetPreambleType(), WIFI_PREAMBLE_HE_TB, "HE TB PPDU expected");
5558 double rssi = rxSignalInfo.rssi;
5559 NS_ASSERT(psdu->GetNMpdus() == 1);
5560 WifiMacHeader hdr = psdu->GetHeader(0);
5561 NS_TEST_ASSERT_MSG_EQ(hdr.GetType(), WIFI_MAC_CTL_BACKRESP, "Block ACK expected");
5562 if (hdr.GetAddr2() == m_sta1Dev->GetAddress())
5563 {
5565 rssi,
5566 m_rssiSta1,
5567 m_tol,
5568 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5569 << rssi << " vs " << m_rssiSta1 << ", with tolerance of " << m_tol << ")");
5570 }
5571 else if (psdu->GetAddr2() == m_sta2Dev->GetAddress())
5572 {
5574 rssi,
5575 m_rssiSta2,
5576 m_tol,
5577 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5578 << rssi << " vs " << m_rssiSta2 << ", with tolerance of " << m_tol << ")");
5579 }
5580 else
5581 {
5582 NS_ABORT_MSG("The receiver address is unknown");
5583 }
5584}
5585
5586void
5588{
5589 // Now that BA session has been established we can plug our method
5592}
5593
5594void
5596{
5597 Ptr<Node> apNode = CreateObject<Node>();
5598 NodeContainer staNodes;
5599 staNodes.Create(2);
5600
5601 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
5602 Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
5603 spectrumChannel->AddPropagationLossModel(lossModel);
5605 CreateObject<ConstantSpeedPropagationDelayModel>();
5606 spectrumChannel->SetPropagationDelayModel(delayModel);
5607
5608 SpectrumWifiPhyHelper spectrumPhy;
5609 spectrumPhy.SetChannel(spectrumChannel);
5610 spectrumPhy.SetErrorRateModel("ns3::NistErrorRateModel");
5611 spectrumPhy.Set("ChannelSettings", StringValue("{0, 0, BAND_5GHZ, 0}"));
5612
5613 WifiHelper wifi;
5614 wifi.SetStandard(WIFI_STANDARD_80211ax);
5615 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
5616 "DataMode",
5617 StringValue("HeMcs7"),
5618 "ControlMode",
5619 StringValue("HeMcs7"));
5620
5621 WifiMacHelper mac;
5622 mac.SetType("ns3::StaWifiMac");
5623 NetDeviceContainer staDevs = wifi.Install(spectrumPhy, mac, staNodes);
5624 wifi.AssignStreams(staDevs, 0);
5625 m_sta1Dev = DynamicCast<WifiNetDevice>(staDevs.Get(0));
5627 m_sta2Dev = DynamicCast<WifiNetDevice>(staDevs.Get(1));
5629
5630 // Set the beacon interval long enough so that associated STAs may not consider link lost when
5631 // beacon generation is disabled during the actual tests. Having such a long interval also
5632 // avoids bloating logs with beacons during the set up phase.
5633 mac.SetType("ns3::ApWifiMac",
5634 "BeaconGeneration",
5635 BooleanValue(true),
5636 "BeaconInterval",
5637 TimeValue(MicroSeconds(1024 * 600)));
5638 m_apDev = DynamicCast<WifiNetDevice>(wifi.Install(spectrumPhy, mac, apNode).Get(0));
5640 m_apDev->GetHeConfiguration()->SetAttribute("BssColor", UintegerValue(m_bssColor));
5641 m_phyAp = DynamicCast<SpectrumWifiPhy>(m_apDev->GetPhy());
5643 // ReceiveOkCallback of AP will be set to corresponding test's method once BA sessions have been
5644 // set up for both STAs
5645
5646 MobilityHelper mobility;
5647 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
5648 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
5649 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
5650 positionAlloc->Add(Vector(1.0, 0.0, 0.0)); // put close enough in order to use MCS
5651 positionAlloc->Add(
5652 Vector(2.0, 0.0, 0.0)); // STA 2 is a bit further away, but still in range of MCS
5653 mobility.SetPositionAllocator(positionAlloc);
5654
5655 mobility.Install(apNode);
5656 mobility.Install(staNodes);
5657
5658 lossModel->SetDefaultLoss(50.0);
5659 lossModel->SetLoss(apNode->GetObject<MobilityModel>(),
5660 staNodes.Get(1)->GetObject<MobilityModel>(),
5661 56.0,
5662 true); //+6 dB between AP <-> STA 2 compared to AP <-> STA 1
5663}
5664
5665void
5667{
5668 m_phyAp->Dispose();
5669 m_phyAp = nullptr;
5670 m_apDev->Dispose();
5671 m_apDev = nullptr;
5672 m_sta1Dev->Dispose();
5673 m_sta1Dev = nullptr;
5674 m_sta2Dev->Dispose();
5675 m_sta2Dev = nullptr;
5676}
5677
5678void
5680{
5683 int64_t streamNumber = 0;
5684
5685 Ptr<WifiPhy> phySta1 = m_sta1Dev->GetPhy();
5686 Ptr<WifiPhy> phySta2 = m_sta2Dev->GetPhy();
5687
5688 m_phyAp->AssignStreams(streamNumber);
5689 phySta1->AssignStreams(streamNumber);
5690 phySta2->AssignStreams(streamNumber);
5691
5692 m_phyAp->SetAttribute("TxPowerStart", DoubleValue(m_txPowerAp));
5694 m_phyAp->SetAttribute("TxPowerLevels", UintegerValue(1));
5695
5696 phySta1->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5697 phySta1->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5698 phySta1->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5699
5700 phySta2->SetAttribute("TxPowerStart", DoubleValue(m_txPowerStart));
5701 phySta2->SetAttribute("TxPowerEnd", DoubleValue(m_txPowerEnd));
5702 phySta2->SetAttribute("TxPowerLevels", UintegerValue(m_txPowerLevels));
5703
5704 Time relativeStart = MilliSeconds(0);
5705 if (setupBa)
5706 {
5707 // Set up BA for each station once the association phase has ended
5708 // so that a BA session is established when the MU-BAR is received.
5711 this,
5715 this,
5717 relativeStart = MilliSeconds(1000);
5718 }
5719 else
5720 {
5721 Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
5722 NS_ASSERT(apMac);
5723 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
5724 }
5725
5726 Simulator::Schedule(relativeStart,
5728 this);
5729
5730 {
5731 // Verify that the RSSI from STA 1 is consistent with what was requested
5732 std::vector<uint16_t> staIds{1};
5733 Simulator::Schedule(relativeStart, &TestUlOfdmaPowerControl::SendMuBar, this, staIds);
5734 }
5735
5736 {
5737 // Verify that the RSSI from STA 2 is consistent with what was requested
5738 std::vector<uint16_t> staIds{2};
5739 Simulator::Schedule(relativeStart + MilliSeconds(20),
5741 this,
5742 staIds);
5743 }
5744
5745 {
5746 // Verify that the RSSI from STA 1 and 2 is consistent with what was requested
5747 std::vector<uint16_t> staIds{1, 2};
5748 Simulator::Schedule(relativeStart + MilliSeconds(40),
5750 this,
5751 staIds);
5752 }
5753
5754 Simulator::Stop(relativeStart + MilliSeconds(100));
5756}
5757
5758void
5760{
5761 // Power configurations
5762 m_txPowerAp = 20; // dBm, so as to have -30 and -36 dBm at STA 1 and STA 2 resp.,
5763 // since path loss = 50 dB for AP <-> STA 1 and 56 dB for AP <-> STA 2
5764 m_txPowerStart = 15; // dBm
5765
5766 // Requested UL RSSIs: should correspond to 20 dBm transmit power at STAs
5767 m_requestedRssiSta1 = -30.0;
5768 m_requestedRssiSta2 = -36.0;
5769
5770 // Test single power level
5771 {
5772 // STA power configurations: 15 dBm only
5773 m_txPowerEnd = 15;
5774 m_txPowerLevels = 1;
5775
5776 // Expected UL RSSIs, considering that the provided power is 5 dB less than requested,
5777 // regardless of the estimated path loss.
5778 m_rssiSta1 = -35.0; // 15 dBm - 50 dB
5779 m_rssiSta2 = -41.0; // 15 dBm - 56 dB
5780
5781 RunOne(true);
5782 }
5783
5784 // Test 2 dBm granularity
5785 {
5786 // STA power configurations: [15:2:25] dBm
5787 m_txPowerEnd = 25;
5788 m_txPowerLevels = 6;
5789
5790 // Expected UL RSSIs, considering that the provided power (21 dBm) is 1 dB more than
5791 // requested
5792 m_rssiSta1 = -29.0; // 21 dBm - 50 dB
5793 m_rssiSta2 = -35.0; // 21 dBm - 50 dB
5794
5795 RunOne(false);
5796 }
5797
5798 // Test 1 dBm granularity
5799 {
5800 // STA power configurations: [15:1:25] dBm
5801 m_txPowerEnd = 25;
5802 m_txPowerLevels = 11;
5803
5804 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5805 m_rssiSta1 = -30.0; // 20 dBm - 50 dB
5806 m_rssiSta2 = -36.0; // 20 dBm - 56 dB
5807
5808 RunOne(false);
5809 }
5810
5811 // Ask for different power levels (3 dB difference between HE_TB_PPDUs)
5812 {
5813 // STA power configurations: [15:1:25] dBm
5814 m_txPowerEnd = 25;
5815 m_txPowerLevels = 11;
5816
5817 // Requested UL RSSIs
5818 m_requestedRssiSta1 = -28.0; // 2 dB higher than previously -> Tx power = 22 dBm at STA 1
5819 m_requestedRssiSta2 = -37.0; // 1 dB less than previously -> Tx power = 19 dBm at STA 2
5820
5821 // Expected UL RSSIs, considering that we can correctly tune the transmit power
5822 m_rssiSta1 = -28.0; // 22 dBm - 50 dB
5823 m_rssiSta2 = -37.0; // 19 dBm - 56 dB
5824
5825 RunOne(false);
5826 }
5827
5829}
5830
5838{
5839 public:
5841};
5842
5844 : TestSuite("wifi-phy-ofdma", UNIT)
5845{
5853}
5854
SpectrumWifiPhy used for testing OFDMA.
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.
Time GetEnergyDuration(double energyW, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
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 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 CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, double expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
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 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.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy > phy, WifiSpectrumBandInfo band, double expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
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:942
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
static WifiMode GetHeMcs9()
Return MCS 9 from HE MCS values.
static WifiMode GetHeMcs7()
Return MCS 7 from HE MCS values.
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.
Definition: he-phy.cc:576
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
Definition: he-phy.cc:267
@ PSD_HE_PORTION
HE portion of an HE PPDU.
Definition: he-ppdu.h:115
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
Definition: he-ppdu.h:114
RU Specification.
Definition: he-ru.h:66
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:453
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:762
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_242_TONE
Definition: he-ru.h:45
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
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.
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 Dispose()
Dispose of this Object.
Definition: object.cc:219
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:1001
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static void Run()
Run the simulation.
Definition: simulator.cc:176
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:606
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:184
Make it easy to create and manage PHY objects for the spectrum model.
void SetChannel(const Ptr< SpectrumChannel > channel)
802.11 PHY layer model
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void StartRx(Ptr< SpectrumSignalParameters > rxParams, Ptr< const WifiSpectrumPhyInterface > interface)
Input method for delivering a signal from the spectrum channel and low-level PHY interface to this Sp...
void DoInitialize() override
Initialize() implementation.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
void DoDispose() override
Destructor implementation.
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
void StartTx(Ptr< const WifiPpdu > ppdu) override
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
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
Forward calls to a chain of Callback.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
Hold an unsigned integer type.
Definition: uinteger.h:45
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
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 (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.
Ptr< WifiMac > GetMac() const
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetPhy() const
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:633
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:1709
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:641
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:1246
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:783
static Time GetPreambleDetectionDuration()
Definition: wifi-phy.cc:1437
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:457
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:950
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1496
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1269
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:1082
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1005
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1244
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:713
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1249
void SetPreambleDetectionModel(const Ptr< PreambleDetectionModel > preambleDetectionModel)
Sets the preamble detection model.
Definition: wifi-phy.cc:661
void SetMobility(const Ptr< MobilityModel > mobility)
assign a mobility model to this device
Definition: wifi-phy.cc:621
void RegisterListener(WifiPhyListener *listener)
Definition: wifi-phy.cc:463
Ptr< InterferenceHelper > m_interference
Pointer to a helper responsible for interference computations.
Definition: wifi-phy.h:1231
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:451
void Reset()
Reset data upon end of TX or RX.
Definition: wifi-phy.cc:1820
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:872
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1017
Ptr< PhyEntity > GetLatestPhyEntity() const
Get the latest PHY entity supported by this PHY instance.
Definition: wifi-phy.cc:728
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:2180
receive notifications about PHY events.
static ConstIterator FindFirst(uint8_t number, uint16_t frequency, uint16_t width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first channel matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, const WifiSpectrumBandIndices &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40, const std::vector< bool > &puncturedSubchannels=std::vector< bool >{})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
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.
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
#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
#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:702
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
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
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
WifiSpectrumBandInfo structure containing info about a spectrum band.
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.