A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tx-duration-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 CTTC
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Nicola Baldo <nbaldo@cttc.es>
7 * Sébastien Deronne <sebastien.deronne@gmail.com>
8 */
9
10#include "ns3/dsss-phy.h"
11#include "ns3/eht-phy.h" //includes OFDM, HT, VHT and HE
12#include "ns3/eht-ppdu.h" //includes OFDM, HT, VHT and HE
13#include "ns3/erp-ofdm-phy.h"
14#include "ns3/he-ru.h"
15#include "ns3/log.h"
16#include "ns3/packet.h"
17#include "ns3/simulator.h"
18#include "ns3/test.h"
19#include "ns3/wifi-psdu.h"
20#include "ns3/yans-wifi-phy.h"
21
22#include <list>
23#include <numeric>
24
25using namespace ns3;
26
27NS_LOG_COMPONENT_DEFINE("TxDurationTest");
28
29/**
30 * \ingroup wifi-test
31 * \ingroup tests
32 *
33 * \brief Tx Duration Test
34 */
36{
37 public:
39 ~TxDurationTest() override;
40 void DoRun() override;
41
42 private:
43 /**
44 * Check if the payload tx duration returned by InterferenceHelper
45 * corresponds to a known value
46 *
47 * @param size size of payload in octets (includes everything after the PHY header)
48 * @param payloadMode the WifiMode used for the transmission
49 * @param channelWidth the channel width used for the transmission
50 * @param guardInterval the guard interval duration used for the transmission
51 * @param preamble the WifiPreamble used for the transmission
52 * @param knownDuration the known duration value of the transmission
53 *
54 * @return true if values correspond, false otherwise
55 */
57 WifiMode payloadMode,
58 MHz_u channelWidth,
59 Time guardInterval,
60 WifiPreamble preamble,
61 Time knownDuration);
62
63 /**
64 * Check if the overall tx duration returned by InterferenceHelper
65 * corresponds to a known value
66 *
67 * @param size size of payload in octets (includes everything after the PHY header)
68 * @param payloadMode the WifiMode used for the transmission
69 * @param channelWidth the channel width used for the transmission
70 * @param guardInterval the guard interval duration used for the transmission
71 * @param preamble the WifiPreamble used for the transmission
72 * @param knownDuration the known duration value of the transmission
73 *
74 * @return true if values correspond, false otherwise
75 */
76 bool CheckTxDuration(uint32_t size,
77 WifiMode payloadMode,
78 MHz_u channelWidth,
79 Time guardInterval,
80 WifiPreamble preamble,
81 Time knownDuration);
82
83 /**
84 * Check if the overall Tx duration returned by WifiPhy for a MU PPDU
85 * corresponds to a known value
86 *
87 * @param sizes the list of PSDU sizes for each station in octets
88 * @param userInfos the list of HE MU specific user transmission parameters
89 * @param channelWidth the channel width used for the transmission
90 * @param guardInterval the guard interval duration used for the transmission
91 * @param preamble the WifiPreamble used for the transmission
92 * @param knownDuration the known duration value of the transmission
93 *
94 * @return true if values correspond, false otherwise
95 */
96 static bool CheckMuTxDuration(std::list<uint32_t> sizes,
97 std::list<HeMuUserInfo> userInfos,
98 MHz_u channelWidth,
99 Time guardInterval,
100 WifiPreamble preamble,
101 Time knownDuration);
102
103 /**
104 * Calculate the overall Tx duration returned by WifiPhy for list of sizes.
105 * A map of WifiPsdu indexed by STA-ID is built using the provided lists
106 * and handed over to the corresponding SU/MU WifiPhy Tx duration computing
107 * method.
108 * Note that provided lists should be of same size.
109 *
110 * @param sizes the list of PSDU sizes for each station in octets
111 * @param staIds the list of STA-IDs of each station
112 * @param txVector the TXVECTOR used for the transmission of the PPDU
113 * @param band the selected wifi PHY band
114 *
115 * @return the overall Tx duration for the list of sizes (SU or MU PPDU)
116 */
117 static Time CalculateTxDurationUsingList(std::list<uint32_t> sizes,
118 std::list<uint16_t> staIds,
119 WifiTxVector txVector,
120 WifiPhyBand band);
121};
122
124 : TestCase("Wifi TX Duration")
125{
126}
127
131
132bool
134 WifiMode payloadMode,
135 MHz_u channelWidth,
136 Time guardInterval,
137 WifiPreamble preamble,
138 Time knownDuration)
139{
140 WifiTxVector txVector;
141 txVector.SetMode(payloadMode);
142 txVector.SetPreambleType(preamble);
143 txVector.SetChannelWidth(channelWidth);
144 txVector.SetGuardInterval(guardInterval);
145 txVector.SetNss(1);
146 txVector.SetStbc(false);
147 txVector.SetNess(0);
148 std::list<WifiPhyBand> testedBands;
150 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
151 {
152 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
153 }
154 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
155 {
156 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
157 }
158 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
159 {
160 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
161 }
162 for (auto& testedBand : testedBands)
163 {
164 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
165 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
166 {
167 knownDuration +=
168 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
169 }
170 Time calculatedDuration = phy->GetPayloadDuration(size, txVector, testedBand);
171 if (calculatedDuration != knownDuration)
172 {
173 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
174 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
175 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
176 << " known=" << knownDuration << " calculated=" << calculatedDuration
177 << std::endl;
178 return false;
179 }
180 }
181 return true;
182}
183
184bool
186 WifiMode payloadMode,
187 MHz_u channelWidth,
188 Time guardInterval,
189 WifiPreamble preamble,
190 Time knownDuration)
191{
192 WifiTxVector txVector;
193 txVector.SetMode(payloadMode);
194 txVector.SetPreambleType(preamble);
195 txVector.SetChannelWidth(channelWidth);
196 txVector.SetGuardInterval(guardInterval);
197 txVector.SetNss(1);
198 txVector.SetStbc(false);
199 txVector.SetNess(0);
200 std::list<WifiPhyBand> testedBands;
202 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
203 {
204 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
205 }
206 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
207 {
208 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
209 }
210 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
211 {
212 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
213 }
214 for (auto& testedBand : testedBands)
215 {
216 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
217 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
218 {
219 knownDuration +=
220 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
221 }
222 Time calculatedDuration = phy->CalculateTxDuration(size, txVector, testedBand);
223 Time calculatedDurationUsingList =
224 CalculateTxDurationUsingList(std::list<uint32_t>{size},
225 std::list<uint16_t>{SU_STA_ID},
226 txVector,
227 testedBand);
228 if (calculatedDuration != knownDuration ||
229 calculatedDuration != calculatedDurationUsingList)
230 {
231 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
232 << " channelWidth=" << +channelWidth << " guardInterval=" << guardInterval
233 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
234 << " preamble=" << preamble << " known=" << knownDuration
235 << " calculated=" << calculatedDuration
236 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
237 return false;
238 }
239 }
240 return true;
241}
242
243bool
244TxDurationTest::CheckMuTxDuration(std::list<uint32_t> sizes,
245 std::list<HeMuUserInfo> userInfos,
246 MHz_u channelWidth,
247 Time guardInterval,
248 WifiPreamble preamble,
249 Time knownDuration)
250{
251 NS_ASSERT(sizes.size() == userInfos.size() && sizes.size() > 1);
253 channelWidth < std::accumulate(
254 std::begin(userInfos),
255 std::end(userInfos),
256 0,
257 [](const MHz_u prevBw, const HeMuUserInfo& info) {
258 return prevBw + HeRu::GetBandwidth(info.ru.GetRuType());
259 }),
260 "Cannot accommodate all the RUs in the provided band"); // MU-MIMO (for which allocations
261 // use the same RU) is not supported
262 WifiTxVector txVector;
263 txVector.SetPreambleType(preamble);
264 txVector.SetChannelWidth(channelWidth);
265 txVector.SetGuardInterval(guardInterval);
266 txVector.SetStbc(false);
267 txVector.SetNess(0);
268 if (IsEht(preamble))
269 {
270 txVector.SetEhtPpduType(0);
271 }
272 std::list<uint16_t> staIds;
273
274 uint16_t staId = 1;
275 for (const auto& userInfo : userInfos)
276 {
277 txVector.SetHeMuUserInfo(staId, userInfo);
278 staIds.push_back(staId++);
279 }
281 txVector.SetRuAllocation({192, 192}, 0);
282
284 std::list<WifiPhyBand> testedBands{
287 WIFI_PHY_BAND_2_4GHZ}; // Durations vary depending on frequency; test also 2.4 GHz (bug
288 // 1971)
289 for (auto& testedBand : testedBands)
290 {
291 if (testedBand == WIFI_PHY_BAND_2_4GHZ)
292 {
293 knownDuration +=
294 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
295 }
296 Time calculatedDuration = NanoSeconds(0);
297 uint32_t longestSize = 0;
298 auto iterStaId = staIds.begin();
299 for (auto& size : sizes)
300 {
301 Time ppduDurationForSta =
302 phy->CalculateTxDuration(size, txVector, testedBand, *iterStaId);
303 if (ppduDurationForSta > calculatedDuration)
304 {
305 calculatedDuration = ppduDurationForSta;
306 staId = *iterStaId;
307 longestSize = size;
308 }
309 ++iterStaId;
310 }
311 Time calculatedDurationUsingList =
312 CalculateTxDurationUsingList(sizes, staIds, txVector, testedBand);
313 if (calculatedDuration != knownDuration ||
314 calculatedDuration != calculatedDurationUsingList)
315 {
316 std::cerr << "size=" << longestSize << " band=" << testedBand << " staId=" << staId
317 << " nss=" << +txVector.GetNss(staId) << " mode=" << txVector.GetMode(staId)
318 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
319 << " datarate="
320 << txVector.GetMode(staId).GetDataRate(channelWidth,
321 guardInterval,
322 txVector.GetNss(staId))
323 << " known=" << knownDuration << " calculated=" << calculatedDuration
324 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
325 return false;
326 }
327 }
328 return true;
329}
330
331Time
333 std::list<uint16_t> staIds,
334 WifiTxVector txVector,
335 WifiPhyBand band)
336{
337 NS_ASSERT(sizes.size() == staIds.size());
338 WifiConstPsduMap psduMap;
339 auto itStaId = staIds.begin();
340 WifiMacHeader hdr;
341 hdr.SetType(WIFI_MAC_CTL_ACK); // so that size may not be empty while being as short as possible
342 for (auto& size : sizes)
343 {
344 // MAC header and FCS are to deduce from size
345 psduMap[*itStaId++] =
346 Create<WifiPsdu>(Create<Packet>(size - hdr.GetSerializedSize() - 4), hdr);
347 }
348 return WifiPhy::CalculateTxDuration(psduMap, txVector, band);
349}
350
351void
353{
354 bool retval = true;
355
356 // IEEE Std 802.11-2007 Table 18-2 "Example of LENGTH calculations for CCK"
357 retval = retval &&
360 22,
361 NanoSeconds(800),
363 MicroSeconds(744)) &&
366 22,
367 NanoSeconds(800),
369 MicroSeconds(745)) &&
372 22,
373 NanoSeconds(800),
375 MicroSeconds(746)) &&
378 22,
379 NanoSeconds(800),
381 MicroSeconds(747));
382
383 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b CCK duration failed");
384
385 // Similar, but we add PHY preamble and header durations
386 // and we test different rates.
387 // The payload durations for modes other than 11mbb have been
388 // calculated by hand according to IEEE Std 802.11-2007 18.2.3.5
389 retval = retval &&
390 CheckTxDuration(1023,
392 22,
393 NanoSeconds(800),
395 MicroSeconds(744 + 96)) &&
396 CheckTxDuration(1024,
398 22,
399 NanoSeconds(800),
401 MicroSeconds(745 + 96)) &&
402 CheckTxDuration(1025,
404 22,
405 NanoSeconds(800),
407 MicroSeconds(746 + 96)) &&
408 CheckTxDuration(1026,
410 22,
411 NanoSeconds(800),
413 MicroSeconds(747 + 96)) &&
414 CheckTxDuration(1023,
416 22,
417 NanoSeconds(800),
419 MicroSeconds(744 + 192)) &&
420 CheckTxDuration(1024,
422 22,
423 NanoSeconds(800),
425 MicroSeconds(745 + 192)) &&
426 CheckTxDuration(1025,
428 22,
429 NanoSeconds(800),
431 MicroSeconds(746 + 192)) &&
432 CheckTxDuration(1026,
434 22,
435 NanoSeconds(800),
437 MicroSeconds(747 + 192)) &&
438 CheckTxDuration(1023,
440 22,
441 NanoSeconds(800),
443 MicroSeconds(1488 + 96)) &&
444 CheckTxDuration(1024,
446 22,
447 NanoSeconds(800),
449 MicroSeconds(1490 + 96)) &&
450 CheckTxDuration(1025,
452 22,
453 NanoSeconds(800),
455 MicroSeconds(1491 + 96)) &&
456 CheckTxDuration(1026,
458 22,
459 NanoSeconds(800),
461 MicroSeconds(1493 + 96)) &&
462 CheckTxDuration(1023,
464 22,
465 NanoSeconds(800),
467 MicroSeconds(1488 + 192)) &&
468 CheckTxDuration(1024,
470 22,
471 NanoSeconds(800),
473 MicroSeconds(1490 + 192)) &&
474 CheckTxDuration(1025,
476 22,
477 NanoSeconds(800),
479 MicroSeconds(1491 + 192)) &&
480 CheckTxDuration(1026,
482 22,
483 NanoSeconds(800),
485 MicroSeconds(1493 + 192)) &&
486 CheckTxDuration(1023,
488 22,
489 NanoSeconds(800),
491 MicroSeconds(4092 + 96)) &&
492 CheckTxDuration(1024,
494 22,
495 NanoSeconds(800),
497 MicroSeconds(4096 + 96)) &&
498 CheckTxDuration(1025,
500 22,
501 NanoSeconds(800),
503 MicroSeconds(4100 + 96)) &&
504 CheckTxDuration(1026,
506 22,
507 NanoSeconds(800),
509 MicroSeconds(4104 + 96)) &&
510 CheckTxDuration(1023,
512 22,
513 NanoSeconds(800),
515 MicroSeconds(4092 + 192)) &&
516 CheckTxDuration(1024,
518 22,
519 NanoSeconds(800),
521 MicroSeconds(4096 + 192)) &&
522 CheckTxDuration(1025,
524 22,
525 NanoSeconds(800),
527 MicroSeconds(4100 + 192)) &&
528 CheckTxDuration(1026,
530 22,
531 NanoSeconds(800),
533 MicroSeconds(4104 + 192)) &&
534 CheckTxDuration(1023,
536 22,
537 NanoSeconds(800),
539 MicroSeconds(8184 + 192)) &&
540 CheckTxDuration(1024,
542 22,
543 NanoSeconds(800),
545 MicroSeconds(8192 + 192)) &&
546 CheckTxDuration(1025,
548 22,
549 NanoSeconds(800),
551 MicroSeconds(8200 + 192)) &&
552 CheckTxDuration(1026,
554 22,
555 NanoSeconds(800),
557 MicroSeconds(8208 + 192)) &&
558 CheckTxDuration(1023,
560 22,
561 NanoSeconds(800),
563 MicroSeconds(8184 + 192)) &&
564 CheckTxDuration(1024,
566 22,
567 NanoSeconds(800),
569 MicroSeconds(8192 + 192)) &&
570 CheckTxDuration(1025,
572 22,
573 NanoSeconds(800),
575 MicroSeconds(8200 + 192)) &&
576 CheckTxDuration(1026,
578 22,
579 NanoSeconds(800),
581 MicroSeconds(8208 + 192));
582
583 // values from
584 // https://web.archive.org/web/20100711002639/http://mailman.isi.edu/pipermail/ns-developers/2009-July/006226.html
585 retval = retval && CheckTxDuration(14,
587 22,
588 NanoSeconds(800),
590 MicroSeconds(304));
591
592 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
593 retval = retval &&
594 CheckTxDuration(1536,
596 22,
597 NanoSeconds(800),
599 MicroSeconds(1310)) &&
602 22,
603 NanoSeconds(800),
605 MicroSeconds(248)) &&
608 22,
609 NanoSeconds(800),
611 MicroSeconds(203));
612
613 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b duration failed");
614
615 // 802.11a durations
616 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
617 retval = retval &&
618 CheckTxDuration(1536,
620 20,
621 NanoSeconds(800),
623 MicroSeconds(248)) &&
626 20,
627 NanoSeconds(800),
629 MicroSeconds(32)) &&
632 20,
633 NanoSeconds(800),
635 MicroSeconds(24));
636
637 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11a duration failed");
638
639 // 802.11g durations are same as 802.11a durations but with 6 us signal extension
640 retval = retval &&
641 CheckTxDuration(1536,
643 20,
644 NanoSeconds(800),
646 MicroSeconds(254)) &&
649 20,
650 NanoSeconds(800),
652 MicroSeconds(38)) &&
655 20,
656 NanoSeconds(800),
658 MicroSeconds(30));
659
660 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11g duration failed");
661
662 // 802.11n durations
663 retval = retval &&
664 CheckTxDuration(1536,
666 20,
667 NanoSeconds(800),
669 MicroSeconds(228)) &&
672 20,
673 NanoSeconds(800),
675 MicroSeconds(48)) &&
678 20,
679 NanoSeconds(800),
681 MicroSeconds(40)) &&
682 CheckTxDuration(1536,
684 20,
685 NanoSeconds(400),
687 NanoSeconds(1742400)) &&
690 20,
691 NanoSeconds(400),
693 MicroSeconds(126)) &&
696 20,
697 NanoSeconds(400),
699 NanoSeconds(57600)) &&
700 CheckTxDuration(1536,
702 20,
703 NanoSeconds(400),
705 NanoSeconds(226800)) &&
708 20,
709 NanoSeconds(400),
711 NanoSeconds(46800)) &&
714 20,
715 NanoSeconds(400),
717 NanoSeconds(39600)) &&
718 CheckTxDuration(1536,
720 40,
721 NanoSeconds(800),
723 MicroSeconds(128)) &&
726 40,
727 NanoSeconds(800),
729 MicroSeconds(44)) &&
732 40,
733 NanoSeconds(800),
735 MicroSeconds(40)) &&
736 CheckTxDuration(1536,
738 40,
739 NanoSeconds(400),
741 NanoSeconds(118800)) &&
744 40,
745 NanoSeconds(400),
747 NanoSeconds(43200)) &&
750 40,
751 NanoSeconds(400),
753 NanoSeconds(39600));
754
755 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11n duration failed");
756
757 // 802.11ac durations
758 retval = retval &&
759 CheckTxDuration(1536,
761 20,
762 NanoSeconds(800),
764 MicroSeconds(196)) &&
767 20,
768 NanoSeconds(800),
770 MicroSeconds(48)) &&
773 20,
774 NanoSeconds(800),
776 MicroSeconds(40)) &&
777 CheckTxDuration(1536,
779 20,
780 NanoSeconds(400),
782 MicroSeconds(180)) &&
785 20,
786 NanoSeconds(400),
788 NanoSeconds(46800)) &&
791 20,
792 NanoSeconds(400),
794 NanoSeconds(39600)) &&
795 CheckTxDuration(1536,
797 40,
798 NanoSeconds(800),
800 MicroSeconds(108)) &&
803 40,
804 NanoSeconds(800),
806 MicroSeconds(40)) &&
809 40,
810 NanoSeconds(800),
812 MicroSeconds(40)) &&
813 CheckTxDuration(1536,
815 40,
816 NanoSeconds(400),
818 NanoSeconds(100800)) &&
821 40,
822 NanoSeconds(400),
824 NanoSeconds(39600)) &&
827 40,
828 NanoSeconds(400),
830 NanoSeconds(39600)) &&
831 CheckTxDuration(1536,
833 80,
834 NanoSeconds(800),
836 MicroSeconds(460)) &&
839 80,
840 NanoSeconds(800),
842 MicroSeconds(60)) &&
845 80,
846 NanoSeconds(800),
848 MicroSeconds(44)) &&
849 CheckTxDuration(1536,
851 80,
852 NanoSeconds(400),
854 NanoSeconds(417600)) &&
857 80,
858 NanoSeconds(400),
860 NanoSeconds(57600)) &&
863 80,
864 NanoSeconds(400),
866 NanoSeconds(43200)) &&
867 CheckTxDuration(1536,
869 80,
870 NanoSeconds(800),
872 MicroSeconds(68)) &&
875 80,
876 NanoSeconds(800),
878 MicroSeconds(40)) &&
881 80,
882 NanoSeconds(800),
884 MicroSeconds(40)) &&
885 CheckTxDuration(1536,
887 80,
888 NanoSeconds(400),
890 NanoSeconds(64800)) &&
893 80,
894 NanoSeconds(400),
896 NanoSeconds(39600)) &&
899 80,
900 NanoSeconds(400),
902 NanoSeconds(39600)) &&
903 CheckTxDuration(1536,
905 160,
906 NanoSeconds(800),
908 MicroSeconds(56)) &&
911 160,
912 NanoSeconds(800),
914 MicroSeconds(40)) &&
917 160,
918 NanoSeconds(800),
920 MicroSeconds(40)) &&
921 CheckTxDuration(1536,
923 160,
924 NanoSeconds(400),
926 MicroSeconds(54)) &&
929 160,
930 NanoSeconds(400),
932 NanoSeconds(39600)) &&
935 160,
936 NanoSeconds(400),
938 NanoSeconds(39600));
939
940 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ac duration failed");
941
942 // 802.11ax SU durations
943 retval = retval &&
944 CheckTxDuration(1536,
946 20,
947 NanoSeconds(800),
949 NanoSeconds(1485600)) &&
952 20,
953 NanoSeconds(800),
955 NanoSeconds(125600)) &&
958 20,
959 NanoSeconds(800),
961 NanoSeconds(71200)) &&
962 CheckTxDuration(1536,
964 40,
965 NanoSeconds(800),
967 NanoSeconds(764800)) &&
970 40,
971 NanoSeconds(800),
973 NanoSeconds(84800)) &&
976 40,
977 NanoSeconds(800),
979 NanoSeconds(57600)) &&
980 CheckTxDuration(1536,
982 80,
983 NanoSeconds(800),
985 NanoSeconds(397600)) &&
988 80,
989 NanoSeconds(800),
991 NanoSeconds(71200)) &&
994 80,
995 NanoSeconds(800),
997 NanoSeconds(57600)) &&
998 CheckTxDuration(1536,
1000 160,
1001 NanoSeconds(800),
1003 NanoSeconds(220800)) &&
1004 CheckTxDuration(76,
1006 160,
1007 NanoSeconds(800),
1009 NanoSeconds(57600)) &&
1010 CheckTxDuration(14,
1012 160,
1013 NanoSeconds(800),
1015 NanoSeconds(57600)) &&
1016 CheckTxDuration(1536,
1018 20,
1019 NanoSeconds(1600),
1021 NanoSeconds(1570400)) &&
1022 CheckTxDuration(76,
1024 20,
1025 NanoSeconds(1600),
1027 NanoSeconds(130400)) &&
1028 CheckTxDuration(14,
1030 20,
1031 NanoSeconds(1600),
1033 NanoSeconds(72800)) &&
1034 CheckTxDuration(1536,
1036 40,
1037 NanoSeconds(1600),
1039 NanoSeconds(807200)) &&
1040 CheckTxDuration(76,
1042 40,
1043 NanoSeconds(1600),
1045 NanoSeconds(87200)) &&
1046 CheckTxDuration(14,
1048 40,
1049 NanoSeconds(1600),
1051 NanoSeconds(58400)) &&
1052 CheckTxDuration(1536,
1054 80,
1055 NanoSeconds(1600),
1057 NanoSeconds(418400)) &&
1058 CheckTxDuration(76,
1060 80,
1061 NanoSeconds(1600),
1063 NanoSeconds(72800)) &&
1064 CheckTxDuration(14,
1066 80,
1067 NanoSeconds(1600),
1069 NanoSeconds(58400)) &&
1070 CheckTxDuration(1536,
1072 160,
1073 NanoSeconds(1600),
1075 NanoSeconds(231200)) &&
1076 CheckTxDuration(76,
1078 160,
1079 NanoSeconds(1600),
1081 NanoSeconds(58400)) &&
1082 CheckTxDuration(14,
1084 160,
1085 NanoSeconds(1600),
1087 NanoSeconds(58400)) &&
1088 CheckTxDuration(1536,
1090 20,
1091 NanoSeconds(3200),
1093 MicroSeconds(1740)) &&
1094 CheckTxDuration(76,
1096 20,
1097 NanoSeconds(3200),
1099 MicroSeconds(140)) &&
1100 CheckTxDuration(14,
1102 20,
1103 NanoSeconds(3200),
1105 MicroSeconds(76)) &&
1106 CheckTxDuration(1536,
1108 40,
1109 NanoSeconds(3200),
1111 MicroSeconds(892)) &&
1112 CheckTxDuration(76,
1114 40,
1115 NanoSeconds(3200),
1117 MicroSeconds(92)) &&
1118 CheckTxDuration(14,
1120 40,
1121 NanoSeconds(3200),
1123 MicroSeconds(60)) &&
1124 CheckTxDuration(1536,
1126 80,
1127 NanoSeconds(3200),
1129 MicroSeconds(460)) &&
1130 CheckTxDuration(76,
1132 80,
1133 NanoSeconds(3200),
1135 MicroSeconds(76)) &&
1136 CheckTxDuration(14,
1138 80,
1139 NanoSeconds(3200),
1141 MicroSeconds(60)) &&
1142 CheckTxDuration(1536,
1144 160,
1145 NanoSeconds(3200),
1147 MicroSeconds(252)) &&
1148 CheckTxDuration(76,
1150 160,
1151 NanoSeconds(3200),
1153 MicroSeconds(60)) &&
1154 CheckTxDuration(14,
1156 160,
1157 NanoSeconds(3200),
1159 MicroSeconds(60)) &&
1160 CheckTxDuration(1536,
1162 20,
1163 NanoSeconds(800),
1165 NanoSeconds(139200)) &&
1166 CheckTxDuration(76,
1168 20,
1169 NanoSeconds(800),
1171 NanoSeconds(57600)) &&
1172 CheckTxDuration(14,
1174 20,
1175 NanoSeconds(800),
1177 NanoSeconds(57600)) &&
1178 CheckTxDuration(1536,
1180 40,
1181 NanoSeconds(800),
1183 NanoSeconds(98400)) &&
1184 CheckTxDuration(76,
1186 40,
1187 NanoSeconds(800),
1189 NanoSeconds(57600)) &&
1190 CheckTxDuration(14,
1192 40,
1193 NanoSeconds(800),
1195 NanoSeconds(57600)) &&
1196 CheckTxDuration(1536,
1198 80,
1199 NanoSeconds(800),
1201 NanoSeconds(71200)) &&
1202 CheckTxDuration(76,
1204 80,
1205 NanoSeconds(800),
1207 NanoSeconds(57600)) &&
1208 CheckTxDuration(14,
1210 80,
1211 NanoSeconds(800),
1213 NanoSeconds(57600)) &&
1214 CheckTxDuration(1536,
1216 160,
1217 NanoSeconds(800),
1219 NanoSeconds(57600)) &&
1220 CheckTxDuration(76,
1222 160,
1223 NanoSeconds(800),
1225 NanoSeconds(57600)) &&
1226 CheckTxDuration(14,
1228 160,
1229 NanoSeconds(800),
1231 NanoSeconds(57600)) &&
1232 CheckTxDuration(1536,
1234 20,
1235 NanoSeconds(1600),
1237 NanoSeconds(144800)) &&
1238 CheckTxDuration(76,
1240 20,
1241 NanoSeconds(1600),
1243 NanoSeconds(58400)) &&
1244 CheckTxDuration(14,
1246 20,
1247 NanoSeconds(1600),
1249 NanoSeconds(58400)) &&
1250 CheckTxDuration(1536,
1252 40,
1253 NanoSeconds(1600),
1255 NanoSeconds(101600)) &&
1256 CheckTxDuration(76,
1258 40,
1259 NanoSeconds(1600),
1261 NanoSeconds(58400)) &&
1262 CheckTxDuration(14,
1264 40,
1265 NanoSeconds(1600),
1267 NanoSeconds(58400)) &&
1268 CheckTxDuration(1536,
1270 80,
1271 NanoSeconds(1600),
1273 NanoSeconds(72800)) &&
1274 CheckTxDuration(76,
1276 80,
1277 NanoSeconds(1600),
1279 NanoSeconds(58400)) &&
1280 CheckTxDuration(14,
1282 80,
1283 NanoSeconds(1600),
1285 NanoSeconds(58400)) &&
1286 CheckTxDuration(1536,
1288 160,
1289 NanoSeconds(1600),
1291 NanoSeconds(58400)) &&
1292 CheckTxDuration(76,
1294 160,
1295 NanoSeconds(1600),
1297 NanoSeconds(58400)) &&
1298 CheckTxDuration(14,
1300 160,
1301 NanoSeconds(1600),
1303 NanoSeconds(58400)) &&
1304 CheckTxDuration(1536,
1306 20,
1307 NanoSeconds(3200),
1309 MicroSeconds(156)) &&
1310 CheckTxDuration(76,
1312 20,
1313 NanoSeconds(3200),
1315 MicroSeconds(60)) &&
1316 CheckTxDuration(14,
1318 20,
1319 NanoSeconds(3200),
1321 MicroSeconds(60)) &&
1322 CheckTxDuration(1536,
1324 40,
1325 NanoSeconds(3200),
1327 MicroSeconds(108)) &&
1328 CheckTxDuration(76,
1330 40,
1331 NanoSeconds(3200),
1333 MicroSeconds(60)) &&
1334 CheckTxDuration(14,
1336 40,
1337 NanoSeconds(3200),
1339 MicroSeconds(60)) &&
1340 CheckTxDuration(1536,
1342 80,
1343 NanoSeconds(3200),
1345 MicroSeconds(76)) &&
1346 CheckTxDuration(76,
1348 80,
1349 NanoSeconds(3200),
1351 MicroSeconds(60)) &&
1352 CheckTxDuration(14,
1354 80,
1355 NanoSeconds(3200),
1357 MicroSeconds(60)) &&
1358 CheckTxDuration(1536,
1360 160,
1361 NanoSeconds(3200),
1363 MicroSeconds(60)) &&
1364 CheckTxDuration(76,
1366 160,
1367 NanoSeconds(3200),
1369 MicroSeconds(60)) &&
1370 CheckTxDuration(14,
1372 160,
1373 NanoSeconds(3200),
1375 MicroSeconds(60));
1376
1377 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax SU duration failed");
1378
1379 // 802.11ax MU durations
1380 retval = retval &&
1382 std::list<uint32_t>{1536, 1536},
1383 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1384 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1385 40,
1386 NanoSeconds(800),
1389 1493600)) // equivalent to HE_SU for 20 MHz with 2 extra HE-SIG-B (i.e. 8 us)
1390 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1391 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1392 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1393 40,
1394 NanoSeconds(800),
1396 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1397 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1398 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1399 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1400 40,
1401 NanoSeconds(800),
1403 NanoSeconds(1493600));
1404
1405 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax MU duration failed");
1406
1407 // 802.11be MU durations
1408 retval = retval &&
1409 CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1410 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1411 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1412 40,
1413 NanoSeconds(800),
1415 NanoSeconds(1493600)) // equivalent to 802.11ax MU
1416 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1417 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1418 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1419 40,
1420 NanoSeconds(800),
1422 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1423 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1424 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1425 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1426 40,
1427 NanoSeconds(800),
1429 NanoSeconds(1493600));
1430
1431 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11be MU duration failed");
1432
1434}
1435
1436/**
1437 * \ingroup wifi-test
1438 * \ingroup tests
1439 *
1440 * \brief HE-SIG-B duration test
1441 */
1443{
1444 public:
1445 /**
1446 * OFDMA or MU-MIMO
1447 */
1449 {
1451 MU_MIMO
1453
1454 /**
1455 * Constructor
1456 *
1457 * \param userInfos the HE MU specific per-user information to use for the test
1458 * \param sigBMode the mode to transmit HE-SIG-B for the test
1459 * \param channelWidth the channel width to select for the test
1460 * \param expectedMuType the expected MU type (OFDMA or MU-MIMO)
1461 * \param expectedRuAllocation the expected RU_ALLOCATION
1462 * \param expectedNumUsersPerCc the expected number of users per content channel
1463 * \param expectedSigBDuration the expected duration of the HE-SIG-B header
1464 */
1465 HeSigBDurationTest(const std::list<HeMuUserInfo>& userInfos,
1466 const WifiMode& sigBMode,
1467 MHz_u channelWidth,
1468 MuType expectedMuType,
1469 const RuAllocation& expectedRuAllocation,
1470 const std::pair<std::size_t, std::size_t>& expectedNumUsersPerCc,
1471 Time expectedSigBDuration);
1472
1473 private:
1474 void DoRun() override;
1475
1476 /**
1477 * Build a TXVECTOR for HE MU.
1478 *
1479 * \return the configured HE MU TXVECTOR
1480 */
1482
1483 std::list<HeMuUserInfo> m_userInfos; ///< HE MU specific per-user information
1484 WifiMode m_sigBMode; ///< Mode used to transmit HE-SIG-B
1485 MHz_u m_channelWidth; ///< Channel width
1486 MuType m_expectedMuType; ///< Expected MU type (OFDMA or MU-MIMO)
1487 RuAllocation m_expectedRuAllocation; ///< Expected RU_ALLOCATION
1488 std::pair<std::size_t, std::size_t>
1489 m_expectedNumUsersPerCc; ///< Expected number of users per content channel
1490 Time m_expectedSigBDuration; ///< Expected duration of the HE-SIG-B header
1491};
1492
1494 const std::list<HeMuUserInfo>& userInfos,
1495 const WifiMode& sigBMode,
1496 MHz_u channelWidth,
1497 MuType expectedMuType,
1498 const RuAllocation& expectedRuAllocation,
1499 const std::pair<std::size_t, std::size_t>& expectedNumUsersPerCc,
1500 Time expectedSigBDuration)
1501 : TestCase{"Check HE-SIG-B duration computation"},
1502 m_userInfos{userInfos},
1503 m_sigBMode{sigBMode},
1504 m_channelWidth{channelWidth},
1505 m_expectedMuType{expectedMuType},
1506 m_expectedRuAllocation{expectedRuAllocation},
1507 m_expectedNumUsersPerCc{expectedNumUsersPerCc},
1508 m_expectedSigBDuration{expectedSigBDuration}
1509{
1510}
1511
1514{
1515 WifiTxVector txVector;
1518 txVector.SetGuardInterval(NanoSeconds(3200));
1519 txVector.SetStbc(false);
1520 txVector.SetNess(0);
1521 std::list<uint16_t> staIds;
1522 uint16_t staId = 1;
1523 for (const auto& userInfo : m_userInfos)
1524 {
1525 txVector.SetHeMuUserInfo(staId, userInfo);
1526 staIds.push_back(staId++);
1527 }
1528 txVector.SetSigBMode(m_sigBMode);
1529 NS_ASSERT(m_expectedMuType == OFDMA ? txVector.IsDlOfdma() : txVector.IsDlMuMimo());
1530 return txVector;
1531}
1532
1533void
1535{
1537 const auto& txVector = BuildTxVector();
1538
1539 // Verify mode for HE-SIG-B field
1540 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1541 m_sigBMode,
1542 "Incorrect mode used to send HE-SIG-B");
1543
1544 // Verify RU_ALLOCATION in TXVECTOR
1545 NS_TEST_EXPECT_MSG_EQ((txVector.GetRuAllocation(0) == m_expectedRuAllocation),
1546 true,
1547 "Incorrect RU_ALLOCATION");
1548
1549 // Verify number of users for content channels 1 and 2
1550 const auto& numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(
1551 txVector.GetChannelWidth(),
1552 txVector.GetRuAllocation(0),
1553 txVector.IsSigBCompression(),
1554 txVector.IsSigBCompression() ? txVector.GetHeMuUserInfoMap().size() : 0);
1555 const auto contentChannels = HePpdu::GetHeSigBContentChannels(txVector, 0);
1556 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1558 "Incorrect number of users in HE-SIG-B content channel 1");
1559 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1561 "Incorrect number of users in HE-SIG-B content channel 2");
1562 NS_TEST_EXPECT_MSG_EQ(contentChannels.at(0).size(),
1564 "Incorrect number of users in HE-SIG-B content channel 1");
1565 NS_TEST_EXPECT_MSG_EQ((contentChannels.size() > 1 ? contentChannels.at(1).size() : 0),
1567 "Incorrect number of users in HE-SIG-B content channel 2");
1568
1569 // Verify total HE-SIG-B duration
1570 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1572 "Incorrect duration for HE-SIG-B");
1573}
1574
1575/**
1576 * \ingroup wifi-test
1577 * \ingroup tests
1578 *
1579 * \brief PHY header sections consistency test
1580 */
1582{
1583 public:
1585 ~PhyHeaderSectionsTest() override;
1586 void DoRun() override;
1587
1588 private:
1589 /**
1590 * Check if map of PHY header sections returned by a given PHY entity
1591 * corresponds to a known value
1592 *
1593 * @param obtained the map of PHY header sections to check
1594 * @param expected the expected map of PHY header sections
1595 */
1598};
1599
1601 : TestCase("PHY header sections consistency")
1602{
1603}
1604
1608
1609void
1612{
1613 NS_ASSERT_MSG(obtained.size() == expected.size(),
1614 "The expected map size (" << expected.size() << ") was not obtained ("
1615 << obtained.size() << ")");
1616
1617 auto itObtained = obtained.begin();
1618 auto itExpected = expected.begin();
1619 for (; itObtained != obtained.end() || itExpected != expected.end();)
1620 {
1621 WifiPpduField field = itObtained->first;
1622 auto window = itObtained->second.first;
1623 auto mode = itObtained->second.second;
1624
1625 WifiPpduField fieldRef = itExpected->first;
1626 auto windowRef = itExpected->second.first;
1627 auto modeRef = itExpected->second.second;
1628
1630 fieldRef,
1631 "The expected PPDU field (" << fieldRef << ") was not obtained ("
1632 << field << ")");
1633 NS_TEST_EXPECT_MSG_EQ(window.first,
1634 windowRef.first,
1635 "The expected start time (" << windowRef.first
1636 << ") was not obtained (" << window.first
1637 << ")");
1638 NS_TEST_EXPECT_MSG_EQ(window.second,
1639 windowRef.second,
1640 "The expected stop time (" << windowRef.second
1641 << ") was not obtained (" << window.second
1642 << ")");
1644 modeRef,
1645 "The expected mode (" << modeRef << ") was not obtained (" << mode
1646 << ")");
1647 ++itObtained;
1648 ++itExpected;
1649 }
1650}
1651
1652void
1654{
1655 Time ppduStart = Seconds(1.0);
1656 Ptr<PhyEntity> phyEntity;
1658 WifiTxVector txVector;
1659 WifiMode nonHtMode;
1660
1661 // ==================================================================================
1662 // 11b (HR/DSSS)
1663 phyEntity = Create<DsssPhy>();
1665 txVector.SetChannelWidth(22);
1666
1667 // -> long PPDU format
1669 nonHtMode = DsssPhy::GetDsssRate1Mbps();
1670 sections = {
1671 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(144)}, nonHtMode}},
1673 {{ppduStart + MicroSeconds(144), ppduStart + MicroSeconds(192)}, nonHtMode}},
1674 };
1675 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1676
1677 // -> long PPDU format if data rate is 1 Mbps (even if preamble is tagged short)
1679 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1680
1681 // -> short PPDU format
1683 nonHtMode = DsssPhy::GetDsssRate2Mbps();
1685 sections = {
1686 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(72)}, nonHtMode}},
1688 {{ppduStart + MicroSeconds(72), ppduStart + MicroSeconds(96)}, nonHtMode}},
1689 };
1690 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1691
1692 // ==================================================================================
1693 // 11a (OFDM)
1695
1696 // -> one iteration per variant: default, 10 MHz, and 5 MHz
1697 std::map<OfdmPhyVariant, std::size_t> variants{
1698 // number to use to deduce rate and BW info for each variant
1699 {OFDM_PHY_DEFAULT, 1},
1700 {OFDM_PHY_10_MHZ, 2},
1701 {OFDM_PHY_5_MHZ, 4},
1702 };
1703 for (auto variant : variants)
1704 {
1705 phyEntity = Create<OfdmPhy>(variant.first);
1706 std::size_t ratio = variant.second;
1707 MHz_u bw = 20 / ratio;
1708 txVector.SetChannelWidth(bw);
1709 txVector.SetMode(OfdmPhy::GetOfdmRate(12000000 / ratio, bw));
1710 nonHtMode = OfdmPhy::GetOfdmRate(6000000 / ratio, bw);
1711 sections = {
1713 {{ppduStart, ppduStart + MicroSeconds(16 * ratio)}, nonHtMode}},
1715 {{ppduStart + MicroSeconds(16 * ratio), ppduStart + MicroSeconds(20 * ratio)},
1716 nonHtMode}},
1717 };
1718 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1719 }
1720
1721 // ==================================================================================
1722 // 11g (ERP-OFDM)
1723 phyEntity = Create<ErpOfdmPhy>();
1724 txVector.SetChannelWidth(20);
1725 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(54000000));
1726 nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps();
1727 sections = {
1728 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1730 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1731 };
1732 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1733
1734 // ==================================================================================
1735 // 11n (HT)
1736 phyEntity = Create<HtPhy>(4);
1737 txVector.SetChannelWidth(20);
1738 txVector.SetMode(HtPhy::GetHtMcs6());
1739 nonHtMode = OfdmPhy::GetOfdmRate6Mbps();
1740 WifiMode htSigMode = nonHtMode;
1741
1742 // -> HT-mixed format for 2 SS and no ESS
1744 txVector.SetNss(2);
1745 txVector.SetNess(0);
1746 sections = {
1747 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1749 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1751 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, htSigMode}},
1753 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(40)}, // 1 HT-STF + 2 HT-LTFs
1754 htSigMode}},
1755 };
1756 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1757 txVector.SetChannelWidth(20); // shouldn't have any impact
1758 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1759
1760 // -> HT-mixed format for 3 SS and 1 ESS
1761 txVector.SetNss(3);
1762 txVector.SetNess(1);
1763 sections[WIFI_PPDU_FIELD_TRAINING] = {
1764 {ppduStart + MicroSeconds(28),
1765 ppduStart + MicroSeconds(52)}, // 1 HT-STF + 5 HT-LTFs (4 data + 1 extension)
1766 htSigMode};
1767 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1768
1769 // ==================================================================================
1770 // 11ac (VHT)
1771 phyEntity = Create<VhtPhy>();
1772 txVector.SetChannelWidth(20);
1773 txVector.SetNess(0);
1774 txVector.SetMode(VhtPhy::GetVhtMcs7());
1775 WifiMode sigAMode = nonHtMode;
1776 WifiMode sigBMode = VhtPhy::GetVhtMcs0();
1777
1778 // -> VHT SU format for 5 SS
1780 txVector.SetNss(5);
1781 sections = {
1782 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1784 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1786 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, sigAMode}},
1788 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(56)}, // 1 VHT-STF + 6 VHT-LTFs
1789 sigAMode}},
1790 };
1791 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1792
1793 // -> VHT SU format for 7 SS
1794 txVector.SetNss(7);
1795 sections[WIFI_PPDU_FIELD_TRAINING] = {
1796 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(64)}, // 1 VHT-STF + 8 VHT-LTFs
1797 sigAMode};
1798 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1799
1800 // -> VHT MU format for 3 SS
1802 txVector.SetNss(3);
1803 sections[WIFI_PPDU_FIELD_TRAINING] = {
1804 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(48)}, // 1 VHT-STF + 4 VHT-LTFs
1805 sigAMode};
1806 sections[WIFI_PPDU_FIELD_SIG_B] = {{ppduStart + MicroSeconds(48), ppduStart + MicroSeconds(52)},
1807 sigBMode};
1808 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1809 txVector.SetChannelWidth(80); // shouldn't have any impact
1810 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1811
1812 // ==================================================================================
1813 // 11ax (HE)
1814 phyEntity = Create<HePhy>();
1815 txVector.SetChannelWidth(20);
1816 txVector.SetNss(2); // HE-LTF duration assumed to be always 8 us for the time being (see note in
1817 // HePhy::GetTrainingDuration)
1818 txVector.SetMode(HePhy::GetHeMcs9());
1819 std::map<uint16_t, HeMuUserInfo> userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1820 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1821 sigAMode = HePhy::GetVhtMcs0();
1822 sigBMode = HePhy::GetVhtMcs4(); // because of first user info map
1823
1824 // -> HE SU format
1826 sections = {
1827 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1829 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(24)}, // L-SIG + RL-SIG
1830 nonHtMode}},
1832 {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)}, sigAMode}},
1834 {{ppduStart + MicroSeconds(32),
1835 ppduStart + MicroSeconds(52)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1836 sigAMode}},
1837 };
1838 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1839
1840 // -> HE ER SU format
1842 sections[WIFI_PPDU_FIELD_SIG_A] = {
1843 {ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(40)}, // 16 us HE-SIG-A
1844 sigAMode};
1845 sections[WIFI_PPDU_FIELD_TRAINING] = {
1846 {ppduStart + MicroSeconds(40),
1847 ppduStart + MicroSeconds(60)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1848 sigAMode};
1849 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1850
1851 // -> HE TB format
1853 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1854 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1855 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1856 sigAMode};
1857 sections[WIFI_PPDU_FIELD_TRAINING] = {
1858 {ppduStart + MicroSeconds(32),
1859 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 8 us) + 2 HE-LTFs (@ 8 us)
1860 sigAMode};
1861 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1862
1863 // -> HE MU format
1865 txVector.SetSigBMode(sigBMode);
1866 txVector.SetRuAllocation({96}, 0);
1867 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1868 sigAMode};
1869 sections[WIFI_PPDU_FIELD_SIG_B] = {
1870 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1871 sigBMode};
1872 sections[WIFI_PPDU_FIELD_TRAINING] = {
1873 {ppduStart + MicroSeconds(36),
1874 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1875 sigBMode};
1876 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1877 txVector.SetChannelWidth(160); // shouldn't have any impact
1878 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113}, 0);
1879
1880 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1881
1882 // ==================================================================================
1883 // 11be (EHT)
1884 sections.erase(WIFI_PPDU_FIELD_SIG_A); // FIXME: do we keep using separate type for 11be?
1885 sections.erase(WIFI_PPDU_FIELD_SIG_B); // FIXME: do we keep using separate type for 11be?
1886 phyEntity = Create<EhtPhy>();
1887 txVector.SetChannelWidth(20);
1888 txVector.SetNss(2); // EHT-LTF duration assumed to be always 8 us for the time being (see note
1889 // in HePhy::GetTrainingDuration)
1890 txVector.SetMode(EhtPhy::GetEhtMcs9());
1891 userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1892 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1893 WifiMode uSigMode = EhtPhy::GetVhtMcs0();
1894 WifiMode ehtSigMode = EhtPhy::GetVhtMcs4(); // because of first user info map
1895
1896 // -> EHT TB format
1898 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1899 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1900 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1901 uSigMode};
1902 sections[WIFI_PPDU_FIELD_TRAINING] = {
1903 {ppduStart + MicroSeconds(32),
1904 ppduStart + MicroSeconds(56)}, // 1 EHT-STF (@ 8 us) + 2 EHT-LTFs (@ 8 us)
1905 uSigMode};
1906 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1907
1908 // -> EHT MU format
1910 txVector.SetEhtPpduType(0); // EHT MU transmission
1911 txVector.SetRuAllocation({96}, 0);
1912 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1913 uSigMode};
1914 sections[WIFI_PPDU_FIELD_EHT_SIG] = {
1915 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1916 ehtSigMode};
1917 sections[WIFI_PPDU_FIELD_TRAINING] = {
1918 {ppduStart + MicroSeconds(36),
1919 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1920 ehtSigMode};
1921 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1922 txVector.SetChannelWidth(160); // shouldn't have any impact
1923 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113}, 0);
1924
1925 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1926}
1927
1928/**
1929 * \ingroup wifi-test
1930 * \ingroup tests
1931 *
1932 * \brief Tx Duration Test Suite
1933 */
1935{
1936 public:
1938};
1939
1941 : TestSuite("wifi-devices-tx-duration", Type::UNIT)
1942{
1943 AddTestCase(new TxDurationTest, TestCase::Duration::QUICK);
1944
1945 AddTestCase(new PhyHeaderSectionsTest, TestCase::Duration::QUICK);
1946
1947 // 20 MHz band, HeSigBDurationTest::OFDMA, even number of users per HE-SIG-B content channel
1949 {{{HeRu::RU_106_TONE, 1, true}, 11, 1}, {{HeRu::RU_106_TONE, 2, true}, 10, 4}},
1951 20,
1953 {96},
1954 std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
1955 MicroSeconds(4)), // one OFDM symbol;
1956 TestCase::Duration::QUICK);
1957
1958 // 40 MHz band, HeSigBDurationTest::OFDMA, even number of users per HE-SIG-B content channel
1960 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1961 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1962 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1963 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1964 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1965 {{HeRu::RU_52_TONE, 8, true}, 6, 2}},
1967 40,
1969 {96, 112},
1970 std::make_pair(2, 4), // two users in HE-SIG-B content channel 1 and
1971 // four users in HE-SIG-B content channel 2
1972 MicroSeconds(4)), // one OFDM symbol;
1973 TestCase::Duration::QUICK);
1974
1975 // 40 MHz band, HeSigBDurationTest::OFDMA, odd number of users per HE-SIG-B content channel
1977 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1978 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1979 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1980 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1981 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1982 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1983 {{HeRu::RU_26_TONE, 14, true}, 3, 1}},
1985 40,
1987 {96, 15},
1988 std::make_pair(2, 5), // two users in HE-SIG-B content channel 1 and
1989 // five users in HE-SIG-B content channel 2
1990 MicroSeconds(8)), // two OFDM symbols
1991 TestCase::Duration::QUICK);
1992
1993 // 80 MHz band, OFDMA
1995 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1996 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1997 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1998 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1999 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
2000 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
2001 {{HeRu::RU_26_TONE, 14, true}, 3, 1},
2002 {{HeRu::RU_242_TONE, 3, true}, 1, 1},
2003 {{HeRu::RU_242_TONE, 4, true}, 4, 1}},
2005 80,
2007 {96, 15, 192, 192},
2008 std::make_pair(3, 6), // three users in HE-SIG-B content channel 1
2009 // and six users in HE-SIG-B content channel 2
2010 MicroSeconds(16)), // four OFDM symbols
2011 TestCase::Duration::QUICK);
2012
2013 // 160 MHz band, OFDMA
2015 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
2016 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
2017 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
2018 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
2019 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
2020 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
2021 {{HeRu::RU_26_TONE, 14, true}, 3, 1},
2022 {{HeRu::RU_242_TONE, 3, true}, 1, 1},
2023 {{HeRu::RU_242_TONE, 4, true}, 4, 1},
2024 {{HeRu::RU_996_TONE, 1, false}, 1, 1}},
2026 160,
2028 {96, 15, 192, 192, 208, 208, 208, 208},
2029 std::make_pair(4, 7), // four users in HE-SIG-B content channel 1 and
2030 // seven users in HE-SIG-B content channel 2
2031 MicroSeconds(20)), // five OFDM symbols
2032 TestCase::Duration::QUICK);
2033
2034 // 20 MHz band, HeSigBDurationTest::OFDMA, one unallocated RU at the middle
2036 new HeSigBDurationTest({{{HeRu::RU_26_TONE, 1, true}, 11, 1},
2037 {{HeRu::RU_26_TONE, 2, true}, 11, 1},
2038 {{HeRu::RU_26_TONE, 3, true}, 11, 1},
2039 {{HeRu::RU_26_TONE, 4, true}, 11, 1},
2040 {{HeRu::RU_26_TONE, 6, true}, 11, 1},
2041 {{HeRu::RU_26_TONE, 7, true}, 11, 1},
2042 {{HeRu::RU_26_TONE, 8, true}, 11, 1},
2043 {{HeRu::RU_26_TONE, 9, true}, 11, 1}},
2045 20,
2047 {0},
2048 std::make_pair(9, 0), // 9 users in HE-SIG-B content channel 1
2049 MicroSeconds(8)), // two OFDM symbols
2050 TestCase::Duration::QUICK);
2051
2052 // 40 MHz band, HeSigBDurationTest::OFDMA, unallocated RUs at the begin and at the end of the
2053 // first 20 MHz subband and in the middle of the second 20 MHz subband
2055 new HeSigBDurationTest({{{HeRu::RU_52_TONE, 2, true}, 10, 1},
2056 {{HeRu::RU_52_TONE, 3, true}, 10, 2},
2057 {{HeRu::RU_52_TONE, 5, true}, 11, 1},
2058 {{HeRu::RU_52_TONE, 8, true}, 11, 2}},
2060 40,
2062 {112, 112},
2063 std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
2064 MicroSeconds(4)), // two OFDM symbols
2065 TestCase::Duration::QUICK);
2066
2067 // 40 MHz band, HeSigBDurationTest::OFDMA, one unallocated RUs in the first 20 MHz subband and
2068 // two unallocated RUs in second 20 MHz subband
2070 new HeSigBDurationTest({{{HeRu::RU_52_TONE, 1, true}, 10, 1},
2071 {{HeRu::RU_52_TONE, 2, true}, 10, 2},
2072 {{HeRu::RU_52_TONE, 3, true}, 11, 1},
2073 {{HeRu::RU_52_TONE, 5, true}, 11, 2},
2074 {{HeRu::RU_52_TONE, 6, true}, 11, 3}},
2076 40,
2078 {112, 112},
2079 std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
2080 MicroSeconds(4)), // two OFDM symbols
2081 TestCase::Duration::QUICK);
2082
2083 // 20 MHz band, MU-MIMO, 2 users
2085 {{{HeRu::RU_242_TONE, 1, true}, 11, 1}, {{HeRu::RU_242_TONE, 1, true}, 10, 4}},
2087 20,
2089 {192},
2090 std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
2091 MicroSeconds(4)), // one OFDM symbol
2092 TestCase::Duration::QUICK);
2093
2094 // 20 MHz band, MU-MIMO, 3 users
2096 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 3},
2097 {{HeRu::RU_242_TONE, 1, true}, 5, 2},
2098 {{HeRu::RU_242_TONE, 1, true}, 6, 1}},
2100 20,
2102 {192},
2103 std::make_pair(3, 0), // all users in HE-SIG-B content channel 1
2104 MicroSeconds(4)), // one OFDM symbol
2105 TestCase::Duration::QUICK);
2106
2107 // 20 MHz band, MU-MIMO, 4 users
2109 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
2110 {{HeRu::RU_242_TONE, 1, true}, 5, 2},
2111 {{HeRu::RU_242_TONE, 1, true}, 6, 3},
2112 {{HeRu::RU_242_TONE, 1, true}, 7, 2}},
2114 20,
2116 {192},
2117 std::make_pair(4, 0), // all users in HE-SIG-B content channel 1
2118 MicroSeconds(4)), // one OFDM symbol
2119 TestCase::Duration::QUICK);
2120
2121 // 20 MHz band, MU-MIMO, 6 users
2123 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
2124 {{HeRu::RU_242_TONE, 1, true}, 5, 1},
2125 {{HeRu::RU_242_TONE, 1, true}, 6, 2},
2126 {{HeRu::RU_242_TONE, 1, true}, 7, 2},
2127 {{HeRu::RU_242_TONE, 1, true}, 8, 1},
2128 {{HeRu::RU_242_TONE, 1, true}, 9, 1}},
2130 20,
2132 {192},
2133 std::make_pair(6, 0), // all users in HE-SIG-B content channel 1
2134 MicroSeconds(4)), // one OFDM symbol
2135 TestCase::Duration::QUICK);
2136
2137 // 20 MHz band, MU-MIMO, 8 users
2139 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
2140 {{HeRu::RU_242_TONE, 1, true}, 5, 1},
2141 {{HeRu::RU_242_TONE, 1, true}, 6, 1},
2142 {{HeRu::RU_242_TONE, 1, true}, 7, 1},
2143 {{HeRu::RU_242_TONE, 1, true}, 8, 1},
2144 {{HeRu::RU_242_TONE, 1, true}, 9, 1},
2145 {{HeRu::RU_242_TONE, 1, true}, 10, 1},
2146 {{HeRu::RU_242_TONE, 1, true}, 11, 1}},
2148 20,
2150 {192},
2151 std::make_pair(8, 0), // all users in HE-SIG-B content channel 1
2152 MicroSeconds(8)), // two OFDM symbols
2153 TestCase::Duration::QUICK);
2154
2155 // 40 MHz band, MU-MIMO, 2 users
2157 {{{HeRu::RU_484_TONE, 1, true}, 11, 1}, {{HeRu::RU_484_TONE, 1, true}, 10, 4}},
2159 40,
2161 {200, 200},
2162 std::make_pair(1, 1), // users equally split between the two content channels
2163 MicroSeconds(4)), // one OFDM symbol
2164 TestCase::Duration::QUICK);
2165
2166 // 40 MHz band, MU-MIMO, 3 users
2169 {{{HeRu::RU_484_TONE, 1, true}, 4, 3},
2170 {{HeRu::RU_484_TONE, 1, true}, 5, 2},
2171 {{HeRu::RU_484_TONE, 1, true}, 6, 1}},
2173 40,
2175 {200, 200},
2176 std::make_pair(2, 1), // 2 users in content channel 1 and 1 user in content channel 2
2177 MicroSeconds(4)), // one OFDM symbol
2178 TestCase::Duration::QUICK);
2179
2180 // 40 MHz band, MU-MIMO, 4 users
2182 {{{HeRu::RU_484_TONE, 1, true}, 4, 1},
2183 {{HeRu::RU_484_TONE, 1, true}, 5, 2},
2184 {{HeRu::RU_484_TONE, 1, true}, 6, 3},
2185 {{HeRu::RU_484_TONE, 1, true}, 7, 2}},
2187 40,
2189 {200, 200},
2190 std::make_pair(2, 2), // users equally split between the two content channels
2191 MicroSeconds(4)), // one OFDM symbol
2192 TestCase::Duration::QUICK);
2193
2194 // 40 MHz band, MU-MIMO, 6 users
2196 {{{HeRu::RU_484_TONE, 1, true}, 4, 1},
2197 {{HeRu::RU_484_TONE, 1, true}, 5, 1},
2198 {{HeRu::RU_484_TONE, 1, true}, 6, 2},
2199 {{HeRu::RU_484_TONE, 1, true}, 7, 2},
2200 {{HeRu::RU_484_TONE, 1, true}, 8, 1},
2201 {{HeRu::RU_484_TONE, 1, true}, 9, 1}},
2203 40,
2205 {200, 200},
2206 std::make_pair(3, 3), // users equally split between the two content channels
2207 MicroSeconds(4)), // one OFDM symbol
2208 TestCase::Duration::QUICK);
2209
2210 // 40 MHz band, MU-MIMO, 8 users
2212 {{{HeRu::RU_484_TONE, 1, true}, 4, 1},
2213 {{HeRu::RU_484_TONE, 1, true}, 5, 1},
2214 {{HeRu::RU_484_TONE, 1, true}, 6, 1},
2215 {{HeRu::RU_484_TONE, 1, true}, 7, 1},
2216 {{HeRu::RU_484_TONE, 1, true}, 8, 1},
2217 {{HeRu::RU_484_TONE, 1, true}, 9, 1},
2218 {{HeRu::RU_484_TONE, 1, true}, 10, 1},
2219 {{HeRu::RU_484_TONE, 1, true}, 11, 1}},
2221 40,
2223 {200, 200},
2224 std::make_pair(4, 4), // users equally split between the two content channels
2225 MicroSeconds(4)), // one OFDM symbol
2226 TestCase::Duration::QUICK);
2227
2228 // 80 MHz band, MU-MIMO, 2 users
2230 {{{HeRu::RU_996_TONE, 1, true}, 11, 1}, {{HeRu::RU_996_TONE, 1, true}, 10, 4}},
2232 80,
2234 {208, 208, 208, 208},
2235 std::make_pair(1, 1), // users equally split between the two content channels
2236 MicroSeconds(4)), // one OFDM symbol
2237 TestCase::Duration::QUICK);
2238
2239 // 80 MHz band, MU-MIMO, 3 users
2242 {{{HeRu::RU_996_TONE, 1, true}, 4, 3},
2243 {{HeRu::RU_996_TONE, 1, true}, 5, 2},
2244 {{HeRu::RU_996_TONE, 1, true}, 6, 1}},
2246 80,
2248 {208, 208, 208, 208},
2249 std::make_pair(2, 1), // 2 users in content channel 1 and 1 user in content channel 2
2250 MicroSeconds(4)), // one OFDM symbol
2251 TestCase::Duration::QUICK);
2252
2253 // 80 MHz band, MU-MIMO, 4 users
2255 {{{HeRu::RU_996_TONE, 1, true}, 4, 1},
2256 {{HeRu::RU_996_TONE, 1, true}, 5, 2},
2257 {{HeRu::RU_996_TONE, 1, true}, 6, 3},
2258 {{HeRu::RU_996_TONE, 1, true}, 7, 2}},
2260 80,
2262 {208, 208, 208, 208},
2263 std::make_pair(2, 2), // users equally split between the two content channels
2264 MicroSeconds(4)), // one OFDM symbol
2265 TestCase::Duration::QUICK);
2266
2267 // 80 MHz band, MU-MIMO, 6 users
2269 {{{HeRu::RU_996_TONE, 1, true}, 4, 1},
2270 {{HeRu::RU_996_TONE, 1, true}, 5, 1},
2271 {{HeRu::RU_996_TONE, 1, true}, 6, 2},
2272 {{HeRu::RU_996_TONE, 1, true}, 7, 2},
2273 {{HeRu::RU_996_TONE, 1, true}, 8, 1},
2274 {{HeRu::RU_996_TONE, 1, true}, 9, 1}},
2276 80,
2278 {208, 208, 208, 208},
2279 std::make_pair(3, 3), // users equally split between the two content channels
2280 MicroSeconds(4)), // one OFDM symbol
2281 TestCase::Duration::QUICK);
2282
2283 // 80 MHz band, MU-MIMO, 8 users
2285 {{{HeRu::RU_996_TONE, 1, true}, 4, 1},
2286 {{HeRu::RU_996_TONE, 1, true}, 5, 1},
2287 {{HeRu::RU_996_TONE, 1, true}, 6, 1},
2288 {{HeRu::RU_996_TONE, 1, true}, 7, 1},
2289 {{HeRu::RU_996_TONE, 1, true}, 8, 1},
2290 {{HeRu::RU_996_TONE, 1, true}, 9, 1},
2291 {{HeRu::RU_996_TONE, 1, true}, 10, 1},
2292 {{HeRu::RU_996_TONE, 1, true}, 11, 1}},
2294 80,
2296 {208, 208, 208, 208},
2297 std::make_pair(4, 4), // users equally split between the two content channels
2298 MicroSeconds(4)), // one OFDM symbol
2299 TestCase::Duration::QUICK);
2300
2301 // 160 MHz band, MU-MIMO, 2 users
2304 {{{HeRu::RU_2x996_TONE, 1, true}, 11, 1}, {{HeRu::RU_2x996_TONE, 1, true}, 10, 4}},
2306 160,
2308 {208, 208, 208, 208, 208, 208, 208, 208},
2309 std::make_pair(1, 1), // users equally split between the two content channels
2310 MicroSeconds(4)), // one OFDM symbol
2311 TestCase::Duration::QUICK);
2312
2313 // 160 MHz band, MU-MIMO, 3 users
2316 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 3},
2317 {{HeRu::RU_2x996_TONE, 1, true}, 5, 2},
2318 {{HeRu::RU_2x996_TONE, 1, true}, 6, 1}},
2320 160,
2322 {208, 208, 208, 208, 208, 208, 208, 208},
2323 std::make_pair(2, 1), // 2 users in content channel 1 and 1 user in content channel 2
2324 MicroSeconds(4)), // one OFDM symbol
2325 TestCase::Duration::QUICK);
2326
2327 // 160 MHz band, MU-MIMO, 4 users
2329 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
2330 {{HeRu::RU_2x996_TONE, 1, true}, 5, 2},
2331 {{HeRu::RU_2x996_TONE, 1, true}, 6, 3},
2332 {{HeRu::RU_2x996_TONE, 1, true}, 7, 2}},
2334 160,
2336 {208, 208, 208, 208, 208, 208, 208, 208},
2337 std::make_pair(2, 2), // users equally split between the two content channels
2338 MicroSeconds(4)), // one OFDM symbol
2339 TestCase::Duration::QUICK);
2340
2341 // 160 MHz band, MU-MIMO, 6 users
2343 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
2344 {{HeRu::RU_2x996_TONE, 1, true}, 5, 1},
2345 {{HeRu::RU_2x996_TONE, 1, true}, 6, 2},
2346 {{HeRu::RU_2x996_TONE, 1, true}, 7, 2},
2347 {{HeRu::RU_2x996_TONE, 1, true}, 8, 1},
2348 {{HeRu::RU_2x996_TONE, 1, true}, 9, 1}},
2350 160,
2352 {208, 208, 208, 208, 208, 208, 208, 208},
2353 std::make_pair(3, 3), // users equally split between the two content channels
2354 MicroSeconds(4)), // one OFDM symbol
2355 TestCase::Duration::QUICK);
2356
2357 // 160 MHz band, MU-MIMO, 8 users
2359 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
2360 {{HeRu::RU_2x996_TONE, 1, true}, 5, 1},
2361 {{HeRu::RU_2x996_TONE, 1, true}, 6, 1},
2362 {{HeRu::RU_2x996_TONE, 1, true}, 7, 1},
2363 {{HeRu::RU_2x996_TONE, 1, true}, 8, 1},
2364 {{HeRu::RU_2x996_TONE, 1, true}, 9, 1},
2365 {{HeRu::RU_2x996_TONE, 1, true}, 10, 1},
2366 {{HeRu::RU_2x996_TONE, 1, true}, 11, 1}},
2368 160,
2370 {208, 208, 208, 208, 208, 208, 208, 208},
2371 std::make_pair(4, 4), // users equally split between the two content channels
2372 MicroSeconds(4)), // one OFDM symbol
2373 TestCase::Duration::QUICK);
2374}
2375
HE-SIG-B duration test.
std::list< HeMuUserInfo > m_userInfos
HE MU specific per-user information.
MuType
OFDMA or MU-MIMO.
MuType m_expectedMuType
Expected MU type (OFDMA or MU-MIMO)
RuAllocation m_expectedRuAllocation
Expected RU_ALLOCATION.
Time m_expectedSigBDuration
Expected duration of the HE-SIG-B header.
WifiMode m_sigBMode
Mode used to transmit HE-SIG-B.
HeSigBDurationTest(const std::list< HeMuUserInfo > &userInfos, const WifiMode &sigBMode, MHz_u channelWidth, MuType expectedMuType, const RuAllocation &expectedRuAllocation, const std::pair< std::size_t, std::size_t > &expectedNumUsersPerCc, Time expectedSigBDuration)
Constructor.
MHz_u m_channelWidth
Channel width.
WifiTxVector BuildTxVector() const
Build a TXVECTOR for HE MU.
void DoRun() override
Implementation to actually run this TestCase.
std::pair< std::size_t, std::size_t > m_expectedNumUsersPerCc
Expected number of users per content channel.
PHY header sections consistency test.
void DoRun() override
Implementation to actually run this TestCase.
void CheckPhyHeaderSections(PhyEntity::PhyHeaderSections obtained, PhyEntity::PhyHeaderSections expected)
Check if map of PHY header sections returned by a given PHY entity corresponds to a known value.
Tx Duration Test.
~TxDurationTest() override
static Time CalculateTxDurationUsingList(std::list< uint32_t > sizes, std::list< uint16_t > staIds, WifiTxVector txVector, WifiPhyBand band)
Calculate the overall Tx duration returned by WifiPhy for list of sizes.
bool CheckTxDuration(uint32_t size, WifiMode payloadMode, MHz_u channelWidth, Time guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the overall tx duration returned by InterferenceHelper corresponds to a known value.
static bool CheckMuTxDuration(std::list< uint32_t > sizes, std::list< HeMuUserInfo > userInfos, MHz_u channelWidth, Time guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the overall Tx duration returned by WifiPhy for a MU PPDU corresponds to a known value.
void DoRun() override
Implementation to actually run this TestCase.
bool CheckPayloadDuration(uint32_t size, WifiMode payloadMode, MHz_u channelWidth, Time guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the payload tx duration returned by InterferenceHelper corresponds to a known value.
Tx Duration Test Suite.
static WifiMode GetDsssRate5_5Mbps()
Return a WifiMode for HR/DSSS at 5.5 Mbps.
static WifiMode GetDsssRate1Mbps()
Return a WifiMode for DSSS at 1 Mbps.
static WifiMode GetDsssRate11Mbps()
Return a WifiMode for HR/DSSS at 11 Mbps.
static WifiMode GetDsssRate2Mbps()
Return a WifiMode for DSSS at 2 Mbps.
static WifiMode GetEhtMcs9()
Return MCS 9 from EHT MCS values.
static WifiMode GetErpOfdmRate(uint64_t rate)
Return a WifiMode for ERP-OFDM corresponding to the provided rate.
static WifiMode GetErpOfdmRate6Mbps()
Return a WifiMode for ERP-OFDM at 6 Mbps.
static WifiMode GetErpOfdmRate54Mbps()
Return a WifiMode for ERP-OFDM at 54 Mbps.
static WifiMode GetHeMcs9()
Return MCS 9 from HE MCS values.
static WifiMode GetHeMcs11()
Return MCS 11 from HE MCS values.
static WifiMode GetHeMcs0()
Return MCS 0 from HE MCS values.
static HeSigBContentChannels GetHeSigBContentChannels(const WifiTxVector &txVector, uint8_t p20Index)
Get the HE SIG-B content channels for a given PPDU IEEE 802.11ax-2021 27.3.11.8.2 HE-SIG-B content ch...
Definition he-ppdu.cc:544
static std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel(MHz_u channelWidth, const RuAllocation &ruAllocation, bool sigBCompression, uint8_t numMuMimoUsers)
Get the number of STAs per HE-SIG-B content channel.
Definition he-ppdu.cc:475
RuType GetRuType() const
Get the RU type.
Definition he-ru.cc:447
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition he-ru.cc:756
@ RU_26_TONE
Definition he-ru.h:33
@ RU_484_TONE
Definition he-ru.h:37
@ RU_996_TONE
Definition he-ru.h:38
@ RU_106_TONE
Definition he-ru.h:35
@ RU_52_TONE
Definition he-ru.h:34
@ RU_242_TONE
Definition he-ru.h:36
@ RU_2x996_TONE
Definition he-ru.h:39
static WifiMode GetHtMcs0()
Return MCS 0 from HT MCS values.
static WifiMode GetHtMcs6()
Return MCS 6 from HT MCS values.
static WifiMode GetHtMcs7()
Return MCS 7 from HT MCS values.
static WifiMode GetOfdmRate6Mbps()
Return a WifiMode for OFDM at 6 Mbps.
static WifiMode GetOfdmRate(uint64_t rate, MHz_u bw=20)
Return a WifiMode for OFDM corresponding to the provided rate and the channel bandwidth (20,...
Definition ofdm-phy.cc:404
static WifiMode GetOfdmRate54Mbps()
Return a WifiMode for OFDM at 54 Mbps.
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition phy-entity.h:294
Smart pointer class similar to boost::intrusive_ptr.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
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
static WifiMode GetVhtMcs0()
Return MCS 0 from VHT MCS values.
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
static WifiMode GetVhtMcs3()
Return MCS 3 from VHT MCS values.
static WifiMode GetVhtMcs1()
Return MCS 1 from VHT MCS values.
static WifiMode GetVhtMcs4()
Return MCS 4 from VHT MCS values.
static WifiMode GetVhtMcs9()
Return MCS 9 from VHT MCS values.
static WifiMode GetVhtMcs8()
Return MCS 8 from VHT MCS values.
static WifiMode GetVhtMcs7()
Return MCS 7 from VHT MCS values.
Implements the IEEE 802.11 MAC header.
uint32_t GetSerializedSize() const override
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
represent a single transmission mode
Definition wifi-mode.h:40
WifiModulationClass GetModulationClass() const
Definition wifi-mode.cc:174
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:111
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1572
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition wifi-phy.cc:745
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 SetStbc(bool stbc)
Sets if STBC is being used.
void SetNess(uint8_t ness)
Sets the Ness number.
void SetEhtPpduType(uint8_t type)
Set the EHT_PPDU_TYPE parameter.
void SetGuardInterval(Time guardInterval)
Sets the guard interval duration (in nanoseconds)
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetChannelWidth(MHz_u channelWidth)
Sets the selected channelWidth.
bool IsDlOfdma() const
Return true if this TX vector is used for a downlink multi-user transmission using OFDMA.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
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:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
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_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:1332
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
WifiPpduField
The type of PPDU field (grouped for convenience)
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_EHT_TB
@ WIFI_PREAMBLE_HE_ER_SU
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_HE_SU
@ WIFI_PREAMBLE_VHT_MU
@ WIFI_PREAMBLE_VHT_SU
@ WIFI_PREAMBLE_SHORT
@ WIFI_PREAMBLE_HT_MF
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ OFDM_PHY_10_MHZ
Definition ofdm-phy.h:35
@ OFDM_PHY_DEFAULT
Definition ofdm-phy.h:34
@ OFDM_PHY_5_MHZ
Definition ofdm-phy.h:36
@ WIFI_PPDU_FIELD_SIG_B
SIG-B field.
@ WIFI_PPDU_FIELD_TRAINING
STF + LTF fields (excluding those in preamble for HT-GF)
@ WIFI_PPDU_FIELD_NON_HT_HEADER
PHY header field for DSSS or ERP, short PHY header field for HR/DSSS or ERP, field not present for HT...
@ WIFI_PPDU_FIELD_EHT_SIG
EHT-SIG field.
@ WIFI_PPDU_FIELD_HT_SIG
HT-SIG field.
@ WIFI_PPDU_FIELD_PREAMBLE
SYNC + SFD fields for DSSS or ERP, shortSYNC + shortSFD fields for HR/DSSS or ERP,...
@ WIFI_PPDU_FIELD_U_SIG
U-SIG field.
@ WIFI_PPDU_FIELD_SIG_A
SIG-A field.
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.
bool IsEht(WifiPreamble preamble)
Return true if a preamble corresponds to an EHT transmission.
@ WIFI_MAC_CTL_ACK
std::vector< uint8_t > RuAllocation
8 bit 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
HE MU specific user transmission parameters.
HeRu::RuSpec ru
RU specification.
static TxDurationTestSuite g_txDurationTestSuite
the test suite