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/string.h"
30#include "ns3/test.h"
31#include "ns3/wifi-mac-header.h"
32#include "ns3/wifi-net-device.h"
33#include "ns3/wifi-phy-listener.h"
34#include "ns3/wifi-psdu.h"
35#include "ns3/wifi-spectrum-phy-interface.h"
36#include "ns3/wifi-spectrum-signal-parameters.h"
37#include "ns3/wifi-spectrum-value-helper.h"
38#include "ns3/wifi-utils.h"
39
40#include <memory>
41#include <tuple>
42#include <vector>
43
44using namespace ns3;
45
46NS_LOG_COMPONENT_DEFINE("SpectrumWifiPhyTest");
47
48static const uint8_t CHANNEL_NUMBER = 36;
49static const uint16_t CHANNEL_WIDTH = 20; // MHz
50static const uint16_t GUARD_WIDTH =
51 CHANNEL_WIDTH; // MHz (expanded to channel width to model spectrum mask)
52
57{
58 public:
60 using WifiPhy::GetBand;
61};
62
70{
71 public:
78 SpectrumWifiPhyBasicTest(std::string name);
80
81 protected:
82 void DoSetup() override;
83 void DoTeardown() override;
91 Ptr<SpectrumSignalParameters> MakeSignal(double txPowerWatts,
92 const WifiPhyOperatingChannel& channel);
97 void SendSignal(double txPowerWatts);
106 RxSignalInfo rxSignalInfo,
107 WifiTxVector txVector,
108 std::vector<bool> statusPerMpdu);
115
116 private:
117 void DoRun() override;
118
119 uint64_t m_uid;
120};
121
123 : SpectrumWifiPhyBasicTest("SpectrumWifiPhy test case receives one packet")
124{
125}
126
128 : TestCase(name),
129 m_count(0),
130 m_uid(0)
131{
132}
133
134// Make a Wi-Fi signal to inject directly to the StartRx() method
137{
139 0,
141 800,
142 1,
143 1,
144 0,
146 false);
147
148 Ptr<Packet> pkt = Create<Packet>(1000);
149 WifiMacHeader hdr;
150
152 hdr.SetQosTid(0);
153
154 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
155 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
156
157 Ptr<WifiPpdu> ppdu = Create<OfdmPpdu>(psdu, txVector, channel, m_uid++);
158
160 channel.GetPrimaryChannelCenterFrequency(CHANNEL_WIDTH),
162 txPowerWatts,
164 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
165 txParams->psd = txPowerSpectrum;
166 txParams->txPhy = nullptr;
167 txParams->duration = txDuration;
168 txParams->ppdu = ppdu;
169
170 return txParams;
171}
172
173// Make a Wi-Fi signal to inject directly to the StartRx() method
174void
176{
177 m_phy->StartRx(MakeSignal(txPowerWatts, m_phy->GetOperatingChannel()), nullptr);
178}
179
180void
182 RxSignalInfo rxSignalInfo,
183 WifiTxVector txVector,
184 std::vector<bool> statusPerMpdu)
185{
186 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
187 m_count++;
188}
189
190void
192{
193 NS_LOG_FUNCTION(this << *psdu);
194 m_count++;
195}
196
198{
199}
200
201// Create necessary objects, and inject signals. Test that the expected
202// number of packet receptions occur.
203void
205{
206 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
207 Ptr<Node> node = CreateObject<Node>();
208 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
209 m_phy = CreateObject<SpectrumWifiPhy>();
210 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
211 m_phy->SetInterferenceHelper(interferenceHelper);
212 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
213 m_phy->SetErrorRateModel(error);
214 m_phy->SetDevice(dev);
215 m_phy->AddChannel(spectrumChannel);
222 dev->SetPhy(m_phy);
223 node->AddDevice(dev);
224}
225
226void
228{
229 m_phy->Dispose();
230 m_phy = nullptr;
231}
232
233// Test that the expected number of packet receptions occur.
234void
236{
237 double txPowerWatts = 0.010;
238 // Send packets spaced 1 second apart; all should be received
242 // Send packets spaced 1 microsecond second apart; none should be received (PHY header reception
243 // failure)
246 this,
247 txPowerWatts);
250 this,
251 txPowerWatts);
254
255 NS_TEST_ASSERT_MSG_EQ(m_count, 3, "Didn't receive right number of packets");
256}
257
265{
266 public:
270 TestPhyListener() = default;
271 ~TestPhyListener() override = default;
272
273 void NotifyRxStart(Time duration) override
274 {
275 NS_LOG_FUNCTION(this << duration);
277 }
278
279 void NotifyRxEndOk() override
280 {
281 NS_LOG_FUNCTION(this);
283 }
284
285 void NotifyRxEndError() override
286 {
287 NS_LOG_FUNCTION(this);
289 }
290
291 void NotifyTxStart(Time duration, double txPowerDbm) override
292 {
293 NS_LOG_FUNCTION(this << duration << txPowerDbm);
294 }
295
297 WifiChannelListType channelType,
298 const std::vector<Time>& /*per20MhzDurations*/) override
299 {
300 NS_LOG_FUNCTION(this << duration << channelType);
301 if (duration.IsStrictlyPositive())
302 {
305 {
307 }
308 m_ccaBusyEnd = std::max(m_ccaBusyEnd, Simulator::Now() + duration);
309 }
310 }
311
312 void NotifySwitchingStart(Time duration) override
313 {
314 }
315
316 void NotifySleep() override
317 {
318 }
319
320 void NotifyOff() override
321 {
322 }
323
324 void NotifyWakeup() override
325 {
326 }
327
328 void NotifyOn() override
329 {
330 }
331
335 void Reset()
336 {
337 NS_LOG_FUNCTION(this);
338 m_notifyRxStart = 0;
339 m_notifyRxEndOk = 0;
344 }
345
352};
353
361{
362 public:
365
366 private:
367 void DoSetup() override;
368 void DoRun() override;
369 std::shared_ptr<TestPhyListener> m_listener;
370};
371
373 : SpectrumWifiPhyBasicTest("SpectrumWifiPhy test operation of WifiPhyListener")
374{
375}
376
378{
379}
380
381void
383{
385 m_listener = std::make_shared<TestPhyListener>();
387}
388
389void
391{
392 double txPowerWatts = 0.010;
395
396 NS_TEST_ASSERT_MSG_EQ(m_count, 1, "Didn't receive right number of packets");
398 m_listener->m_notifyMaybeCcaBusyStart,
399 2,
400 "Didn't receive NotifyCcaBusyStart (once preamble is detected + prolonged by L-SIG "
401 "reception, then switched to Rx by at the beginning of data)");
402 NS_TEST_ASSERT_MSG_EQ(m_listener->m_notifyRxStart, 1, "Didn't receive NotifyRxStart");
403 NS_TEST_ASSERT_MSG_EQ(m_listener->m_notifyRxEndOk, 1, "Didn't receive NotifyRxEnd");
404
406 m_listener.reset();
407}
408
416{
417 public:
424 SpectrumWifiPhyFilterTest(std::string name);
426
427 private:
428 void DoSetup() override;
429 void DoTeardown() override;
430 void DoRun() override;
431
435 void RunOne();
436
440 void SendPpdu();
441
448
451
454
455 std::set<WifiSpectrumBandIndices> m_ruBands;
456};
457
459 : TestCase("SpectrumWifiPhy test RX filters"),
460 m_txChannelWidth(20),
461 m_rxChannelWidth(20)
462{
463}
464
466 : TestCase(name)
467{
468}
469
470void
472{
474 0,
476 800,
477 1,
478 1,
479 0,
481 false,
482 false);
483 Ptr<Packet> pkt = Create<Packet>(1000);
484 WifiMacHeader hdr;
486 hdr.SetQosTid(0);
487 hdr.SetAddr1(Mac48Address("00:00:00:00:00:01"));
488 hdr.SetSequenceNumber(1);
489 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
490 m_txPhy->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
491}
492
494{
495 m_txPhy = nullptr;
496 m_rxPhy = nullptr;
497}
498
499void
501{
502 for (const auto& pair : rxPowersW)
503 {
504 NS_LOG_INFO("band: (" << pair.first << ") -> powerW=" << pair.second << " ("
505 << WToDbm(pair.second) << " dBm)");
506 }
507
508 size_t numBands = rxPowersW.size();
509 size_t expectedNumBands = std::max(1, (m_rxChannelWidth / 20));
510 expectedNumBands += (m_rxChannelWidth / 40);
511 expectedNumBands += (m_rxChannelWidth / 80);
512 expectedNumBands += (m_rxChannelWidth / 160);
513 expectedNumBands += m_ruBands.size();
514
515 NS_TEST_ASSERT_MSG_EQ(numBands,
516 expectedNumBands,
517 "Total number of bands handled by the receiver is incorrect");
518
519 uint16_t channelWidth = std::min(m_txChannelWidth, m_rxChannelWidth);
520 auto band = m_rxPhy->GetBand(channelWidth, 0);
521 auto it = rxPowersW.find(band);
522 NS_LOG_INFO("powerW total band: " << it->second << " (" << WToDbm(it->second) << " dBm)");
523 int totalRxPower = static_cast<int>(WToDbm(it->second) + 0.5);
524 int expectedTotalRxPower;
526 {
527 // PHY sends at 16 dBm, and since there is no loss, this should be the total power at the
528 // receiver.
529 expectedTotalRxPower = 16;
530 }
531 else
532 {
533 // Only a part of the transmitted power is received
534 expectedTotalRxPower =
535 16 - static_cast<int>(RatioToDb(m_txChannelWidth / m_rxChannelWidth));
536 }
537 NS_TEST_ASSERT_MSG_EQ(totalRxPower,
538 expectedTotalRxPower,
539 "Total received power is not correct");
540
541 if ((m_txChannelWidth <= m_rxChannelWidth) && (channelWidth >= 20))
542 {
543 band = m_rxPhy->GetBand(20, 0); // primary 20 MHz
544 it = rxPowersW.find(band);
545 NS_LOG_INFO("powerW in primary 20 MHz channel: " << it->second << " (" << WToDbm(it->second)
546 << " dBm)");
547 int rxPowerPrimaryChannel20 = static_cast<int>(WToDbm(it->second) + 0.5);
548 int expectedRxPowerPrimaryChannel20 = 16 - static_cast<int>(RatioToDb(channelWidth / 20));
549 NS_TEST_ASSERT_MSG_EQ(rxPowerPrimaryChannel20,
550 expectedRxPowerPrimaryChannel20,
551 "Received power in the primary 20 MHz band is not correct");
552 }
553}
554
555void
557{
558 // WifiHelper::EnableLogComponents();
559 // LogComponentEnable("SpectrumWifiPhyTest", LOG_LEVEL_ALL);
560
561 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
562 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
563 lossModel->SetFrequency(5.180e9);
564 spectrumChannel->AddPropagationLossModel(lossModel);
566 CreateObject<ConstantSpeedPropagationDelayModel>();
567 spectrumChannel->SetPropagationDelayModel(delayModel);
568
569 Ptr<Node> txNode = CreateObject<Node>();
570 Ptr<WifiNetDevice> txDev = CreateObject<WifiNetDevice>();
571 m_txPhy = CreateObject<ExtSpectrumWifiPhy>();
572 Ptr<InterferenceHelper> txInterferenceHelper = CreateObject<InterferenceHelper>();
573 m_txPhy->SetInterferenceHelper(txInterferenceHelper);
574 Ptr<ErrorRateModel> txErrorModel = CreateObject<NistErrorRateModel>();
575 m_txPhy->SetErrorRateModel(txErrorModel);
576 m_txPhy->SetDevice(txDev);
577 m_txPhy->AddChannel(spectrumChannel);
579 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
580 m_txPhy->SetMobility(apMobility);
581 txDev->SetPhy(m_txPhy);
582 txNode->AggregateObject(apMobility);
583 txNode->AddDevice(txDev);
584
585 Ptr<Node> rxNode = CreateObject<Node>();
586 Ptr<WifiNetDevice> rxDev = CreateObject<WifiNetDevice>();
587 m_rxPhy = CreateObject<ExtSpectrumWifiPhy>();
588 Ptr<InterferenceHelper> rxInterferenceHelper = CreateObject<InterferenceHelper>();
589 m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
590 Ptr<ErrorRateModel> rxErrorModel = CreateObject<NistErrorRateModel>();
591 m_rxPhy->SetErrorRateModel(rxErrorModel);
592 m_rxPhy->AddChannel(spectrumChannel);
594 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
595 m_rxPhy->SetMobility(sta1Mobility);
596 rxDev->SetPhy(m_rxPhy);
597 rxNode->AggregateObject(sta1Mobility);
598 rxNode->AddDevice(rxDev);
601}
602
603void
605{
606 m_txPhy->Dispose();
607 m_txPhy = nullptr;
608 m_rxPhy->Dispose();
609 m_rxPhy = nullptr;
610}
611
612void
614{
615 uint16_t txFrequency;
616 switch (m_txChannelWidth)
617 {
618 case 20:
619 default:
620 txFrequency = 5180;
621 break;
622 case 40:
623 txFrequency = 5190;
624 break;
625 case 80:
626 txFrequency = 5210;
627 break;
628 case 160:
629 txFrequency = 5250;
630 break;
631 }
632 auto txChannelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
633 txFrequency,
639
640 uint16_t rxFrequency;
641 switch (m_rxChannelWidth)
642 {
643 case 20:
644 default:
645 rxFrequency = 5180;
646 break;
647 case 40:
648 rxFrequency = 5190;
649 break;
650 case 80:
651 rxFrequency = 5210;
652 break;
653 case 160:
654 rxFrequency = 5250;
655 break;
656 }
657 auto rxChannelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
658 rxFrequency,
664
665 m_ruBands.clear();
666 for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
667 {
668 for (uint16_t i = 0; i < (m_rxChannelWidth / bw); ++i)
669 {
670 for (unsigned int type = 0; type < 7; type++)
671 {
672 auto ruType = static_cast<HeRu::RuType>(type);
673 for (std::size_t index = 1; index <= HeRu::GetNRus(bw, ruType); index++)
674 {
675 HeRu::SubcarrierGroup subcarrierGroup =
676 HeRu::GetSubcarrierGroup(bw, ruType, index);
677 HeRu::SubcarrierRange subcarrierRange =
678 std::make_pair(subcarrierGroup.front().first,
679 subcarrierGroup.back().second);
680 const auto band =
684 subcarrierRange,
685 i);
686 m_ruBands.insert(band);
687 }
688 }
689 }
690 }
691
693
695}
696
697void
699{
700 m_txChannelWidth = 20;
701 m_rxChannelWidth = 20;
702 RunOne();
703
704 m_txChannelWidth = 40;
705 m_rxChannelWidth = 40;
706 RunOne();
707
708 m_txChannelWidth = 80;
709 m_rxChannelWidth = 80;
710 RunOne();
711
712 m_txChannelWidth = 160;
713 m_rxChannelWidth = 160;
714 RunOne();
715
716 m_txChannelWidth = 20;
717 m_rxChannelWidth = 40;
718 RunOne();
719
720 m_txChannelWidth = 20;
721 m_rxChannelWidth = 80;
722 RunOne();
723
724 m_txChannelWidth = 40;
725 m_rxChannelWidth = 80;
726 RunOne();
727
728 m_txChannelWidth = 20;
729 m_rxChannelWidth = 160;
730 RunOne();
731
732 m_txChannelWidth = 40;
733 m_rxChannelWidth = 160;
734 RunOne();
735
736 m_txChannelWidth = 80;
737 m_rxChannelWidth = 160;
738 RunOne();
739
740 m_txChannelWidth = 40;
741 m_rxChannelWidth = 20;
742 RunOne();
743
744 m_txChannelWidth = 80;
745 m_rxChannelWidth = 20;
746 RunOne();
747
748 m_txChannelWidth = 80;
749 m_rxChannelWidth = 40;
750 RunOne();
751
752 m_txChannelWidth = 160;
753 m_rxChannelWidth = 20;
754 RunOne();
755
756 m_txChannelWidth = 160;
757 m_rxChannelWidth = 40;
758 RunOne();
759
760 m_txChannelWidth = 160;
761 m_rxChannelWidth = 80;
762 RunOne();
763
765}
766
790{
791 public:
798 SpectrumWifiPhyMultipleInterfacesTest(bool trackSignalsInactiveInterfaces);
799
800 private:
801 void DoSetup() override;
802 void DoTeardown() override;
803 void DoRun() override;
804
813 void SwitchChannel(std::size_t index,
814 WifiPhyBand band,
815 uint8_t channelNumber,
816 uint16_t channelWidth);
817
825 void SendPpdu(Ptr<SpectrumWifiPhy> phy, double txPowerDbm);
826
833 void RxCallback(std::size_t index,
834 Ptr<const Packet> packet,
835 RxPowerWattPerChannelBand rxPowersW);
836
845 const FrequencyRange& freqRange,
846 const WifiSpectrumBandInfo& band,
847 bool interferencesExpected);
848
856 const WifiSpectrumBandInfo& band,
857 bool interferencesExpected);
858
869 void CheckResults(std::size_t index,
870 uint32_t expectedNumRx,
871 FrequencyRange expectedFrequencyRangeActiveRfInterface,
872 const std::vector<std::size_t>& expectedConnectedPhysPerChannel);
873
882 void CheckCcaIndication(std::size_t index, bool expectedCcaBusyIndication, Time switchingDelay);
883
887 void Reset();
888
889 bool
892
893 std::vector<Ptr<MultiModelSpectrumChannel>> m_spectrumChannels;
894 std::vector<Ptr<SpectrumWifiPhy>> m_txPhys{};
895 std::vector<Ptr<SpectrumWifiPhy>> m_rxPhys{};
896 std::vector<std::shared_ptr<TestPhyListener>> m_listeners{};
897
898 std::vector<uint32_t> m_counts{0};
899
902};
903
905 bool trackSignalsInactiveInterfaces)
906 : TestCase{"SpectrumWifiPhy test operation with multiple RF interfaces"},
907 m_trackSignalsInactiveInterfaces{trackSignalsInactiveInterfaces}
908{
909}
910
911void
913 WifiPhyBand band,
914 uint8_t channelNumber,
915 uint16_t channelWidth)
916{
917 NS_LOG_FUNCTION(this << index << band << +channelNumber << channelWidth);
918 auto& listener = m_listeners.at(index);
919 listener->m_notifyMaybeCcaBusyStart = 0;
920 listener->m_ccaBusyStart = Seconds(0);
921 listener->m_ccaBusyEnd = Seconds(0);
922 auto phy = m_rxPhys.at(index);
923 phy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNumber, channelWidth, band, 0});
924}
925
926void
928{
929 NS_LOG_FUNCTION(this << phy << txPowerDbm << phy->GetCurrentFrequencyRange()
930 << phy->GetChannelWidth() << phy->GetChannelNumber());
931
932 WifiTxVector txVector =
933 WifiTxVector(HePhy::GetHeMcs0(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false);
934 Ptr<Packet> pkt = Create<Packet>(1000);
935 WifiMacHeader hdr;
937 hdr.SetQosTid(0);
938 hdr.SetAddr1(Mac48Address("00:00:00:00:00:01"));
939 hdr.SetSequenceNumber(1);
940 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
941
944 txVector,
945 phy->GetPhyBand());
946 phy->SetTxPowerStart(txPowerDbm);
947 phy->SetTxPowerEnd(txPowerDbm);
948 phy->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
949}
950
951void
953 Ptr<const Packet> /*packet*/,
954 RxPowerWattPerChannelBand /*rxPowersW*/)
955{
956 auto phy = m_rxPhys.at(index);
957 NS_LOG_FUNCTION(this << index << phy->GetCurrentFrequencyRange() << phy->GetChannelWidth()
958 << phy->GetChannelNumber());
959 m_counts.at(index)++;
960}
961
962void
964 const FrequencyRange& freqRange,
965 const WifiSpectrumBandInfo& band,
966 bool interferencesExpected)
967{
968 if ((!m_trackSignalsInactiveInterfaces) && (phy->GetCurrentFrequencyRange() != freqRange))
969 {
970 // ignore since no bands for that range exists in interference helper in that case
971 return;
972 }
973 // This is needed to make sure PHY state will be checked as the last event if a state change
974 // occurred at the exact same time as the check
976 this,
977 phy,
978 band,
979 interferencesExpected);
980}
981
982void
984 const WifiSpectrumBandInfo& band,
985 bool interferencesExpected)
986{
987 NS_LOG_FUNCTION(this << phy << band << interferencesExpected);
988 PointerValue ptr;
989 phy->GetAttribute("InterferenceHelper", ptr);
990 auto interferenceHelper = DynamicCast<InterferenceHelper>(ptr.Get<InterferenceHelper>());
991 NS_ASSERT(interferenceHelper);
992 const auto energyDuration = interferenceHelper->GetEnergyDuration(0, band);
993 NS_TEST_ASSERT_MSG_EQ(energyDuration.IsStrictlyPositive(),
994 interferencesExpected,
995 "Incorrect interferences detection");
996}
997
998void
1000 std::size_t index,
1001 uint32_t expectedNumRx,
1002 FrequencyRange expectedFrequencyRangeActiveRfInterface,
1003 const std::vector<std::size_t>& expectedConnectedPhysPerChannel)
1004{
1005 NS_LOG_FUNCTION(this << index << expectedNumRx << expectedFrequencyRangeActiveRfInterface);
1006 const auto phy = m_rxPhys.at(index);
1007 std::size_t numActiveInterfaces = 0;
1008 for (const auto& [freqRange, interface] : phy->GetSpectrumPhyInterfaces())
1009 {
1010 const auto expectedActive = (freqRange == expectedFrequencyRangeActiveRfInterface);
1011 const auto isActive = (interface == phy->GetCurrentInterface());
1012 NS_TEST_ASSERT_MSG_EQ(isActive, expectedActive, "Incorrect active interface");
1013 if (isActive)
1014 {
1015 numActiveInterfaces++;
1016 }
1017 }
1018 NS_TEST_ASSERT_MSG_EQ(numActiveInterfaces, 1, "There should always be one active interface");
1019 NS_ASSERT(expectedConnectedPhysPerChannel.size() == m_spectrumChannels.size());
1020 for (std::size_t i = 0; i < m_spectrumChannels.size(); ++i)
1021 {
1022 NS_TEST_ASSERT_MSG_EQ(m_spectrumChannels.at(i)->GetNDevices(),
1023 expectedConnectedPhysPerChannel.at(i),
1024 "Incorrect number of PHYs attached to the spectrum channel");
1025 }
1027 expectedNumRx,
1028 "Didn't receive right number of packets");
1029 NS_TEST_ASSERT_MSG_EQ(m_listeners.at(index)->m_notifyRxStart,
1030 expectedNumRx,
1031 "Didn't receive NotifyRxStart");
1032}
1033
1034void
1036 bool expectedCcaBusyIndication,
1037 Time switchingDelay)
1038{
1039 const auto expectedCcaBusyStart =
1040 expectedCcaBusyIndication ? m_lastTxStart + switchingDelay : Seconds(0);
1041 const auto expectedCcaBusyEnd = expectedCcaBusyIndication ? m_lastTxEnd : Seconds(0);
1042 NS_LOG_FUNCTION(this << index << expectedCcaBusyIndication << expectedCcaBusyStart
1043 << expectedCcaBusyEnd);
1044 auto& listener = m_listeners.at(index);
1045 const auto ccaBusyIndication = (listener->m_notifyMaybeCcaBusyStart > 0);
1046 const auto ccaBusyStart = listener->m_ccaBusyStart;
1047 const auto ccaBusyEnd = listener->m_ccaBusyEnd;
1048 NS_TEST_ASSERT_MSG_EQ(ccaBusyIndication,
1049 expectedCcaBusyIndication,
1050 "CCA busy indication check failed");
1051 NS_TEST_ASSERT_MSG_EQ(ccaBusyStart, expectedCcaBusyStart, "CCA busy start mismatch");
1052 NS_TEST_ASSERT_MSG_EQ(ccaBusyEnd, expectedCcaBusyEnd, "CCA busy end mismatch");
1053}
1054
1055void
1057{
1058 NS_LOG_FUNCTION(this);
1059 for (auto& count : m_counts)
1060 {
1061 count = 0;
1062 }
1063 for (auto& listener : m_listeners)
1064 {
1065 listener->Reset();
1066 }
1067 // restore all RX PHYs to initial channels
1068 for (std::size_t rxPhyIndex = 0; rxPhyIndex < m_rxPhys.size(); ++rxPhyIndex)
1069 {
1070 auto txPhy = m_txPhys.at(rxPhyIndex);
1071 SwitchChannel(rxPhyIndex,
1072 txPhy->GetPhyBand(),
1073 txPhy->GetChannelNumber(),
1074 txPhy->GetChannelWidth());
1075 }
1076}
1077
1078void
1080{
1081 NS_LOG_FUNCTION(this);
1082
1083 // WifiHelper::EnableLogComponents();
1084 // LogComponentEnable("SpectrumWifiPhyTest", LOG_LEVEL_ALL);
1085
1086 NodeContainer wifiApNode(1);
1087 NodeContainer wifiStaNode(1);
1088
1089 WifiHelper wifi;
1090 wifi.SetStandard(WIFI_STANDARD_80211be);
1091
1092 SpectrumWifiPhyHelper phyHelper(4);
1094
1095 struct SpectrumPhyInterfaceInfo
1096 {
1097 FrequencyRange range;
1098 uint8_t number;
1099 WifiPhyBand band;
1100 std::string bandName;
1101 };
1102
1103 const FrequencyRange WIFI_SPECTRUM_5_GHZ_LOW{
1107 const FrequencyRange WIFI_SPECTRUM_5_GHZ_HIGH{
1111
1112 const std::vector<SpectrumPhyInterfaceInfo> interfaces{
1113 {WIFI_SPECTRUM_2_4_GHZ, 2, WIFI_PHY_BAND_2_4GHZ, "BAND_2_4GHZ"},
1114 {WIFI_SPECTRUM_5_GHZ_LOW, 42, WIFI_PHY_BAND_5GHZ, "BAND_5GHZ"},
1115 {WIFI_SPECTRUM_5_GHZ_HIGH, 163, WIFI_PHY_BAND_5GHZ, "BAND_5GHZ"},
1116 {WIFI_SPECTRUM_6_GHZ, 215, WIFI_PHY_BAND_6GHZ, "BAND_6GHZ"}};
1117
1118 for (std::size_t i = 0; i < interfaces.size(); ++i)
1119 {
1120 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1121 [[maybe_unused]] const auto [channel, frequency, channelWidth, type, band] =
1122 (*WifiPhyOperatingChannel::FindFirst(interfaces.at(i).number,
1123 0,
1124 0,
1126 interfaces.at(i).band));
1127
1128 std::ostringstream oss;
1129 oss << "{" << +interfaces.at(i).number << ", 0, " << interfaces.at(i).bandName << ", 0}";
1130 phyHelper.Set(i, "ChannelSettings", StringValue(oss.str()));
1131 phyHelper.AddChannel(spectrumChannel, interfaces.at(i).range);
1132
1133 m_spectrumChannels.emplace_back(spectrumChannel);
1134 }
1135
1136 WifiMacHelper mac;
1137 mac.SetType("ns3::ApWifiMac", "BeaconGeneration", BooleanValue(false));
1138 phyHelper.Set("TrackSignalsFromInactiveInterfaces", BooleanValue(false));
1139 auto apDevice = wifi.Install(phyHelper, mac, wifiApNode.Get(0));
1140
1141 mac.SetType("ns3::StaWifiMac", "ActiveProbing", BooleanValue(false));
1142 phyHelper.Set("TrackSignalsFromInactiveInterfaces",
1144 auto staDevice = wifi.Install(phyHelper, mac, wifiStaNode.Get(0));
1145
1146 for (std::size_t i = 0; i < interfaces.size(); ++i)
1147 {
1148 auto txPhy =
1149 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(apDevice.Get(0))->GetPhy(i));
1150 m_txPhys.push_back(txPhy);
1151
1152 const auto index = m_rxPhys.size();
1153 auto rxPhy =
1154 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(staDevice.Get(0))->GetPhy(i));
1155 rxPhy->TraceConnectWithoutContext(
1156 "PhyRxBegin",
1158
1159 auto listener = std::make_shared<TestPhyListener>();
1160 rxPhy->RegisterListener(listener);
1161 m_listeners.push_back(std::move(listener));
1162
1163 m_rxPhys.push_back(rxPhy);
1164 m_counts.push_back(0);
1165 }
1166}
1167
1168void
1170{
1171 NS_LOG_FUNCTION(this);
1172 for (auto& phy : m_txPhys)
1173 {
1174 phy->Dispose();
1175 phy = nullptr;
1176 }
1177 for (auto& phy : m_rxPhys)
1178 {
1179 phy->Dispose();
1180 phy = nullptr;
1181 }
1183}
1184
1185void
1187{
1188 NS_LOG_FUNCTION(this);
1189
1190 const auto ccaEdThresholdDbm = -62.0;
1191 const auto txAfterChannelSwitchDelay =
1192 Seconds(0.25);
1194 const auto checkResultsDelay =
1195 Seconds(0.5);
1196 const auto flushResultsDelay =
1197 Seconds(0.9);
1198 const auto txOngoingAfterTxStartedDelay =
1199 MicroSeconds(50);
1201
1202 Time delay{0};
1203
1204 // default channels active for all PHYs: each PHY only receives from its associated TX
1205 std::vector<std::size_t> expectedConnectedPhysPerChannel =
1206 m_trackSignalsInactiveInterfaces ? std::vector<std::size_t>{5, 5, 5, 5}
1207 : // all RX PHYs keep all channels active when tracking
1208 // interferences on inactive interfaces
1209 std::vector<std::size_t>{2, 2, 2, 2}; // default channels active for all PHYs: each PHY
1210 // only receives from its associated TX
1211 for (std::size_t i = 0; i < 4; ++i)
1212 {
1213 auto txPpduPhy = m_txPhys.at(i);
1214 delay += Seconds(1);
1215 Simulator::Schedule(delay,
1217 this,
1218 txPpduPhy,
1219 0);
1220 for (std::size_t j = 0; j < 4; ++j)
1221 {
1222 auto txPhy = m_txPhys.at(j);
1223 auto rxPhy = m_rxPhys.at(j);
1224 const auto& expectedFreqRange = txPhy->GetCurrentFrequencyRange();
1225 Simulator::Schedule(delay + txOngoingAfterTxStartedDelay,
1227 this,
1228 rxPhy,
1229 txPpduPhy->GetCurrentFrequencyRange(),
1230 txPpduPhy->GetBand(txPpduPhy->GetChannelWidth(), 0),
1231 true);
1232 Simulator::Schedule(delay + checkResultsDelay,
1234 this,
1235 j,
1236 (i == j) ? 1 : 0,
1237 expectedFreqRange,
1238 expectedConnectedPhysPerChannel);
1239 }
1240 Simulator::Schedule(delay + flushResultsDelay,
1242 this);
1243 }
1244
1245 // same channel active for all PHYs: all PHYs receive from TX
1246 for (std::size_t i = 0; i < 4; ++i)
1247 {
1248 delay += Seconds(1);
1249 auto txPpduPhy = m_txPhys.at(i);
1250 Simulator::Schedule(delay + txAfterChannelSwitchDelay,
1252 this,
1253 txPpduPhy,
1254 0);
1255 const auto& expectedFreqRange = txPpduPhy->GetCurrentFrequencyRange();
1256 for (std::size_t j = 0; j < 4; ++j)
1257 {
1259 {
1260 for (std::size_t k = 0; k < expectedConnectedPhysPerChannel.size(); ++k)
1261 {
1262 expectedConnectedPhysPerChannel.at(k) = (k == i) ? 5 : 1;
1263 }
1264 }
1265 auto rxPhy = m_rxPhys.at(j);
1266 Simulator::Schedule(delay,
1268 this,
1269 j,
1270 txPpduPhy->GetPhyBand(),
1271 txPpduPhy->GetChannelNumber(),
1272 txPpduPhy->GetChannelWidth());
1273 Simulator::Schedule(delay + txAfterChannelSwitchDelay + txOngoingAfterTxStartedDelay,
1275 this,
1276 rxPhy,
1277 txPpduPhy->GetCurrentFrequencyRange(),
1278 txPpduPhy->GetBand(txPpduPhy->GetChannelWidth(), 0),
1279 true);
1280 Simulator::Schedule(delay + checkResultsDelay,
1282 this,
1283 j,
1284 1,
1285 expectedFreqRange,
1286 expectedConnectedPhysPerChannel);
1287 }
1288 Simulator::Schedule(delay + flushResultsDelay,
1290 this);
1291 }
1292
1293 // Switch all PHYs to channel 36: all PHYs switch to the second spectrum channel
1294 // since second spectrum channel is 42 (80 MHz) and hence covers channel 36 (20 MHz)
1295 const auto secondSpectrumChannelIndex = 1;
1296 auto channel36TxPhy = m_txPhys.at(secondSpectrumChannelIndex);
1297 const auto& expectedFreqRange = channel36TxPhy->GetCurrentFrequencyRange();
1298 for (std::size_t i = 0; i < 4; ++i)
1299 {
1300 delay += Seconds(1);
1301 auto txPpduPhy = m_txPhys.at(i);
1302 Simulator::Schedule(delay + txAfterChannelSwitchDelay,
1304 this,
1305 txPpduPhy,
1306 0);
1307 for (std::size_t j = 0; j < 4; ++j)
1308 {
1310 {
1311 for (std::size_t k = 0; k < expectedConnectedPhysPerChannel.size(); ++k)
1312 {
1313 expectedConnectedPhysPerChannel.at(k) =
1314 (k == secondSpectrumChannelIndex) ? 5 : 1;
1315 }
1316 }
1317 Simulator::Schedule(delay,
1319 this,
1320 j,
1324 Simulator::Schedule(delay + checkResultsDelay,
1326 this,
1327 j,
1328 (i == secondSpectrumChannelIndex) ? 1 : 0,
1329 expectedFreqRange,
1330 expectedConnectedPhysPerChannel);
1331 }
1332 Simulator::Schedule(delay + flushResultsDelay,
1334 this);
1335 }
1336
1337 // verify CCA indication when switching to a channel with an ongoing transmission
1338 for (const auto txPowerDbm : {-60.0 /* above CCA-ED */, -70.0 /* below CCA-ED */})
1339 {
1340 for (std::size_t i = 0; i < 4; ++i)
1341 {
1342 for (std::size_t j = 0; j < 4; ++j)
1343 {
1344 auto txPpduPhy = m_txPhys.at(i);
1345 const auto startChannel =
1346 WifiPhyOperatingChannel::FindFirst(txPpduPhy->GetPrimaryChannelNumber(20),
1347 0,
1348 20,
1350 txPpduPhy->GetPhyBand());
1351 for (uint16_t bw = txPpduPhy->GetChannelWidth(); bw >= 20; bw /= 2)
1352 {
1353 [[maybe_unused]] const auto [channel, frequency, channelWidth, type, band] =
1355 0,
1356 bw,
1358 txPpduPhy->GetPhyBand(),
1359 startChannel));
1360 delay += Seconds(1);
1361 Simulator::Schedule(delay,
1363 this,
1364 txPpduPhy,
1365 txPowerDbm);
1366 Simulator::Schedule(delay + txOngoingAfterTxStartedDelay,
1368 this,
1369 j,
1370 band,
1371 channel,
1372 channelWidth);
1373 for (std::size_t k = 0; k < 4; ++k)
1374 {
1375 if ((i != j) && (k == i))
1376 {
1377 continue;
1378 }
1379 const auto expectCcaBusyIndication =
1380 (k == i) ? (txPowerDbm >= ccaEdThresholdDbm)
1382 ? ((txPowerDbm >= ccaEdThresholdDbm) ? (j == k) : false)
1383 : false);
1385 delay + checkResultsDelay,
1387 this,
1388 k,
1389 expectCcaBusyIndication,
1390 txOngoingAfterTxStartedDelay);
1391 }
1392 Simulator::Schedule(delay + flushResultsDelay,
1394 this);
1395 }
1396 }
1397 }
1398 }
1399
1402}
1403
1414{
1415 public:
1418
1419 private:
1420 void DoRun() override;
1421};
1422
1424 : TestCase("Check PHY interfaces added to PHY instances using helper")
1425{
1426}
1427
1428void
1430{
1431 WifiHelper wifiHelper;
1433
1434 SpectrumWifiPhyHelper phyHelper(3);
1435 phyHelper.Set(0, "ChannelSettings", StringValue("{2, 0, BAND_2_4GHZ, 0}"));
1436 phyHelper.Set(1, "ChannelSettings", StringValue("{36, 0, BAND_5GHZ, 0}"));
1437 phyHelper.Set(2, "ChannelSettings", StringValue("{1, 0, BAND_6GHZ, 0}"));
1438
1439 phyHelper.AddChannel(CreateObject<MultiModelSpectrumChannel>(), WIFI_SPECTRUM_2_4_GHZ);
1440 phyHelper.AddChannel(CreateObject<MultiModelSpectrumChannel>(), WIFI_SPECTRUM_5_GHZ);
1441 phyHelper.AddChannel(CreateObject<MultiModelSpectrumChannel>(), WIFI_SPECTRUM_6_GHZ);
1442
1443 WifiMacHelper macHelper;
1445
1446 /* Default case: all interfaces are added to each link */
1447 auto device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(0));
1448
1449 // Verify each PHY has 3 interfaces
1450 auto phyLink0 =
1451 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1452 NS_ASSERT(phyLink0);
1453 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1454 3,
1455 "Incorrect number of PHY interfaces added to PHY link ID 0");
1456
1457 auto phyLink1 =
1458 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1459 NS_ASSERT(phyLink1);
1460 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1461 3,
1462 "Incorrect number of PHY interfaces added to PHY link ID 1");
1463
1464 auto phyLink2 =
1465 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1466 NS_ASSERT(phyLink2);
1467 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1468 3,
1469 "Incorrect number of PHY interfaces added to PHY link ID 2");
1470
1471 /* each PHY has a single interface */
1475 device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(1));
1476
1477 // Verify each PHY has a single interface
1478 phyLink0 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1479 NS_ASSERT(phyLink0);
1480 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1481 1,
1482 "Incorrect number of PHY interfaces added to PHY link ID 0");
1483 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1484 1,
1485 "Incorrect PHY interfaces added to PHY link ID 0");
1486
1487 phyLink1 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1488 NS_ASSERT(phyLink1);
1489 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1490 1,
1491 "Incorrect number of PHY interfaces added to PHY link ID 1");
1492 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1493 1,
1494 "Incorrect PHY interfaces added to PHY link ID 1");
1495
1496 phyLink2 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1497 NS_ASSERT(phyLink2);
1498 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().size(),
1499 1,
1500 "Incorrect number of PHY interfaces added to PHY link ID 2");
1501 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1502 1,
1503 "Incorrect PHY interfaces added to PHY link ID 2");
1504
1505 /* add yet another interface to PHY 0 */
1507 device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(2));
1508
1509 // Verify each PHY has a single interface except PHY 0 that should have 2 interfaces
1510 phyLink0 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1511 NS_ASSERT(phyLink0);
1512 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1513 2,
1514 "Incorrect number of PHY interfaces added to PHY link ID 0");
1515 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1516 1,
1517 "Incorrect PHY interfaces added to PHY link ID 0");
1518 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1519 1,
1520 "Incorrect PHY interfaces added to PHY link ID 0");
1521
1522 phyLink1 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1523 NS_ASSERT(phyLink1);
1524 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1525 1,
1526 "Incorrect number of PHY interfaces added to PHY link ID 1");
1527 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1528 1,
1529 "Incorrect PHY interfaces added to PHY link ID 1");
1530
1531 phyLink2 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1532 NS_ASSERT(phyLink2);
1533 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().size(),
1534 1,
1535 "Incorrect number of PHY interfaces added to PHY link ID 2");
1536 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1537 1,
1538 "Incorrect PHY interfaces added to PHY link ID 2");
1539
1540 /* reset mapping previously configured to helper: back to default */
1541 phyHelper.ResetPhyToFreqRangeMapping();
1542 device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(3));
1543
1544 // Verify each PHY has 3 interfaces
1545 phyLink0 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1546 NS_ASSERT(phyLink0);
1547 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1548 3,
1549 "Incorrect number of PHY interfaces added to PHY link ID 0");
1550 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1551 1,
1552 "Incorrect PHY interfaces added to PHY link ID 0");
1553 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1554 1,
1555 "Incorrect PHY interfaces added to PHY link ID 0");
1556 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1557 1,
1558 "Incorrect PHY interfaces added to PHY link ID 0");
1559
1560 phyLink1 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1561 NS_ASSERT(phyLink1);
1562 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1563 3,
1564 "Incorrect number of PHY interfaces added to PHY link ID 1");
1565 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1566 1,
1567 "Incorrect PHY interfaces added to PHY link ID 0");
1568 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1569 1,
1570 "Incorrect PHY interfaces added to PHY link ID 0");
1571 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1572 1,
1573 "Incorrect PHY interfaces added to PHY link ID 0");
1574
1575 phyLink2 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1576 NS_ASSERT(phyLink2);
1577 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().size(),
1578 3,
1579 "Incorrect number of PHY interfaces added to PHY link ID 2");
1580 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1581 1,
1582 "Incorrect PHY interfaces added to PHY link ID 0");
1583 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1584 1,
1585 "Incorrect PHY interfaces added to PHY link ID 0");
1586 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1587 1,
1588 "Incorrect PHY interfaces added to PHY link ID 0");
1589
1591}
1592
1600{
1601 public:
1603};
1604
1606 : TestSuite("wifi-spectrum-wifi-phy", UNIT)
1607{
1614}
1615
Extended SpectrumWifiPhy class for the purpose of the tests.
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 Interfaces Helper Test.
~SpectrumWifiPhyInterfacesHelperTest() override=default
void DoRun() override
Implementation to actually run this TestCase.
Spectrum Wifi Phy Listener Test.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::shared_ptr< TestPhyListener > m_listener
listener
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< SpectrumWifiPhy > > m_rxPhys
RX PHYs.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void DoCheckInterferences(Ptr< SpectrumWifiPhy > phy, const WifiSpectrumBandInfo &band, bool interferencesExpected)
Check the interferences.
SpectrumWifiPhyMultipleInterfacesTest(bool trackSignalsInactiveInterfaces)
Constructor.
bool m_trackSignalsInactiveInterfaces
flag to indicate whether signals coming from inactive spectrum PHY interfaces are tracked during the ...
std::vector< std::shared_ptr< TestPhyListener > > m_listeners
listeners
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.
std::vector< Ptr< SpectrumWifiPhy > > m_txPhys
TX PHYs.
void SendPpdu(Ptr< SpectrumWifiPhy > phy, double txPowerDbm)
Send PPDU function.
std::vector< Ptr< MultiModelSpectrumChannel > > m_spectrumChannels
Spectrum channels.
void CheckInterferences(Ptr< SpectrumWifiPhy > phy, const FrequencyRange &freqRange, const WifiSpectrumBandInfo &band, 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.
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:1819
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:587
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:491
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
keep track of a set of node pointers.
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:315
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:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition: simulator.h:605
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Make it easy to create and manage PHY objects for the spectrum model.
void ResetPhyToFreqRangeMapping()
Reset mapping of the spectrum PHY interfaces added to the PHY instances.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
void AddPhyToFreqRangeMapping(uint8_t linkId, const FrequencyRange &freqRange)
Add a given spectrum PHY interface to the PHY instance corresponding of a given link.
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 AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
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.
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
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
Definition: nstime.h:351
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
virtual void SetStandard(WifiStandard standard)
Definition: wifi-helper.cc:738
virtual NetDeviceContainer Install(const WifiPhyHelper &phy, const WifiMacHelper &mac, NodeContainer::Iterator first, NodeContainer::Iterator last) const
Definition: wifi-helper.cc:756
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.
virtual 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.
create MAC layers for a ns3::WifiNetDevice.
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
Definition: wifi-helper.cc:543
void Set(std::string name, const AttributeValue &v)
Definition: wifi-helper.cc:163
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
Definition: wifi-helper.h:178
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:631
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:1720
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:639
uint32_t GetSubcarrierSpacing() const
Definition: wifi-phy.cc:2251
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:455
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:961
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1507
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition: wifi-phy.cc:461
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:1098
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1021
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:891
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:619
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:449
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1033
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:1350
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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_80211be
@ 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
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr FrequencyRange WIFI_SPECTRUM_6_GHZ
Identifier for the frequency range covering the wifi spectrum in the 6 GHz band.
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:704
constexpr FrequencyRange WIFI_SPECTRUM_5_GHZ
Identifier for the frequency range covering the wifi spectrum in the 5 GHz band.
@ WIFI_MAC_QOSDATA
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:77
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
constexpr FrequencyRange WIFI_SPECTRUM_2_4_GHZ
Identifier for the frequency range covering the wifi spectrum in the 2.4 GHz band.
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).
uint16_t maxFrequency
the maximum frequency in MHz
uint16_t minFrequency
the minimum frequency in MHz
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
WifiSpectrumBandInfo structure containing info about a spectrum band.