A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-primary-channels-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/attribute-container.h"
11#include "ns3/boolean.h"
12#include "ns3/config.h"
13#include "ns3/ctrl-headers.h"
14#include "ns3/enum.h"
15#include "ns3/he-configuration.h"
16#include "ns3/he-phy.h"
17#include "ns3/mobility-helper.h"
18#include "ns3/multi-model-spectrum-channel.h"
19#include "ns3/rng-seed-manager.h"
20#include "ns3/spectrum-wifi-helper.h"
21#include "ns3/sta-wifi-mac.h"
22#include "ns3/test.h"
23#include "ns3/tuple.h"
24#include "ns3/wifi-net-device.h"
25#include "ns3/wifi-psdu.h"
26
27#include <algorithm>
28#include <bitset>
29#include <sstream>
30
31using namespace ns3;
32
33NS_LOG_COMPONENT_DEFINE("WifiPrimaryChannelsTest");
34
35/**
36 * @ingroup wifi-test
37 * @ingroup tests
38 *
39 * @brief Test transmissions under different primary channel settings
40 *
41 * This test can be repeated for different widths of the operating channel. We
42 * configure as many BSSes as the number of distinct 20 MHz subchannels in the
43 * operating channel, so that each BSS is assigned a distinct primary20 channel.
44 * For each BSS, we test the transmission of SU PPDUs, DL MU PPDUs and HE TB PPDUs
45 * of all the widths (20 MHz, 40 MHz, etc.) allowed by the operating channel.
46 * Transmissions of a given type take place simultaneously in BSSes that do not
47 * operate on adjacent primary channels of the considered width (so that
48 * transmissions do not interfere with each other). It is also possible to
49 * select whether BSSes should be assigned (distinct) BSS colors or not.
50 */
52{
53 public:
54 /**
55 * Constructor
56 *
57 * @param channelWidth the operating channel width
58 * @param useDistinctBssColors whether to set distinct BSS colors to BSSes
59 */
61 ~WifiPrimaryChannelsTest() override;
62
63 /**
64 * Callback invoked when PHY receives a PSDU to transmit. Used to print
65 * transmitted PSDUs for debug purposes.
66 *
67 * @param context the context
68 * @param psduMap the PSDU map
69 * @param txVector the TX vector
70 * @param txPowerW the tx power in Watts
71 */
72 void Transmit(std::string context,
73 WifiConstPsduMap psduMap,
74 WifiTxVector txVector,
75 double txPowerW);
76 /**
77 * Have the AP of the given BSS transmit a SU PPDU using the given
78 * transmission channel width
79 *
80 * @param bss the given BSS
81 * @param txChannelWidth the given transmission channel width
82 */
83 void SendDlSuPpdu(uint8_t bss, MHz_u txChannelWidth);
84 /**
85 * Have the AP of the given BSS transmit a MU PPDU using the given
86 * transmission channel width and RU type
87 *
88 * @param bss the given BSS
89 * @param txChannelWidth the given transmission channel width
90 * @param ruType the given RU type
91 * @param nRus the number of RUs
92 */
93 void SendDlMuPpdu(uint8_t bss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus);
94 /**
95 * Have the AP of the given BSS transmit a Basic Trigger Frame. This method calls
96 * DoSendHeTbPpdu to actually have STAs transmit HE TB PPDUs using the given
97 * transmission channel width and RU type
98 *
99 * @param bss the given BSS
100 * @param txChannelWidth the given transmission channel width
101 * @param ruType the given RU type
102 * @param nRus the number of RUs
103 */
104 void SendHeTbPpdu(uint8_t bss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus);
105 /**
106 * Have the STAs of the given BSS transmit an HE TB PPDU using the given
107 * transmission channel width and RU type
108 *
109 * @param bss the given BSS
110 * @param txChannelWidth the given transmission channel width
111 * @param ruType the given RU type
112 * @param nRus the number of RUs
113 */
114 void DoSendHeTbPpdu(uint8_t bss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus);
115 /**
116 * Callback invoked when a station receives a DL PPDU.
117 *
118 * @param bss the BSS the receiving STA belongs to
119 * @param station the receiving station
120 * @param psdu the received PSDU
121 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
122 * @param txVector TxVector of the received PSDU
123 * @param perMpduStatus per MPDU reception status
124 */
125 void ReceiveDl(uint8_t bss,
126 uint8_t station,
129 const WifiTxVector& txVector,
130 const std::vector<bool>& perMpduStatus);
131 /**
132 * Callback invoked when an AP receives an UL PPDU.
133 *
134 * @param bss the BSS the receiving AP belongs to
135 * @param psdu the received PSDU
136 * @param rxSignalInfo the info on the received signal (\see RxSignalInfo)
137 * @param txVector TxVector of the received PSDU
138 * @param perMpduStatus per MPDU reception status
139 */
140 void ReceiveUl(uint8_t bss,
143 const WifiTxVector& txVector,
144 const std::vector<bool>& perMpduStatus);
145 /**
146 * Check that all stations associated with an AP.
147 */
148 void CheckAssociation();
149 /**
150 * Check that (i) all stations belonging to the given BSSes received the SU PPDUs
151 * transmitted over the given channel width; and (ii) all stations belonging to
152 * the other BSSes did not receive any frame if BSS Color is set (due to BSS Color
153 * filtering) or if no transmission was performed on a channel adjacent to the one
154 * they operate on, otherwise.
155 *
156 * @param txBss the set of BSSes that transmitted an SU PPDU
157 * @param txChannelWidth the given transmission channel width
158 */
159 void CheckReceivedSuPpdus(std::set<uint8_t> txBss, MHz_u txChannelWidth);
160 /**
161 * Check that (i) all stations/APs belonging to the given BSSes received the DL/UL MU PPDUs
162 * transmitted over the given channel width and RU width; and (ii) stations/APs belonging to
163 * the other BSSes did not receive any frame if BSS Color is set (due to BSS Color
164 * filtering) or if no transmission addressed to/from stations with the same AID was
165 * performed on a channel adjacent to the one they operate on, otherwise.
166 *
167 * @param txBss the set of BSSes that transmitted an SU PPDU
168 * @param txChannelWidth the given transmission channel width
169 * @param ruType the given RU type
170 * @param nRus the number of RUs
171 * @param isDlMu true for DL MU PPDU, false for HE TB PPDU
172 */
173 void CheckReceivedMuPpdus(std::set<uint8_t> txBss,
176 std::size_t nRus,
177 bool isDlMu);
178 /**
179 * Check that (i) all stations belonging to the given BSSes received the transmitted
180 * Trigger Frame; and (ii) all stations belonging to the other BSSes did not receive
181 * any frame Trigger Frame (given that a Trigger Frame is transmitted on the primary20
182 * channel and all the primary20 channels are distinct).
183 *
184 * @param txBss the set of BSSes that transmitted a Trigger Frame
185 * @param txChannelWidth the given transmission channel width
186 */
187 void CheckReceivedTriggerFrames(std::set<uint8_t> txBss, MHz_u txChannelWidth);
188
189 private:
190 void DoSetup() override;
191 void DoRun() override;
192
193 MHz_u m_channelWidth; ///< operating channel width
194 bool m_useDistinctBssColors; ///< true to set distinct BSS colors to BSSes
195 uint8_t m_nBss; ///< number of BSSes
196 uint8_t m_nStationsPerBss; ///< number of stations per AP
197 std::vector<NetDeviceContainer> m_staDevices; ///< containers for stations' NetDevices
198 NetDeviceContainer m_apDevices; ///< container for AP's NetDevice
199 std::vector<std::bitset<74>> m_received; /**< whether the last packet transmitted to/from each
200 of the (up to 74 per BSS) stations was received */
201 std::vector<std::bitset<74>> m_processed; /**< whether the last packet transmitted to/from each
202 of the (up to 74 per BSS) stations was processed */
203 Time m_time; ///< the time when the current action is executed
204 Ptr<WifiPsdu> m_trigger; ///< Basic Trigger Frame
205 WifiTxVector m_triggerTxVector; ///< TX vector for Basic Trigger Frame
206 Time m_triggerTxDuration; ///< TX duration for Basic Trigger Frame
207};
208
210 : TestCase("Check correct transmissions for various primary channel settings"),
211 m_channelWidth(channelWidth),
212 m_useDistinctBssColors(useDistinctBssColors)
213{
214}
215
219
220void
222 WifiConstPsduMap psduMap,
223 WifiTxVector txVector,
224 double txPowerW)
225{
226 for (const auto& psduPair : psduMap)
227 {
228 std::stringstream ss;
229
230 if (psduPair.first != SU_STA_ID)
231 {
232 ss << " STA-ID " << psduPair.first;
233 }
234 ss << " " << psduPair.second->GetHeader(0).GetTypeString() << " seq "
235 << psduPair.second->GetHeader(0).GetSequenceNumber() << " from "
236 << psduPair.second->GetAddr2() << " to " << psduPair.second->GetAddr1();
237 NS_LOG_INFO(ss.str());
238 }
239 NS_LOG_INFO(" TXVECTOR " << txVector);
240}
241
242void
244 uint8_t station,
247 const WifiTxVector& txVector,
248 const std::vector<bool>& perMpduStatus)
249{
250 if (psdu->GetNMpdus() == 1)
251 {
252 const WifiMacHeader& hdr = psdu->GetHeader(0);
253
254 if (hdr.IsQosData() || hdr.IsTrigger())
255 {
256 NS_LOG_INFO("RECEIVED BY BSS=" << +bss << " STA=" << +station << " " << *psdu);
257 // the MAC received a PSDU from the PHY
259 false,
260 "Station [" << +bss << "][" << +station
261 << "] received a frame twice");
262 m_received[bss].set(station);
263 // check if we are the intended destination of the PSDU
264 auto dev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(station));
265 if ((hdr.IsQosData() && hdr.GetAddr1() == dev->GetMac()->GetAddress()) ||
266 (hdr.IsTrigger() && hdr.GetAddr1() == Mac48Address::GetBroadcast()))
267 {
269 false,
270 "Station [" << +bss << "][" << +station
271 << "] processed a frame twice");
272 m_processed[bss].set(station);
273 }
274 }
275 }
276}
277
278void
282 const WifiTxVector& txVector,
283 const std::vector<bool>& perMpduStatus)
284{
285 // if the BSS color is zero, this AP might receive the frame sent by another AP. Given that
286 // stations only send TB PPDUs, we ignore this frame if the TX vector is not UL MU.
287 if (psdu->GetNMpdus() == 1 && psdu->GetHeader(0).IsQosData() && txVector.IsUlMu())
288 {
290
291 uint16_t staId = txVector.GetHeMuUserInfoMap().begin()->first;
292 uint8_t station = staId - 1;
293 NS_LOG_INFO("RECEIVED FROM BSSID=" << psdu->GetHeader(0).GetAddr3() << " STA=" << +station
294 << " " << *psdu);
295 // the MAC received a PSDU containing a QoS data frame from the PHY
297 false,
298 "AP of BSS " << +bss << " received a frame from station " << +station
299 << " twice");
300 m_received[bss].set(station);
301 // check if we are the intended destination of the PSDU
302 if (psdu->GetHeader(0).GetAddr1() == dev->GetMac()->GetAddress())
303 {
305 false,
306 "AP of BSS " << +bss << " received a frame from station "
307 << +station << " twice");
308 m_processed[bss].set(station);
309 }
310 }
311}
312
313void
315{
318 int64_t streamNumber = 100;
319 uint8_t channelNum;
320
321 // we create as many stations per BSS as the number of 26-tone RUs in a channel
322 // of the configured width
323 switch (static_cast<uint16_t>(m_channelWidth))
324 {
325 case 20:
327 channelNum = 36;
328 break;
329 case 40:
331 channelNum = 38;
332 break;
333 case 80:
335 channelNum = 42;
336 break;
337 case 160:
339 channelNum = 50;
340 break;
341 default:
342 NS_ABORT_MSG("Channel width (" << m_channelWidth << ") not allowed");
343 }
344
345 // we create as many BSSes as the number of 20 MHz subchannels
347
350
351 std::vector<NodeContainer> wifiStaNodes(m_nBss);
352 for (auto& container : wifiStaNodes)
353 {
354 container.Create(m_nStationsPerBss);
355 }
356
359 spectrumChannel->AddPropagationLossModel(lossModel);
362 spectrumChannel->SetPropagationDelayModel(delayModel);
363
365 phy.SetChannel(spectrumChannel);
366
367 WifiHelper wifi;
368 wifi.SetStandard(WIFI_STANDARD_80211ax);
369 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager");
370
371 WifiMacHelper mac;
372 mac.SetType("ns3::StaWifiMac",
373 "Ssid",
374 SsidValue(Ssid("non-existent-ssid")),
375 "MaxMissedBeacons",
376 UintegerValue(20),
377 "WaitBeaconTimeout",
378 TimeValue(MicroSeconds(102400))); // same as BeaconInterval
379
382 ';'>
384
385 // Each BSS uses a distinct primary20 channel
386 for (uint8_t bss = 0; bss < m_nBss; bss++)
387 {
390 phy.Set("ChannelSettings", channelValue);
391
392 m_staDevices.push_back(wifi.Install(phy, mac, wifiStaNodes[bss]));
393 }
394
395 for (uint8_t bss = 0; bss < m_nBss; bss++)
396 {
397 channelValue.Set(
399 phy.Set("ChannelSettings", channelValue);
400
401 mac.SetType("ns3::ApWifiMac",
402 "Ssid",
403 SsidValue(Ssid("wifi-ssid-" + std::to_string(bss))),
404 "BeaconInterval",
405 TimeValue(MicroSeconds(102400)),
406 "EnableBeaconJitter",
407 BooleanValue(false));
408
409 m_apDevices.Add(wifi.Install(phy, mac, wifiApNodes.Get(bss)));
410 }
411
412 // Assign fixed streams to random variables in use
414 for (uint8_t bss = 0; bss < m_nBss; bss++)
415 {
417 }
418
419 // set BSS color
421 {
422 for (uint8_t bss = 0; bss < m_nBss; bss++)
423 {
425 dev->GetHeConfiguration()->m_bssColor = bss + 1;
426 }
427 }
428
429 MobilityHelper mobility;
431
432 positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // all stations are co-located
433 mobility.SetPositionAllocator(positionAlloc);
434
435 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
436 mobility.Install(wifiApNodes);
437 for (uint8_t bss = 0; bss < m_nBss; bss++)
438 {
439 mobility.Install(wifiStaNodes[bss]);
440 }
441
442 m_received.resize(m_nBss);
443 m_processed.resize(m_nBss);
444
445 // pre-compute the Basic Trigger Frame to send
447
451 // Addr2 has to be set
452 hdr.SetSequenceNumber(1);
453
455 CtrlTriggerHeader trigger;
456 trigger.SetType(TriggerFrameType::BASIC_TRIGGER);
457 pkt->AddHeader(trigger);
458
460 0,
462 NanoSeconds(800),
463 1,
464 1,
465 0,
466 MHz_u{20},
467 false,
468 false,
469 false);
471
474 apDev->GetMac()->GetWifiPhy()->GetPhyBand());
475}
476
477void
479{
480 // schedule association requests at different times. One station's SSID is
481 // set to the correct value before initialization, so that such a station
482 // starts the scanning procedure by looking for the correct SSID
484
485 // association can be done in parallel over the multiple BSSes
486 for (uint8_t bss = 0; bss < m_nBss; bss++)
487 {
488 dev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(0));
489 dev->GetMac()->SetSsid(Ssid("wifi-ssid-" + std::to_string(bss)));
490
491 for (uint16_t i = 1; i < m_nStationsPerBss; i++)
492 {
496 dev->GetMac(),
497 Ssid("wifi-ssid-" + std::to_string(bss)));
498 }
499 }
500
501 // just before sending the beacon preceding the last association, increase the beacon
502 // interval (to the max allowed value) so that beacons do not interfere with data frames
503 for (uint8_t bss = 0; bss < m_nBss; bss++)
504 {
506 auto mac = DynamicCast<ApWifiMac>(dev->GetMac());
507
510 mac,
511 MicroSeconds(1024 * 65535));
512 }
513
514 m_time = (m_nStationsPerBss + 1) * MicroSeconds(102400);
515
517
518 // we are done with association. We now intercept frames received by the
519 // PHY layer on stations and APs, which will no longer be passed to the FEM.
520 for (uint8_t bss = 0; bss < m_nBss; bss++)
521 {
522 for (uint8_t i = 0; i < m_nStationsPerBss; i++)
523 {
524 auto dev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(i));
526 m_time,
528 dev->GetPhy(),
530 }
534 dev->GetPhy(),
536 }
537
538 /*
539 * We start generating (downlink) SU PPDUs.
540 * First, APs operating on non-adjacent primary20 channels send a frame simultaneously
541 * in their primary20. This is done in two rounds. As an example, we consider the
542 * case of an 160 MHz operating channel:
543 *
544 * AP0 AP2 AP4 AP6
545 * |-----| |-----| |-----| |-----| |
546 *
547 * AP1 AP3 AP5 AP7
548 * | |-----| |-----| |-----| |-----|
549 *
550 * Then, we double the transmission channel width. We will have four rounds
551 * of transmissions. We avoid using adjacent channels to avoid interference
552 * among transmissions:
553 *
554 * AP0 AP4
555 * |-----------| |-----------| |
556 * AP1 AP5
557 * |-----------| |-----------| |
558 * AP2 AP6
559 * | |-----------| |-----------|
560 * AP3 AP7
561 * | |-----------| |-----------|
562 *
563 * We double the transmission channel width again. We will have eight rounds
564 * of transmissions:
565 *
566 * AP0
567 * |-----------------------| |
568 * AP1
569 * |-----------------------| |
570 * AP2
571 * |-----------------------| |
572 * AP3
573 * |-----------------------| |
574 * AP4
575 * | |-----------------------|
576 * AP5
577 * | |-----------------------|
578 * AP6
579 * | |-----------------------|
580 * AP7
581 * | |-----------------------|
582 *
583 * We double the transmission channel width again. We will have eight rounds
584 * of transmissions:
585 *
586 * AP0
587 * |-----------------------------------------------|
588 * AP1
589 * |-----------------------------------------------|
590 * AP2
591 * |-----------------------------------------------|
592 * AP3
593 * |-----------------------------------------------|
594 * AP4
595 * |-----------------------------------------------|
596 * AP5
597 * |-----------------------------------------------|
598 * AP6
599 * |-----------------------------------------------|
600 * AP7
601 * |-----------------------------------------------|
602 *
603 * The transmission channel width reached the operating channel width, we are done.
604 */
605
606 Time roundDuration = MilliSeconds(5); // upper bound on the duration of a round
607
608 // To have simultaneous transmissions on adjacent channels, just initialize
609 // nRounds to 1 and nApsPerRound to m_channelWidth / 20. Of course, the test
610 // will fail because some stations will not receive some frames due to interference
611 uint16_t nRounds = 2;
614 txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
615 {
616 nRounds = std::min<uint16_t>(nRounds, m_nBss);
617 nApsPerRound = std::max<uint16_t>(nApsPerRound, 1);
618
619 for (uint16_t round = 0; round < nRounds; round++)
620 {
621 std::set<uint8_t> txBss;
622
623 for (uint16_t i = 0; i < nApsPerRound; i++)
624 {
625 uint16_t ap = round + i * nRounds;
626 txBss.insert(ap);
629 this,
630 ap,
632 }
633 // check that the SU frames were correctly received
636 this,
637 txBss,
640 }
641 }
642
643 /*
644 * Repeat the same scheme as before with DL MU transmissions. For each transmission
645 * channel width, every round is repeated as many times as the number of ways in
646 * which we can partition the transmission channel width in equal sized RUs.
647 */
648 nRounds = 2;
651 txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
652 {
653 nRounds = std::min<uint16_t>(nRounds, m_nBss);
654 nApsPerRound = std::max<uint16_t>(nApsPerRound, 1);
655
656 for (uint16_t round = 0; round < nRounds; round++)
657 {
658 for (unsigned int type = 0; type < 7; type++)
659 {
660 auto ruType = static_cast<HeRu::RuType>(type);
661 std::size_t nRus = HeRu::GetNRus(txChannelWidth, ruType);
662 std::set<uint8_t> txBss;
663 if (nRus > 0)
664 {
665 for (uint16_t i = 0; i < nApsPerRound; i++)
666 {
667 uint16_t ap = round + i * nRounds;
668 txBss.insert(ap);
671 this,
672 ap,
674 ruType,
675 nRus);
676 }
677 // check that the MU frame was correctly received
680 this,
681 txBss,
683 ruType,
684 nRus,
685 /* isDlMu */ true);
687 }
688 }
689 }
690 }
691
692 /*
693 * Repeat the same scheme as before with UL MU transmissions. For each transmission
694 * channel width, every round is repeated as many times as the number of ways in
695 * which we can partition the transmission channel width in equal sized RUs.
696 */
697 nRounds = 2;
700 txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
701 {
702 nRounds = std::min<uint16_t>(nRounds, m_nBss);
703 nApsPerRound = std::max<uint16_t>(nApsPerRound, 1);
704
705 for (uint16_t round = 0; round < nRounds; round++)
706 {
707 for (unsigned int type = 0; type < 7; type++)
708 {
709 auto ruType = static_cast<HeRu::RuType>(type);
710 std::size_t nRus = HeRu::GetNRus(txChannelWidth, ruType);
711 std::set<uint8_t> txBss;
712 if (nRus > 0)
713 {
714 for (uint16_t i = 0; i < nApsPerRound; i++)
715 {
716 uint16_t ap = round + i * nRounds;
717 txBss.insert(ap);
720 this,
721 ap,
723 ruType,
724 nRus);
725 }
726 // check that Trigger Frames and TB PPDUs were correctly received
728 MicroSeconds(10), /* during SIFS */
730 this,
731 txBss,
735 this,
736 txBss,
738 ruType,
739 nRus,
740 /* isDlMu */ false);
742 }
743 }
744 }
745 }
746
747 // Trace PSDUs passed to the PHY on all devices
748 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
750
753
755}
756
757void
759{
760 NS_LOG_INFO("*** BSS " << +bss << " transmits on primary " << txChannelWidth << " MHz channel");
761
764
765 uint8_t bssColor = apDev->GetHeConfiguration()->m_bssColor;
767 0,
769 NanoSeconds(800),
770 1,
771 1,
772 0,
774 false,
775 false,
776 false,
777 bssColor);
780 hdr.SetQosTid(0);
781 hdr.SetAddr1(staDev->GetMac()->GetAddress());
782 hdr.SetAddr2(apDev->GetMac()->GetAddress());
783 hdr.SetAddr3(apDev->GetMac()->GetBssid(0));
784 hdr.SetSequenceNumber(1);
786 apDev->GetPhy()->Send(WifiConstPsduMap({std::make_pair(SU_STA_ID, psdu)}), txVector);
787}
788
789void
793 std::size_t nRus)
794{
795 NS_LOG_INFO("*** BSS " << +bss << " transmits on primary " << txChannelWidth
796 << " MHz channel a DL MU PPDU "
797 << "addressed to " << nRus << " stations (RU type: " << ruType << ")");
798
800 uint8_t bssColor = apDev->GetHeConfiguration()->m_bssColor;
801
803 0,
805 NanoSeconds(800),
806 1,
807 1,
808 0,
810 false,
811 false,
812 false,
813 bssColor);
816 hdr.SetQosTid(0);
817 hdr.SetAddr2(apDev->GetMac()->GetAddress());
818 hdr.SetAddr3(apDev->GetMac()->GetBssid(0));
819 hdr.SetSequenceNumber(1);
820
821 WifiConstPsduMap psduMap;
822
823 for (std::size_t i = 1; i <= nRus; i++)
824 {
825 bool primary80 = !(txChannelWidth == MHz_u{160} && i > nRus / 2);
826 std::size_t index = (primary80 ? i : i - nRus / 2);
827
828 auto staDev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(i - 1));
829 uint16_t staId = DynamicCast<StaWifiMac>(staDev->GetMac())->GetAssociationId();
830 txVector.SetHeMuUserInfo(staId, {{ruType, index, primary80}, 8, 1});
831 hdr.SetAddr1(staDev->GetMac()->GetAddress());
832 psduMap[staId] = Create<const WifiPsdu>(Create<Packet>(1000), hdr);
833 }
838 auto IsOddNum = (nRus / numRuAllocs) % 2 == 1;
840 std::fill_n(ruAllocations.begin(), numRuAllocs, ruAlloc);
841 txVector.SetRuAllocation(ruAllocations, 0);
842
843 apDev->GetPhy()->Send(psduMap, txVector);
844}
845
846void
850 std::size_t nRus)
851{
852 NS_LOG_INFO("*** BSS " << +bss << " transmits a Basic Trigger Frame");
853
855
856 m_trigger->GetHeader(0).SetAddr2(apDev->GetMac()->GetAddress());
857
858 apDev->GetPhy()->Send(m_trigger, m_triggerTxVector);
859
860 // schedule the transmission of HE TB PPDUs
861 Simulator::Schedule(m_triggerTxDuration + apDev->GetPhy()->GetSifs(),
863 this,
864 bss,
866 ruType,
867 nRus);
868}
869
870void
874 std::size_t nRus)
875{
877 uint8_t bssColor = apDev->GetHeConfiguration()->m_bssColor;
878
881 hdr.SetQosTid(0);
882 hdr.SetAddr1(apDev->GetMac()->GetAddress());
883 hdr.SetAddr3(apDev->GetMac()->GetBssid(0));
884 hdr.SetSequenceNumber(1);
885
886 Time duration;
887 uint16_t length = 0;
889 0,
891 NanoSeconds(3200),
892 1,
893 1,
894 0,
896 false,
897 false,
898 false,
899 bssColor);
900
901 for (std::size_t i = 1; i <= nRus; i++)
902 {
903 NS_LOG_INFO("*** BSS " << +bss << " STA " << i - 1 << " transmits on primary "
905 << " MHz channel an HE TB PPDU (RU type: " << ruType << ")");
906
907 bool primary80 = !(txChannelWidth == MHz_u{160} && i > nRus / 2);
908 std::size_t index = (primary80 ? i : i - nRus / 2);
909
910 auto staDev = DynamicCast<WifiNetDevice>(m_staDevices[bss].Get(i - 1));
911 uint16_t staId = DynamicCast<StaWifiMac>(staDev->GetMac())->GetAssociationId();
912
914 0,
916 NanoSeconds(3200),
917 1,
918 1,
919 0,
921 false,
922 false,
923 false,
924 bssColor);
925 txVector.SetHeMuUserInfo(staId, {{ruType, index, primary80}, 8, 1});
926 trigVector.SetHeMuUserInfo(staId, {{ruType, index, primary80}, 8, 1});
927
928 hdr.SetAddr2(staDev->GetMac()->GetAddress());
930
931 if (duration.IsZero())
932 {
933 // calculate just once
934 duration = WifiPhy::CalculateTxDuration(psdu->GetSize(),
935 txVector,
936 staDev->GetMac()->GetWifiPhy()->GetPhyBand(),
937 staId);
938 std::tie(length, duration) = HePhy::ConvertHeTbPpduDurationToLSigLength(
939 duration,
940 txVector,
941 staDev->GetMac()->GetWifiPhy()->GetPhyBand());
942 }
943 txVector.SetLength(length);
944
945 staDev->GetPhy()->Send(WifiConstPsduMap{{staId, psdu}}, txVector);
946 }
947
948 // AP's PHY expects to receive a TRIGVECTOR (just once)
949 trigVector.SetLength(length);
950 auto apHePhy = StaticCast<HePhy>(apDev->GetPhy()->GetLatestPhyEntity());
951 apHePhy->SetTrigVector(trigVector, duration);
952}
953
954void
956{
957 for (uint8_t bss = 0; bss < m_nBss; bss++)
958 {
960 auto mac = DynamicCast<ApWifiMac>(dev->GetMac());
961 NS_TEST_EXPECT_MSG_EQ(mac->GetStaList(SINGLE_LINK_OP_ID).size(),
963 "Not all the stations completed association");
964 }
965}
966
967void
969{
970 for (uint8_t bss = 0; bss < m_nBss; bss++)
971 {
972 if (txBss.find(bss) != txBss.end())
973 {
974 // Every station in the BSS of an AP that transmitted the frame hears (i.e.,
975 // passes to the MAC) the frame
976 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
977 {
979 true,
980 "Station [" << +bss << "][" << +sta
981 << "] did not receive the SU frame on primary"
982 << txChannelWidth << " channel");
983 }
984 // only the first station actually processed the frames
986 true,
987 "Station [" << +bss << "][0]"
988 << " did not process the SU frame on primary"
989 << txChannelWidth << " channel");
990 for (uint8_t sta = 1; sta < m_nStationsPerBss; sta++)
991 {
993 false,
994 "Station [" << +bss << "][" << +sta
995 << "] processed the SU frame on primary"
996 << txChannelWidth << " channel");
997 }
998 }
999 else
1000 {
1001 // There was no transmission in this BSS. If BSS Color filtering is enabled or no frame
1002 // transmission overlaps with the primary20 channel of this BSS, stations in this BSS
1003 // did not hear any frame.
1005 std::none_of(txBss.begin(), txBss.end(), [&](const uint8_t& txAp) {
1006 auto txApPhy = DynamicCast<WifiNetDevice>(m_apDevices.Get(txAp))->GetPhy();
1007 auto thisApPhy = DynamicCast<WifiNetDevice>(m_apDevices.Get(bss))->GetPhy();
1008 return txApPhy->GetOperatingChannel().GetPrimaryChannelIndex(txChannelWidth) ==
1009 thisApPhy->GetOperatingChannel().GetPrimaryChannelIndex(txChannelWidth);
1010 }))
1011 {
1012 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
1013 {
1015 false,
1016 "Station [" << +bss << "][" << +sta
1017 << "] received the SU frame on primary"
1018 << txChannelWidth << " channel");
1019 }
1020 }
1021 else
1022 {
1023 // all stations heard the frame but no station processed it
1024 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
1025 {
1027 true,
1028 "Station [" << +bss << "][" << +sta
1029 << "] did not receive the SU frame on primary"
1030 << txChannelWidth << " channel");
1032 false,
1033 "Station [" << +bss << "][" << +sta
1034 << "] processed the SU frame on primary"
1035 << txChannelWidth << " channel");
1036 }
1037 }
1038 }
1039 // reset bitmaps
1040 m_received[bss].reset();
1041 m_processed[bss].reset();
1042 }
1043}
1044
1045void
1049 std::size_t nRus,
1050 bool isDlMu)
1051{
1052 for (uint8_t bss = 0; bss < m_nBss; bss++)
1053 {
1054 if (txBss.find(bss) != txBss.end())
1055 {
1056 // There was a transmission in this BSS.
1057 // [DL] Due to AID filtering, only stations that are addressed by the MU PPDU do hear
1058 // the frame [UL] The AP hears a TB PPDU sent by all and only the solicited stations
1059 for (std::size_t sta = 0; sta < nRus; sta++)
1060 {
1062 m_received[bss].test(sta),
1063 true,
1064 (isDlMu ? "A DL MU PPDU transmitted to" : "An HE TB PPDU transmitted by")
1065 << " station [" << +bss << "][" << +sta << "] on primary" << txChannelWidth
1066 << " channel, RU type " << ruType << " was not received");
1067 }
1068 for (uint8_t sta = nRus; sta < m_nStationsPerBss; sta++)
1069 {
1071 false,
1072 (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
1073 << " transmitted on primary" << txChannelWidth
1074 << " channel, RU type " << ruType << " was received "
1075 << (isDlMu ? "by" : "from") << " station [" << +bss
1076 << "][" << +sta << "]");
1077 }
1078 // [DL] Only the addressed stations actually processed the frames
1079 // [UL] The AP processed the frames sent by all and only the addressed stations
1080 for (std::size_t sta = 0; sta < nRus; sta++)
1081 {
1083 m_processed[bss].test(sta),
1084 true,
1085 (isDlMu ? "A DL MU PPDU transmitted to" : "An HE TB PPDU transmitted by")
1086 << " station [" << +bss << "][" << +sta << "] on primary" << txChannelWidth
1087 << " channel, RU type " << ruType << " was not processed");
1088 }
1089 for (uint8_t sta = nRus; sta < m_nStationsPerBss; sta++)
1090 {
1092 false,
1093 (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
1094 << " transmitted on primary" << txChannelWidth
1095 << " channel, RU type " << ruType << " was received "
1096 << (isDlMu ? "by" : "from") << " station [" << +bss
1097 << "][" << +sta << "] and processed");
1098 }
1099 }
1100 else
1101 {
1102 // There was no transmission in this BSS.
1103 // [DL] If BSS Color filtering is enabled or no frame transmission overlaps with
1104 // the primary20 channel of this BSS, stations in this BSS did not hear any frame.
1105 // [UL] The AP did not hear any TB PPDU because no TRIGVECTOR was passed to the PHY
1107 std::none_of(txBss.begin(), txBss.end(), [&](const uint8_t& txAp) {
1108 auto txApPhy = DynamicCast<WifiNetDevice>(m_apDevices.Get(txAp))->GetPhy();
1109 auto thisApPhy = DynamicCast<WifiNetDevice>(m_apDevices.Get(bss))->GetPhy();
1110 return txApPhy->GetOperatingChannel().GetPrimaryChannelIndex(txChannelWidth) ==
1111 thisApPhy->GetOperatingChannel().GetPrimaryChannelIndex(txChannelWidth);
1112 }))
1113 {
1114 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
1115 {
1117 false,
1118 (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
1119 << " transmitted on primary" << txChannelWidth
1120 << " channel, RU type " << ruType << " was received "
1121 << (isDlMu ? "by" : "from") << " station [" << +bss
1122 << "][" << +sta << "]");
1123 }
1124 }
1125 else
1126 {
1127 // [DL] Stations having the same AID of the stations addressed by the MU PPDU
1128 // received the frame
1129 for (std::size_t sta = 0; sta < nRus; sta++)
1130 {
1132 m_received[bss].test(sta),
1133 true,
1134 (isDlMu ? "A DL MU PPDU transmitted to" : "An HE TB PPDU transmitted by")
1135 << " station [" << +bss << "][" << +sta << "] on primary"
1136 << txChannelWidth << " channel, RU type " << ruType
1137 << " was not received");
1138 }
1139 for (uint8_t sta = nRus; sta < m_nStationsPerBss; sta++)
1140 {
1142 false,
1143 (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
1144 << " transmitted on primary" << txChannelWidth
1145 << " channel, RU type " << ruType << " was received "
1146 << (isDlMu ? "by" : "from") << " station [" << +bss
1147 << "][" << +sta << "]");
1148 }
1149 // no station processed the frame
1150 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
1151 {
1153 false,
1154 (isDlMu ? "A DL MU PPDU" : "An HE TB PPDU")
1155 << " transmitted on primary" << txChannelWidth
1156 << " channel, RU type " << ruType << " was received "
1157 << (isDlMu ? "by" : "from") << " station [" << +bss
1158 << "][" << +sta << "] and processed");
1159 }
1160 }
1161 }
1162 // reset bitmaps
1163 m_received[bss].reset();
1164 m_processed[bss].reset();
1165 }
1166}
1167
1168void
1170{
1171 for (uint8_t bss = 0; bss < m_nBss; bss++)
1172 {
1173 if (txBss.find(bss) != txBss.end())
1174 {
1175 // Every station in the BSS of an AP that transmitted the Trigger Frame hears (i.e.,
1176 // passes to the MAC) and processes the frame
1177 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
1178 {
1180 true,
1181 "Station [" << +bss << "][" << +sta
1182 << "] did not receive the Trigger Frame "
1183 "soliciting a transmission on primary"
1184 << txChannelWidth << " channel");
1186 true,
1187 "Station [" << +bss << "][" << +sta
1188 << "] did not process the Trigger Frame "
1189 "soliciting a transmission on primary"
1190 << txChannelWidth << " channel");
1191 }
1192 }
1193 else
1194 {
1195 // Given that a Trigger Frame is transmitted on the primary20 channel and all the
1196 // primary20 channels are distinct, stations in other BSSes did not hear the frame
1197 for (uint8_t sta = 0; sta < m_nStationsPerBss; sta++)
1198 {
1200 m_received[bss].test(sta),
1201 false,
1202 "Station ["
1203 << +bss << "][" << +sta
1204 << "] received the Trigger Frame soliciting a transmission on primary"
1205 << txChannelWidth << " channel");
1206 }
1207 }
1208 // reset bitmaps
1209 m_received[bss].reset();
1210 m_processed[bss].reset();
1211 }
1212}
1213
1214/**
1215 * @ingroup wifi-test
1216 * @ingroup tests
1217 *
1218 * @brief Test functions returning the indices of primary and secondary channels
1219 * of different width.
1220 */
1222{
1223 public:
1224 /**
1225 * Constructor
1226 */
1228 ~Wifi20MHzChannelIndicesTest() override = default;
1229
1230 /**
1231 * Check that the indices of the 20 MHz channels included in all the primary
1232 * and secondary channels are correct when setting the given primary20 channel.
1233 *
1234 * @param primary20 the index of the primary20 channel to configure
1235 * @param secondary20 the expected index of the secondary20 channel
1236 * @param primary40 the expected indices of the 20 MHz channels in the primary40 channel
1237 * @param secondary40 the expected indices of the 20 MHz channels in the secondary40 channel
1238 * @param primary80 the expected indices of the 20 MHz channels in the primary80 channel
1239 * @param secondary80 the expected indices of the 20 MHz channels in the secondary80 channel
1240 */
1241 void RunOne(uint8_t primary20,
1242 const std::set<uint8_t>& secondary20,
1243 const std::set<uint8_t>& primary40,
1244 const std::set<uint8_t>& secondary40,
1245 const std::set<uint8_t>& primary80,
1246 const std::set<uint8_t>& secondary80);
1247
1248 private:
1249 void DoRun() override;
1250
1251 WifiPhyOperatingChannel m_channel; //!< operating channel
1252};
1253
1255 : TestCase("Check computation of primary and secondary channel indices")
1256{
1257}
1258
1259void
1261 const std::set<uint8_t>& secondary20,
1262 const std::set<uint8_t>& primary40,
1263 const std::set<uint8_t>& secondary40,
1264 const std::set<uint8_t>& primary80,
1265 const std::set<uint8_t>& secondary80)
1266{
1267 auto printToStr = [](const std::set<uint8_t>& s) {
1268 std::stringstream ss;
1269 ss << "{";
1270 for (const auto& index : s)
1271 {
1272 ss << +index << " ";
1273 }
1274 ss << "}";
1275 return ss.str();
1276 };
1277
1279
1281 NS_TEST_ASSERT_MSG_EQ((actualPrimary20 == std::set<uint8_t>{primary20}),
1282 true,
1283 "Expected Primary20 {" << +primary20 << "}"
1284 << " differs from actual "
1286
1289 true,
1290 "Expected Secondary20 " << printToStr(secondary20)
1291 << " differs from actual "
1293
1296 true,
1297 "Expected Primary40 " << printToStr(primary40) << " differs from actual "
1299
1302 true,
1303 "Expected Secondary40 " << printToStr(secondary40)
1304 << " differs from actual "
1306
1309 true,
1310 "Expected Primary80 " << printToStr(primary80) << " differs from actual "
1312
1315 true,
1316 "Expected Secondary80 " << printToStr(secondary80)
1317 << " differs from actual "
1319}
1320
1321void
1323{
1324 /* 20 MHz channel */
1326 RunOne(0, {}, {}, {}, {}, {});
1327
1328 /* 40 MHz channel */
1330 RunOne(0, {1}, {0, 1}, {}, {}, {});
1331 RunOne(1, {0}, {0, 1}, {}, {}, {});
1332
1333 /* 80 MHz channel */
1335 RunOne(0, {1}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {});
1336 RunOne(1, {0}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {});
1337 RunOne(2, {3}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {});
1338 RunOne(3, {2}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {});
1339
1340 /* 160 MHz channel */
1342 RunOne(0, {1}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {4, 5, 6, 7});
1343 RunOne(1, {0}, {0, 1}, {2, 3}, {0, 1, 2, 3}, {4, 5, 6, 7});
1344 RunOne(2, {3}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {4, 5, 6, 7});
1345 RunOne(3, {2}, {2, 3}, {0, 1}, {0, 1, 2, 3}, {4, 5, 6, 7});
1346 RunOne(4, {5}, {4, 5}, {6, 7}, {4, 5, 6, 7}, {0, 1, 2, 3});
1347 RunOne(5, {4}, {4, 5}, {6, 7}, {4, 5, 6, 7}, {0, 1, 2, 3});
1348 RunOne(6, {7}, {6, 7}, {4, 5}, {4, 5, 6, 7}, {0, 1, 2, 3});
1349 RunOne(7, {6}, {6, 7}, {4, 5}, {4, 5, 6, 7}, {0, 1, 2, 3});
1350}
1351
1352/**
1353 * @ingroup wifi-test
1354 * @ingroup tests
1355 *
1356 * @brief wifi primary channels test suite
1357 */
1359{
1360 public:
1362};
1363
1365 : TestSuite("wifi-primary-channels", Type::UNIT)
1366{
1367 // Test cases for 20 MHz can be added, but are not that useful (there would be a single BSS)
1368 AddTestCase(new WifiPrimaryChannelsTest(MHz_u{40}, true), TestCase::Duration::QUICK);
1369 AddTestCase(new WifiPrimaryChannelsTest(MHz_u{40}, false), TestCase::Duration::QUICK);
1370#if 0
1371 // Tests disabled until issue #776 resolved
1372 AddTestCase(new WifiPrimaryChannelsTest(MHz_u{80}, true), TestCase::Duration::EXTENSIVE);
1373 AddTestCase(new WifiPrimaryChannelsTest(MHz_u{80}, false), TestCase::Duration::EXTENSIVE);
1374 AddTestCase(new WifiPrimaryChannelsTest(MHz_u{160}, true), TestCase::Duration::TAKES_FOREVER);
1375 AddTestCase(new WifiPrimaryChannelsTest(MHz_u{160}, false), TestCase::Duration::TAKES_FOREVER);
1376#endif
1377 AddTestCase(new Wifi20MHzChannelIndicesTest(), TestCase::Duration::QUICK);
1378}
1379
Test functions returning the indices of primary and secondary channels of different width.
void DoRun() override
Implementation to actually run this TestCase.
~Wifi20MHzChannelIndicesTest() override=default
void RunOne(uint8_t primary20, const std::set< uint8_t > &secondary20, const std::set< uint8_t > &primary40, const std::set< uint8_t > &secondary40, const std::set< uint8_t > &primary80, const std::set< uint8_t > &secondary80)
Check that the indices of the 20 MHz channels included in all the primary and secondary channels are ...
WifiPhyOperatingChannel m_channel
operating channel
Test transmissions under different primary channel settings.
void DoSendHeTbPpdu(uint8_t bss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the STAs of the given BSS transmit an HE TB PPDU using the given transmission channel width and ...
std::vector< std::bitset< 74 > > m_processed
whether the last packet transmitted to/from each of the (up to 74 per BSS) stations was processed
WifiPrimaryChannelsTest(MHz_u channelWidth, bool useDistinctBssColors)
Constructor.
void CheckAssociation()
Check that all stations associated with an AP.
void CheckReceivedSuPpdus(std::set< uint8_t > txBss, MHz_u txChannelWidth)
Check that (i) all stations belonging to the given BSSes received the SU PPDUs transmitted over the g...
std::vector< std::bitset< 74 > > m_received
whether the last packet transmitted to/from each of the (up to 74 per BSS) stations was received
void CheckReceivedTriggerFrames(std::set< uint8_t > txBss, MHz_u txChannelWidth)
Check that (i) all stations belonging to the given BSSes received the transmitted Trigger Frame; and ...
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when PHY receives a PSDU to transmit.
void SendDlMuPpdu(uint8_t bss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the AP of the given BSS transmit a MU PPDU using the given transmission channel width and RU typ...
MHz_u m_channelWidth
operating channel width
void ReceiveUl(uint8_t bss, Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &perMpduStatus)
Callback invoked when an AP receives an UL PPDU.
Ptr< WifiPsdu > m_trigger
Basic Trigger Frame.
void DoRun() override
Implementation to actually run this TestCase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Time m_time
the time when the current action is executed
Time m_triggerTxDuration
TX duration for Basic Trigger Frame.
uint8_t m_nStationsPerBss
number of stations per AP
void ReceiveDl(uint8_t bss, uint8_t station, Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &perMpduStatus)
Callback invoked when a station receives a DL PPDU.
void CheckReceivedMuPpdus(std::set< uint8_t > txBss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus, bool isDlMu)
Check that (i) all stations/APs belonging to the given BSSes received the DL/UL MU PPDUs transmitted ...
std::vector< NetDeviceContainer > m_staDevices
containers for stations' NetDevices
NetDeviceContainer m_apDevices
container for AP's NetDevice
void SendHeTbPpdu(uint8_t bss, MHz_u txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the AP of the given BSS transmit a Basic Trigger Frame.
bool m_useDistinctBssColors
true to set distinct BSS colors to BSSes
WifiTxVector m_triggerTxVector
TX vector for Basic Trigger Frame.
void SendDlSuPpdu(uint8_t bss, MHz_u txChannelWidth)
Have the AP of the given BSS transmit a SU PPDU using the given transmission channel width.
wifi primary channels test suite
void SetBeaconInterval(Time interval)
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
Headers for Trigger frames.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
static WifiMode GetHeMcs8()
Return MCS 8 from HE MCS values.
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
Definition he-phy.cc:261
static uint8_t GetEqualizedRuAllocation(RuType ruType, bool isOdd)
Get the RU_ALLOCATION value for equal size RUs.
Definition he-ru.cc:414
static std::size_t GetNRus(MHz_u 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:484
RuType
The different HE Resource Unit (RU) types.
Definition he-ru.h:32
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:66
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
bool IsZero() const
Exactly equivalent to t == 0.
Definition nstime.h:304
AttributeValue implementation for Time.
Definition nstime.h:1431
AttributeValue implementation for Tuple.
Definition tuple.h:67
Hold an unsigned integer type.
Definition uinteger.h:34
void Set(const uint64_t &value)
Set the value.
Definition uinteger.cc:26
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
Implements the IEEE 802.11 MAC header.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
create MAC layers for a ns3::WifiNetDevice.
void SetSsid(Ssid ssid)
Definition wifi-mac.cc:527
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1587
std::vector< ChannelTuple > ChannelSegments
segments identifying an operating channel
Definition wifi-phy.h:947
void SetReceiveOkCallback(RxOkCallback callback)
Definition wifi-phy.cc:478
Class that keeps track of all information about the current PHY operating channel.
std::set< uint8_t > GetAll20MHzChannelIndicesInSecondary(MHz_u width) const
Get the channel indices of all the 20 MHz channels included in the secondary channel of the given wid...
void SetPrimary20Index(uint8_t index)
Set the index of the primary 20 MHz channel (0 indicates the 20 MHz subchannel with the lowest center...
std::set< uint8_t > GetAll20MHzChannelIndicesInPrimary(MHz_u width) const
Get the channel indices of all the 20 MHz channels included in the primary channel of the given width...
void SetDefault(MHz_u width, WifiStandard standard, WifiPhyBand band)
Set the default channel of the given width and for the given standard and band.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Definition wifi-psdu.cc:278
uint32_t GetSize() const
Return the size of the PSDU in bytes.
Definition wifi-psdu.cc:272
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:134
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1380
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
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:684
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
Definition wifi-utils.h:135
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition wifi-utils.h:272
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_QOSDATA
std::vector< uint16_t > RuAllocation
9 bits RU_ALLOCATION per 20 MHz
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
-ns3 Test suite for the ns3 wrapper script
RxSignalInfo structure containing info on the received signal.
Definition wifi-types.h:72
static WifiPrimaryChannelsTestSuite g_wifiPrimaryChannelsTestSuite
the test suite