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
53/**
54 * Extended SpectrumWifiPhy class for the purpose of the tests.
55 */
57{
58 public:
59 using WifiPhy::GetBand;
60};
61
62/**
63 * \ingroup wifi-test
64 * \ingroup tests
65 *
66 * \brief Spectrum Wifi Phy Basic Test
67 */
69{
70 public:
72 /**
73 * Constructor
74 *
75 * \param name reference name
76 */
77 SpectrumWifiPhyBasicTest(std::string name);
79
80 protected:
81 void DoSetup() override;
82 void DoTeardown() override;
84 /**
85 * Make signal function
86 * \param txPowerWatts the transmit power in watts
87 * \param channel the operating channel of the PHY used for the transmission
88 * \returns Ptr<SpectrumSignalParameters>
89 */
90 Ptr<SpectrumSignalParameters> MakeSignal(double txPowerWatts,
91 const WifiPhyOperatingChannel& channel);
92 /**
93 * Send signal function
94 * \param txPowerWatts the transmit power in watts
95 */
96 void SendSignal(double txPowerWatts);
97 /**
98 * Spectrum wifi receive success function
99 * \param psdu the PSDU
100 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
101 * \param txVector the transmit vector
102 * \param statusPerMpdu reception status per MPDU
103 */
105 RxSignalInfo rxSignalInfo,
106 WifiTxVector txVector,
107 std::vector<bool> statusPerMpdu);
108 /**
109 * Spectrum wifi receive failure function
110 * \param psdu the PSDU
111 */
113 uint32_t m_count; ///< count
114
115 private:
116 void DoRun() override;
117
118 uint64_t m_uid; //!< the UID to use for the PPDU
119};
120
122 : SpectrumWifiPhyBasicTest("SpectrumWifiPhy test case receives one packet")
123{
124}
125
127 : TestCase(name),
128 m_count(0),
129 m_uid(0)
130{
131}
132
133// Make a Wi-Fi signal to inject directly to the StartRx() method
136{
138 0,
140 800,
141 1,
142 1,
143 0,
145 false);
146
147 Ptr<Packet> pkt = Create<Packet>(1000);
148 WifiMacHeader hdr;
149
151 hdr.SetQosTid(0);
152
153 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
154 Time txDuration = m_phy->CalculateTxDuration(psdu->GetSize(), txVector, m_phy->GetPhyBand());
155
156 Ptr<WifiPpdu> ppdu = Create<OfdmPpdu>(psdu, txVector, channel, m_uid++);
157
159 channel.GetPrimaryChannelCenterFrequency(CHANNEL_WIDTH),
161 txPowerWatts,
163 Ptr<WifiSpectrumSignalParameters> txParams = Create<WifiSpectrumSignalParameters>();
164 txParams->psd = txPowerSpectrum;
165 txParams->txPhy = nullptr;
166 txParams->duration = txDuration;
167 txParams->ppdu = ppdu;
168
169 return txParams;
170}
171
172// Make a Wi-Fi signal to inject directly to the StartRx() method
173void
175{
176 m_phy->StartRx(MakeSignal(txPowerWatts, m_phy->GetOperatingChannel()), nullptr);
177}
178
179void
181 RxSignalInfo rxSignalInfo,
182 WifiTxVector txVector,
183 std::vector<bool> statusPerMpdu)
184{
185 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
186 m_count++;
187}
188
189void
191{
192 NS_LOG_FUNCTION(this << *psdu);
193 m_count++;
194}
195
197{
198}
199
200// Create necessary objects, and inject signals. Test that the expected
201// number of packet receptions occur.
202void
204{
205 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
206 Ptr<Node> node = CreateObject<Node>();
207 Ptr<WifiNetDevice> dev = CreateObject<WifiNetDevice>();
208 m_phy = CreateObject<SpectrumWifiPhy>();
209 Ptr<InterferenceHelper> interferenceHelper = CreateObject<InterferenceHelper>();
210 m_phy->SetInterferenceHelper(interferenceHelper);
211 Ptr<ErrorRateModel> error = CreateObject<NistErrorRateModel>();
212 m_phy->SetErrorRateModel(error);
213 m_phy->SetDevice(dev);
214 m_phy->AddChannel(spectrumChannel);
221 dev->SetPhy(m_phy);
222 node->AddDevice(dev);
223}
224
225void
227{
228 m_phy->Dispose();
229 m_phy = nullptr;
230}
231
232// Test that the expected number of packet receptions occur.
233void
235{
236 double txPowerWatts = 0.010;
237 // Send packets spaced 1 second apart; all should be received
241 // Send packets spaced 1 microsecond second apart; none should be received (PHY header reception
242 // failure)
245 this,
246 txPowerWatts);
249 this,
250 txPowerWatts);
253
254 NS_TEST_ASSERT_MSG_EQ(m_count, 3, "Didn't receive right number of packets");
255}
256
257/**
258 * \ingroup wifi-test
259 * \ingroup tests
260 *
261 * \brief Test Phy Listener
262 */
264{
265 public:
266 /**
267 * Create a test PhyListener
268 */
269 TestPhyListener() = default;
270 ~TestPhyListener() override = default;
271
272 void NotifyRxStart(Time duration) override
273 {
274 NS_LOG_FUNCTION(this << duration);
276 }
277
278 void NotifyRxEndOk() override
279 {
280 NS_LOG_FUNCTION(this);
282 }
283
284 void NotifyRxEndError() override
285 {
286 NS_LOG_FUNCTION(this);
288 }
289
290 void NotifyTxStart(Time duration, double txPowerDbm) override
291 {
292 NS_LOG_FUNCTION(this << duration << txPowerDbm);
293 }
294
296 WifiChannelListType channelType,
297 const std::vector<Time>& /*per20MhzDurations*/) override
298 {
299 NS_LOG_FUNCTION(this << duration << channelType);
300 if (duration.IsStrictlyPositive())
301 {
304 {
306 }
307 m_ccaBusyEnd = std::max(m_ccaBusyEnd, Simulator::Now() + duration);
308 }
309 }
310
311 void NotifySwitchingStart(Time duration) override
312 {
313 }
314
315 void NotifySleep() override
316 {
317 }
318
319 void NotifyOff() override
320 {
321 }
322
323 void NotifyWakeup() override
324 {
325 }
326
327 void NotifyOn() override
328 {
329 }
330
331 /**
332 * Reset function
333 */
334 void Reset()
335 {
336 NS_LOG_FUNCTION(this);
337 m_notifyRxStart = 0;
338 m_notifyRxEndOk = 0;
343 }
344
345 uint32_t m_notifyRxStart{0}; ///< notify receive start
346 uint32_t m_notifyRxEndOk{0}; ///< notify receive end OK
347 uint32_t m_notifyRxEndError{0}; ///< notify receive end error
348 uint32_t m_notifyMaybeCcaBusyStart{0}; ///< notify maybe CCA busy start
349 Time m_ccaBusyStart{0}; ///< CCA_BUSY start time
350 Time m_ccaBusyEnd{0}; ///< CCA_BUSY end time
351};
352
353/**
354 * \ingroup wifi-test
355 * \ingroup tests
356 *
357 * \brief Spectrum Wifi Phy Listener Test
358 */
360{
361 public:
364
365 private:
366 void DoSetup() override;
367 void DoRun() override;
368 std::shared_ptr<TestPhyListener> m_listener; ///< listener
369};
370
372 : SpectrumWifiPhyBasicTest("SpectrumWifiPhy test operation of WifiPhyListener")
373{
374}
375
377{
378}
379
380void
382{
384 m_listener = std::make_shared<TestPhyListener>();
386}
387
388void
390{
391 double txPowerWatts = 0.010;
394
395 NS_TEST_ASSERT_MSG_EQ(m_count, 1, "Didn't receive right number of packets");
397 m_listener->m_notifyMaybeCcaBusyStart,
398 2,
399 "Didn't receive NotifyCcaBusyStart (once preamble is detected + prolonged by L-SIG "
400 "reception, then switched to Rx by at the beginning of data)");
401 NS_TEST_ASSERT_MSG_EQ(m_listener->m_notifyRxStart, 1, "Didn't receive NotifyRxStart");
402 NS_TEST_ASSERT_MSG_EQ(m_listener->m_notifyRxEndOk, 1, "Didn't receive NotifyRxEnd");
403
405 m_listener.reset();
406}
407
408/**
409 * \ingroup wifi-test
410 * \ingroup tests
411 *
412 * \brief Spectrum Wifi Phy Filter Test
413 */
415{
416 public:
418 /**
419 * Constructor
420 *
421 * \param name reference name
422 */
423 SpectrumWifiPhyFilterTest(std::string name);
425
426 private:
427 void DoSetup() override;
428 void DoTeardown() override;
429 void DoRun() override;
430
431 /**
432 * Run one function
433 */
434 void RunOne();
435
436 /**
437 * Send PPDU function
438 */
439 void SendPpdu();
440
441 /**
442 * Callback triggered when a packet is received by the PHYs
443 * \param p the received packet
444 * \param rxPowersW the received power per channel band in watts
445 */
447
450
451 uint16_t m_txChannelWidth; ///< TX channel width (MHz)
452 uint16_t m_rxChannelWidth; ///< RX channel width (MHz)
453
454 std::set<WifiSpectrumBandIndices> m_ruBands; ///< spectrum bands associated to all the RUs
455};
456
458 : TestCase("SpectrumWifiPhy test RX filters"),
459 m_txChannelWidth(20),
460 m_rxChannelWidth(20)
461{
462}
463
465 : TestCase(name)
466{
467}
468
469void
471{
473 0,
475 800,
476 1,
477 1,
478 0,
480 false,
481 false);
482 Ptr<Packet> pkt = Create<Packet>(1000);
483 WifiMacHeader hdr;
485 hdr.SetQosTid(0);
486 hdr.SetAddr1(Mac48Address("00:00:00:00:00:01"));
487 hdr.SetSequenceNumber(1);
488 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
489 m_txPhy->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
490}
491
493{
494 m_txPhy = nullptr;
495 m_rxPhy = nullptr;
496}
497
498void
500{
501 for (const auto& pair : rxPowersW)
502 {
503 NS_LOG_INFO("band: (" << pair.first << ") -> powerW=" << pair.second << " ("
504 << WToDbm(pair.second) << " dBm)");
505 }
506
507 size_t numBands = rxPowersW.size();
508 size_t expectedNumBands = std::max(1, (m_rxChannelWidth / 20));
509 expectedNumBands += (m_rxChannelWidth / 40);
510 expectedNumBands += (m_rxChannelWidth / 80);
511 expectedNumBands += (m_rxChannelWidth / 160);
512 expectedNumBands += m_ruBands.size();
513
514 NS_TEST_ASSERT_MSG_EQ(numBands,
515 expectedNumBands,
516 "Total number of bands handled by the receiver is incorrect");
517
518 uint16_t channelWidth = std::min(m_txChannelWidth, m_rxChannelWidth);
519 auto band = m_rxPhy->GetBand(channelWidth, 0);
520 auto it = rxPowersW.find(band);
521 NS_LOG_INFO("powerW total band: " << it->second << " (" << WToDbm(it->second) << " dBm)");
522 int totalRxPower = static_cast<int>(WToDbm(it->second) + 0.5);
523 int expectedTotalRxPower;
525 {
526 // PHY sends at 16 dBm, and since there is no loss, this should be the total power at the
527 // receiver.
528 expectedTotalRxPower = 16;
529 }
530 else
531 {
532 // Only a part of the transmitted power is received
533 expectedTotalRxPower =
534 16 - static_cast<int>(RatioToDb(m_txChannelWidth / m_rxChannelWidth));
535 }
536 NS_TEST_ASSERT_MSG_EQ(totalRxPower,
537 expectedTotalRxPower,
538 "Total received power is not correct");
539
540 if ((m_txChannelWidth <= m_rxChannelWidth) && (channelWidth >= 20))
541 {
542 band = m_rxPhy->GetBand(20, 0); // primary 20 MHz
543 it = rxPowersW.find(band);
544 NS_LOG_INFO("powerW in primary 20 MHz channel: " << it->second << " (" << WToDbm(it->second)
545 << " dBm)");
546 int rxPowerPrimaryChannel20 = static_cast<int>(WToDbm(it->second) + 0.5);
547 int expectedRxPowerPrimaryChannel20 = 16 - static_cast<int>(RatioToDb(channelWidth / 20));
548 NS_TEST_ASSERT_MSG_EQ(rxPowerPrimaryChannel20,
549 expectedRxPowerPrimaryChannel20,
550 "Received power in the primary 20 MHz band is not correct");
551 }
552}
553
554void
556{
557 // WifiHelper::EnableLogComponents();
558 // LogComponentEnable("SpectrumWifiPhyTest", LOG_LEVEL_ALL);
559
560 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
561 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
562 lossModel->SetFrequency(5.180e9);
563 spectrumChannel->AddPropagationLossModel(lossModel);
565 CreateObject<ConstantSpeedPropagationDelayModel>();
566 spectrumChannel->SetPropagationDelayModel(delayModel);
567
568 Ptr<Node> txNode = CreateObject<Node>();
569 Ptr<WifiNetDevice> txDev = CreateObject<WifiNetDevice>();
570 m_txPhy = CreateObject<ExtSpectrumWifiPhy>();
571 Ptr<InterferenceHelper> txInterferenceHelper = CreateObject<InterferenceHelper>();
572 m_txPhy->SetInterferenceHelper(txInterferenceHelper);
573 Ptr<ErrorRateModel> txErrorModel = CreateObject<NistErrorRateModel>();
574 m_txPhy->SetErrorRateModel(txErrorModel);
575 m_txPhy->SetDevice(txDev);
576 m_txPhy->AddChannel(spectrumChannel);
578 Ptr<ConstantPositionMobilityModel> apMobility = CreateObject<ConstantPositionMobilityModel>();
579 m_txPhy->SetMobility(apMobility);
580 txDev->SetPhy(m_txPhy);
581 txNode->AggregateObject(apMobility);
582 txNode->AddDevice(txDev);
583
584 Ptr<Node> rxNode = CreateObject<Node>();
585 Ptr<WifiNetDevice> rxDev = CreateObject<WifiNetDevice>();
586 m_rxPhy = CreateObject<ExtSpectrumWifiPhy>();
587 Ptr<InterferenceHelper> rxInterferenceHelper = CreateObject<InterferenceHelper>();
588 m_rxPhy->SetInterferenceHelper(rxInterferenceHelper);
589 Ptr<ErrorRateModel> rxErrorModel = CreateObject<NistErrorRateModel>();
590 m_rxPhy->SetErrorRateModel(rxErrorModel);
591 m_rxPhy->AddChannel(spectrumChannel);
593 Ptr<ConstantPositionMobilityModel> sta1Mobility = CreateObject<ConstantPositionMobilityModel>();
594 m_rxPhy->SetMobility(sta1Mobility);
595 rxDev->SetPhy(m_rxPhy);
596 rxNode->AggregateObject(sta1Mobility);
597 rxNode->AddDevice(rxDev);
600}
601
602void
604{
605 m_txPhy->Dispose();
606 m_txPhy = nullptr;
607 m_rxPhy->Dispose();
608 m_rxPhy = nullptr;
609}
610
611void
613{
614 uint16_t txFrequency;
615 switch (m_txChannelWidth)
616 {
617 case 20:
618 default:
619 txFrequency = 5180;
620 break;
621 case 40:
622 txFrequency = 5190;
623 break;
624 case 80:
625 txFrequency = 5210;
626 break;
627 case 160:
628 txFrequency = 5250;
629 break;
630 }
631 auto txChannelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
632 txFrequency,
638
639 uint16_t rxFrequency;
640 switch (m_rxChannelWidth)
641 {
642 case 20:
643 default:
644 rxFrequency = 5180;
645 break;
646 case 40:
647 rxFrequency = 5190;
648 break;
649 case 80:
650 rxFrequency = 5210;
651 break;
652 case 160:
653 rxFrequency = 5250;
654 break;
655 }
656 auto rxChannelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
657 rxFrequency,
663
664 m_ruBands.clear();
665 for (uint16_t bw = 160; bw >= 20; bw = bw / 2)
666 {
667 for (uint16_t i = 0; i < (m_rxChannelWidth / bw); ++i)
668 {
669 for (unsigned int type = 0; type < 7; type++)
670 {
671 auto ruType = static_cast<HeRu::RuType>(type);
672 for (std::size_t index = 1; index <= HeRu::GetNRus(bw, ruType); index++)
673 {
674 HeRu::SubcarrierGroup subcarrierGroup =
675 HeRu::GetSubcarrierGroup(bw, ruType, index);
676 HeRu::SubcarrierRange subcarrierRange =
677 std::make_pair(subcarrierGroup.front().first,
678 subcarrierGroup.back().second);
679 const auto band =
683 subcarrierRange,
684 i);
685 m_ruBands.insert(band);
686 }
687 }
688 }
689 }
690
692
694}
695
696void
698{
699 m_txChannelWidth = 20;
700 m_rxChannelWidth = 20;
701 RunOne();
702
703 m_txChannelWidth = 40;
704 m_rxChannelWidth = 40;
705 RunOne();
706
707 m_txChannelWidth = 80;
708 m_rxChannelWidth = 80;
709 RunOne();
710
711 m_txChannelWidth = 160;
712 m_rxChannelWidth = 160;
713 RunOne();
714
715 m_txChannelWidth = 20;
716 m_rxChannelWidth = 40;
717 RunOne();
718
719 m_txChannelWidth = 20;
720 m_rxChannelWidth = 80;
721 RunOne();
722
723 m_txChannelWidth = 40;
724 m_rxChannelWidth = 80;
725 RunOne();
726
727 m_txChannelWidth = 20;
728 m_rxChannelWidth = 160;
729 RunOne();
730
731 m_txChannelWidth = 40;
732 m_rxChannelWidth = 160;
733 RunOne();
734
735 m_txChannelWidth = 80;
736 m_rxChannelWidth = 160;
737 RunOne();
738
739 m_txChannelWidth = 40;
740 m_rxChannelWidth = 20;
741 RunOne();
742
743 m_txChannelWidth = 80;
744 m_rxChannelWidth = 20;
745 RunOne();
746
747 m_txChannelWidth = 80;
748 m_rxChannelWidth = 40;
749 RunOne();
750
751 m_txChannelWidth = 160;
752 m_rxChannelWidth = 20;
753 RunOne();
754
755 m_txChannelWidth = 160;
756 m_rxChannelWidth = 40;
757 RunOne();
758
759 m_txChannelWidth = 160;
760 m_rxChannelWidth = 80;
761 RunOne();
762
764}
765
766/**
767 * \ingroup wifi-test
768 * \ingroup tests
769 *
770 * \brief Spectrum Wifi Phy Multiple Spectrum Test
771 *
772 * This test is testing the ability to plug multiple spectrum channels to the spectrum wifi PHY.
773 * It considers 4 TX-RX PHY pairs that are independent from each others and are plugged to different
774 * spectrum channels that are covering different frequency range. Each RX PHY is also attached to
775 * each of the other 3 spectrum channels it can switch to.
776 *
777 * In the first scenario, we consider the default case where each TX-RX PHY pairs are operating on
778 * different frequency ranges and hence using independent spectrum channels. We validate that no
779 * packets is received from other TX PHYs attached to different spectrum channels and we also verify
780 * the amount of connected PHYs to each spectrum channel is exactly 2. The test also makes sure each
781 * PHY has only one active spectrum channel and that the active one is operating at the expected
782 * frequency range.
783 *
784 * In the second scenario, we consecutively switch the channel of all RX PHYs to the one of each TX
785 * PHY. We validate that packets are received by all PHYs and we also verify the amount of connected
786 * PHYs to each spectrum channels is either 5 (1 TX PHY and 4 RX PHYs) or 1 (the TX PHY left alone).
787 */
789{
790 public:
791 /**
792 * Constructor
793 *
794 * \param trackSignalsInactiveInterfaces flag to indicate whether signals coming from inactive
795 * spectrum PHY interfaces shall be tracked during the test
796 */
797 SpectrumWifiPhyMultipleInterfacesTest(bool trackSignalsInactiveInterfaces);
798
799 private:
800 void DoSetup() override;
801 void DoTeardown() override;
802 void DoRun() override;
803
804 /**
805 * Switch channel function
806 *
807 * \param index the index to identify the RX PHY
808 * \param band the PHY band to use
809 * \param channelNumber number the channel number to use
810 * \param channelWidth the channel width to use
811 */
812 void SwitchChannel(std::size_t index,
813 WifiPhyBand band,
814 uint8_t channelNumber,
815 uint16_t channelWidth);
816
817 /**
818 * Send PPDU function
819 *
820 * \param phy the PHY to transmit the signal
821 * \param txPowerDbm the power in dBm to transmit the signal (this is also the received power
822 * since we do not have propagation loss to simplify)
823 * \param payloadSize the payload size in bytes
824 */
825 void SendPpdu(Ptr<SpectrumWifiPhy> phy, double txPowerDbm, uint32_t payloadSize);
826
827 /**
828 * Callback triggered when a packet is received by a PHY
829 * \param index the index to identify the RX PHY
830 * \param packet the received packet
831 * \param rxPowersW the received power per channel band in watts
832 */
833 void RxCallback(std::size_t index,
834 Ptr<const Packet> packet,
835 RxPowerWattPerChannelBand rxPowersW);
836
837 /**
838 * Receive success function
839 * \param index index of the RX STA
840 * \param psdu the PSDU
841 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
842 * \param txVector the transmit vector
843 * \param statusPerMpdu reception status per MPDU
844 */
845 void RxSuccess(std::size_t index,
847 RxSignalInfo rxSignalInfo,
848 WifiTxVector txVector,
849 std::vector<bool> statusPerMpdu);
850
851 /**
852 * Receive failure function
853 * \param index index of the RX STA
854 * \param psdu the PSDU
855 */
856 void RxFailure(std::size_t index, Ptr<const WifiPsdu> psdu);
857
858 /**
859 * Schedule now to check the interferences
860 * \param phy the PHY for which the check has to be executed
861 * \param freqRange the frequency range for which the check has to be executed
862 * \param band the band for which the check has to be executed
863 * \param interferencesExpected flag whether interferences are expected to have been tracked
864 */
866 const FrequencyRange& freqRange,
867 const WifiSpectrumBandInfo& band,
868 bool interferencesExpected);
869
870 /**
871 * Check the interferences
872 * \param phy the PHY for which the check has to be executed
873 * \param band the band for which the check has to be executed
874 * \param interferencesExpected flag whether interferences are expected to have been tracked
875 */
877 const WifiSpectrumBandInfo& band,
878 bool interferencesExpected);
879
880 /**
881 * Verify results
882 *
883 * \param index the index to identify the RX PHY to check
884 * \param expectedNumRx the expected number of RX events for that PHY
885 * \param expectedNumRxSuccess the expected amount of successfully received packets
886 * \param expectedRxBytes the expected amount of received bytes
887 * \param expectedFrequencyRangeActiveRfInterface the expected frequency range (in MHz) of the
888 * active RF interface
889 * \param expectedConnectedPhysPerChannel the expected
890 * number of PHYs attached for each spectrum channel
891 */
892 void CheckResults(std::size_t index,
893 uint32_t expectedNumRx,
894 uint32_t expectedNumRxSuccess,
895 uint32_t expectedRxBytes,
896 FrequencyRange expectedFrequencyRangeActiveRfInterface,
897 const std::vector<std::size_t>& expectedConnectedPhysPerChannel);
898
899 /**
900 * Verify CCA indication reported by a given PHY
901 *
902 * \param index the index to identify the RX PHY to check
903 * \param expectedCcaBusyIndication flag to indicate whether a CCA BUSY notification is expected
904 * \param switchingDelay delay between the TX has started and the time RX switched to the TX
905 * channel
906 */
907 void CheckCcaIndication(std::size_t index, bool expectedCcaBusyIndication, Time switchingDelay);
908
909 /**
910 * Reset function
911 */
912 void Reset();
913
914 bool
915 m_trackSignalsInactiveInterfaces; //!< flag to indicate whether signals coming from inactive
916 //!< spectrum PHY interfaces are tracked during the test
917
918 std::vector<Ptr<MultiModelSpectrumChannel>> m_spectrumChannels; //!< Spectrum channels
919 std::vector<Ptr<SpectrumWifiPhy>> m_txPhys{}; //!< TX PHYs
920 std::vector<Ptr<SpectrumWifiPhy>> m_rxPhys{}; //!< RX PHYs
921 std::vector<std::shared_ptr<TestPhyListener>> m_listeners{}; //!< listeners
922
923 std::vector<uint32_t> m_counts; //!< count number of packets received by PHYs
924 std::vector<uint32_t>
925 m_countRxSuccess; //!< count number of packets successfully received by PHYs
926 std::vector<uint32_t>
927 m_countRxFailure; //!< count number of packets unsuccessfully received by PHYs
928 std::vector<uint32_t> m_rxBytes; //!< count number of received bytes
929
930 Time m_lastTxStart{0}; //!< hold the time at which the last transmission started
931 Time m_lastTxEnd{0}; //!< hold the time at which the last transmission ended
932};
933
935 bool trackSignalsInactiveInterfaces)
936 : TestCase{"SpectrumWifiPhy test operation with multiple RF interfaces"},
937 m_trackSignalsInactiveInterfaces{trackSignalsInactiveInterfaces}
938{
939}
940
941void
943 WifiPhyBand band,
944 uint8_t channelNumber,
945 uint16_t channelWidth)
946{
947 NS_LOG_FUNCTION(this << index << band << +channelNumber << channelWidth);
948 auto& listener = m_listeners.at(index);
949 listener->m_notifyMaybeCcaBusyStart = 0;
950 listener->m_ccaBusyStart = Seconds(0);
951 listener->m_ccaBusyEnd = Seconds(0);
952 auto phy = m_rxPhys.at(index);
953 phy->SetOperatingChannel(WifiPhy::ChannelTuple{channelNumber, channelWidth, band, 0});
954}
955
956void
958 double txPowerDbm,
959 uint32_t payloadSize)
960{
961 NS_LOG_FUNCTION(this << phy << txPowerDbm << payloadSize << phy->GetCurrentFrequencyRange()
962 << phy->GetChannelWidth() << phy->GetChannelNumber());
963
964 WifiTxVector txVector =
965 WifiTxVector(HePhy::GetHeMcs11(), 0, WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, 20, false, false);
966 Ptr<Packet> pkt = Create<Packet>(payloadSize);
967 WifiMacHeader hdr;
969 hdr.SetQosTid(0);
970 hdr.SetAddr1(Mac48Address("00:00:00:00:00:01"));
971 hdr.SetSequenceNumber(1);
972 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
973
976 txVector,
977 phy->GetPhyBand());
978 phy->SetTxPowerStart(txPowerDbm);
979 phy->SetTxPowerEnd(txPowerDbm);
980 phy->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
981}
982
983void
985 Ptr<const Packet> packet,
986 RxPowerWattPerChannelBand /*rxPowersW*/)
987{
988 auto phy = m_rxPhys.at(index);
989 const auto payloadBytes = packet->GetSize() - 30;
990 NS_LOG_FUNCTION(this << index << payloadBytes << phy->GetCurrentFrequencyRange()
991 << phy->GetChannelWidth() << phy->GetChannelNumber());
992 m_counts.at(index)++;
993 m_rxBytes.at(index) += payloadBytes;
994}
995
996void
999 RxSignalInfo rxSignalInfo,
1000 WifiTxVector txVector,
1001 std::vector<bool> /*statusPerMpdu*/)
1002{
1003 NS_LOG_FUNCTION(this << index << *psdu << rxSignalInfo << txVector);
1004 m_countRxSuccess.at(index)++;
1005}
1006
1007void
1009{
1010 NS_LOG_FUNCTION(this << index << *psdu);
1011 m_countRxFailure.at(index)++;
1012}
1013
1014void
1016 const FrequencyRange& freqRange,
1017 const WifiSpectrumBandInfo& band,
1018 bool interferencesExpected)
1019{
1020 if ((!m_trackSignalsInactiveInterfaces) && (phy->GetCurrentFrequencyRange() != freqRange))
1021 {
1022 // ignore since no bands for that range exists in interference helper in that case
1023 return;
1024 }
1025 // This is needed to make sure PHY state will be checked as the last event if a state change
1026 // occurred at the exact same time as the check
1028 this,
1029 phy,
1030 band,
1031 interferencesExpected);
1032}
1033
1034void
1036 const WifiSpectrumBandInfo& band,
1037 bool interferencesExpected)
1038{
1039 NS_LOG_FUNCTION(this << phy << band << interferencesExpected);
1040 PointerValue ptr;
1041 phy->GetAttribute("InterferenceHelper", ptr);
1042 auto interferenceHelper = DynamicCast<InterferenceHelper>(ptr.Get<InterferenceHelper>());
1043 NS_ASSERT(interferenceHelper);
1044 const auto energyDuration = interferenceHelper->GetEnergyDuration(0, band);
1045 NS_TEST_ASSERT_MSG_EQ(energyDuration.IsStrictlyPositive(),
1046 interferencesExpected,
1047 "Incorrect interferences detection");
1048}
1049
1050void
1052 std::size_t index,
1053 uint32_t expectedNumRx,
1054 uint32_t expectedNumRxSuccess,
1055 uint32_t expectedRxBytes,
1056 FrequencyRange expectedFrequencyRangeActiveRfInterface,
1057 const std::vector<std::size_t>& expectedConnectedPhysPerChannel)
1058{
1059 NS_LOG_FUNCTION(this << index << expectedNumRx << expectedNumRxSuccess << expectedRxBytes
1060 << expectedFrequencyRangeActiveRfInterface);
1061 const auto phy = m_rxPhys.at(index);
1062 std::size_t numActiveInterfaces = 0;
1063 for (const auto& [freqRange, interface] : phy->GetSpectrumPhyInterfaces())
1064 {
1065 const auto expectedActive = (freqRange == expectedFrequencyRangeActiveRfInterface);
1066 const auto isActive = (interface == phy->GetCurrentInterface());
1067 NS_TEST_ASSERT_MSG_EQ(isActive, expectedActive, "Incorrect active interface");
1068 if (isActive)
1069 {
1070 numActiveInterfaces++;
1071 }
1072 }
1073 NS_TEST_ASSERT_MSG_EQ(numActiveInterfaces, 1, "There should always be one active interface");
1074 NS_ASSERT(expectedConnectedPhysPerChannel.size() == m_spectrumChannels.size());
1075 for (std::size_t i = 0; i < m_spectrumChannels.size(); ++i)
1076 {
1077 NS_TEST_ASSERT_MSG_EQ(m_spectrumChannels.at(i)->GetNDevices(),
1078 expectedConnectedPhysPerChannel.at(i),
1079 "Incorrect number of PHYs attached to the spectrum channel");
1080 }
1081 NS_TEST_ASSERT_MSG_EQ(m_counts.at(index), expectedNumRx, "Unexpected amount of RX events");
1083 expectedNumRxSuccess,
1084 "Unexpected amount of successfully received packets");
1086 0,
1087 "Unexpected amount of unsuccessfully received packets");
1088 NS_TEST_ASSERT_MSG_EQ(m_listeners.at(index)->m_notifyRxStart,
1089 expectedNumRxSuccess,
1090 "Unexpected amount of RX payload start indication");
1091}
1092
1093void
1095 bool expectedCcaBusyIndication,
1096 Time switchingDelay)
1097{
1098 const auto expectedCcaBusyStart =
1099 expectedCcaBusyIndication ? m_lastTxStart + switchingDelay : Seconds(0);
1100 const auto expectedCcaBusyEnd = expectedCcaBusyIndication ? m_lastTxEnd : Seconds(0);
1101 NS_LOG_FUNCTION(this << index << expectedCcaBusyIndication << expectedCcaBusyStart
1102 << expectedCcaBusyEnd);
1103 auto& listener = m_listeners.at(index);
1104 const auto ccaBusyIndication = (listener->m_notifyMaybeCcaBusyStart > 0);
1105 const auto ccaBusyStart = listener->m_ccaBusyStart;
1106 const auto ccaBusyEnd = listener->m_ccaBusyEnd;
1107 NS_TEST_ASSERT_MSG_EQ(ccaBusyIndication,
1108 expectedCcaBusyIndication,
1109 "CCA busy indication check failed");
1110 NS_TEST_ASSERT_MSG_EQ(ccaBusyStart, expectedCcaBusyStart, "CCA busy start mismatch");
1111 NS_TEST_ASSERT_MSG_EQ(ccaBusyEnd, expectedCcaBusyEnd, "CCA busy end mismatch");
1112}
1113
1114void
1116{
1117 NS_LOG_FUNCTION(this);
1118 for (auto& count : m_counts)
1119 {
1120 count = 0;
1121 }
1122 for (auto& listener : m_listeners)
1123 {
1124 listener->Reset();
1125 }
1126 // restore all RX PHYs to initial channels
1127 for (std::size_t rxPhyIndex = 0; rxPhyIndex < m_rxPhys.size(); ++rxPhyIndex)
1128 {
1129 auto txPhy = m_txPhys.at(rxPhyIndex);
1130 SwitchChannel(rxPhyIndex,
1131 txPhy->GetPhyBand(),
1132 txPhy->GetChannelNumber(),
1133 txPhy->GetChannelWidth());
1134 }
1135 // reset counters
1136 for (auto& countRxSuccess : m_countRxSuccess)
1137 {
1138 countRxSuccess = 0;
1139 }
1140 for (auto& countRxFailure : m_countRxFailure)
1141 {
1142 countRxFailure = 0;
1143 }
1144 for (auto& rxBytes : m_rxBytes)
1145 {
1146 rxBytes = 0;
1147 }
1148}
1149
1150void
1152{
1153 NS_LOG_FUNCTION(this);
1154
1155 // WifiHelper::EnableLogComponents();
1156 // LogComponentEnable("SpectrumWifiPhyTest", LOG_LEVEL_ALL);
1157
1158 NodeContainer wifiApNode(1);
1159 NodeContainer wifiStaNode(1);
1160
1161 WifiHelper wifi;
1162 wifi.SetStandard(WIFI_STANDARD_80211be);
1163
1164 SpectrumWifiPhyHelper phyHelper(4);
1166
1167 struct SpectrumPhyInterfaceInfo
1168 {
1169 FrequencyRange range; ///< frequency range covered by the interface
1170 uint8_t number; ///< channel number the interface operates on
1171 WifiPhyBand band; ///< PHY band the interface operates on
1172 std::string bandName; ///< name of the PHY band the interface operates on
1173 };
1174
1175 const FrequencyRange WIFI_SPECTRUM_5_GHZ_LOW{
1179 const FrequencyRange WIFI_SPECTRUM_5_GHZ_HIGH{
1183
1184 const std::vector<SpectrumPhyInterfaceInfo> interfaces{
1185 {WIFI_SPECTRUM_2_4_GHZ, 2, WIFI_PHY_BAND_2_4GHZ, "BAND_2_4GHZ"},
1186 {WIFI_SPECTRUM_5_GHZ_LOW, 42, WIFI_PHY_BAND_5GHZ, "BAND_5GHZ"},
1187 {WIFI_SPECTRUM_5_GHZ_HIGH, 163, WIFI_PHY_BAND_5GHZ, "BAND_5GHZ"},
1188 {WIFI_SPECTRUM_6_GHZ, 215, WIFI_PHY_BAND_6GHZ, "BAND_6GHZ"}};
1189
1190 for (std::size_t i = 0; i < interfaces.size(); ++i)
1191 {
1192 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1193 [[maybe_unused]] const auto [channel, frequency, channelWidth, type, band] =
1194 (*WifiPhyOperatingChannel::FindFirst(interfaces.at(i).number,
1195 0,
1196 0,
1198 interfaces.at(i).band));
1199
1200 std::ostringstream oss;
1201 oss << "{" << +interfaces.at(i).number << ", 0, " << interfaces.at(i).bandName << ", 0}";
1202 phyHelper.Set(i, "ChannelSettings", StringValue(oss.str()));
1203 phyHelper.AddChannel(spectrumChannel, interfaces.at(i).range);
1204
1205 m_spectrumChannels.emplace_back(spectrumChannel);
1206 }
1207
1208 WifiMacHelper mac;
1209 mac.SetType("ns3::ApWifiMac", "BeaconGeneration", BooleanValue(false));
1210 phyHelper.Set("TrackSignalsFromInactiveInterfaces", BooleanValue(false));
1211 auto apDevice = wifi.Install(phyHelper, mac, wifiApNode.Get(0));
1212
1213 mac.SetType("ns3::StaWifiMac", "ActiveProbing", BooleanValue(false));
1214 phyHelper.Set("TrackSignalsFromInactiveInterfaces",
1216 auto staDevice = wifi.Install(phyHelper, mac, wifiStaNode.Get(0));
1217
1218 for (std::size_t i = 0; i < interfaces.size(); ++i)
1219 {
1220 auto txPhy =
1221 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(apDevice.Get(0))->GetPhy(i));
1222 m_txPhys.push_back(txPhy);
1223
1224 const auto index = m_rxPhys.size();
1225 auto rxPhy =
1226 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(staDevice.Get(0))->GetPhy(i));
1227 rxPhy->TraceConnectWithoutContext(
1228 "PhyRxBegin",
1230
1231 rxPhy->SetReceiveOkCallback(
1233 rxPhy->SetReceiveErrorCallback(
1235
1236 auto listener = std::make_shared<TestPhyListener>();
1237 rxPhy->RegisterListener(listener);
1238 m_listeners.push_back(std::move(listener));
1239
1240 m_rxPhys.push_back(rxPhy);
1241 m_counts.push_back(0);
1242 m_countRxSuccess.push_back(0);
1243 m_countRxFailure.push_back(0);
1244 m_rxBytes.push_back(0);
1245 }
1246}
1247
1248void
1250{
1251 NS_LOG_FUNCTION(this);
1252 for (auto& phy : m_txPhys)
1253 {
1254 phy->Dispose();
1255 phy = nullptr;
1256 }
1257 for (auto& phy : m_rxPhys)
1258 {
1259 phy->Dispose();
1260 phy = nullptr;
1261 }
1263}
1264
1265void
1267{
1268 NS_LOG_FUNCTION(this);
1269
1270 const auto ccaEdThresholdDbm = -62.0; ///< CCA-ED threshold in dBm
1271 const auto txAfterChannelSwitchDelay =
1272 Seconds(0.25); ///< delay in seconds between channel switch is triggered and a transmission
1273 ///< gets started
1274 const auto checkResultsDelay =
1275 Seconds(0.5); ///< delay in seconds between start of test and moment results are verified
1276 const auto flushResultsDelay =
1277 Seconds(0.9); ///< delay in seconds between start of test and moment results are flushed
1278 const auto txOngoingAfterTxStartedDelay =
1279 MicroSeconds(50); ///< delay in microseconds between a transmission has started and a point
1280 ///< in time the transmission is ongoing
1281
1282 Time delay{0};
1283
1284 // default channels active for all PHYs: each PHY only receives from its associated TX
1285 std::vector<std::size_t> expectedConnectedPhysPerChannel =
1286 m_trackSignalsInactiveInterfaces ? std::vector<std::size_t>{5, 5, 5, 5}
1287 : // all RX PHYs keep all channels active when tracking
1288 // interferences on inactive interfaces
1289 std::vector<std::size_t>{2, 2, 2, 2}; // default channels active for all PHYs: each PHY
1290 // only receives from its associated TX
1291
1292 for (std::size_t i = 0; i < 4; ++i)
1293 {
1294 auto txPpduPhy = m_txPhys.at(i);
1295 delay += Seconds(1);
1296 Simulator::Schedule(delay,
1298 this,
1299 txPpduPhy,
1300 0,
1301 1000);
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 auto& expectedFreqRange = txPhy->GetCurrentFrequencyRange();
1307 Simulator::Schedule(delay + txOngoingAfterTxStartedDelay,
1309 this,
1310 rxPhy,
1311 txPpduPhy->GetCurrentFrequencyRange(),
1312 txPpduPhy->GetBand(txPpduPhy->GetChannelWidth(), 0),
1313 true);
1314 Simulator::Schedule(delay + checkResultsDelay,
1316 this,
1317 j,
1318 (i == j) ? 1 : 0,
1319 (i == j) ? 1 : 0,
1320 (i == j) ? 1000 : 0,
1321 expectedFreqRange,
1322 expectedConnectedPhysPerChannel);
1323 }
1324 Simulator::Schedule(delay + flushResultsDelay,
1326 this);
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 1000);
1340 const auto& expectedFreqRange = txPpduPhy->GetCurrentFrequencyRange();
1341 for (std::size_t j = 0; j < 4; ++j)
1342 {
1344 {
1345 for (std::size_t k = 0; k < expectedConnectedPhysPerChannel.size(); ++k)
1346 {
1347 expectedConnectedPhysPerChannel.at(k) = (k == i) ? 5 : 1;
1348 }
1349 }
1350 auto rxPhy = m_rxPhys.at(j);
1351 Simulator::Schedule(delay,
1353 this,
1354 j,
1355 txPpduPhy->GetPhyBand(),
1356 txPpduPhy->GetChannelNumber(),
1357 txPpduPhy->GetChannelWidth());
1358 Simulator::Schedule(delay + txAfterChannelSwitchDelay + txOngoingAfterTxStartedDelay,
1360 this,
1361 rxPhy,
1362 txPpduPhy->GetCurrentFrequencyRange(),
1363 txPpduPhy->GetBand(txPpduPhy->GetChannelWidth(), 0),
1364 true);
1365 Simulator::Schedule(delay + checkResultsDelay,
1367 this,
1368 j,
1369 1,
1370 1,
1371 1000,
1372 expectedFreqRange,
1373 expectedConnectedPhysPerChannel);
1374 }
1375 Simulator::Schedule(delay + flushResultsDelay,
1377 this);
1378 }
1379
1380 // Switch all PHYs to channel 36: all PHYs switch to the second spectrum channel
1381 // since second spectrum channel is 42 (80 MHz) and hence covers channel 36 (20 MHz)
1382 const auto secondSpectrumChannelIndex = 1;
1383 auto channel36TxPhy = m_txPhys.at(secondSpectrumChannelIndex);
1384 const auto& expectedFreqRange = channel36TxPhy->GetCurrentFrequencyRange();
1385 for (std::size_t i = 0; i < 4; ++i)
1386 {
1387 delay += Seconds(1);
1388 auto txPpduPhy = m_txPhys.at(i);
1389 Simulator::Schedule(delay + txAfterChannelSwitchDelay,
1391 this,
1392 txPpduPhy,
1393 0,
1394 1000);
1395 for (std::size_t j = 0; j < 4; ++j)
1396 {
1398 {
1399 for (std::size_t k = 0; k < expectedConnectedPhysPerChannel.size(); ++k)
1400 {
1401 expectedConnectedPhysPerChannel.at(k) =
1402 (k == secondSpectrumChannelIndex) ? 5 : 1;
1403 }
1404 }
1405 Simulator::Schedule(delay,
1407 this,
1408 j,
1412 Simulator::Schedule(delay + checkResultsDelay,
1414 this,
1415 j,
1416 (i == secondSpectrumChannelIndex) ? 1 : 0,
1417 (i == secondSpectrumChannelIndex) ? 1 : 0,
1418 (i == secondSpectrumChannelIndex) ? 1000 : 0,
1419 expectedFreqRange,
1420 expectedConnectedPhysPerChannel);
1421 }
1422 Simulator::Schedule(delay + flushResultsDelay,
1424 this);
1425 }
1426
1427 // verify CCA indication when switching to a channel with an ongoing transmission
1428 for (const auto txPowerDbm : {-60.0 /* above CCA-ED */, -70.0 /* below CCA-ED */})
1429 {
1430 for (std::size_t i = 0; i < 4; ++i)
1431 {
1432 for (std::size_t j = 0; j < 4; ++j)
1433 {
1434 auto txPpduPhy = m_txPhys.at(i);
1435 const auto startChannel =
1436 WifiPhyOperatingChannel::FindFirst(txPpduPhy->GetPrimaryChannelNumber(20),
1437 0,
1438 20,
1440 txPpduPhy->GetPhyBand());
1441 for (uint16_t bw = txPpduPhy->GetChannelWidth(); bw >= 20; bw /= 2)
1442 {
1443 [[maybe_unused]] const auto [channel, frequency, channelWidth, type, band] =
1445 0,
1446 bw,
1448 txPpduPhy->GetPhyBand(),
1449 startChannel));
1450 delay += Seconds(1);
1451 Simulator::Schedule(delay,
1453 this,
1454 txPpduPhy,
1455 txPowerDbm,
1456 1000);
1457 Simulator::Schedule(delay + txOngoingAfterTxStartedDelay,
1459 this,
1460 j,
1461 band,
1462 channel,
1463 channelWidth);
1464 for (std::size_t k = 0; k < 4; ++k)
1465 {
1466 if ((i != j) && (k == i))
1467 {
1468 continue;
1469 }
1470 const auto expectCcaBusyIndication =
1471 (k == i) ? (txPowerDbm >= ccaEdThresholdDbm)
1473 ? ((txPowerDbm >= ccaEdThresholdDbm) ? (j == k) : false)
1474 : false);
1476 delay + checkResultsDelay,
1478 this,
1479 k,
1480 expectCcaBusyIndication,
1481 txOngoingAfterTxStartedDelay);
1482 }
1483 Simulator::Schedule(delay + flushResultsDelay,
1485 this);
1486 }
1487 }
1488 }
1489 }
1490
1491 /* Reproduce an EMLSR scenario where a PHY is on an initial band and receives a packet.
1492 * Then, the PHY switches to another band where it starts receiving another packet.
1493 * During reception of the PHY header, the PHY switches back to the initial band and starts
1494 * receiving yet another packet. In this case, first and last packets should be successfully
1495 * received (no interference), the second packet reception has been interrupted (before the
1496 * payload reception does start, hence it does not reach the RX state). */
1498 {
1499 // first TX on initial band
1500 auto txPpduPhy = m_txPhys.at(0);
1501 delay += Seconds(1);
1502 Simulator::Schedule(delay,
1504 this,
1505 txPpduPhy,
1506 20,
1507 500);
1508
1509 // switch channel to other band
1510 delay += Seconds(1);
1511 txPpduPhy = m_txPhys.at(1);
1512 Simulator::Schedule(delay,
1514 this,
1515 0,
1516 txPpduPhy->GetPhyBand(),
1517 txPpduPhy->GetChannelNumber(),
1518 txPpduPhy->GetChannelWidth());
1519
1520 // TX on other band with high power
1521 delay += Seconds(1);
1522 Simulator::Schedule(delay,
1524 this,
1525 txPpduPhy,
1526 0,
1527 1000);
1528
1529 // switch back to initial band during PHY header reception
1530 txPpduPhy = m_txPhys.at(0);
1531 delay += MicroSeconds(20); // right after legacy PHY header reception
1532 Simulator::Schedule(delay,
1534 this,
1535 0,
1536 txPpduPhy->GetPhyBand(),
1537 txPpduPhy->GetChannelNumber(),
1538 txPpduPhy->GetChannelWidth());
1539
1540 // TX once more on the initial band
1541 delay += Seconds(1);
1542 Simulator::Schedule(delay,
1544 this,
1545 txPpduPhy,
1546 0,
1547 1500);
1548
1549 // check results
1550 Simulator::Schedule(delay + checkResultsDelay,
1552 this,
1553 0,
1554 3, // 3 RX events
1555 2, // 2 packets should have been successfully received, 1 packet should
1556 // have been interrupted (switch during PHY header reception)
1557 2000, // 500 bytes (firstpacket) and 1500 bytes (third packet)
1558 txPpduPhy->GetCurrentFrequencyRange(),
1559 expectedConnectedPhysPerChannel);
1560
1561 // reset
1562 Simulator::Schedule(delay + flushResultsDelay,
1564 this);
1565 }
1566
1567 delay += Seconds(1);
1568 Simulator::Stop(delay);
1570}
1571
1572/**
1573 * \ingroup wifi-test
1574 * \ingroup tests
1575 *
1576 * \brief Spectrum Wifi Phy Interfaces Helper Test
1577 *
1578 * This test checks the expected interfaces are added to the spectrum PHY instances
1579 * created by the helper.
1580 */
1582{
1583 public:
1586
1587 private:
1588 void DoRun() override;
1589};
1590
1592 : TestCase("Check PHY interfaces added to PHY instances using helper")
1593{
1594}
1595
1596void
1598{
1599 WifiHelper wifiHelper;
1601
1602 SpectrumWifiPhyHelper phyHelper(3);
1603 phyHelper.Set(0, "ChannelSettings", StringValue("{2, 0, BAND_2_4GHZ, 0}"));
1604 phyHelper.Set(1, "ChannelSettings", StringValue("{36, 0, BAND_5GHZ, 0}"));
1605 phyHelper.Set(2, "ChannelSettings", StringValue("{1, 0, BAND_6GHZ, 0}"));
1606
1607 phyHelper.AddChannel(CreateObject<MultiModelSpectrumChannel>(), WIFI_SPECTRUM_2_4_GHZ);
1608 phyHelper.AddChannel(CreateObject<MultiModelSpectrumChannel>(), WIFI_SPECTRUM_5_GHZ);
1609 phyHelper.AddChannel(CreateObject<MultiModelSpectrumChannel>(), WIFI_SPECTRUM_6_GHZ);
1610
1611 WifiMacHelper macHelper;
1613
1614 /* Default case: all interfaces are added to each link */
1615 auto device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(0));
1616
1617 // Verify each PHY has 3 interfaces
1618 auto phyLink0 =
1619 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1620 NS_ASSERT(phyLink0);
1621 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1622 3,
1623 "Incorrect number of PHY interfaces added to PHY link ID 0");
1624
1625 auto phyLink1 =
1626 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1627 NS_ASSERT(phyLink1);
1628 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1629 3,
1630 "Incorrect number of PHY interfaces added to PHY link ID 1");
1631
1632 auto phyLink2 =
1633 DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1634 NS_ASSERT(phyLink2);
1635 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1636 3,
1637 "Incorrect number of PHY interfaces added to PHY link ID 2");
1638
1639 /* each PHY has a single interface */
1643 device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(1));
1644
1645 // Verify each PHY has a single interface
1646 phyLink0 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1647 NS_ASSERT(phyLink0);
1648 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1649 1,
1650 "Incorrect number of PHY interfaces added to PHY link ID 0");
1651 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1652 1,
1653 "Incorrect PHY interfaces added to PHY link ID 0");
1654
1655 phyLink1 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1656 NS_ASSERT(phyLink1);
1657 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1658 1,
1659 "Incorrect number of PHY interfaces added to PHY link ID 1");
1660 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1661 1,
1662 "Incorrect PHY interfaces added to PHY link ID 1");
1663
1664 phyLink2 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1665 NS_ASSERT(phyLink2);
1666 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().size(),
1667 1,
1668 "Incorrect number of PHY interfaces added to PHY link ID 2");
1669 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1670 1,
1671 "Incorrect PHY interfaces added to PHY link ID 2");
1672
1673 /* add yet another interface to PHY 0 */
1675 device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(2));
1676
1677 // Verify each PHY has a single interface except PHY 0 that should have 2 interfaces
1678 phyLink0 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1679 NS_ASSERT(phyLink0);
1680 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1681 2,
1682 "Incorrect number of PHY interfaces added to PHY link ID 0");
1683 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1684 1,
1685 "Incorrect PHY interfaces added to PHY link ID 0");
1686 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1687 1,
1688 "Incorrect PHY interfaces added to PHY link ID 0");
1689
1690 phyLink1 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1691 NS_ASSERT(phyLink1);
1692 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1693 1,
1694 "Incorrect number of PHY interfaces added to PHY link ID 1");
1695 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1696 1,
1697 "Incorrect PHY interfaces added to PHY link ID 1");
1698
1699 phyLink2 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1700 NS_ASSERT(phyLink2);
1701 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().size(),
1702 1,
1703 "Incorrect number of PHY interfaces added to PHY link ID 2");
1704 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1705 1,
1706 "Incorrect PHY interfaces added to PHY link ID 2");
1707
1708 /* reset mapping previously configured to helper: back to default */
1709 phyHelper.ResetPhyToFreqRangeMapping();
1710 device = wifiHelper.Install(phyHelper, macHelper, nodes.Get(3));
1711
1712 // Verify each PHY has 3 interfaces
1713 phyLink0 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(0));
1714 NS_ASSERT(phyLink0);
1715 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().size(),
1716 3,
1717 "Incorrect number of PHY interfaces added to PHY link ID 0");
1718 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1719 1,
1720 "Incorrect PHY interfaces added to PHY link ID 0");
1721 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1722 1,
1723 "Incorrect PHY interfaces added to PHY link ID 0");
1724 NS_TEST_ASSERT_MSG_EQ(phyLink0->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1725 1,
1726 "Incorrect PHY interfaces added to PHY link ID 0");
1727
1728 phyLink1 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(1));
1729 NS_ASSERT(phyLink1);
1730 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().size(),
1731 3,
1732 "Incorrect number of PHY interfaces added to PHY link ID 1");
1733 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1734 1,
1735 "Incorrect PHY interfaces added to PHY link ID 0");
1736 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1737 1,
1738 "Incorrect PHY interfaces added to PHY link ID 0");
1739 NS_TEST_ASSERT_MSG_EQ(phyLink1->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1740 1,
1741 "Incorrect PHY interfaces added to PHY link ID 0");
1742
1743 phyLink2 = DynamicCast<SpectrumWifiPhy>(DynamicCast<WifiNetDevice>(device.Get(0))->GetPhy(2));
1744 NS_ASSERT(phyLink2);
1745 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().size(),
1746 3,
1747 "Incorrect number of PHY interfaces added to PHY link ID 2");
1748 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_2_4_GHZ),
1749 1,
1750 "Incorrect PHY interfaces added to PHY link ID 0");
1751 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_5_GHZ),
1752 1,
1753 "Incorrect PHY interfaces added to PHY link ID 0");
1754 NS_TEST_ASSERT_MSG_EQ(phyLink2->GetSpectrumPhyInterfaces().count(WIFI_SPECTRUM_6_GHZ),
1755 1,
1756 "Incorrect PHY interfaces added to PHY link ID 0");
1757
1759}
1760
1761/**
1762 * \ingroup wifi-test
1763 * \ingroup tests
1764 *
1765 * \brief Spectrum Wifi Phy Test Suite
1766 */
1768{
1769 public:
1771};
1772
1774 : TestSuite("wifi-spectrum-wifi-phy", Type::UNIT)
1775{
1776 AddTestCase(new SpectrumWifiPhyBasicTest, TestCase::Duration::QUICK);
1777 AddTestCase(new SpectrumWifiPhyListenerTest, TestCase::Duration::QUICK);
1778 AddTestCase(new SpectrumWifiPhyFilterTest, TestCase::Duration::QUICK);
1779 AddTestCase(new SpectrumWifiPhyMultipleInterfacesTest(false), TestCase::Duration::QUICK);
1780 AddTestCase(new SpectrumWifiPhyMultipleInterfacesTest(true), TestCase::Duration::QUICK);
1781 AddTestCase(new SpectrumWifiPhyInterfacesHelperTest, TestCase::Duration::QUICK);
1782}
1783
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< uint32_t > m_rxBytes
count number of received bytes
std::vector< Ptr< SpectrumWifiPhy > > m_rxPhys
RX PHYs.
std::vector< uint32_t > m_countRxSuccess
count number of packets successfully received by 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 ...
void RxSuccess(std::size_t index, Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
std::vector< std::shared_ptr< TestPhyListener > > m_listeners
listeners
Time m_lastTxEnd
hold the time at which the last transmission ended
void RxFailure(std::size_t index, Ptr< const WifiPsdu > psdu)
Receive failure function.
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 SendPpdu(Ptr< SpectrumWifiPhy > phy, double txPowerDbm, uint32_t payloadSize)
Send PPDU function.
void SwitchChannel(std::size_t index, WifiPhyBand band, uint8_t channelNumber, uint16_t channelWidth)
Switch channel function.
void CheckResults(std::size_t index, uint32_t expectedNumRx, uint32_t expectedNumRxSuccess, uint32_t expectedRxBytes, FrequencyRange expectedFrequencyRangeActiveRfInterface, const std::vector< std::size_t > &expectedConnectedPhysPerChannel)
Verify results.
std::vector< Ptr< SpectrumWifiPhy > > m_txPhys
TX PHYs.
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.
std::vector< uint32_t > m_countRxFailure
count number of packets unsuccessfully received by PHYs
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 GetHeMcs11()
Return MCS 11 from HE MCS values.
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:1820
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:591
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:495
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:322
void Dispose()
Dispose of this Object.
Definition: object.cc:258
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Ptr< T > Get() const
Definition: pointer.h:234
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:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
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:651
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:1741
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:660
uint32_t GetSubcarrierSpacing() const
Definition: wifi-phy.cc:2282
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:462
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:982
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1528
void RegisterListener(const std::shared_ptr< WifiPhyListener > &listener)
Definition: wifi-phy.cc:468
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:1119
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1042
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:903
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:626
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:456
const WifiPhyOperatingChannel & GetOperatingChannel() const
Get a const reference to the operating channel.
Definition: wifi-phy.cc:1054
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:145
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
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:706
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.