A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-mu-mimo-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 DERONNE SOFTWARE ENGINEERING
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
18 */
19
20#include "ns3/ap-wifi-mac.h"
21#include "ns3/boolean.h"
22#include "ns3/double.h"
23#include "ns3/he-configuration.h"
24#include "ns3/he-phy.h"
25#include "ns3/interference-helper.h"
26#include "ns3/log.h"
27#include "ns3/multi-model-spectrum-channel.h"
28#include "ns3/nist-error-rate-model.h"
29#include "ns3/node.h"
30#include "ns3/pointer.h"
31#include "ns3/rng-seed-manager.h"
32#include "ns3/simulator.h"
33#include "ns3/spectrum-wifi-helper.h"
34#include "ns3/spectrum-wifi-phy.h"
35#include "ns3/string.h"
36#include "ns3/test.h"
37#include "ns3/txop.h"
38#include "ns3/uinteger.h"
39#include "ns3/wifi-mac-header.h"
40#include "ns3/wifi-net-device.h"
41#include "ns3/wifi-psdu.h"
42#include "ns3/wifi-spectrum-value-helper.h"
43#include "ns3/wifi-utils.h"
44
45#include <list>
46#include <tuple>
47
48using namespace ns3;
49
50NS_LOG_COMPONENT_DEFINE("WifiPhyMuMimoTest");
51
52constexpr uint32_t DEFAULT_FREQUENCY = 5180; // MHz
53constexpr uint16_t DEFAULT_CHANNEL_WIDTH = 20; // MHz
54
55/**
56 * \ingroup wifi-test
57 * \ingroup tests
58 *
59 * \brief DL MU TX-VECTOR test
60 */
62{
63 public:
65
66 private:
67 void DoRun() override;
68
69 /**
70 * Build a TXVECTOR for DL MU with the given bandwidth and user information.
71 *
72 * \param bw the channel width of the PPDU in MHz
73 * \param userInfos the list of HE MU specific user transmission parameters
74 *
75 * \return the configured MU TXVECTOR
76 */
77 static WifiTxVector BuildTxVector(uint16_t bw, const std::list<HeMuUserInfo>& userInfos);
78};
79
81 : TestCase("Check for valid combinations of MU TX-VECTOR")
82{
83}
84
86TestDlMuTxVector::BuildTxVector(uint16_t bw, const std::list<HeMuUserInfo>& userInfos)
87{
88 WifiTxVector txVector;
90 txVector.SetChannelWidth(bw);
91 std::list<uint16_t> staIds;
92 uint16_t staId = 1;
93 for (const auto& userInfo : userInfos)
94 {
95 txVector.SetHeMuUserInfo(staId, userInfo);
96 staIds.push_back(staId++);
97 }
98 return txVector;
99}
100
101void
103{
104 // Verify TxVector is OFDMA
105 std::list<HeMuUserInfo> userInfos;
106 userInfos.push_back({{HeRu::RU_106_TONE, 1, true}, 11, 1});
107 userInfos.push_back({{HeRu::RU_106_TONE, 2, true}, 10, 2});
108 WifiTxVector txVector = BuildTxVector(20, userInfos);
110 true,
111 "TX-VECTOR should indicate an OFDMA transmission");
113 false,
114 "TX-VECTOR should not indicate a MU-MIMO transmission");
116 false,
117 "TX-VECTOR should not indicate a SIG-B compression");
119 true,
120 "TX-VECTOR should indicate all checks are passed");
121 userInfos.clear();
122
123 // Verify TxVector is a full BW MU-MIMO
124 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 11, 1});
125 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 10, 2});
126 txVector = BuildTxVector(20, userInfos);
128 false,
129 "TX-VECTOR should indicate a MU-MIMO transmission");
131 true,
132 "TX-VECTOR should not indicate an OFDMA transmission");
134 true,
135 "TX-VECTOR should indicate a SIG-B compression");
137 true,
138 "TX-VECTOR should indicate all checks are passed");
139 userInfos.clear();
140
141 // Verify TxVector is not valid if there are more than 8 STAs using the same RU
142 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 11, 1});
143 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 10, 1});
144 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 9, 1});
145 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 8, 1});
146 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 7, 1});
147 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 6, 1});
148 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 5, 1});
149 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 4, 1});
150 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 3, 1});
151 txVector = BuildTxVector(20, userInfos);
153 false,
154 "TX-VECTOR should indicate a MU-MIMO transmission");
156 true,
157 "TX-VECTOR should not indicate an OFDMA transmission");
159 true,
160 "TX-VECTOR should indicate a SIG-B compression");
162 false,
163 "TX-VECTOR should not indicate all checks are passed");
164
165 // Verify TxVector is not valid if the total number of antennas in a full BW MU-MIMO is above 8
166 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 11, 2});
167 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 10, 2});
168 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 9, 3});
169 userInfos.push_back({{HeRu::RU_242_TONE, 1, true}, 8, 3});
170 txVector = BuildTxVector(20, userInfos);
172 false,
173 "TX-VECTOR should indicate a MU-MIMO transmission");
175 true,
176 "TX-VECTOR should not indicate an OFDMA transmission");
178 true,
179 "TX-VECTOR should indicate a SIG-B compression");
181 false,
182 "TX-VECTOR should not indicate all checks are passed");
183}
184
185/**
186 * HE PHY slightly modified so as to return a given
187 * STA-ID in case of DL MU for MuMimoSpectrumWifiPhy.
188 */
189class MuMimoTestHePhy : public HePhy
190{
191 public:
192 /**
193 * Constructor
194 *
195 * \param staId the ID of the STA to which this PHY belongs to
196 */
197 MuMimoTestHePhy(uint16_t staId);
198
199 /**
200 * Return the STA ID that has been assigned to the station this PHY belongs to.
201 * This is typically called for MU PPDUs, in order to pick the correct PSDU.
202 *
203 * \param ppdu the PPDU for which the STA ID is requested
204 * \return the STA ID
205 */
206 uint16_t GetStaId(const Ptr<const WifiPpdu> ppdu) const override;
207
208 /**
209 * Set the global PPDU UID counter.
210 *
211 * \param uid the value to which the global PPDU UID counter should be set
212 */
213 void SetGlobalPpduUid(uint64_t uid);
214
215 private:
216 uint16_t m_staId; ///< ID of the STA to which this PHY belongs to
217}; // class MuMimoTestHePhy
218
220 : HePhy(),
221 m_staId(staId)
222{
223}
224
225uint16_t
227{
228 if (ppdu->GetType() == WIFI_PPDU_TYPE_DL_MU)
229 {
230 return m_staId;
231 }
232 return HePhy::GetStaId(ppdu);
233}
234
235void
237{
238 m_globalPpduUid = uid;
239}
240
241/**
242 * SpectrumWifiPhy used for testing MU-MIMO.
243 */
245{
246 public:
247 /**
248 * \brief Get the type ID.
249 * \return the object TypeId
250 */
251 static TypeId GetTypeId();
252 /**
253 * Constructor
254 *
255 * \param staId the ID of the STA to which this PHY belongs to
256 */
257 MuMimoSpectrumWifiPhy(uint16_t staId);
258 ~MuMimoSpectrumWifiPhy() override;
259
260 /**
261 * Set the global PPDU UID counter.
262 *
263 * \param uid the value to which the global PPDU UID counter should be set
264 */
265 void SetPpduUid(uint64_t uid);
266
267 /**
268 * Since we assume trigger frame was previously received from AP, this is used to set its UID
269 *
270 * \param uid the PPDU UID of the trigger frame
271 */
272 void SetTriggerFrameUid(uint64_t uid);
273
274 /**
275 * \return the current event
276 */
278
279 private:
280 void DoInitialize() override;
281 void DoDispose() override;
282
283 Ptr<MuMimoTestHePhy> m_ofdmTestHePhy; ///< Pointer to HE PHY instance used for MU-MIMO test
284}; // class MuMimoSpectrumWifiPhy
285
286TypeId
288{
289 static TypeId tid =
290 TypeId("ns3::MuMimoSpectrumWifiPhy").SetParent<SpectrumWifiPhy>().SetGroupName("Wifi");
291 return tid;
292}
293
296{
297 m_ofdmTestHePhy = Create<MuMimoTestHePhy>(staId);
299}
300
302{
303}
304
305void
307{
308 // Replace HE PHY instance with test instance
311}
312
313void
315{
316 m_ofdmTestHePhy = nullptr;
318}
319
320void
322{
325}
326
327void
329{
331}
332
335{
336 return m_currentEvent;
337}
338
339/**
340 * \ingroup wifi-test
341 * \ingroup tests
342 *
343 * \brief DL MU-MIMO PHY test
344 */
346{
347 public:
349
350 private:
351 void DoSetup() override;
352 void DoTeardown() override;
353 void DoRun() override;
354
355 /**
356 * Receive success function for STA 1
357 * \param psdu the PSDU
358 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
359 * \param txVector the transmit vector
360 * \param statusPerMpdu reception status per MPDU
361 */
363 RxSignalInfo rxSignalInfo,
364 WifiTxVector txVector,
365 std::vector<bool> statusPerMpdu);
366 /**
367 * Receive success function for STA 2
368 * \param psdu the PSDU
369 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
370 * \param txVector the transmit vector
371 * \param statusPerMpdu reception status per MPDU
372 */
374 RxSignalInfo rxSignalInfo,
375 WifiTxVector txVector,
376 std::vector<bool> statusPerMpdu);
377 /**
378 * Receive success function for STA 3
379 * \param psdu the PSDU
380 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
381 * \param txVector the transmit vector
382 * \param statusPerMpdu reception status per MPDU
383 */
385 RxSignalInfo rxSignalInfo,
386 WifiTxVector txVector,
387 std::vector<bool> statusPerMpdu);
388
389 /**
390 * Receive failure function for STA 1
391 * \param psdu the PSDU
392 */
394 /**
395 * Receive failure function for STA 2
396 * \param psdu the PSDU
397 */
399 /**
400 * Receive failure function for STA 3
401 * \param psdu the PSDU
402 */
404
405 /**
406 * Check the results for STA 1
407 * \param expectedRxSuccess the expected number of RX success
408 * \param expectedRxFailure the expected number of RX failures
409 * \param expectedRxBytes the expected number of RX bytes
410 */
411 void CheckResultsSta1(uint32_t expectedRxSuccess,
412 uint32_t expectedRxFailure,
413 uint32_t expectedRxBytes);
414 /**
415 * Check the results for STA 2
416 * \param expectedRxSuccess the expected number of RX success
417 * \param expectedRxFailure the expected number of RX failures
418 * \param expectedRxBytes the expected number of RX bytes
419 */
420 void CheckResultsSta2(uint32_t expectedRxSuccess,
421 uint32_t expectedRxFailure,
422 uint32_t expectedRxBytes);
423 /**
424 * Check the results for STA 3
425 * \param expectedRxSuccess the expected number of RX success
426 * \param expectedRxFailure the expected number of RX failures
427 * \param expectedRxBytes the expected number of RX bytes
428 */
429 void CheckResultsSta3(uint32_t expectedRxSuccess,
430 uint32_t expectedRxFailure,
431 uint32_t expectedRxBytes);
432
433 /**
434 * Reset the results
435 */
436 void ResetResults();
437
438 /**
439 * STA info
440 */
441 struct StaInfo
442 {
443 uint16_t staId; //!< STA ID
444 uint8_t staNss; //!< Number of spatial streams used for the STA
445 };
446
447 /**
448 * Send DL MU-MIMO PPDU function
449 * \param staInfos the STAs infos
450 */
451 void SendMuPpdu(const std::vector<StaInfo>& staInfos);
452
453 /**
454 * Generate interference function
455 * \param interferencePsd the PSD of the interference to be generated
456 * \param duration the duration of the interference
457 */
458 void GenerateInterference(Ptr<SpectrumValue> interferencePsd, Time duration);
459 /**
460 * Stop interference function
461 */
463
464 /**
465 * Run one function
466 */
467 void RunOne();
468
469 /**
470 * Schedule now to check the PHY state
471 * \param phy the PHY
472 * \param expectedState the expected state of the PHY
473 */
475 /**
476 * Check the PHY state now
477 * \param phy the PHY
478 * \param expectedState the expected state of the PHY
479 */
481
482 uint32_t m_countRxSuccessSta1; ///< count RX success for STA 1
483 uint32_t m_countRxSuccessSta2; ///< count RX success for STA 2
484 uint32_t m_countRxSuccessSta3; ///< count RX success for STA 3
485 uint32_t m_countRxFailureSta1; ///< count RX failure for STA 1
486 uint32_t m_countRxFailureSta2; ///< count RX failure for STA 2
487 uint32_t m_countRxFailureSta3; ///< count RX failure for STA 3
488 uint32_t m_countRxBytesSta1; ///< count RX bytes for STA 1
489 uint32_t m_countRxBytesSta2; ///< count RX bytes for STA 2
490 uint32_t m_countRxBytesSta3; ///< count RX bytes for STA 3
491
496
497 uint8_t m_nss; ///< number of spatial streams per STA
498 uint16_t m_frequency; ///< frequency in MHz
499 uint16_t m_channelWidth; ///< channel width in MHz
500 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
501};
502
504 : TestCase("DL MU-MIMO PHY test"),
505 m_countRxSuccessSta1{0},
506 m_countRxSuccessSta2{0},
507 m_countRxSuccessSta3{0},
508 m_countRxFailureSta1{0},
509 m_countRxFailureSta2{0},
510 m_countRxFailureSta3{0},
511 m_countRxBytesSta1{0},
512 m_countRxBytesSta2{0},
513 m_countRxBytesSta3{0},
514 m_nss{1},
515 m_frequency{DEFAULT_FREQUENCY},
516 m_channelWidth{DEFAULT_CHANNEL_WIDTH},
517 m_expectedPpduDuration{NanoSeconds(306400)}
518{
519}
520
521void
523{
533}
534
535void
536TestDlMuMimoPhyTransmission::SendMuPpdu(const std::vector<StaInfo>& staInfos)
537{
538 NS_LOG_FUNCTION(this << staInfos.size());
539 NS_ASSERT(staInfos.size() > 1);
540
542 0,
544 800,
545 1,
546 1,
547 0,
549 false,
550 false);
551
552 WifiConstPsduMap psdus;
553 HeRu::RuSpec ru(HeRu::GetRuType(m_channelWidth), 1, true); // full BW MU-MIMO
554 for (const auto& staInfo : staInfos)
555 {
556 txVector.SetRu(ru, staInfo.staId);
557 txVector.SetMode(HePhy::GetHeMcs7(), staInfo.staId);
558 txVector.SetNss(staInfo.staNss, staInfo.staId);
559
560 Ptr<Packet> pkt = Create<Packet>(1000 + (8 * staInfo.staId));
561 WifiMacHeader hdr;
563 hdr.SetQosTid(0);
564 std::ostringstream addr;
565 addr << "00:00:00:00:00:0" << staInfo.staId;
566 hdr.SetAddr1(Mac48Address(addr.str().c_str()));
567 hdr.SetSequenceNumber(1 + staInfo.staId);
568 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
569 psdus.insert(std::make_pair(staInfo.staId, psdu));
570 }
571
573
574 NS_ASSERT(txVector.IsDlMuMimo());
575 NS_ASSERT(!txVector.IsDlOfdma());
576
577 m_phyAp->Send(psdus, txVector);
578}
579
580void
582 RxSignalInfo rxSignalInfo,
583 WifiTxVector txVector,
584 std::vector<bool> /*statusPerMpdu*/)
585{
586 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
588 m_countRxBytesSta1 += (psdu->GetSize() - 30);
589}
590
591void
593 RxSignalInfo rxSignalInfo,
594 WifiTxVector txVector,
595 std::vector<bool> /*statusPerMpdu*/)
596{
597 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
599 m_countRxBytesSta2 += (psdu->GetSize() - 30);
600}
601
602void
604 RxSignalInfo rxSignalInfo,
605 WifiTxVector txVector,
606 std::vector<bool> /*statusPerMpdu*/)
607{
608 NS_LOG_FUNCTION(this << *psdu << rxSignalInfo << txVector);
610 m_countRxBytesSta3 += (psdu->GetSize() - 30);
611}
612
613void
615{
616 NS_LOG_FUNCTION(this << *psdu);
618}
619
620void
622{
623 NS_LOG_FUNCTION(this << *psdu);
625}
626
627void
629{
630 NS_LOG_FUNCTION(this << *psdu);
632}
633
634void
636 uint32_t expectedRxFailure,
637 uint32_t expectedRxBytes)
638{
640 expectedRxSuccess,
641 "The number of successfully received packets by STA 1 is not correct!");
643 expectedRxFailure,
644 "The number of unsuccessfully received packets by STA 1 is not correct!");
646 expectedRxBytes,
647 "The number of bytes received by STA 1 is not correct!");
648}
649
650void
652 uint32_t expectedRxFailure,
653 uint32_t expectedRxBytes)
654{
656 expectedRxSuccess,
657 "The number of successfully received packets by STA 2 is not correct!");
659 expectedRxFailure,
660 "The number of unsuccessfully received packets by STA 2 is not correct!");
662 expectedRxBytes,
663 "The number of bytes received by STA 2 is not correct!");
664}
665
666void
668 uint32_t expectedRxFailure,
669 uint32_t expectedRxBytes)
670{
672 expectedRxSuccess,
673 "The number of successfully received packets by STA 3 is not correct!");
675 expectedRxFailure,
676 "The number of unsuccessfully received packets by STA 3 is not correct!");
678 expectedRxBytes,
679 "The number of bytes received by STA 3 is not correct!");
680}
681
682void
684 WifiPhyState expectedState)
685{
686 // This is needed to make sure PHY state will be checked as the last event if a state change
687 // occurred at the exact same time as the check
689}
690
691void
693 WifiPhyState expectedState)
694{
695 WifiPhyState currentState;
696 PointerValue ptr;
697 phy->GetAttribute("State", ptr);
698 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
699 currentState = state->GetState();
700 NS_LOG_FUNCTION(this << currentState << expectedState);
701 NS_TEST_ASSERT_MSG_EQ(currentState,
702 expectedState,
703 "PHY State " << currentState << " does not match expected state "
704 << expectedState << " at " << Simulator::Now());
705}
706
707void
709{
710 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
712 CreateObject<ConstantSpeedPropagationDelayModel>();
713 spectrumChannel->SetPropagationDelayModel(delayModel);
714
715 Ptr<Node> apNode = CreateObject<Node>();
716 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
717 m_phyAp = CreateObject<SpectrumWifiPhy>();
718 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
719 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
720 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
721 m_phyAp->SetErrorRateModel(apErrorModel);
722 m_phyAp->SetDevice(apDev);
723 m_phyAp->AddChannel(spectrumChannel);
725 apDev->SetPhy(m_phyAp);
726 apNode->AddDevice(apDev);
727
728 Ptr<Node> sta1Node = CreateObject<Node>();
729 Ptr<WifiNetDevice> sta1Dev = CreateObject<WifiNetDevice>();
730 m_phySta1 = CreateObject<MuMimoSpectrumWifiPhy>(1);
731 Ptr<InterferenceHelper> sta1InterferenceHelper = CreateObject<InterferenceHelper>();
732 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
733 Ptr<ErrorRateModel> sta1ErrorModel = CreateObject<NistErrorRateModel>();
734 m_phySta1->SetErrorRateModel(sta1ErrorModel);
735 m_phySta1->SetDevice(sta1Dev);
736 m_phySta1->AddChannel(spectrumChannel);
742 sta1Dev->SetPhy(m_phySta1);
743 sta1Node->AddDevice(sta1Dev);
744
745 Ptr<Node> sta2Node = CreateObject<Node>();
746 Ptr<WifiNetDevice> sta2Dev = CreateObject<WifiNetDevice>();
747 m_phySta2 = CreateObject<MuMimoSpectrumWifiPhy>(2);
748 Ptr<InterferenceHelper> sta2InterferenceHelper = CreateObject<InterferenceHelper>();
749 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
750 Ptr<ErrorRateModel> sta2ErrorModel = CreateObject<NistErrorRateModel>();
751 m_phySta2->SetErrorRateModel(sta2ErrorModel);
752 m_phySta2->SetDevice(sta2Dev);
753 m_phySta2->AddChannel(spectrumChannel);
759 sta2Dev->SetPhy(m_phySta2);
760 sta2Node->AddDevice(sta2Dev);
761
762 Ptr<Node> sta3Node = CreateObject<Node>();
763 Ptr<WifiNetDevice> sta3Dev = CreateObject<WifiNetDevice>();
764 m_phySta3 = CreateObject<MuMimoSpectrumWifiPhy>(3);
765 Ptr<InterferenceHelper> sta3InterferenceHelper = CreateObject<InterferenceHelper>();
766 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
767 Ptr<ErrorRateModel> sta3ErrorModel = CreateObject<NistErrorRateModel>();
768 m_phySta3->SetErrorRateModel(sta3ErrorModel);
769 m_phySta3->SetDevice(sta3Dev);
770 m_phySta3->AddChannel(spectrumChannel);
776 sta3Dev->SetPhy(m_phySta3);
777 sta3Node->AddDevice(sta3Dev);
778}
779
780void
782{
783 m_phyAp->Dispose();
784 m_phyAp = nullptr;
786 m_phySta1 = nullptr;
788 m_phySta2 = nullptr;
790 m_phySta3 = nullptr;
791}
792
793void
795{
798 int64_t streamNumber = 0;
799 m_phyAp->AssignStreams(streamNumber);
800 m_phySta1->AssignStreams(streamNumber);
801 m_phySta2->AssignStreams(streamNumber);
802
803 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
808
817
820
821 //----------------------------------------------------------------------------------------------------
822 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 2:
823 // STA 1 and STA 2 should receive their PSDUs, whereas STA 3 should not receive any PSDU
824 // but should keep its PHY busy during all PPDU duration.
827 this,
828 std::vector<StaInfo>{{1, m_nss}, {2, m_nss}});
829
830 // Since it takes m_expectedPpduDuration to transmit the PPDU,
831 // all 3 PHYs should be back to IDLE at the same time,
832 // even the PHY that has no PSDU addressed to it.
835 this,
836 m_phySta1,
837 WifiPhyState::RX);
840 this,
841 m_phySta2,
842 WifiPhyState::RX);
845 this,
846 m_phySta3,
847 WifiPhyState::CCA_BUSY);
850 this,
851 m_phySta1,
852 WifiPhyState::IDLE);
855 this,
856 m_phySta2,
857 WifiPhyState::IDLE);
860 this,
861 m_phySta3,
862 WifiPhyState::IDLE);
863
864 // One PSDU of 1008 bytes should have been successfully received by STA 1
867 this,
868 1,
869 0,
870 1008);
871 // One PSDU of 1016 bytes should have been successfully received by STA 2
874 this,
875 1,
876 0,
877 1016);
878 // No PSDU should have been received by STA 3
881 this,
882 0,
883 0,
884 0);
885
887
888 //----------------------------------------------------------------------------------------------------
889 // Send MU PPDU with two PSDUs addressed to STA 1 and STA 3:
890 // STA 1 and STA 3 should receive their PSDUs, whereas STA 2 should not receive any PSDU
891 // but should keep its PHY busy during all PPDU duration.
894 this,
895 std::vector<StaInfo>{{1, m_nss}, {3, m_nss}});
896
897 // Since it takes m_expectedPpduDuration to transmit the PPDU,
898 // all 3 PHYs should be back to IDLE at the same time,
899 // even the PHY that has no PSDU addressed to it.
902 this,
903 m_phySta1,
904 WifiPhyState::RX);
907 this,
908 m_phySta2,
909 WifiPhyState::CCA_BUSY);
912 this,
913 m_phySta3,
914 WifiPhyState::RX);
917 this,
918 m_phySta1,
919 WifiPhyState::IDLE);
922 this,
923 m_phySta2,
924 WifiPhyState::IDLE);
927 this,
928 m_phySta3,
929 WifiPhyState::IDLE);
930
931 // One PSDU of 1008 bytes should have been successfully received by STA 1
934 this,
935 1,
936 0,
937 1008);
938 // No PSDU should have been received by STA 2
941 this,
942 0,
943 0,
944 0);
945 // One PSDU of 1024 bytes should have been successfully received by STA 3
948 this,
949 1,
950 0,
951 1024);
952
954
955 //----------------------------------------------------------------------------------------------------
956 // Send MU PPDU with two PSDUs addressed to STA 2 and STA 3:
957 // STA 2 and STA 3 should receive their PSDUs, whereas STA 1 should not receive any PSDU
958 // but should keep its PHY busy during all PPDU duration.
961 this,
962 std::vector<StaInfo>{{2, m_nss}, {3, m_nss}});
963
964 // Since it takes m_expectedPpduDuration to transmit the PPDU,
965 // all 3 PHYs should be back to IDLE at the same time,
966 // even the PHY that has no PSDU addressed to it.
969 this,
970 m_phySta1,
971 WifiPhyState::CCA_BUSY);
974 this,
975 m_phySta2,
976 WifiPhyState::RX);
979 this,
980 m_phySta3,
981 WifiPhyState::RX);
984 this,
985 m_phySta1,
986 WifiPhyState::IDLE);
989 this,
990 m_phySta2,
991 WifiPhyState::IDLE);
994 this,
995 m_phySta3,
996 WifiPhyState::IDLE);
997
998 // No PSDU should have been received by STA 1
1001 this,
1002 0,
1003 0,
1004 0);
1005 // One PSDU of 1016 bytes should have been successfully received by STA 2
1008 this,
1009 1,
1010 0,
1011 1016);
1012 // One PSDU of 1024 bytes should have been successfully received by STA 3
1015 this,
1016 1,
1017 0,
1018 1024);
1019
1021
1022 //----------------------------------------------------------------------------------------------------
1023 // Send MU PPDU with three PSDUs addressed to STA 1, STA 2 and STA 3:
1024 // All STAs should receive their PSDUs.
1027 this,
1028 std::vector<StaInfo>{{1, m_nss}, {2, m_nss}, {3, m_nss}});
1029
1030 // Since it takes m_expectedPpduDuration to transmit the PPDU,
1031 // all 3 PHYs should be back to IDLE at the same time.
1034 this,
1035 m_phySta1,
1036 WifiPhyState::RX);
1039 this,
1040 m_phySta2,
1041 WifiPhyState::RX);
1044 this,
1045 m_phySta3,
1046 WifiPhyState::RX);
1049 this,
1050 m_phySta1,
1051 WifiPhyState::IDLE);
1054 this,
1055 m_phySta2,
1056 WifiPhyState::IDLE);
1059 this,
1060 m_phySta3,
1061 WifiPhyState::IDLE);
1062
1063 // One PSDU of 1008 bytes should have been successfully received by STA 1
1066 this,
1067 1,
1068 0,
1069 1008);
1070 // One PSDU of 1016 bytes should have been successfully received by STA 2
1073 this,
1074 1,
1075 0,
1076 1016);
1077 // One PSDU of 1024 bytes should have been successfully received by STA 3
1080 this,
1081 1,
1082 0,
1083 1024);
1084
1086
1088}
1089
1090void
1092{
1093 std::vector<uint8_t> nssToTest{1, 2};
1094 for (auto nss : nssToTest)
1095 {
1096 m_nss = nss;
1097 m_frequency = 5180;
1098 m_channelWidth = 20;
1099 m_expectedPpduDuration = (nss > 1) ? NanoSeconds(110400) : NanoSeconds(156800);
1100 RunOne();
1101
1102 m_frequency = 5190;
1103 m_channelWidth = 40;
1104 m_expectedPpduDuration = (nss > 1) ? NanoSeconds(83200) : NanoSeconds(102400);
1105 RunOne();
1106
1107 m_frequency = 5210;
1108 m_channelWidth = 80;
1109 m_expectedPpduDuration = (nss > 1) ? NanoSeconds(69600) : NanoSeconds(75200);
1110 RunOne();
1111
1112 m_frequency = 5250;
1113 m_channelWidth = 160;
1114 m_expectedPpduDuration = (nss > 1) ? NanoSeconds(69600) : NanoSeconds(61600);
1115 RunOne();
1116 }
1117 // FIXME: test also different nss over STAs once RX durations when receiving different PPDUs
1118 // with different nss over STAs are fixed
1119
1121}
1122
1123/**
1124 * \ingroup wifi-test
1125 * \ingroup tests
1126 *
1127 * \brief UL MU-MIMO PHY test
1128 */
1130{
1131 public:
1133
1134 private:
1135 void DoSetup() override;
1136 void DoTeardown() override;
1137 void DoRun() override;
1138
1139 /**
1140 * Get TXVECTOR for HE TB PPDU.
1141 * \param txStaId the ID of the TX STA
1142 * \param nss the number of spatial streams used for the transmission
1143 * \param bssColor the BSS color of the TX STA
1144 * \return the TXVECTOR for HE TB PPDU
1145 */
1146 WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, uint8_t nss, uint8_t bssColor) const;
1147 /**
1148 * Set TRIGVECTOR for HE TB PPDU
1149 *
1150 * \param staIds the IDs of the STAs sollicited for the HE TB transmission
1151 * \param bssColor the BSS color of the TX STA
1152 */
1153 void SetTrigVector(const std::vector<uint16_t>& staIds, uint8_t bssColor);
1154 /**
1155 * Send HE TB PPDU function
1156 * \param txStaId the ID of the TX STA
1157 * \param nss the number of spatial streams used for the transmission
1158 * \param payloadSize the size of the payload in bytes
1159 * \param uid the UID of the trigger frame that is initiating this transmission
1160 * \param bssColor the BSS color of the TX STA
1161 */
1162 void SendHeTbPpdu(uint16_t txStaId,
1163 uint8_t nss,
1164 std::size_t payloadSize,
1165 uint64_t uid,
1166 uint8_t bssColor);
1167
1168 /**
1169 * Send HE SU PPDU function
1170 * \param txStaId the ID of the TX STA
1171 * \param payloadSize the size of the payload in bytes
1172 * \param uid the UID of the trigger frame that is initiating this transmission
1173 * \param bssColor the BSS color of the TX STA
1174 */
1175 void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
1176
1177 /**
1178 * Set the BSS color
1179 * \param phy the PHY
1180 * \param bssColor the BSS color
1181 */
1182 void SetBssColor(Ptr<WifiPhy> phy, uint8_t bssColor);
1183
1184 /**
1185 * Run one function
1186 */
1187 void RunOne();
1188
1189 /**
1190 * Check the received PSDUs from a given STA
1191 * \param staId the ID of the STA to check
1192 * \param expectedSuccess the expected number of success
1193 * \param expectedFailures the expected number of failures
1194 * \param expectedBytes the expected number of bytes
1195 */
1196 void CheckRxFromSta(uint16_t staId,
1197 uint32_t expectedSuccess,
1198 uint32_t expectedFailures,
1199 uint32_t expectedBytes);
1200
1201 /**
1202 * Verify all events are cleared at end of TX or RX
1203 */
1204 void VerifyEventsCleared();
1205
1206 /**
1207 * Check the PHY state
1208 * \param phy the PHY
1209 * \param expectedState the expected state of the PHY
1210 */
1211 void CheckPhyState(Ptr<MuMimoSpectrumWifiPhy> phy, WifiPhyState expectedState);
1212 /// \copydoc CheckPhyState
1214
1215 /**
1216 * Reset function
1217 */
1218 void Reset();
1219
1220 /**
1221 * Receive success function
1222 * \param psdu the PSDU
1223 * \param rxSignalInfo the info on the received signal (\see RxSignalInfo)
1224 * \param txVector the transmit vector
1225 * \param statusPerMpdu reception status per MPDU
1226 */
1228 RxSignalInfo rxSignalInfo,
1229 WifiTxVector txVector,
1230 std::vector<bool> statusPerMpdu);
1231
1232 /**
1233 * Receive failure function
1234 * \param psdu the PSDU
1235 */
1236 void RxFailure(Ptr<const WifiPsdu> psdu);
1237
1238 /**
1239 * Schedule test to perform.
1240 * The interference generation should be scheduled apart.
1241 *
1242 * \param delay the reference delay to schedule the events
1243 * \param txStaIds the IDs of the STAs planned to transmit an HE TB PPDU
1244 * \param expectedStateAtEnd the expected state of the PHY at the end of the reception
1245 * \param expectedCountersPerSta the expected counters per STA
1246 */
1247 void ScheduleTest(
1248 Time delay,
1249 const std::vector<uint16_t>& txStaIds,
1250 WifiPhyState expectedStateAtEnd,
1251 const std::vector<std::tuple<uint32_t, uint32_t, uint32_t>>& expectedCountersPerSta);
1252
1253 /**
1254 * Log scenario description
1255 *
1256 * \param log the scenario description to add to log
1257 */
1258 void LogScenario(const std::string& log) const;
1259
1261 std::vector<Ptr<MuMimoSpectrumWifiPhy>> m_phyStas; ///< PHYs of STAs
1262
1263 std::vector<uint32_t> m_countRxSuccessFromStas; ///< count RX success from STAs
1264 std::vector<uint32_t> m_countRxFailureFromStas; ///< count RX failure from STAs
1265 std::vector<uint32_t> m_countRxBytesFromStas; ///< count RX bytes from STAs
1266
1267 Time m_delayStart; ///< delay between the start of each HE TB PPDUs
1268 uint16_t m_frequency; ///< frequency in MHz
1269 uint16_t m_channelWidth; ///< channel width in MHz
1270 Time m_expectedPpduDuration; ///< expected duration to send MU PPDU
1271};
1272
1274 : TestCase("UL MU-MIMO PHY test"),
1275 m_countRxSuccessFromStas{},
1276 m_countRxFailureFromStas{},
1277 m_countRxBytesFromStas{},
1278 m_delayStart{Seconds(0)},
1279 m_frequency{DEFAULT_FREQUENCY},
1280 m_channelWidth{DEFAULT_CHANNEL_WIDTH},
1281 m_expectedPpduDuration{NanoSeconds(271200)}
1282{
1283}
1284
1285void
1287 std::size_t payloadSize,
1288 uint64_t uid,
1289 uint8_t bssColor)
1290{
1291 NS_LOG_FUNCTION(this << txStaId << payloadSize << uid << +bssColor);
1292 WifiConstPsduMap psdus;
1293
1295 0,
1297 800,
1298 1,
1299 1,
1300 0,
1302 false,
1303 false,
1304 false,
1305 bssColor);
1306
1307 Ptr<Packet> pkt = Create<Packet>(payloadSize);
1308 WifiMacHeader hdr;
1310 hdr.SetQosTid(0);
1311 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
1312 std::ostringstream addr;
1313 addr << "00:00:00:00:00:0" << txStaId;
1314 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
1315 hdr.SetSequenceNumber(1);
1316 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
1317 psdus.insert(std::make_pair(SU_STA_ID, psdu));
1318
1319 Ptr<MuMimoSpectrumWifiPhy> phy = (txStaId == 0) ? m_phyAp : m_phyStas.at(txStaId - 1);
1320 phy->SetPpduUid(uid);
1321 phy->Send(psdus, txVector);
1322}
1323
1326 uint8_t nss,
1327 uint8_t bssColor) const
1328{
1330 0,
1332 1600,
1333 1,
1334 nss,
1335 0,
1337 false,
1338 false,
1339 false,
1340 bssColor);
1341
1342 HeRu::RuSpec ru(HeRu::GetRuType(m_channelWidth), 1, true); // full BW MU-MIMO
1343 txVector.SetRu(ru, txStaId);
1344 txVector.SetMode(HePhy::GetHeMcs7(), txStaId);
1345 txVector.SetNss(nss, txStaId);
1346
1347 return txVector;
1348}
1349
1350void
1351TestUlMuMimoPhyTransmission::SetTrigVector(const std::vector<uint16_t>& staIds, uint8_t bssColor)
1352{
1353 WifiTxVector txVector(HePhy::GetHeMcs7(),
1354 0,
1356 1600,
1357 1,
1358 1,
1359 0,
1361 false,
1362 false,
1363 false,
1364 bssColor);
1365
1366 HeRu::RuSpec ru(HeRu::GetRuType(m_channelWidth), 1, true); // full BW MU-MIMO
1367 for (auto staId : staIds)
1368 {
1369 txVector.SetRu(ru, staId);
1370 txVector.SetMode(HePhy::GetHeMcs7(), staId);
1371 txVector.SetNss(1, staId);
1372 }
1373
1374 uint16_t length;
1375 std::tie(length, m_expectedPpduDuration) =
1377 txVector,
1378 m_phyAp->GetPhyBand());
1379 txVector.SetLength(length);
1380 auto hePhyAp = DynamicCast<HePhy>(m_phyAp->GetPhyEntity(WIFI_MOD_CLASS_HE));
1381 hePhyAp->SetTrigVector(txVector, m_expectedPpduDuration);
1382}
1383
1384void
1386 uint8_t nss,
1387 std::size_t payloadSize,
1388 uint64_t uid,
1389 uint8_t bssColor)
1390{
1391 NS_LOG_FUNCTION(this << txStaId << +nss << payloadSize << uid << +bssColor);
1392 WifiConstPsduMap psdus;
1393
1394 WifiTxVector txVector = GetTxVectorForHeTbPpdu(txStaId, nss, bssColor);
1395 Ptr<Packet> pkt = Create<Packet>(payloadSize);
1396 WifiMacHeader hdr;
1398 hdr.SetQosTid(0);
1399 hdr.SetAddr1(Mac48Address("00:00:00:00:00:00"));
1400 std::ostringstream addr;
1401 addr << "00:00:00:00:00:0" << txStaId;
1402 hdr.SetAddr2(Mac48Address(addr.str().c_str()));
1403 hdr.SetSequenceNumber(1);
1404 Ptr<WifiPsdu> psdu = Create<WifiPsdu>(pkt, hdr);
1405 psdus.insert(std::make_pair(txStaId, psdu));
1406
1407 Ptr<MuMimoSpectrumWifiPhy> phy = m_phyStas.at(txStaId - 1);
1408 Time txDuration =
1409 phy->CalculateTxDuration(psdu->GetSize(), txVector, phy->GetPhyBand(), txStaId);
1410 txVector.SetLength(
1411 HePhy::ConvertHeTbPpduDurationToLSigLength(txDuration, txVector, phy->GetPhyBand()).first);
1412
1413 phy->SetPpduUid(uid);
1414 phy->Send(psdus, txVector);
1415}
1416
1417void
1419 RxSignalInfo rxSignalInfo,
1420 WifiTxVector txVector,
1421 std::vector<bool> /*statusPerMpdu*/)
1422{
1423 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2() << RatioToDb(rxSignalInfo.snr) << txVector);
1424 NS_TEST_ASSERT_MSG_EQ((RatioToDb(rxSignalInfo.snr) > 0), true, "Incorrect SNR value");
1425 for (std::size_t index = 0; index < m_countRxSuccessFromStas.size(); ++index)
1426 {
1427 std::ostringstream addr;
1428 addr << "00:00:00:00:00:0" << index + 1;
1429 if (psdu->GetAddr2() == Mac48Address(addr.str().c_str()))
1430 {
1431 m_countRxSuccessFromStas.at(index)++;
1432 m_countRxBytesFromStas.at(index) += (psdu->GetSize() - 30);
1433 break;
1434 }
1435 }
1436}
1437
1438void
1440{
1441 NS_LOG_FUNCTION(this << *psdu << psdu->GetAddr2());
1442 for (std::size_t index = 0; index < m_countRxFailureFromStas.size(); ++index)
1443 {
1444 std::ostringstream addr;
1445 addr << "00:00:00:00:00:0" << index + 1;
1446 if (psdu->GetAddr2() == Mac48Address(addr.str().c_str()))
1447 {
1448 m_countRxFailureFromStas.at(index)++;
1449 break;
1450 }
1451 }
1452}
1453
1454void
1456 uint32_t expectedSuccess,
1457 uint32_t expectedFailures,
1458 uint32_t expectedBytes)
1459{
1460 NS_LOG_FUNCTION(this << staId << expectedSuccess << expectedFailures << expectedBytes);
1462 expectedSuccess,
1463 "The number of successfully received packets from STA "
1464 << staId << " is not correct!");
1466 expectedFailures,
1467 "The number of unsuccessfully received packets from STA "
1468 << staId << " is not correct!");
1470 expectedBytes,
1471 "The number of bytes received from STA " << staId << " is not correct!");
1472}
1473
1474void
1476{
1478 nullptr,
1479 "m_currentEvent for AP was not cleared");
1480 std::size_t sta = 1;
1481 for (auto& phy : m_phyStas)
1482 {
1483 NS_TEST_ASSERT_MSG_EQ(phy->GetCurrentEvent(),
1484 nullptr,
1485 "m_currentEvent for STA " << sta << " was not cleared");
1486 sta++;
1487 }
1488}
1489
1490void
1492 WifiPhyState expectedState)
1493{
1494 // This is needed to make sure PHY state will be checked as the last event if a state change
1495 // occurred at the exact same time as the check
1497}
1498
1499void
1501 WifiPhyState expectedState)
1502{
1503 WifiPhyState currentState;
1504 PointerValue ptr;
1505 phy->GetAttribute("State", ptr);
1506 Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
1507 currentState = state->GetState();
1508 NS_LOG_FUNCTION(this << currentState << expectedState);
1509 NS_TEST_ASSERT_MSG_EQ(currentState,
1510 expectedState,
1511 "PHY State " << currentState << " does not match expected state "
1512 << expectedState << " at " << Simulator::Now());
1513}
1514
1515void
1517{
1518 for (auto& counter : m_countRxSuccessFromStas)
1519 {
1520 counter = 0;
1521 }
1522 for (auto& counter : m_countRxFailureFromStas)
1523 {
1524 counter = 0;
1525 }
1526 for (auto& counter : m_countRxBytesFromStas)
1527 {
1528 counter = 0;
1529 }
1530 for (auto& phy : m_phyStas)
1531 {
1532 phy->SetPpduUid(0);
1533 phy->SetTriggerFrameUid(0);
1534 }
1535 SetBssColor(m_phyAp, 0);
1536}
1537
1538void
1540{
1541 Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(phy->GetDevice());
1542 Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
1543 heConfiguration->SetAttribute("BssColor", UintegerValue(bssColor));
1544}
1545
1546void
1548{
1549 // WifiHelper::EnableLogComponents();
1550 // LogComponentEnable("WifiPhyMuMimoTest", LOG_LEVEL_ALL);
1551
1552 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1554 CreateObject<ConstantSpeedPropagationDelayModel>();
1555 spectrumChannel->SetPropagationDelayModel(delayModel);
1556
1557 Ptr<Node> apNode = CreateObject<Node>();
1558 Ptr<WifiNetDevice> apDev = CreateObject<WifiNetDevice>();
1559 apDev->SetStandard(WIFI_STANDARD_80211ax);
1560 auto apMac = CreateObjectWithAttributes<ApWifiMac>(
1561 "Txop",
1562 PointerValue(CreateObjectWithAttributes<Txop>("AcIndex", StringValue("AC_BE_NQOS"))));
1563 apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
1564 apDev->SetMac(apMac);
1565 m_phyAp = CreateObject<MuMimoSpectrumWifiPhy>(0);
1566 Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration>();
1567 apDev->SetHeConfiguration(heConfiguration);
1568 Ptr<InterferenceHelper> apInterferenceHelper = CreateObject<InterferenceHelper>();
1569 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1570 Ptr<ErrorRateModel> apErrorModel = CreateObject<NistErrorRateModel>();
1571 m_phyAp->SetErrorRateModel(apErrorModel);
1572 m_phyAp->SetDevice(apDev);
1573 m_phyAp->AddChannel(spectrumChannel);
1577 apDev->SetPhy(m_phyAp);
1578 apNode->AddDevice(apDev);
1579
1580 for (std::size_t i = 1; i <= 4; ++i)
1581 {
1582 Ptr<Node> staNode = CreateObject<Node>();
1583 Ptr<WifiNetDevice> staDev = CreateObject<WifiNetDevice>();
1584 staDev->SetStandard(WIFI_STANDARD_80211ax);
1585 Ptr<MuMimoSpectrumWifiPhy> phy = CreateObject<MuMimoSpectrumWifiPhy>(i);
1586 staDev->SetHeConfiguration(CreateObject<HeConfiguration>());
1587 Ptr<InterferenceHelper> staInterferenceHelper = CreateObject<InterferenceHelper>();
1588 phy->SetInterferenceHelper(staInterferenceHelper);
1589 Ptr<ErrorRateModel> staErrorModel = CreateObject<NistErrorRateModel>();
1590 phy->SetErrorRateModel(staErrorModel);
1591 phy->SetDevice(staDev);
1592 phy->AddChannel(spectrumChannel);
1593 phy->ConfigureStandard(WIFI_STANDARD_80211ax);
1594 phy->SetAttribute("TxGain", DoubleValue(1.0));
1595 phy->SetAttribute("TxPowerStart", DoubleValue(16.0));
1596 phy->SetAttribute("TxPowerEnd", DoubleValue(16.0));
1597 phy->SetAttribute("PowerDensityLimit", DoubleValue(100.0)); // no impact by default
1598 phy->SetAttribute("RxGain", DoubleValue(2.0));
1599 staDev->SetPhy(phy);
1600 staNode->AddDevice(staDev);
1601 m_phyStas.push_back(phy);
1602 m_countRxSuccessFromStas.push_back(0);
1603 m_countRxFailureFromStas.push_back(0);
1604 m_countRxBytesFromStas.push_back(0);
1605 }
1606}
1607
1608void
1610{
1611 for (auto& phy : m_phyStas)
1612 {
1613 phy->Dispose();
1614 phy = nullptr;
1615 }
1616}
1617
1618void
1619TestUlMuMimoPhyTransmission::LogScenario(const std::string& log) const
1620{
1621 NS_LOG_INFO(log);
1622}
1623
1624void
1626 Time delay,
1627 const std::vector<uint16_t>& txStaIds,
1628 WifiPhyState expectedStateAtEnd,
1629 const std::vector<std::tuple<uint32_t, uint32_t, uint32_t>>& expectedCountersPerSta)
1630{
1631 static uint64_t uid = 0;
1632
1633 // AP sends an SU packet preceding HE TB PPDUs
1636 this,
1637 0,
1638 50,
1639 ++uid,
1640 0);
1641
1643
1644 // STAs send MU UL PPDUs addressed to AP
1645 uint16_t payloadSize = 1000;
1646 std::size_t index = 0;
1647 for (auto txStaId : txStaIds)
1648 {
1649 Simulator::Schedule(delay + (index * m_delayStart),
1651 this,
1652 txStaId,
1653 1,
1654 payloadSize,
1655 uid,
1656 0);
1657 payloadSize++;
1658 index++;
1659 }
1660
1661 // Verify it takes m_expectedPpduDuration to transmit the PPDUs
1664 this,
1665 m_phyAp,
1666 WifiPhyState::RX);
1668 (m_delayStart * expectedCountersPerSta.size()),
1670 this,
1671 m_phyAp,
1672 expectedStateAtEnd);
1673
1674 delay += MilliSeconds(100);
1675 // Check reception state from STAs
1676 uint16_t staId = 1;
1677 for (const auto& expectedCounters : expectedCountersPerSta)
1678 {
1679 uint16_t expectedSuccessFromSta = std::get<0>(expectedCounters);
1680 uint16_t expectedFailuresFromSta = std::get<1>(expectedCounters);
1681 uint16_t expectedBytesFromSta = std::get<2>(expectedCounters);
1682 Simulator::Schedule(delay + (m_delayStart * (staId - 1)),
1684 this,
1685 staId,
1686 expectedSuccessFromSta,
1687 expectedFailuresFromSta,
1688 expectedBytesFromSta);
1689 staId++;
1690 }
1691
1692 // Verify events data have been cleared
1694
1695 delay += MilliSeconds(100);
1697}
1698
1699void
1701{
1704 int64_t streamNumber = 0;
1705 m_phyAp->AssignStreams(streamNumber);
1706 for (auto& phy : m_phyStas)
1707 {
1708 phy->AssignStreams(streamNumber);
1709 }
1710
1711 auto channelNum = std::get<0>(*WifiPhyOperatingChannel::FindFirst(0,
1716
1719 for (auto& phy : m_phyStas)
1720 {
1721 phy->SetOperatingChannel(
1723 }
1724
1725 Time delay = Seconds(0.0);
1727 delay += Seconds(1.0);
1728
1729 //---------------------------------------------------------------------------
1730 // Verify that all HE TB PPDUs using full BW MU-MIMO have been corrected received
1731 Simulator::Schedule(delay,
1733 this,
1734 "Reception of HE TB PPDUs using full BW MU-MIMO");
1735 ScheduleTest(delay,
1736 {1, 2, 3},
1737 WifiPhyState::IDLE,
1738 {
1739 std::make_tuple(1, 0, 1000), // One PSDU of 1000 bytes should have been
1740 // successfully received from STA 1
1741 std::make_tuple(1, 0, 1001), // One PSDU of 1001 bytes should have been
1742 // successfully received from STA 2
1743 std::make_tuple(1, 0, 1002) // One PSDU of 1002 bytes should have been
1744 // successfully received from STA 3
1745 });
1746 delay += Seconds(1.0);
1747
1748 //---------------------------------------------------------------------------
1749 // Send an HE SU PPDU during 400 ns window and verify that all HE TB PPDUs using full BW MU-MIMO
1750 // have been impacted
1751 Simulator::Schedule(delay,
1753 this,
1754 "Reception of HE TB PPDUs HE TB PPDUs using full BW MU-MIMO with an HE SU "
1755 "PPDU arriving during the 400 ns window");
1756 // One HE SU arrives at AP during the 400ns window
1757 Simulator::Schedule(delay + NanoSeconds(150),
1759 this,
1760 4,
1761 1002,
1762 2,
1763 0);
1764 ScheduleTest(delay,
1765 {1, 2, 3},
1766 WifiPhyState::IDLE,
1767 {
1768 std::make_tuple(0, 1, 0), // Reception of the PSDU from STA 1 should have
1769 // failed (since interference from STA 4)
1770 std::make_tuple(0, 1, 0), // Reception of the PSDU from STA 2 should have
1771 // failed (since interference from STA 4)
1772 std::make_tuple(0, 1, 0) // Reception of the PSDU from STA 3 should have failed
1773 // (since interference from STA 4)
1774 });
1775 delay += Seconds(1.0);
1776
1777 //---------------------------------------------------------------------------
1778 // Send an HE SU PPDU during HE portion reception and verify that all HE TB PPDUs have been
1779 // impacted
1780 Simulator::Schedule(delay,
1782 this,
1783 "Reception of HE TB PPDUs using full BW MU-MIMO with an HE SU PPDU "
1784 "arriving during the HE portion");
1785 // One HE SU arrives at AP during the HE portion
1788 this,
1789 4,
1790 1002,
1791 2,
1792 0);
1793 ScheduleTest(delay,
1794 {1, 2, 3},
1795 WifiPhyState::CCA_BUSY,
1796 {
1797 std::make_tuple(0, 1, 0), // Reception of the PSDU from STA 1 should have
1798 // failed (since interference from STA 4)
1799 std::make_tuple(0, 1, 0), // Reception of the PSDU from STA 2 should have
1800 // failed (since interference from STA 4)
1801 std::make_tuple(0, 1, 0) // Reception of the PSDU from STA 3 should have failed
1802 // (since interference from STA 4)
1803 });
1804 delay += Seconds(1.0);
1805
1807}
1808
1809void
1811{
1812 std::vector<Time> startDelays{NanoSeconds(0), NanoSeconds(100)};
1813
1814 for (const auto& delayStart : startDelays)
1815 {
1816 m_delayStart = delayStart;
1817
1818 m_frequency = 5180;
1819 m_channelWidth = 20;
1821 NS_LOG_DEBUG("Run UL MU-MIMO PHY transmission test for "
1822 << m_channelWidth << " MHz with delay between each HE TB PPDUs of "
1823 << m_delayStart);
1824 RunOne();
1825
1826 m_frequency = 5190;
1827 m_channelWidth = 40;
1829 NS_LOG_DEBUG("Run UL MU-MIMO PHY transmission test for "
1830 << m_channelWidth << " MHz with delay between each HE TB PPDUs of "
1831 << m_delayStart);
1832 RunOne();
1833
1834 m_frequency = 5210;
1835 m_channelWidth = 80;
1837 NS_LOG_DEBUG("Run UL MU-MIMO PHY transmission test for "
1838 << m_channelWidth << " MHz with delay between each HE TB PPDUs of "
1839 << m_delayStart);
1840 RunOne();
1841
1842 m_frequency = 5250;
1843 m_channelWidth = 160;
1845 NS_LOG_DEBUG("Run UL MU-MIMO PHY transmission test for "
1846 << m_channelWidth << " MHz with delay between each HE TB PPDUs of "
1847 << m_delayStart);
1848 RunOne();
1849 }
1850
1852}
1853
1854/**
1855 * \ingroup wifi-test
1856 * \ingroup tests
1857 *
1858 * \brief wifi PHY MU-MIMO Test Suite
1859 */
1861{
1862 public:
1864};
1865
1867 : TestSuite("wifi-phy-mu-mimo", Type::UNIT)
1868{
1869 AddTestCase(new TestDlMuTxVector, TestCase::Duration::QUICK);
1870 AddTestCase(new TestDlMuMimoPhyTransmission, TestCase::Duration::QUICK);
1871 AddTestCase(new TestUlMuMimoPhyTransmission, TestCase::Duration::QUICK);
1872}
1873
SpectrumWifiPhy used for testing MU-MIMO.
void SetTriggerFrameUid(uint64_t uid)
Since we assume trigger frame was previously received from AP, this is used to set its UID.
MuMimoSpectrumWifiPhy(uint16_t staId)
Constructor.
void DoInitialize() override
Initialize() implementation.
static TypeId GetTypeId()
Get the type ID.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
void DoDispose() override
Destructor implementation.
Ptr< MuMimoTestHePhy > m_ofdmTestHePhy
Pointer to HE PHY instance used for MU-MIMO test.
HE PHY slightly modified so as to return a given STA-ID in case of DL MU for MuMimoSpectrumWifiPhy.
MuMimoTestHePhy(uint16_t staId)
Constructor.
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< MuMimoSpectrumWifiPhy > m_phySta1
PHY of STA 1.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
uint16_t m_frequency
frequency in MHz
void CheckPhyState(Ptr< MuMimoSpectrumWifiPhy > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
void ResetResults()
Reset the results.
uint8_t m_nss
number of spatial streams per STA
uint16_t m_channelWidth
channel width in MHz
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 3.
Ptr< MuMimoSpectrumWifiPhy > m_phySta3
PHY of STA 3.
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 2.
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
void RunOne()
Run one function.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
void SendMuPpdu(const std::vector< StaInfo > &staInfos)
Send DL MU-MIMO PPDU function.
void DoCheckPhyState(Ptr< MuMimoSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state now.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function for STA 1.
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
Ptr< MuMimoSpectrumWifiPhy > m_phySta2
PHY of STA 2.
void DoRun() override
Implementation to actually run this TestCase.
void StopInterference()
Stop interference function.
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
DL MU TX-VECTOR test.
void DoRun() override
Implementation to actually run this TestCase.
static WifiTxVector BuildTxVector(uint16_t bw, const std::list< HeMuUserInfo > &userInfos)
Build a TXVECTOR for DL MU with the given bandwidth and user information.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void DoRun() override
Implementation to actually run this TestCase.
void LogScenario(const std::string &log) const
Log scenario description.
std::vector< uint32_t > m_countRxFailureFromStas
count RX failure from STAs
void SendHeSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
void SendHeTbPpdu(uint16_t txStaId, uint8_t nss, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE TB PPDU function.
std::vector< uint32_t > m_countRxSuccessFromStas
count RX success from STAs
void DoSetup() override
Implementation to do any local setup required for this TestCase.
std::vector< uint32_t > m_countRxBytesFromStas
count RX bytes from STAs
void CheckRxFromSta(uint16_t staId, uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from a given STA.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint16_t m_channelWidth
channel width in MHz
void DoCheckPhyState(Ptr< MuMimoSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
void ScheduleTest(Time delay, const std::vector< uint16_t > &txStaIds, WifiPhyState expectedStateAtEnd, const std::vector< std::tuple< uint32_t, uint32_t, uint32_t > > &expectedCountersPerSta)
Schedule test to perform.
void CheckPhyState(Ptr< MuMimoSpectrumWifiPhy > phy, WifiPhyState expectedState)
Check the PHY state.
Time m_expectedPpduDuration
expected duration to send MU PPDU
Ptr< MuMimoSpectrumWifiPhy > m_phyAp
PHY of AP.
void SetTrigVector(const std::vector< uint16_t > &staIds, uint8_t bssColor)
Set TRIGVECTOR for HE TB PPDU.
std::vector< Ptr< MuMimoSpectrumWifiPhy > > m_phyStas
PHYs of STAs.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > statusPerMpdu)
Receive success function.
uint16_t m_frequency
frequency in MHz
Time m_delayStart
delay between the start of each HE TB PPDUs
WifiTxVector GetTxVectorForHeTbPpdu(uint16_t txStaId, uint8_t nss, uint8_t bssColor) const
Get TXVECTOR for HE TB PPDU.
wifi PHY MU-MIMO Test Suite
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
PHY entity for HE (11ax)
Definition: he-phy.h:68
static WifiMode GetHeMcs7()
Return MCS 7 from HE MCS values.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
Definition: he-phy.cc:575
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:272
RU Specification.
Definition: he-ru.h:66
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_242_TONE
Definition: he-ru.h:45
static RuType GetRuType(uint16_t bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition: he-ru.cc:792
an EUI-48 address
Definition: mac48-address.h:46
void Dispose()
Dispose of this Object.
Definition: object.cc:258
void SetOwner(Ptr< WifiPhy > wifiPhy)
Set the WifiPhy owning this PHY entity.
Definition: phy-entity.cc:92
static uint64_t m_globalPpduUid
Global counter of the PPDU UID.
Definition: phy-entity.h:1005
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 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: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
802.11 PHY layer model
void SetDevice(const Ptr< WifiNetDevice > device) override
Sets the device this PHY is associated with.
void DoInitialize() override
Initialize() implementation.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
void DoDispose() override
Destructor implementation.
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:302
A suite of tests to run.
Definition: test.h:1273
Type
Type of test.
Definition: test.h:1280
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Hold an unsigned integer type.
Definition: uinteger.h:45
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
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.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetNumberOfAntennas(uint8_t antennas)
Definition: wifi-phy.cc:1289
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:662
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:1759
void SetErrorRateModel(const Ptr< ErrorRateModel > model)
Sets the error rate model.
Definition: wifi-phy.cc:671
void SetMaxSupportedTxSpatialStreams(uint8_t streams)
Definition: wifi-phy.cc:1307
void SetReceiveErrorCallback(RxErrorCallback callback)
Definition: wifi-phy.cc:473
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:993
std::map< WifiModulationClass, Ptr< PhyEntity > > m_phyEntities
This map holds the supported PHY entities.
Definition: wifi-phy.h:1358
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:1130
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1053
Ptr< Event > m_currentEvent
Hold the current event.
Definition: wifi-phy.h:1333
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:744
uint64_t m_previouslyRxPpduUid
UID of the previously received PPDU, reset to UINT64_MAX upon transmission.
Definition: wifi-phy.h:1338
std::tuple< uint8_t, uint16_t, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:926
void SetReceiveOkCallback(RxOkCallback callback)
Definition: wifi-phy.cc:467
virtual int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: wifi-phy.cc:2298
static ConstIterator FindFirst(uint8_t number, uint16_t frequency, uint16_t width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first channel matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
bool IsSigBCompression() const
Indicate whether the Common field is present in the HE-SIG-B field.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
bool IsValid(WifiPhyBand band=WIFI_PHY_BAND_UNSPECIFIED) const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
bool IsDlOfdma() const
Return true if this TX vector is used for a downlink multi-user transmission using OFDMA.
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.
bool IsDlMuMimo() const
Return true if this TX vector is used for a downlink multi-user transmission using MU-MIMO.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#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_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:145
#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:252
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1355
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_PPDU_TYPE_DL_MU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double RatioToDb(double ratio)
Convert from ratio to dB.
Definition: wifi-utils.cc:54
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
WifiPhyState
The state of the PHY layer.
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:700
@ WIFI_MAC_QOSDATA
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
uint8_t staNss
Number of spatial streams used for the STA.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
double snr
SNR in linear scale.
Definition: phy-entity.h:70
constexpr uint16_t DEFAULT_CHANNEL_WIDTH
constexpr uint32_t DEFAULT_FREQUENCY