A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
spectrum-wifi-phy-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015 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
18#include "ns3/boolean.h"
19#include "ns3/constant-position-mobility-model.h"
20#include "ns3/he-phy.h" //includes OFDM PHY
21#include "ns3/interference-helper.h"
22#include "ns3/log.h"
23#include "ns3/multi-model-spectrum-channel.h"
24#include "ns3/nist-error-rate-model.h"
25#include "ns3/ofdm-ppdu.h"
26#include "ns3/pointer.h"
27#include "ns3/spectrum-wifi-helper.h"
28#include "ns3/spectrum-wifi-phy.h"
29#include "ns3/test.h"
30#include "ns3/wifi-mac-header.h"
31#include "ns3/wifi-net-device.h"
32#include "ns3/wifi-phy-listener.h"
33#include "ns3/wifi-psdu.h"
34#include "ns3/wifi-spectrum-phy-interface.h"
35#include "ns3/wifi-spectrum-signal-parameters.h"
36#include "ns3/wifi-spectrum-value-helper.h"
37#include "ns3/wifi-utils.h"
38
39#include <memory>
40#include <tuple>
41#include <vector>
42
43using namespace ns3;
44
45NS_LOG_COMPONENT_DEFINE("SpectrumWifiPhyTest");
46
47static const uint8_t CHANNEL_NUMBER = 36;
48static const uint16_t CHANNEL_WIDTH = 20; // MHz
49static const uint16_t GUARD_WIDTH =
50 CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
51
56{
57 public:
59 using WifiPhy::GetBand;
60
66 const std::map<FrequencyRange, Ptr<WifiSpectrumPhyInterface>>& GetSpectrumPhyInterfaces() const
67 {
69 }
70
75 {
77 }
78
90 uint8_t bandIndex,
91 const FrequencyRange& freqRange,
92 uint16_t channelWidth)
93 {
94 auto subcarrierSpacing = GetSubcarrierSpacing();
95 auto numBandsInChannel = static_cast<size_t>(channelWidth * 1e6 / subcarrierSpacing);
96 auto numBandsInBand = static_cast<size_t>(bandWidth * 1e6 / subcarrierSpacing);
97 auto rxSpectrumModel = m_spectrumPhyInterfaces.at(freqRange)->GetRxSpectrumModel();
98 size_t totalNumBands = rxSpectrumModel->GetNumBands();
99 auto startIndex = ((totalNumBands - numBandsInChannel) / 2) + (bandIndex * numBandsInBand);
100 auto stopIndex = startIndex + numBandsInBand - 1;
101 auto startGuardBand = rxSpectrumModel->Begin();
102 auto startChannel = startGuardBand + startIndex;
103 auto endChannel = startGuardBand + stopIndex + 1;
104 auto lowFreq = static_cast<uint64_t>(startChannel->fc);
105 auto highFreq = static_cast<uint64_t>(endChannel->fc);
106 return {{startIndex, stopIndex}, {lowFreq, highFreq}};
107 }
108};
109
117{
118 public:
125 SpectrumWifiPhyBasicTest(std::string name);
126 ~SpectrumWifiPhyBasicTest() override;
127
128 protected:
129 void DoSetup() override;
130 void DoTeardown() override;
138 Ptr<SpectrumSignalParameters> MakeSignal(double txPowerWatts,
139 const WifiPhyOperatingChannel& channel);
144 void SendSignal(double txPowerWatts);
153 RxSignalInfo rxSignalInfo,
154 WifiTxVector txVector,
155 std::vector<bool> statusPerMpdu);
162
163 private:
164 void DoRun() override;
165
166 uint64_t m_uid;
167};
168
170 : SpectrumWifiPhyBasicTest("SpectrumWifiPhy test case receives one packet")
171{
172}
173
175 : TestCase(name),
176 m_count(0),
177 m_uid(0)
178{
179}
180
181// Make a Wi-Fi signal to inject directly to the StartRx() method
184{
186 0,
188 800,
189 1,
190 1,
191 0,
193 false);
194
195 Ptr<Packet> pkt = Create<Packet>(1000);
196 WifiMacHeader hdr;
197
199 hdr.SetQosTid(0);
200
201 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
202 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
203
204 Ptr<WifiPpdu> ppdu = Create<OfdmPpdu>(psdu, txVector, channel, m_uid++);
205
207 channel.GetPrimaryChannelCenterFrequency(CHANNEL_WIDTH),
209 txPowerWatts,
211 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
212 txParams->psd = txPowerSpectrum;
213 txParams->txPhy = nullptr;
214 txParams->duration = txDuration;
215 txParams->ppdu = ppdu;
216 txParams->txWidth = CHANNEL_WIDTH;
217
218 return txParams;
219}
220
221// Make a Wi-Fi signal to inject directly to the StartRx() method
222void
224{
225 m_phy->StartRx(MakeSignal(txPowerWatts, m_phy->GetOperatingChannel()), nullptr);
226}
227
228void
230 RxSignalInfo rxSignalInfo,
231 WifiTxVector txVector,
232 std::vector<bool> statusPerMpdu)
233{
234 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
235 m_count++;
236}
237
238void
240{
241 NS_LOG_FUNCTION(this << *psdu);
242 m_count++;
243}
244
246{
247}
248
249// Create necessary objects, and inject signals. Test that the expected
250// number of packet receptions occur.
251void
253{
254 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
255 Ptr<Node> node = CreateObject<Node>();
256 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
257 m_phy = CreateObject<SpectrumWifiPhy>();
258 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
259 m_phy->SetInterferenceHelper(interferenceHelper);
260 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
261 m_phy->SetErrorRateModel(error);
262 m_phy->SetDevice(dev);
263 m_phy->AddChannel(spectrumChannel);
270 dev->SetPhy(m_phy);
271 node->AddDevice(dev);
272}
273
274void
276{
277 m_phy->Dispose();
278 m_phy = nullptr;
279}
280
281// Test that the expected number of packet receptions occur.
282void
284{
285 double txPowerWatts = 0.010;
286 // Send packets spaced 1 second apart; all should be received
290 // Send packets spaced 1 microsecond second apart; none should be received (PHY header reception
291 // failure)
294 this,
295 txPowerWatts);
298 this,
299 txPowerWatts);
302
303 NS_TEST_ASSERT_MSG_EQ(m_count, 3, "Didn't receive right number of packets");
304}
305
313{
314 public:
318 TestPhyListener() = default;
319 ~TestPhyListener() override = default;
320
321 void NotifyRxStart(Time duration) override
322 {
323 NS_LOG_FUNCTION(this << duration);
325 }
326
327 void NotifyRxEndOk() override
328 {
329 NS_LOG_FUNCTION(this);
331 }
332
333 void NotifyRxEndError() override
334 {
335 NS_LOG_FUNCTION(this);
337 }
338
339 void NotifyTxStart(Time duration, double txPowerDbm) override
340 {
341 NS_LOG_FUNCTION(this << duration << txPowerDbm);
342 }
343
345 WifiChannelListType channelType,
346 const std::vector<Time>& /*per20MhzDurations*/) override
347 {
348 NS_LOG_FUNCTION(this << duration << channelType);
349 if (duration.IsStrictlyPositive())
350 {
353 {
355 }
356 m_ccaBusyEnd = std::max(m_ccaBusyEnd, Simulator::Now() + duration);
357 }
358 }
359
360 void NotifySwitchingStart(Time duration) override
361 {
362 }
363
364 void NotifySleep() override
365 {
366 }
367
368 void NotifyOff() override
369 {
370 }
371
372 void NotifyWakeup() override
373 {
374 }
375
376 void NotifyOn() override
377 {
378 }
379
383 void Reset()
384 {
385 NS_LOG_FUNCTION(this);
386 m_notifyRxStart = 0;
387 m_notifyRxEndOk = 0;
392 }
393
400};
401
409{
410 public:
413
414 private:
415 void DoSetup() override;
416 void DoRun() override;
418};
419
421 : SpectrumWifiPhyBasicTest("SpectrumWifiPhy test operation of WifiPhyListener")
422{
423}
424
426{
427}
428
429void
431{
435}
436
437void
439{
440 double txPowerWatts = 0.010;
443
444 NS_TEST_ASSERT_MSG_EQ(m_count, 1, "Didn't receive right number of packets");
447 2,
448 "Didn't receive NotifyCcaBusyStart (once preamble is detected + prolonged by L-SIG "
449 "reception, then switched to Rx by at the beginning of data)");
450 NS_TEST_ASSERT_MSG_EQ(m_listener->m_notifyRxStart, 1, "Didn't receive NotifyRxStart");
451 NS_TEST_ASSERT_MSG_EQ(m_listener->m_notifyRxEndOk, 1, "Didn't receive NotifyRxEnd");
452
454 delete m_listener;
455}
456
464{
465 public:
472 SpectrumWifiPhyFilterTest(std::string name);
474
475 private:
476 void DoSetup() override;
477 void DoTeardown() override;
478 void DoRun() override;
479
483 void RunOne();
484
488 void SendPpdu();
489
496
499
502
503 std::set<WifiSpectrumBandIndices> m_ruBands;
504};
505
507 : TestCase("SpectrumWifiPhy test RX filters"),
508 m_txChannelWidth(20),
509 m_rxChannelWidth(20)
510{
511}
512
514 : TestCase(name)
515{
516}
517
518void
520{
522 0,
524 800,
525 1,
526 1,
527 0,
529 false,
530 false);
531 Ptr<Packet> pkt = Create<Packet>(1000);
532 WifiMacHeader hdr;
534 hdr.SetQosTid(0);
535 hdr.SetAddr1(Mac48Address("00:00:00:00:00:01"));
536 hdr.SetSequenceNumber(1);
537 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
538 m_txPhy->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
539}
540
542{
543 m_txPhy = nullptr;
544 m_rxPhy = nullptr;
545}
546
547void
549{
550 for (const auto& pair : rxPowersW)
551 {
552 NS_LOG_INFO("band: (" << pair.first << ") -> powerW=" << pair.second << " ("
553 << WToDbm(pair.second) << " dBm)");
554 }
555
556 size_t numBands = rxPowersW.size();
557 size_t expectedNumBands = std::max(1, (m_rxChannelWidth / 20));
558 expectedNumBands += (m_rxChannelWidth / 40);
559 expectedNumBands += (m_rxChannelWidth / 80);
560 expectedNumBands += (m_rxChannelWidth / 160);
561 expectedNumBands += m_ruBands.size();
562
563 NS_TEST_ASSERT_MSG_EQ(numBands,
564 expectedNumBands,
565 "Total number of bands handled by the receiver is incorrect");
566
567 uint16_t channelWidth = std::min(m_txChannelWidth, m_rxChannelWidth);
568 auto band = m_rxPhy->GetBand(channelWidth, 0);
569 auto it = rxPowersW.find(band);
570 NS_LOG_INFO("powerW total band: " << it->second << " (" << WToDbm(it->second) << " dBm)");
571 int totalRxPower = static_cast<int>(WToDbm(it->second) + 0.5);
572 int expectedTotalRxPower;
574 {
575 // PHY sends at 16 dBm, and since there is no loss, this should be the total power at the
576 // receiver.
577 expectedTotalRxPower = 16;
578 }
579 else
580 {
581 // Only a part of the transmitted power is received
582 expectedTotalRxPower =
583 16 - static_cast<int>(RatioToDb(m_txChannelWidth / m_rxChannelWidth));
584 }
585 NS_TEST_ASSERT_MSG_EQ(totalRxPower,
586 expectedTotalRxPower,
587 "Total received power is not correct");
588
589 if ((m_txChannelWidth <= m_rxChannelWidth) && (channelWidth >= 20))
590 {
591 band = m_rxPhy->GetBand(20, 0); // primary 20 MHz
592 it = rxPowersW.find(band);
593 NS_LOG_INFO("powerW in primary 20 MHz channel: " << it->second << " (" << WToDbm(it->second)
594 << " dBm)");
595 int rxPowerPrimaryChannel20 = static_cast<int>(WToDbm(it->second) + 0.5);
596 int expectedRxPowerPrimaryChannel20 = 16 - static_cast<int>(RatioToDb(channelWidth / 20));
597 NS_TEST_ASSERT_MSG_EQ(rxPowerPrimaryChannel20,
598 expectedRxPowerPrimaryChannel20,
599 "Received power in the primary 20 MHz band is not correct");
600 }
601}
602
603void
605{
606 // WifiHelper::EnableLogComponents();
607 // LogComponentEnable("SpectrumWifiPhyTest", LOG_LEVEL_ALL);
608
609 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
610 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
611 lossModel->SetFrequency(5.180e9);
612 spectrumChannel->AddPropagationLossModel(lossModel);
614 CreateObject<ConstantSpeedPropagationDelayModel>();
615 spectrumChannel->SetPropagationDelayModel(delayModel);
616
617 Ptr<Node> txNode = CreateObject<Node>();
618 Ptr<WifiNetDevice> txDev = CreateObject<WifiNetDevice>();
619 m_txPhy = CreateObject<ExtSpectrumWifiPhy>();
620 Ptr<InterferenceHelper> txInterferenceHelper = CreateObject<InterferenceHelper>();
621 m_txPhy->SetInterferenceHelper(txInterferenceHelper);
622 Ptr<ErrorRateModel> txErrorModel = CreateObject<NistErrorRateModel>();
623 m_txPhy->SetErrorRateModel(txErrorModel);
624 m_txPhy->SetDevice(txDev);
625 m_txPhy->AddChannel(spectrumChannel);
627 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
628 m_txPhy->SetMobility(apMobility);
629 txDev->SetPhy(m_txPhy);
630 txNode->AggregateObject(apMobility);
631 txNode->AddDevice(txDev);
632
633 Ptr<Node> rxNode = CreateObject<Node>();
634 Ptr<WifiNetDevice> rxDev = CreateObject<WifiNetDevice>();
635 m_rxPhy = CreateObject<ExtSpectrumWifiPhy>();
636 Ptr<InterferenceHelper> rxInterferenceHelper = CreateObject<InterferenceHelper>();
637 m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
638 Ptr<ErrorRateModel> rxErrorModel = CreateObject<NistErrorRateModel>();
639 m_rxPhy->SetErrorRateModel(rxErrorModel);
640 m_rxPhy->AddChannel(spectrumChannel);
642 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
643 m_rxPhy->SetMobility(sta1Mobility);
644 rxDev->SetPhy(m_rxPhy);
645 rxNode->AggregateObject(sta1Mobility);
646 rxNode->AddDevice(rxDev);
649}
650
651void
653{
654 m_txPhy->Dispose();
655 m_txPhy = nullptr;
656 m_rxPhy->Dispose();
657 m_rxPhy = nullptr;
658}
659
660void
662{
663 uint16_t txFrequency;
664 switch (m_txChannelWidth)
665 {
666 case 20:
667 default:
668 txFrequency = 5180;
669 break;
670 case 40:
671 txFrequency = 5190;
672 break;
673 case 80:
674 txFrequency = 5210;
675 break;
676 case 160:
677 txFrequency = 5250;
678 break;
679 }
680 auto txChannelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
681 txFrequency,
687
688 uint16_t rxFrequency;
689 switch (m_rxChannelWidth)
690 {
691 case 20:
692 default:
693 rxFrequency = 5180;
694 break;
695 case 40:
696 rxFrequency = 5190;
697 break;
698 case 80:
699 rxFrequency = 5210;
700 break;
701 case 160:
702 rxFrequency = 5250;
703 break;
704 }
705 auto rxChannelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
706 rxFrequency,
712
713 m_ruBands.clear();
714 for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
715 {
716 for (uint16_t i = 0; i < (m_rxChannelWidth / bw); ++i)
717 {
718 for (unsigned int type = 0; type < 7; type++)
719 {
720 HeRu::RuType ruType = static_cast<HeRu::RuType>(type);
721 for (std::size_t index = 1; index <= HeRu::GetNRus(bw, ruType); index++)
722 {
723 HeRu::SubcarrierGroup subcarrierGroup =
724 HeRu::GetSubcarrierGroup(bw, ruType, index);
725 HeRu::SubcarrierRange subcarrierRange =
726 std::make_pair(subcarrierGroup.front().first,
727 subcarrierGroup.back().second);
728 const auto band =
732 subcarrierRange,
733 i);
734 m_ruBands.insert(band);
735 }
736 }
737 }
738 }
739
741
743}
744
745void
747{
748 m_txChannelWidth = 20;
749 m_rxChannelWidth = 20;
750 RunOne();
751
752 m_txChannelWidth = 40;
753 m_rxChannelWidth = 40;
754 RunOne();
755
756 m_txChannelWidth = 80;
757 m_rxChannelWidth = 80;
758 RunOne();
759
760 m_txChannelWidth = 160;
761 m_rxChannelWidth = 160;
762 RunOne();
763
764 m_txChannelWidth = 20;
765 m_rxChannelWidth = 40;
766 RunOne();
767
768 m_txChannelWidth = 20;
769 m_rxChannelWidth = 80;
770 RunOne();
771
772 m_txChannelWidth = 40;
773 m_rxChannelWidth = 80;
774 RunOne();
775
776 m_txChannelWidth = 20;
777 m_rxChannelWidth = 160;
778 RunOne();
779
780 m_txChannelWidth = 40;
781 m_rxChannelWidth = 160;
782 RunOne();
783
784 m_txChannelWidth = 80;
785 m_rxChannelWidth = 160;
786 RunOne();
787
788 m_txChannelWidth = 40;
789 m_rxChannelWidth = 20;
790 RunOne();
791
792 m_txChannelWidth = 80;
793 m_rxChannelWidth = 20;
794 RunOne();
795
796 m_txChannelWidth = 80;
797 m_rxChannelWidth = 40;
798 RunOne();
799
800 m_txChannelWidth = 160;
801 m_rxChannelWidth = 20;
802 RunOne();
803
804 m_txChannelWidth = 160;
805 m_rxChannelWidth = 40;
806 RunOne();
807
808 m_txChannelWidth = 160;
809 m_rxChannelWidth = 80;
810 RunOne();
811
813}
814
838{
839 public:
846 SpectrumWifiPhyMultipleInterfacesTest(bool trackSignalsInactiveInterfaces);
847
848 private:
849 void DoSetup() override;
850 void DoTeardown() override;
851 void DoRun() override;
852
861 void SwitchChannel(std::size_t index,
862 WifiPhyBand band,
863 uint8_t channelNumber,
864 uint16_t channelWidth);
865
873 void SendPpdu(Ptr<SpectrumWifiPhy> phy, double txPowerDbm);
874
881 void RxCallback(std::size_t index,
882 Ptr<const Packet> packet,
883 RxPowerWattPerChannelBand rxPowersW);
884
893 const FrequencyRange& freqRange,
894 uint16_t channelWidth,
895 bool interferencesExpected);
896
905 const FrequencyRange& freqRange,
906 uint16_t channelWidth,
907 bool interferencesExpected);
908
919 void CheckResults(std::size_t index,
920 uint32_t expectedNumRx,
921 FrequencyRange expectedFrequencyRangeActiveRfInterface,
922 const std::vector<std::size_t>& expectedConnectedPhysPerChannel);
923
932 void CheckCcaIndication(std::size_t index, bool expectedCcaBusyIndication, Time switchingDelay);
933
937 void Reset();
938
940 using SpectrumChannelInfos = std::tuple<Ptr<MultiModelSpectrumChannel>, uint16_t, uint16_t>;
941
942 bool
945
946 std::vector<SpectrumChannelInfos> m_spectrumChannelInfos;
947 std::vector<Ptr<ExtSpectrumWifiPhy>> m_txPhys{};
948 std::vector<Ptr<ExtSpectrumWifiPhy>> m_rxPhys{};
949 std::vector<std::unique_ptr<TestPhyListener>> m_listeners{};
950
951 std::vector<uint32_t> m_counts{0};
952
955};
956
958 bool trackSignalsInactiveInterfaces)
959 : TestCase{"SpectrumWifiPhy test operation with multiple RF interfaces"},
960 m_trackSignalsInactiveInterfaces{trackSignalsInactiveInterfaces}
961{
962}
963
964void
966 WifiPhyBand band,
967 uint8_t channelNumber,
968 uint16_t channelWidth)
969{
970 NS_LOG_FUNCTION(this << index << band << +channelNumber << channelWidth);
971 auto& listener = m_listeners.at(index);
972 listener->m_notifyMaybeCcaBusyStart = 0;
973 listener->m_ccaBusyStart = Seconds(0);
974 listener->m_ccaBusyEnd = Seconds(0);
975 auto phy = m_rxPhys.at(index);
976 phy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNumber, channelWidth, band, 0});
977}
978
979void
981{
982 NS_LOG_FUNCTION(this << phy << txPowerDbm << phy->GetCurrentFrequencyRange()
983 << phy->GetChannelWidth() << phy->GetChannelNumber());
984
985 WifiTxVector txVector =
986 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false);
987 Ptr<Packet> pkt = Create<Packet>(1000);
988 WifiMacHeader hdr;
990 hdr.SetQosTid(0);
991 hdr.SetAddr1(Mac48Address("00:00:00:00:00:01"));
992 hdr.SetSequenceNumber(1);
993 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
994
997 txVector,
998 phy->GetPhyBand());
999 phy->SetTxPowerStart(txPowerDbm);
1000 phy->SetTxPowerEnd(txPowerDbm);
1001 phy->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
1002}
1003
1004void
1006 Ptr<const Packet> /*packet*/,
1007 RxPowerWattPerChannelBand /*rxPowersW*/)
1008{
1009 auto phy = m_rxPhys.at(index);
1010 NS_LOG_FUNCTION(this << index << phy->GetCurrentFrequencyRange() << phy->GetChannelWidth()
1011 << phy->GetChannelNumber());
1012 m_counts.at(index)++;
1013}
1014
1015void
1017 const FrequencyRange& freqRange,
1018 uint16_t channelWidth,
1019 bool interferencesExpected)
1020{
1021 if ((!m_trackSignalsInactiveInterfaces) && (phy->GetCurrentFrequencyRange() != freqRange))
1022 {
1023 // ignore since no bands for that range exists in interference helper in that case
1024 return;
1025 }
1026 // This is needed to make sure PHY state will be checked as the last event if a state change
1027 // occurred at the exact same time as the check
1029 this,
1030 phy,
1031 freqRange,
1032 channelWidth,
1033 interferencesExpected);
1034}
1035
1036void
1038 const FrequencyRange& freqRange,
1039 uint16_t channelWidth,
1040 bool interferencesExpected)
1041{
1042 NS_LOG_FUNCTION(this << phy << freqRange << interferencesExpected);
1043 PointerValue ptr;
1044 phy->GetAttribute("InterferenceHelper", ptr);
1045 auto interferenceHelper = DynamicCast<InterferenceHelper>(ptr.Get<InterferenceHelper>());
1046 NS_ASSERT(interferenceHelper);
1047 const auto band = phy->GetBandForInterface(channelWidth, 0, freqRange, channelWidth);
1048 const auto energyDuration = interferenceHelper->GetEnergyDuration(0, band);
1049 NS_TEST_ASSERT_MSG_EQ(energyDuration.IsStrictlyPositive(),
1050 interferencesExpected,
1051 "Incorrect interferences detection");
1052}
1053
1054void
1056 std::size_t index,
1057 uint32_t expectedNumRx,
1058 FrequencyRange expectedFrequencyRangeActiveRfInterface,
1059 const std::vector<std::size_t>& expectedConnectedPhysPerChannel)
1060{
1061 NS_LOG_FUNCTION(this << index << expectedNumRx << expectedFrequencyRangeActiveRfInterface);
1062 const auto phy = m_rxPhys.at(index);
1063 std::size_t numActiveInterfaces = 0;
1064 for (const auto& [freqRange, interface] : phy->GetSpectrumPhyInterfaces())
1065 {
1066 const auto expectedActive = (freqRange == expectedFrequencyRangeActiveRfInterface);
1067 const auto isActive = (interface == phy->GetCurrentSpectrumPhyInterface());
1068 NS_TEST_ASSERT_MSG_EQ(isActive, expectedActive, "Incorrect active interface");
1069 if (isActive)
1070 {
1071 numActiveInterfaces++;
1072 }
1073 }
1074 NS_TEST_ASSERT_MSG_EQ(numActiveInterfaces, 1, "There should always be one active interface");
1075 NS_ASSERT(expectedConnectedPhysPerChannel.size() == m_spectrumChannelInfos.size());
1076 for (std::size_t i = 0; i < m_spectrumChannelInfos.size(); ++i)
1077 {
1078 const auto spectrumChannel = std::get<0>(m_spectrumChannelInfos.at(i));
1079 NS_TEST_ASSERT_MSG_EQ(spectrumChannel->GetNDevices(),
1080 expectedConnectedPhysPerChannel.at(i),
1081 "Incorrect number of PHYs attached to the spectrum channel");
1082 }
1084 expectedNumRx,
1085 "Didn't receive right number of packets");
1086 NS_TEST_ASSERT_MSG_EQ(m_listeners.at(index)->m_notifyRxStart,
1087 expectedNumRx,
1088 "Didn't receive NotifyRxStart");
1089}
1090
1091void
1093 bool expectedCcaBusyIndication,
1094 Time switchingDelay)
1095{
1096 const auto expectedCcaBusyStart =
1097 expectedCcaBusyIndication ? m_lastTxStart + switchingDelay : Seconds(0);
1098 const auto expectedCcaBusyEnd = expectedCcaBusyIndication ? m_lastTxEnd : Seconds(0);
1099 NS_LOG_FUNCTION(this << index << expectedCcaBusyIndication << expectedCcaBusyStart
1100 << expectedCcaBusyEnd);
1101 auto& listener = m_listeners.at(index);
1102 const auto ccaBusyIndication = (listener->m_notifyMaybeCcaBusyStart > 0);
1103 const auto ccaBusyStart = listener->m_ccaBusyStart;
1104 const auto ccaBusyEnd = listener->m_ccaBusyEnd;
1105 NS_TEST_ASSERT_MSG_EQ(ccaBusyIndication,
1106 expectedCcaBusyIndication,
1107 "CCA busy indication check failed");
1108 NS_TEST_ASSERT_MSG_EQ(ccaBusyStart, expectedCcaBusyStart, "CCA busy start mismatch");
1109 NS_TEST_ASSERT_MSG_EQ(ccaBusyEnd, expectedCcaBusyEnd, "CCA busy end mismatch");
1110}
1111
1112void
1114{
1115 NS_LOG_FUNCTION(this);
1116 for (auto& count : m_counts)
1117 {
1118 count = 0;
1119 }
1120 for (auto& listener : m_listeners)
1121 {
1122 listener->Reset();
1123 }
1124 // restore all RX PHYs to initial channels
1125 for (std::size_t rxPhyIndex = 0; rxPhyIndex < m_rxPhys.size(); ++rxPhyIndex)
1126 {
1127 auto txPhy = m_txPhys.at(rxPhyIndex);
1128 SwitchChannel(rxPhyIndex,
1129 txPhy->GetPhyBand(),
1130 txPhy->GetChannelNumber(),
1131 txPhy->GetChannelWidth());
1132 }
1133}
1134
1135void
1137{
1138 NS_LOG_FUNCTION(this);
1139
1140 // WifiHelper::EnableLogComponents();
1141 // LogComponentEnable("SpectrumWifiPhyTest", LOG_LEVEL_ALL);
1142
1143 const std::vector<std::pair<WifiPhyBand, uint8_t>> channels{{WIFI_PHY_BAND_2_4GHZ, 2},
1144 {WIFI_PHY_BAND_5GHZ, 42},
1145 {WIFI_PHY_BAND_5GHZ, 114},
1146 {WIFI_PHY_BAND_6GHZ, 215}};
1147
1148 // create spectrum channels
1149 for (std::size_t i = 0; i < channels.size(); ++i)
1150 {
1151 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1152 [[maybe_unused]] const auto [channel, frequency, channelWidth, type, band] =
1153 (*WifiPhyOperatingChannel::FindFirst(channels.at(i).second,
1154 0,
1155 0,
1157 channels.at(i).first));
1158
1159 m_spectrumChannelInfos.emplace_back(spectrumChannel, frequency, channelWidth);
1160 }
1161
1162 // create PHYs and add all channels to each of them
1163 for (std::size_t i = 0; i < channels.size(); ++i)
1164 {
1165 auto txNode = CreateObject<Node>();
1166 auto txDev = CreateObject<WifiNetDevice>();
1167 auto txPhy = CreateObject<ExtSpectrumWifiPhy>();
1168 txPhy->SetAttribute("ChannelSwitchDelay", TimeValue(Seconds(0)));
1169 txPhy->SetAttribute("TrackSignalsFromInactiveInterfaces",
1171 auto txInterferenceHelper = CreateObject<InterferenceHelper>();
1172 txPhy->SetInterferenceHelper(txInterferenceHelper);
1173 auto txError = CreateObject<NistErrorRateModel>();
1174 txPhy->SetErrorRateModel(txError);
1175 txPhy->SetDevice(txDev);
1176 for (const auto& [spectrumChannel, freq, width] : m_spectrumChannelInfos)
1177 {
1178 const uint16_t minFreq = freq - width / 2;
1179 const uint16_t maxFreq = freq + width / 2;
1180 txPhy->AddChannel(spectrumChannel, {minFreq, maxFreq});
1181 }
1182 txPhy->SetOperatingChannel(
1183 WifiPhy::ChannelTuple{channels.at(i).second, 0, channels.at(i).first, 0});
1184 txPhy->ConfigureStandard(WIFI_STANDARD_80211ax);
1185 txDev->SetPhy(txPhy);
1186 txNode->AddDevice(txDev);
1187
1188 m_txPhys.push_back(txPhy);
1189
1190 auto rxNode = CreateObject<Node>();
1191 auto rxDev = CreateObject<WifiNetDevice>();
1192 auto rxPhy = CreateObject<ExtSpectrumWifiPhy>();
1193 rxPhy->SetAttribute("ChannelSwitchDelay", TimeValue(Seconds(0)));
1194 rxPhy->SetAttribute("TrackSignalsFromInactiveInterfaces",
1196 auto rxInterferenceHelper = CreateObject<InterferenceHelper>();
1197 rxPhy->SetInterferenceHelper(rxInterferenceHelper);
1198 auto rxError = CreateObject<NistErrorRateModel>();
1199 rxPhy->SetErrorRateModel(rxError);
1200 rxPhy->SetDevice(rxDev);
1201 for (const auto& [spectrumChannel, freq, width] : m_spectrumChannelInfos)
1202 {
1203 const uint16_t minFreq = freq - width / 2;
1204 const uint16_t maxFreq = freq + width / 2;
1205 rxPhy->AddChannel(spectrumChannel, {minFreq, maxFreq});
1206 }
1207 rxPhy->SetOperatingChannel(
1208 WifiPhy::ChannelTuple{channels.at(i).second, 0, channels.at(i).first, 0});
1209 rxPhy->ConfigureStandard(WIFI_STANDARD_80211ax);
1210 rxDev->SetPhy(rxPhy);
1211 rxNode->AddDevice(rxDev);
1212
1213 const auto index = m_rxPhys.size();
1214 rxPhy->TraceConnectWithoutContext(
1215 "PhyRxBegin",
1217
1218 auto listener = std::make_unique<TestPhyListener>();
1219 rxPhy->RegisterListener(listener.get());
1220 m_listeners.push_back(std::move(listener));
1221
1222 m_rxPhys.push_back(rxPhy);
1223 m_counts.push_back(0);
1224 }
1225}
1226
1227void
1229{
1230 NS_LOG_FUNCTION(this);
1231 for (auto& phy : m_txPhys)
1232 {
1233 phy->Dispose();
1234 phy = nullptr;
1235 }
1236 for (auto& phy : m_rxPhys)
1237 {
1238 phy->Dispose();
1239 phy = nullptr;
1240 }
1242}
1243
1244void
1246{
1247 NS_LOG_FUNCTION(this);
1248
1249 const auto ccaEdThresholdDbm = -62.0;
1250 const auto txAfterChannelSwitchDelay =
1251 Seconds(0.25);
1253 const auto checkResultsDelay =
1254 Seconds(0.5);
1255 const auto flushResultsDelay =
1256 Seconds(0.9);
1257 const auto txOngoingAfterTxStartedDelay =
1258 MicroSeconds(50);
1260
1261 Time delay{0};
1262 // make sure all interfaces got active once for all RX PHYs to have them monitored
1263 for (std::size_t rxPhyIndex = 0; rxPhyIndex < m_rxPhys.size(); ++rxPhyIndex)
1264 {
1265 for (std::size_t txPhyIndex = 0; txPhyIndex < m_txPhys.size(); ++txPhyIndex)
1266 {
1267 if (txPhyIndex == rxPhyIndex)
1268 {
1269 // handled at end
1270 continue;
1271 }
1272 auto txPhy = m_txPhys.at(txPhyIndex);
1273 Simulator::Schedule(delay + Seconds((rxPhyIndex + rxPhyIndex) * 0.1),
1275 this,
1276 rxPhyIndex,
1277 txPhy->GetPhyBand(),
1278 txPhy->GetChannelNumber(),
1279 txPhy->GetChannelWidth());
1280 }
1281 Simulator::Schedule(delay + flushResultsDelay,
1283 this);
1284 }
1285
1286 // default channels active for all PHYs: each PHY only receives from its associated TX
1287 std::vector<std::size_t> expectedConnectedPhysPerChannel =
1288 m_trackSignalsInactiveInterfaces ? std::vector<std::size_t>{5, 5, 5, 5}
1289 : // all RX PHYs keep all channels active when tracking
1290 // interferences on inactive interfaces
1291 std::vector<std::size_t>{2, 2, 2, 2}; // default channels active for all PHYs: each PHY
1292 // only receives from its associated TX
1293 for (std::size_t i = 0; i < 4; ++i)
1294 {
1295 auto txPpduPhy = m_txPhys.at(i);
1296 delay += Seconds(1);
1297 Simulator::Schedule(delay,
1299 this,
1300 txPpduPhy,
1301 0);
1302 for (std::size_t j = 0; j < 4; ++j)
1303 {
1304 auto txPhy = m_txPhys.at(j);
1305 auto rxPhy = m_rxPhys.at(j);
1306 const uint16_t minExpectedFreq = txPhy->GetFrequency() - (txPhy->GetChannelWidth() / 2);
1307 const uint16_t maxExpectedFreq = txPhy->GetFrequency() + (txPhy->GetChannelWidth() / 2);
1308 const FrequencyRange expectedFreqRange = {minExpectedFreq, maxExpectedFreq};
1309 Simulator::Schedule(delay + txOngoingAfterTxStartedDelay,
1311 this,
1312 rxPhy,
1313 txPpduPhy->GetCurrentFrequencyRange(),
1314 txPpduPhy->GetChannelWidth(),
1315 true);
1316 Simulator::Schedule(delay + checkResultsDelay,
1318 this,
1319 j,
1320 (i == j) ? 1 : 0,
1321 expectedFreqRange,
1322 expectedConnectedPhysPerChannel);
1323 Simulator::Schedule(delay + flushResultsDelay,
1325 this);
1326 }
1327 }
1328
1329 // same channel active for all PHYs: all PHYs receive from TX
1330 for (std::size_t i = 0; i < 4; ++i)
1331 {
1332 delay += Seconds(1);
1333 auto txPpduPhy = m_txPhys.at(i);
1334 Simulator::Schedule(delay + txAfterChannelSwitchDelay,
1336 this,
1337 txPpduPhy,
1338 0);
1339 const uint16_t minExpectedFreq =
1340 txPpduPhy->GetFrequency() - (txPpduPhy->GetChannelWidth() / 2);
1341 const uint16_t maxExpectedFreq =
1342 txPpduPhy->GetFrequency() + (txPpduPhy->GetChannelWidth() / 2);
1343 const FrequencyRange expectedFreqRange = {minExpectedFreq, maxExpectedFreq};
1344 for (std::size_t j = 0; j < 4; ++j)
1345 {
1347 {
1348 for (std::size_t k = 0; k < expectedConnectedPhysPerChannel.size(); ++k)
1349 {
1350 expectedConnectedPhysPerChannel.at(k) = (k == i) ? 5 : 1;
1351 }
1352 }
1353 auto rxPhy = m_rxPhys.at(j);
1354 Simulator::Schedule(delay,
1356 this,
1357 j,
1358 txPpduPhy->GetPhyBand(),
1359 txPpduPhy->GetChannelNumber(),
1360 txPpduPhy->GetChannelWidth());
1361 Simulator::Schedule(delay + txAfterChannelSwitchDelay + txOngoingAfterTxStartedDelay,
1363 this,
1364 rxPhy,
1365 txPpduPhy->GetCurrentFrequencyRange(),
1366 txPpduPhy->GetChannelWidth(),
1367 true);
1368 Simulator::Schedule(delay + checkResultsDelay,
1370 this,
1371 j,
1372 1,
1373 expectedFreqRange,
1374 expectedConnectedPhysPerChannel);
1375 Simulator::Schedule(delay + flushResultsDelay,
1377 this);
1378 }
1379 }
1380
1381 // Switch all PHYs to channel 36: all PHYs switch to the second spectrum channel
1382 // since second spectrum channel is 42 (80 MHz) and hence covers channel 36 (20 MHz)
1383 const auto secondSpectrumChannelIndex = 1;
1384 auto channel36TxPhy = m_txPhys.at(secondSpectrumChannelIndex);
1385 const uint16_t minExpectedFreq =
1386 channel36TxPhy->GetFrequency() - (channel36TxPhy->GetChannelWidth() / 2);
1387 const uint16_t maxExpectedFreq =
1388 channel36TxPhy->GetFrequency() + (channel36TxPhy->GetChannelWidth() / 2);
1389 FrequencyRange expectedFreqRange = {minExpectedFreq, maxExpectedFreq};
1390 for (std::size_t i = 0; i < 4; ++i)
1391 {
1392 delay += Seconds(1);
1393 auto txPpduPhy = m_txPhys.at(i);
1394 Simulator::Schedule(delay + txAfterChannelSwitchDelay,
1396 this,
1397 txPpduPhy,
1398 0);
1399 for (std::size_t j = 0; j < 4; ++j)
1400 {
1402 {
1403 for (std::size_t k = 0; k < expectedConnectedPhysPerChannel.size(); ++k)
1404 {
1405 expectedConnectedPhysPerChannel.at(k) =
1406 (k == secondSpectrumChannelIndex) ? 5 : 1;
1407 }
1408 }
1409 Simulator::Schedule(delay,
1411 this,
1412 j,
1416 Simulator::Schedule(delay + checkResultsDelay,
1418 this,
1419 j,
1420 (i == secondSpectrumChannelIndex) ? 1 : 0,
1421 expectedFreqRange,
1422 expectedConnectedPhysPerChannel);
1423 Simulator::Schedule(delay + flushResultsDelay,
1425 this);
1426 }
1427 }
1428
1429 // verify CCA indication when switching to a channel with an ongoing transmission
1430 for (const auto txPowerDbm : {-60.0 /* above CCA-ED */, -70.0 /* below CCA-ED */})
1431 {
1432 for (std::size_t i = 0; i < 4; ++i)
1433 {
1434 for (std::size_t j = 0; j < 4; ++j)
1435 {
1436 auto txPpduPhy = m_txPhys.at(i);
1437 const auto startChannel =
1438 WifiPhyOperatingChannel::FindFirst(txPpduPhy->GetPrimaryChannelNumber(20),
1439 0,
1440 20,
1442 txPpduPhy->GetPhyBand());
1443 for (uint16_t bw = txPpduPhy->GetChannelWidth(); bw >= 20; bw /= 2)
1444 {
1445 [[maybe_unused]] const auto [channel, frequency, channelWidth, type, band] =
1447 0,
1448 bw,
1450 txPpduPhy->GetPhyBand(),
1451 startChannel));
1452 delay += Seconds(1);
1453 Simulator::Schedule(delay,
1455 this,
1456 txPpduPhy,
1457 txPowerDbm);
1458 Simulator::Schedule(delay + txOngoingAfterTxStartedDelay,
1460 this,
1461 j,
1462 band,
1463 channel,
1464 channelWidth);
1465 for (std::size_t k = 0; k < 4; ++k)
1466 {
1467 Simulator::Schedule(delay + flushResultsDelay,
1469 this);
1470 if ((i != j) && (k == i))
1471 {
1472 continue;
1473 }
1474 const auto expectCcaBusyIndication =
1475 (k == i) ? (txPowerDbm >= ccaEdThresholdDbm)
1477 ? ((txPowerDbm >= ccaEdThresholdDbm) ? (j == k) : false)
1478 : false);
1480 delay + checkResultsDelay,
1482 this,
1483 k,
1484 expectCcaBusyIndication,
1485 txOngoingAfterTxStartedDelay);
1486 }
1487 }
1488 }
1489 }
1490 }
1491
1493}
1494
1502{
1503 public:
1505};
1506
1508 : TestSuite("wifi-spectrum-wifi-phy", UNIT)
1509{
1515}
1516
Extended SpectrumWifiPhy class for the purpose of the tests.
Ptr< WifiSpectrumPhyInterface > GetCurrentSpectrumPhyInterface() const
WifiSpectrumBandInfo GetBandForInterface(uint16_t bandWidth, uint8_t bandIndex, const FrequencyRange &freqRange, uint16_t channelWidth)
Get the info of a given band for a given spectrum PHY interface.
const std::map< FrequencyRange, Ptr< WifiSpectrumPhyInterface > > & GetSpectrumPhyInterfaces() const
Get the spectrum PHY interfaces.
Spectrum Wifi Phy Basic Test.
void SpectrumWifiPhyRxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Spectrum wifi receive success function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
Ptr< SpectrumSignalParameters > MakeSignal(double txPowerWatts, const WifiPhyOperatingChannel &channel)
Make signal function.
void SpectrumWifiPhyRxFailure(Ptr< const WifiPsdu > psdu)
Spectrum wifi receive failure function.
void SendSignal(double txPowerWatts)
Send signal function.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint64_t m_uid
the UID to use for the PPDU
Ptr< SpectrumWifiPhy > m_phy
Phy.
Spectrum Wifi Phy Filter Test.
void RxCallback(Ptr< const Packet > p, RxPowerWattPerChannelBand rxPowersW)
Callback triggered when a packet is received by the PHYs.
uint16_t m_txChannelWidth
TX channel width (MHz)
void DoRun() override
Implementation to actually run this TestCase.
void RunOne()
Run one function.
void SendPpdu()
Send PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
std::set< WifiSpectrumBandIndices > m_ruBands
spectrum bands associated to all the RUs
Ptr< ExtSpectrumWifiPhy > m_rxPhy
RX PHY.
uint16_t m_rxChannelWidth
RX channel width (MHz)
Ptr< ExtSpectrumWifiPhy > m_txPhy
TX PHY.
Spectrum Wifi Phy Listener Test.
TestPhyListener * m_listener
listener
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Spectrum Wifi Phy Multiple Spectrum Test.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckCcaIndication(std::size_t index, bool expectedCcaBusyIndication, Time switchingDelay)
Verify CCA indication reported by a given PHY.
std::vector< Ptr< ExtSpectrumWifiPhy > > m_txPhys
TX PHYs.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
std::vector< SpectrumChannelInfos > m_spectrumChannelInfos
Spectrum channels infos.
void DoRun() override
Implementation to actually run this TestCase.
void DoCheckInterferences(Ptr< ExtSpectrumWifiPhy > phy, const FrequencyRange &freqRange, uint16_t channelWidth, bool interferencesExpected)
Check the interferences.
SpectrumWifiPhyMultipleInterfacesTest(bool trackSignalsInactiveInterfaces)
Constructor.
std::vector< Ptr< ExtSpectrumWifiPhy > > m_rxPhys
RX PHYs.
std::tuple< Ptr< MultiModelSpectrumChannel >, uint16_t, uint16_t > SpectrumChannelInfos
typedef for spectrum channel infos
bool m_trackSignalsInactiveInterfaces
flag to indicate whether signals coming from inactive spectrum PHY interfaces are tracked during the ...
Time m_lastTxEnd
hold the time at which the last transmission ended
void CheckResults(std::size_t index, uint32_t expectedNumRx, FrequencyRange expectedFrequencyRangeActiveRfInterface, const std::vector< std::size_t > &expectedConnectedPhysPerChannel)
Verify results.
Time m_lastTxStart
hold the time at which the last transmission started
std::vector< uint32_t > m_counts
count number of packets received by PHYs
void SwitchChannel(std::size_t index, WifiPhyBand band, uint8_t channelNumber, uint16_t channelWidth)
Switch channel function.
void SendPpdu(Ptr< SpectrumWifiPhy > phy, double txPowerDbm)
Send PPDU function.
void CheckInterferences(Ptr< ExtSpectrumWifiPhy > phy, const FrequencyRange &freqRange, uint16_t channelWidth, bool interferencesExpected)
Schedule now to check the interferences.
void RxCallback(std::size_t index, Ptr< const Packet > packet, RxPowerWattPerChannelBand rxPowersW)
Callback triggered when a packet is received by a PHY.
std::vector< std::unique_ptr< TestPhyListener > > m_listeners
listeners
Spectrum Wifi Phy Test Suite.
Test Phy Listener.
Time m_ccaBusyEnd
CCA_BUSY end time.
void Reset()
Reset function.
void NotifyWakeup() override
Notify listeners that we woke up.
Time m_ccaBusyStart
CCA_BUSY start time.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyOff() override
Notify listeners that we went to switch off.
TestPhyListener()=default
Create a test PhyListener.
void NotifySleep() override
Notify listeners that we went to sleep.
void NotifySwitchingStart(Time duration) override
uint32_t m_notifyMaybeCcaBusyStart
notify maybe CCA busy start
uint32_t m_notifyRxStart
notify receive start
void NotifyTxStart(Time duration, double txPowerDbm) override
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
void NotifyRxStart(Time duration) override
void NotifyOn() override
Notify listeners that we went to switch on.
uint32_t m_notifyRxEndOk
notify receive end OK
void NotifyRxEndError() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
uint32_t m_notifyRxEndError
notify receive end error
~TestPhyListener() override=default
AttributeValue implementation for Boolean.
Definition: boolean.h:37
static WifiMode GetHeMcs0()
Return MCS 0 from HE MCS values.
static WifiSpectrumBandIndices ConvertHeRuSubcarriers(uint16_t bandWidth, uint16_t guardBandwidth, uint32_t subcarrierSpacing, HeRu::SubcarrierRange subcarrierRange, uint8_t bandIndex=0)
Definition: he-phy.cc:1845
static SubcarrierGroup GetSubcarrierGroup(uint16_t bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
Definition: he-ru.cc:586
static std::size_t GetNRus(uint16_t bw, RuType ruType)
Get the number of distinct RUs of the given type (number of tones) available in a HE PPDU of the give...
Definition: he-ru.cc:490
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition: he-ru.h:55
std::pair< int16_t, int16_t > SubcarrierRange
(lowest index, highest index) pair defining a subcarrier range
Definition: he-ru.h:52
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
handles interference calculations
an EUI-48 address
Definition: mac48-address.h:46
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:311
void Dispose()
Dispose of this Object.
Definition: object.cc:219
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
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 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
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...
std::map< FrequencyRange, Ptr< WifiSpectrumPhyInterface > > m_spectrumPhyInterfaces
Spectrum PHY interfaces.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
Ptr< WifiSpectrumPhyInterface > m_currentSpectrumPhyInterface
The current Spectrum PHY interface (held for performance reasons)
uint16_t GetGuardBandwidth(uint16_t currentChannelWidth) const override
WifiSpectrumBandInfo GetBand(uint16_t bandWidth, uint8_t bandIndex=0) override
Get the info of a given band.
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
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:350
AttributeValue implementation for Time.
Definition: nstime.h:1423
Implements the IEEE 802.11 MAC header.
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.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
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
uint32_t GetSubcarrierSpacing() const
Definition: wifi-phy.cc:2204
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
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
virtual WifiSpectrumBandInfo GetBand(uint16_t bandWidth, uint8_t bandIndex=0)=0
Get the info of a given band.
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
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:451
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
receive notifications about PHY events.
Class that keeps track of all information about the current PHY operating channel.
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.
static Ptr< SpectrumValue > CreateOfdmTxPowerSpectralDensity(uint32_t centerFrequency, uint16_t channelWidth, double txPowerW, uint16_t guardBandwidth, double minInnerBandDbr=-20, double minOuterbandDbr=-28, double lowestPointDbr=-40)
Create a transmit power spectral density corresponding to OFDM (802.11a/g).
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
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_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
Definition: wifi-phy-band.h:39
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double RatioToDb(double ratio)
Convert from ratio to dB.
Definition: wifi-utils.cc:52
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
double WToDbm(double w)
Convert from Watts to dBm.
Definition: wifi-utils.cc:46
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
@ WIFI_MAC_QOSDATA
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:78
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
Definition: second.py:1
static const uint8_t CHANNEL_NUMBER
static SpectrumWifiPhyTestSuite spectrumWifiPhyTestSuite
the test suite
static const uint16_t GUARD_WIDTH
static const uint16_t CHANNEL_WIDTH
Struct defining a frequency range between minFrequency (MHz) and maxFrequency (MHz).
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:70
WifiSpectrumBandInfo structure containing info about a spectrum band.