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 * 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 * Authors: Nicola Baldo <nbaldo@cttc.es>
18 * Sébastien Deronne <sebastien.deronne@gmail.com>
19 */
20
21#include "ns3/dsss-phy.h"
22#include "ns3/eht-phy.h" //includes OFDM, HT, VHT and HE
23#include "ns3/eht-ppdu.h" //includes OFDM, HT, VHT and HE
24#include "ns3/erp-ofdm-phy.h"
25#include "ns3/he-ru.h"
26#include "ns3/log.h"
27#include "ns3/packet.h"
28#include "ns3/simulator.h"
29#include "ns3/test.h"
30#include "ns3/wifi-psdu.h"
31#include "ns3/yans-wifi-phy.h"
32
33#include <list>
34#include <numeric>
35
36using namespace ns3;
37
38NS_LOG_COMPONENT_DEFINE("TxDurationTest");
39
40/**
41 * \ingroup wifi-test
42 * \ingroup tests
43 *
44 * \brief Tx Duration Test
45 */
47{
48 public:
50 ~TxDurationTest() override;
51 void DoRun() override;
52
53 private:
54 /**
55 * Check if the payload tx duration returned by InterferenceHelper
56 * corresponds to a known value
57 *
58 * @param size size of payload in octets (includes everything after the PHY header)
59 * @param payloadMode the WifiMode used for the transmission
60 * @param channelWidth the channel width used for the transmission (in MHz)
61 * @param guardInterval the guard interval duration used for the transmission (in nanoseconds)
62 * @param preamble the WifiPreamble used for the transmission
63 * @param knownDuration the known duration value of the transmission
64 *
65 * @return true if values correspond, false otherwise
66 */
68 WifiMode payloadMode,
69 uint16_t channelWidth,
70 uint16_t guardInterval,
71 WifiPreamble preamble,
72 Time knownDuration);
73
74 /**
75 * Check if the overall tx duration returned by InterferenceHelper
76 * corresponds to a known value
77 *
78 * @param size size of payload in octets (includes everything after the PHY header)
79 * @param payloadMode the WifiMode used for the transmission
80 * @param channelWidth the channel width used for the transmission (in MHz)
81 * @param guardInterval the guard interval duration used for the transmission (in nanoseconds)
82 * @param preamble the WifiPreamble used for the transmission
83 * @param knownDuration the known duration value of the transmission
84 *
85 * @return true if values correspond, false otherwise
86 */
87 bool CheckTxDuration(uint32_t size,
88 WifiMode payloadMode,
89 uint16_t channelWidth,
90 uint16_t guardInterval,
91 WifiPreamble preamble,
92 Time knownDuration);
93
94 /**
95 * Check if the overall Tx duration returned by WifiPhy for a MU PPDU
96 * corresponds to a known value
97 *
98 * @param sizes the list of PSDU sizes for each station in octets
99 * @param userInfos the list of HE MU specific user transmission parameters
100 * @param channelWidth the channel width used for the transmission (in MHz)
101 * @param guardInterval the guard interval duration used for the transmission (in nanoseconds)
102 * @param preamble the WifiPreamble used for the transmission
103 * @param knownDuration the known duration value of the transmission
104 *
105 * @return true if values correspond, false otherwise
106 */
107 static bool CheckMuTxDuration(std::list<uint32_t> sizes,
108 std::list<HeMuUserInfo> userInfos,
109 uint16_t channelWidth,
110 uint16_t guardInterval,
111 WifiPreamble preamble,
112 Time knownDuration);
113
114 /**
115 * Calculate the overall Tx duration returned by WifiPhy for list of sizes.
116 * A map of WifiPsdu indexed by STA-ID is built using the provided lists
117 * and handed over to the corresponding SU/MU WifiPhy Tx duration computing
118 * method.
119 * Note that provided lists should be of same size.
120 *
121 * @param sizes the list of PSDU sizes for each station in octets
122 * @param staIds the list of STA-IDs of each station
123 * @param txVector the TXVECTOR used for the transmission of the PPDU
124 * @param band the selected wifi PHY band
125 *
126 * @return the overall Tx duration for the list of sizes (SU or MU PPDU)
127 */
128 static Time CalculateTxDurationUsingList(std::list<uint32_t> sizes,
129 std::list<uint16_t> staIds,
130 WifiTxVector txVector,
131 WifiPhyBand band);
132};
133
135 : TestCase("Wifi TX Duration")
136{
137}
138
140{
141}
142
143bool
145 WifiMode payloadMode,
146 uint16_t channelWidth,
147 uint16_t guardInterval,
148 WifiPreamble preamble,
149 Time knownDuration)
150{
151 WifiTxVector txVector;
152 txVector.SetMode(payloadMode);
153 txVector.SetPreambleType(preamble);
154 txVector.SetChannelWidth(channelWidth);
155 txVector.SetGuardInterval(guardInterval);
156 txVector.SetNss(1);
157 txVector.SetStbc(false);
158 txVector.SetNess(0);
159 std::list<WifiPhyBand> testedBands;
160 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
161 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
162 {
163 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
164 }
165 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
166 {
167 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
168 }
169 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
170 {
171 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
172 }
173 for (auto& testedBand : testedBands)
174 {
175 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
176 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
177 {
178 knownDuration +=
179 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
180 }
181 Time calculatedDuration = phy->GetPayloadDuration(size, txVector, testedBand);
182 if (calculatedDuration != knownDuration)
183 {
184 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
185 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
186 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
187 << " known=" << knownDuration << " calculated=" << calculatedDuration
188 << std::endl;
189 return false;
190 }
191 }
192 return true;
193}
194
195bool
197 WifiMode payloadMode,
198 uint16_t channelWidth,
199 uint16_t guardInterval,
200 WifiPreamble preamble,
201 Time knownDuration)
202{
203 WifiTxVector txVector;
204 txVector.SetMode(payloadMode);
205 txVector.SetPreambleType(preamble);
206 txVector.SetChannelWidth(channelWidth);
207 txVector.SetGuardInterval(guardInterval);
208 txVector.SetNss(1);
209 txVector.SetStbc(false);
210 txVector.SetNess(0);
211 std::list<WifiPhyBand> testedBands;
212 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
213 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
214 {
215 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
216 }
217 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
218 {
219 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
220 }
221 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
222 {
223 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
224 }
225 for (auto& testedBand : testedBands)
226 {
227 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
228 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
229 {
230 knownDuration +=
231 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
232 }
233 Time calculatedDuration = phy->CalculateTxDuration(size, txVector, testedBand);
234 Time calculatedDurationUsingList =
235 CalculateTxDurationUsingList(std::list<uint32_t>{size},
236 std::list<uint16_t>{SU_STA_ID},
237 txVector,
238 testedBand);
239 if (calculatedDuration != knownDuration ||
240 calculatedDuration != calculatedDurationUsingList)
241 {
242 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
243 << " channelWidth=" << +channelWidth << " guardInterval=" << guardInterval
244 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
245 << " preamble=" << preamble << " known=" << knownDuration
246 << " calculated=" << calculatedDuration
247 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
248 return false;
249 }
250 }
251 return true;
252}
253
254bool
255TxDurationTest::CheckMuTxDuration(std::list<uint32_t> sizes,
256 std::list<HeMuUserInfo> userInfos,
257 uint16_t channelWidth,
258 uint16_t guardInterval,
259 WifiPreamble preamble,
260 Time knownDuration)
261{
262 NS_ASSERT(sizes.size() == userInfos.size() && sizes.size() > 1);
264 channelWidth < std::accumulate(
265 std::begin(userInfos),
266 std::end(userInfos),
267 0,
268 [](const uint16_t prevBw, const HeMuUserInfo& info) {
269 return prevBw + HeRu::GetBandwidth(info.ru.GetRuType());
270 }),
271 "Cannot accommodate all the RUs in the provided band"); // MU-MIMO (for which allocations
272 // use the same RU) is not supported
273 WifiTxVector txVector;
274 txVector.SetPreambleType(preamble);
275 txVector.SetChannelWidth(channelWidth);
276 txVector.SetGuardInterval(guardInterval);
277 txVector.SetStbc(false);
278 txVector.SetNess(0);
279 if (IsEht(preamble))
280 {
281 txVector.SetEhtPpduType(0);
282 }
283 std::list<uint16_t> staIds;
284
285 uint16_t staId = 1;
286 for (const auto& userInfo : userInfos)
287 {
288 txVector.SetHeMuUserInfo(staId, userInfo);
289 staIds.push_back(staId++);
290 }
292 txVector.SetRuAllocation({192, 192}, 0);
293
294 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
295 std::list<WifiPhyBand> testedBands{
298 WIFI_PHY_BAND_2_4GHZ}; // Durations vary depending on frequency; test also 2.4 GHz (bug
299 // 1971)
300 for (auto& testedBand : testedBands)
301 {
302 if (testedBand == WIFI_PHY_BAND_2_4GHZ)
303 {
304 knownDuration +=
305 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
306 }
307 Time calculatedDuration = NanoSeconds(0);
308 uint32_t longestSize = 0;
309 auto iterStaId = staIds.begin();
310 for (auto& size : sizes)
311 {
312 Time ppduDurationForSta =
313 phy->CalculateTxDuration(size, txVector, testedBand, *iterStaId);
314 if (ppduDurationForSta > calculatedDuration)
315 {
316 calculatedDuration = ppduDurationForSta;
317 staId = *iterStaId;
318 longestSize = size;
319 }
320 ++iterStaId;
321 }
322 Time calculatedDurationUsingList =
323 CalculateTxDurationUsingList(sizes, staIds, txVector, testedBand);
324 if (calculatedDuration != knownDuration ||
325 calculatedDuration != calculatedDurationUsingList)
326 {
327 std::cerr << "size=" << longestSize << " band=" << testedBand << " staId=" << staId
328 << " nss=" << +txVector.GetNss(staId) << " mode=" << txVector.GetMode(staId)
329 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
330 << " datarate="
331 << txVector.GetMode(staId).GetDataRate(channelWidth,
332 guardInterval,
333 txVector.GetNss(staId))
334 << " known=" << knownDuration << " calculated=" << calculatedDuration
335 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
336 return false;
337 }
338 }
339 return true;
340}
341
342Time
344 std::list<uint16_t> staIds,
345 WifiTxVector txVector,
346 WifiPhyBand band)
347{
348 NS_ASSERT(sizes.size() == staIds.size());
349 WifiConstPsduMap psduMap;
350 auto itStaId = staIds.begin();
351 WifiMacHeader hdr;
352 hdr.SetType(WIFI_MAC_CTL_ACK); // so that size may not be empty while being as short as possible
353 for (auto& size : sizes)
354 {
355 // MAC header and FCS are to deduce from size
356 psduMap[*itStaId++] =
357 Create<WifiPsdu>(Create<Packet>(size - hdr.GetSerializedSize() - 4), hdr);
358 }
359 return WifiPhy::CalculateTxDuration(psduMap, txVector, band);
360}
361
362void
364{
365 bool retval = true;
366
367 // IEEE Std 802.11-2007 Table 18-2 "Example of LENGTH calculations for CCK"
368 retval = retval &&
371 22,
372 800,
374 MicroSeconds(744)) &&
377 22,
378 800,
380 MicroSeconds(745)) &&
383 22,
384 800,
386 MicroSeconds(746)) &&
389 22,
390 800,
392 MicroSeconds(747));
393
394 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b CCK duration failed");
395
396 // Similar, but we add PHY preamble and header durations
397 // and we test different rates.
398 // The payload durations for modes other than 11mbb have been
399 // calculated by hand according to IEEE Std 802.11-2007 18.2.3.5
400 retval = retval &&
401 CheckTxDuration(1023,
403 22,
404 800,
406 MicroSeconds(744 + 96)) &&
407 CheckTxDuration(1024,
409 22,
410 800,
412 MicroSeconds(745 + 96)) &&
413 CheckTxDuration(1025,
415 22,
416 800,
418 MicroSeconds(746 + 96)) &&
419 CheckTxDuration(1026,
421 22,
422 800,
424 MicroSeconds(747 + 96)) &&
425 CheckTxDuration(1023,
427 22,
428 800,
430 MicroSeconds(744 + 192)) &&
431 CheckTxDuration(1024,
433 22,
434 800,
436 MicroSeconds(745 + 192)) &&
437 CheckTxDuration(1025,
439 22,
440 800,
442 MicroSeconds(746 + 192)) &&
443 CheckTxDuration(1026,
445 22,
446 800,
448 MicroSeconds(747 + 192)) &&
449 CheckTxDuration(1023,
451 22,
452 800,
454 MicroSeconds(1488 + 96)) &&
455 CheckTxDuration(1024,
457 22,
458 800,
460 MicroSeconds(1490 + 96)) &&
461 CheckTxDuration(1025,
463 22,
464 800,
466 MicroSeconds(1491 + 96)) &&
467 CheckTxDuration(1026,
469 22,
470 800,
472 MicroSeconds(1493 + 96)) &&
473 CheckTxDuration(1023,
475 22,
476 800,
478 MicroSeconds(1488 + 192)) &&
479 CheckTxDuration(1024,
481 22,
482 800,
484 MicroSeconds(1490 + 192)) &&
485 CheckTxDuration(1025,
487 22,
488 800,
490 MicroSeconds(1491 + 192)) &&
491 CheckTxDuration(1026,
493 22,
494 800,
496 MicroSeconds(1493 + 192)) &&
497 CheckTxDuration(1023,
499 22,
500 800,
502 MicroSeconds(4092 + 96)) &&
503 CheckTxDuration(1024,
505 22,
506 800,
508 MicroSeconds(4096 + 96)) &&
509 CheckTxDuration(1025,
511 22,
512 800,
514 MicroSeconds(4100 + 96)) &&
515 CheckTxDuration(1026,
517 22,
518 800,
520 MicroSeconds(4104 + 96)) &&
521 CheckTxDuration(1023,
523 22,
524 800,
526 MicroSeconds(4092 + 192)) &&
527 CheckTxDuration(1024,
529 22,
530 800,
532 MicroSeconds(4096 + 192)) &&
533 CheckTxDuration(1025,
535 22,
536 800,
538 MicroSeconds(4100 + 192)) &&
539 CheckTxDuration(1026,
541 22,
542 800,
544 MicroSeconds(4104 + 192)) &&
545 CheckTxDuration(1023,
547 22,
548 800,
550 MicroSeconds(8184 + 192)) &&
551 CheckTxDuration(1024,
553 22,
554 800,
556 MicroSeconds(8192 + 192)) &&
557 CheckTxDuration(1025,
559 22,
560 800,
562 MicroSeconds(8200 + 192)) &&
563 CheckTxDuration(1026,
565 22,
566 800,
568 MicroSeconds(8208 + 192)) &&
569 CheckTxDuration(1023,
571 22,
572 800,
574 MicroSeconds(8184 + 192)) &&
575 CheckTxDuration(1024,
577 22,
578 800,
580 MicroSeconds(8192 + 192)) &&
581 CheckTxDuration(1025,
583 22,
584 800,
586 MicroSeconds(8200 + 192)) &&
587 CheckTxDuration(1026,
589 22,
590 800,
592 MicroSeconds(8208 + 192));
593
594 // values from
595 // https://web.archive.org/web/20100711002639/http://mailman.isi.edu/pipermail/ns-developers/2009-July/006226.html
596 retval = retval && CheckTxDuration(14,
598 22,
599 800,
601 MicroSeconds(304));
602
603 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
604 retval = retval &&
605 CheckTxDuration(1536,
607 22,
608 800,
610 MicroSeconds(1310)) &&
613 22,
614 800,
616 MicroSeconds(248)) &&
619 22,
620 800,
622 MicroSeconds(203));
623
624 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b duration failed");
625
626 // 802.11a durations
627 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
628 retval = retval &&
629 CheckTxDuration(1536,
631 20,
632 800,
634 MicroSeconds(248)) &&
637 20,
638 800,
640 MicroSeconds(32)) &&
643 20,
644 800,
646 MicroSeconds(24));
647
648 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11a duration failed");
649
650 // 802.11g durations are same as 802.11a durations but with 6 us signal extension
651 retval = retval &&
652 CheckTxDuration(1536,
654 20,
655 800,
657 MicroSeconds(254)) &&
660 20,
661 800,
663 MicroSeconds(38)) &&
666 20,
667 800,
669 MicroSeconds(30));
670
671 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11g duration failed");
672
673 // 802.11n durations
674 retval =
675 retval &&
676 CheckTxDuration(1536,
678 20,
679 800,
681 MicroSeconds(228)) &&
684 CheckTxDuration(1536,
686 20,
687 400,
689 NanoSeconds(1742400)) &&
692 CheckTxDuration(1536,
694 20,
695 400,
697 NanoSeconds(226800)) &&
700 CheckTxDuration(1536,
702 40,
703 800,
705 MicroSeconds(128)) &&
708 CheckTxDuration(1536,
710 40,
711 400,
713 NanoSeconds(118800)) &&
716
717 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11n duration failed");
718
719 // 802.11ac durations
720 retval = retval &&
721 CheckTxDuration(1536,
723 20,
724 800,
726 MicroSeconds(196)) &&
729 20,
730 800,
732 MicroSeconds(48)) &&
735 20,
736 800,
738 MicroSeconds(40)) &&
739 CheckTxDuration(1536,
741 20,
742 400,
744 MicroSeconds(180)) &&
747 20,
748 400,
750 NanoSeconds(46800)) &&
753 20,
754 400,
756 NanoSeconds(39600)) &&
757 CheckTxDuration(1536,
759 40,
760 800,
762 MicroSeconds(108)) &&
765 40,
766 800,
768 MicroSeconds(40)) &&
771 40,
772 800,
774 MicroSeconds(40)) &&
775 CheckTxDuration(1536,
777 40,
778 400,
780 NanoSeconds(100800)) &&
783 40,
784 400,
786 NanoSeconds(39600)) &&
789 40,
790 400,
792 NanoSeconds(39600)) &&
793 CheckTxDuration(1536,
795 80,
796 800,
798 MicroSeconds(460)) &&
801 80,
802 800,
804 MicroSeconds(60)) &&
807 80,
808 800,
810 MicroSeconds(44)) &&
811 CheckTxDuration(1536,
813 80,
814 400,
816 NanoSeconds(417600)) &&
819 80,
820 400,
822 NanoSeconds(57600)) &&
825 80,
826 400,
828 NanoSeconds(43200)) &&
829 CheckTxDuration(1536,
831 80,
832 800,
834 MicroSeconds(68)) &&
837 80,
838 800,
840 MicroSeconds(40)) &&
843 80,
844 800,
846 MicroSeconds(40)) &&
847 CheckTxDuration(1536,
849 80,
850 400,
852 NanoSeconds(64800)) &&
855 80,
856 400,
858 NanoSeconds(39600)) &&
861 80,
862 400,
864 NanoSeconds(39600)) &&
865 CheckTxDuration(1536,
867 160,
868 800,
870 MicroSeconds(56)) &&
873 160,
874 800,
876 MicroSeconds(40)) &&
879 160,
880 800,
882 MicroSeconds(40)) &&
883 CheckTxDuration(1536,
885 160,
886 400,
888 MicroSeconds(54)) &&
891 160,
892 400,
894 NanoSeconds(39600)) &&
897 160,
898 400,
900 NanoSeconds(39600));
901
902 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ac duration failed");
903
904 // 802.11ax SU durations
905 retval =
906 retval &&
907 CheckTxDuration(1536,
909 20,
910 800,
912 NanoSeconds(1485600)) &&
915 20,
916 800,
918 NanoSeconds(125600)) &&
920 CheckTxDuration(1536,
922 40,
923 800,
925 NanoSeconds(764800)) &&
928 CheckTxDuration(1536,
930 80,
931 800,
933 NanoSeconds(397600)) &&
936 CheckTxDuration(1536,
938 160,
939 800,
941 NanoSeconds(220800)) &&
944 160,
945 800,
947 NanoSeconds(57600)) &&
950 160,
951 800,
953 NanoSeconds(57600)) &&
954 CheckTxDuration(1536,
956 20,
957 1600,
959 NanoSeconds(1570400)) &&
962 20,
963 1600,
965 NanoSeconds(130400)) &&
968 20,
969 1600,
971 NanoSeconds(72800)) &&
972 CheckTxDuration(1536,
974 40,
975 1600,
977 NanoSeconds(807200)) &&
980 40,
981 1600,
983 NanoSeconds(87200)) &&
986 40,
987 1600,
989 NanoSeconds(58400)) &&
990 CheckTxDuration(1536,
992 80,
993 1600,
995 NanoSeconds(418400)) &&
998 80,
999 1600,
1001 NanoSeconds(72800)) &&
1002 CheckTxDuration(14,
1004 80,
1005 1600,
1007 NanoSeconds(58400)) &&
1008 CheckTxDuration(1536,
1010 160,
1011 1600,
1013 NanoSeconds(231200)) &&
1014 CheckTxDuration(76,
1016 160,
1017 1600,
1019 NanoSeconds(58400)) &&
1020 CheckTxDuration(14,
1022 160,
1023 1600,
1025 NanoSeconds(58400)) &&
1026 CheckTxDuration(1536,
1028 20,
1029 3200,
1031 MicroSeconds(1740)) &&
1034 CheckTxDuration(1536,
1036 40,
1037 3200,
1039 MicroSeconds(892)) &&
1042 CheckTxDuration(1536,
1044 80,
1045 3200,
1047 MicroSeconds(460)) &&
1050 CheckTxDuration(1536,
1052 160,
1053 3200,
1055 MicroSeconds(252)) &&
1058 CheckTxDuration(1536,
1060 20,
1061 800,
1063 NanoSeconds(139200)) &&
1064 CheckTxDuration(76,
1066 20,
1067 800,
1069 NanoSeconds(57600)) &&
1070 CheckTxDuration(14,
1072 20,
1073 800,
1075 NanoSeconds(57600)) &&
1076 CheckTxDuration(1536,
1078 40,
1079 800,
1081 NanoSeconds(98400)) &&
1082 CheckTxDuration(76,
1084 40,
1085 800,
1087 NanoSeconds(57600)) &&
1088 CheckTxDuration(14,
1090 40,
1091 800,
1093 NanoSeconds(57600)) &&
1094 CheckTxDuration(1536,
1096 80,
1097 800,
1099 NanoSeconds(71200)) &&
1100 CheckTxDuration(76,
1102 80,
1103 800,
1105 NanoSeconds(57600)) &&
1106 CheckTxDuration(14,
1108 80,
1109 800,
1111 NanoSeconds(57600)) &&
1112 CheckTxDuration(1536,
1114 160,
1115 800,
1117 NanoSeconds(57600)) &&
1118 CheckTxDuration(76,
1120 160,
1121 800,
1123 NanoSeconds(57600)) &&
1124 CheckTxDuration(14,
1126 160,
1127 800,
1129 NanoSeconds(57600)) &&
1130 CheckTxDuration(1536,
1132 20,
1133 1600,
1135 NanoSeconds(144800)) &&
1136 CheckTxDuration(76,
1138 20,
1139 1600,
1141 NanoSeconds(58400)) &&
1142 CheckTxDuration(14,
1144 20,
1145 1600,
1147 NanoSeconds(58400)) &&
1148 CheckTxDuration(1536,
1150 40,
1151 1600,
1153 NanoSeconds(101600)) &&
1154 CheckTxDuration(76,
1156 40,
1157 1600,
1159 NanoSeconds(58400)) &&
1160 CheckTxDuration(14,
1162 40,
1163 1600,
1165 NanoSeconds(58400)) &&
1166 CheckTxDuration(1536,
1168 80,
1169 1600,
1171 NanoSeconds(72800)) &&
1172 CheckTxDuration(76,
1174 80,
1175 1600,
1177 NanoSeconds(58400)) &&
1178 CheckTxDuration(14,
1180 80,
1181 1600,
1183 NanoSeconds(58400)) &&
1184 CheckTxDuration(1536,
1186 160,
1187 1600,
1189 NanoSeconds(58400)) &&
1190 CheckTxDuration(76,
1192 160,
1193 1600,
1195 NanoSeconds(58400)) &&
1196 CheckTxDuration(14,
1198 160,
1199 1600,
1201 NanoSeconds(58400)) &&
1202 CheckTxDuration(1536,
1204 20,
1205 3200,
1207 MicroSeconds(156)) &&
1210 CheckTxDuration(1536,
1212 40,
1213 3200,
1215 MicroSeconds(108)) &&
1218 CheckTxDuration(1536,
1220 80,
1221 3200,
1223 MicroSeconds(76)) &&
1226 CheckTxDuration(1536,
1228 160,
1229 3200,
1231 MicroSeconds(60)) &&
1232 CheckTxDuration(76,
1234 160,
1235 3200,
1237 MicroSeconds(60)) &&
1239
1240 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax SU duration failed");
1241
1242 // 802.11ax MU durations
1243 retval = retval &&
1245 std::list<uint32_t>{1536, 1536},
1246 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1247 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1248 40,
1249 800,
1252 1493600)) // equivalent to HE_SU for 20 MHz with 2 extra HE-SIG-B (i.e. 8 us)
1253 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1254 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1255 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1256 40,
1257 800,
1259 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1260 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1261 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1262 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1263 40,
1264 800,
1266 NanoSeconds(1493600));
1267
1268 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax MU duration failed");
1269
1270 // 802.11be MU durations
1271 retval = retval &&
1272 CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1273 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1274 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1275 40,
1276 800,
1278 NanoSeconds(1493600)) // equivalent to 802.11ax MU
1279 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1280 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1281 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1282 40,
1283 800,
1285 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1286 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1287 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1288 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1289 40,
1290 800,
1292 NanoSeconds(1493600));
1293
1294 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11be MU duration failed");
1295
1297}
1298
1299/**
1300 * \ingroup wifi-test
1301 * \ingroup tests
1302 *
1303 * \brief HE-SIG-B duration test
1304 */
1306{
1307 public:
1308 /**
1309 * OFDMA or MU-MIMO
1310 */
1312 {
1314 MU_MIMO
1316
1317 /**
1318 * Constructor
1319 *
1320 * \param userInfos the HE MU specific per-user information to use for the test
1321 * \param sigBMode the mode to transmit HE-SIG-B for the test
1322 * \param channelWidth the channel width in MHz to select for the test
1323 * \param expectedMuType the expected MU type (OFDMA or MU-MIMO)
1324 * \param expectedRuAllocation the expected RU_ALLOCATION
1325 * \param expectedNumUsersPerCc the expected number of users per content channel
1326 * \param expectedSigBDuration the expected duration of the HE-SIG-B header
1327 */
1328 HeSigBDurationTest(const std::list<HeMuUserInfo>& userInfos,
1329 const WifiMode& sigBMode,
1330 uint16_t channelWidth,
1331 MuType expectedMuType,
1332 const RuAllocation& expectedRuAllocation,
1333 const std::pair<std::size_t, std::size_t>& expectedNumUsersPerCc,
1334 Time expectedSigBDuration);
1335
1336 private:
1337 void DoRun() override;
1338
1339 /**
1340 * Build a TXVECTOR for HE MU.
1341 *
1342 * \return the configured HE MU TXVECTOR
1343 */
1345
1346 std::list<HeMuUserInfo> m_userInfos; ///< HE MU specific per-user information
1347 WifiMode m_sigBMode; ///< Mode used to transmit HE-SIG-B
1348 uint16_t m_channelWidth; ///< Channel width in MHz
1349 MuType m_expectedMuType; ///< Expected MU type (OFDMA or MU-MIMO)
1350 RuAllocation m_expectedRuAllocation; ///< Expected RU_ALLOCATION
1351 std::pair<std::size_t, std::size_t>
1352 m_expectedNumUsersPerCc; ///< Expected number of users per content channel
1353 Time m_expectedSigBDuration; ///< Expected duration of the HE-SIG-B header
1354};
1355
1357 const std::list<HeMuUserInfo>& userInfos,
1358 const WifiMode& sigBMode,
1359 uint16_t channelWidth,
1360 MuType expectedMuType,
1361 const RuAllocation& expectedRuAllocation,
1362 const std::pair<std::size_t, std::size_t>& expectedNumUsersPerCc,
1363 Time expectedSigBDuration)
1364 : TestCase{"Check HE-SIG-B duration computation"},
1365 m_userInfos{userInfos},
1366 m_sigBMode{sigBMode},
1367 m_channelWidth{channelWidth},
1368 m_expectedMuType{expectedMuType},
1369 m_expectedRuAllocation{expectedRuAllocation},
1370 m_expectedNumUsersPerCc{expectedNumUsersPerCc},
1371 m_expectedSigBDuration{expectedSigBDuration}
1372{
1373}
1374
1377{
1378 WifiTxVector txVector;
1381 txVector.SetGuardInterval(3200);
1382 txVector.SetStbc(false);
1383 txVector.SetNess(0);
1384 std::list<uint16_t> staIds;
1385 uint16_t staId = 1;
1386 for (const auto& userInfo : m_userInfos)
1387 {
1388 txVector.SetHeMuUserInfo(staId, userInfo);
1389 staIds.push_back(staId++);
1390 }
1391 txVector.SetSigBMode(m_sigBMode);
1392 NS_ASSERT(m_expectedMuType == OFDMA ? txVector.IsDlOfdma() : txVector.IsDlMuMimo());
1393 return txVector;
1394}
1395
1396void
1398{
1400 const auto& txVector = BuildTxVector();
1401
1402 // Verify mode for HE-SIG-B field
1403 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1404 m_sigBMode,
1405 "Incorrect mode used to send HE-SIG-B");
1406
1407 // Verify RU_ALLOCATION in TXVECTOR
1408 NS_TEST_EXPECT_MSG_EQ((txVector.GetRuAllocation(0) == m_expectedRuAllocation),
1409 true,
1410 "Incorrect RU_ALLOCATION");
1411
1412 // Verify number of users for content channels 1 and 2
1413 const auto& numUsersPerCc = HePpdu::GetNumRusPerHeSigBContentChannel(
1414 txVector.GetChannelWidth(),
1415 txVector.GetRuAllocation(0),
1416 txVector.IsSigBCompression(),
1417 txVector.IsSigBCompression() ? txVector.GetHeMuUserInfoMap().size() : 0);
1418 const auto contentChannels = HePpdu::GetHeSigBContentChannels(txVector, 0);
1419 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1421 "Incorrect number of users in HE-SIG-B content channel 1");
1422 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1424 "Incorrect number of users in HE-SIG-B content channel 2");
1425 NS_TEST_EXPECT_MSG_EQ(contentChannels.at(0).size(),
1427 "Incorrect number of users in HE-SIG-B content channel 1");
1428 NS_TEST_EXPECT_MSG_EQ((contentChannels.size() > 1 ? contentChannels.at(1).size() : 0),
1430 "Incorrect number of users in HE-SIG-B content channel 2");
1431
1432 // Verify total HE-SIG-B duration
1433 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1435 "Incorrect duration for HE-SIG-B");
1436}
1437
1438/**
1439 * \ingroup wifi-test
1440 * \ingroup tests
1441 *
1442 * \brief PHY header sections consistency test
1443 */
1445{
1446 public:
1448 ~PhyHeaderSectionsTest() override;
1449 void DoRun() override;
1450
1451 private:
1452 /**
1453 * Check if map of PHY header sections returned by a given PHY entity
1454 * corresponds to a known value
1455 *
1456 * @param obtained the map of PHY header sections to check
1457 * @param expected the expected map of PHY header sections
1458 */
1461};
1462
1464 : TestCase("PHY header sections consistency")
1465{
1466}
1467
1469{
1470}
1471
1472void
1475{
1476 NS_ASSERT_MSG(obtained.size() == expected.size(),
1477 "The expected map size (" << expected.size() << ") was not obtained ("
1478 << obtained.size() << ")");
1479
1480 auto itObtained = obtained.begin();
1481 auto itExpected = expected.begin();
1482 for (; itObtained != obtained.end() || itExpected != expected.end();)
1483 {
1484 WifiPpduField field = itObtained->first;
1485 auto window = itObtained->second.first;
1486 auto mode = itObtained->second.second;
1487
1488 WifiPpduField fieldRef = itExpected->first;
1489 auto windowRef = itExpected->second.first;
1490 auto modeRef = itExpected->second.second;
1491
1493 fieldRef,
1494 "The expected PPDU field (" << fieldRef << ") was not obtained ("
1495 << field << ")");
1496 NS_TEST_EXPECT_MSG_EQ(window.first,
1497 windowRef.first,
1498 "The expected start time (" << windowRef.first
1499 << ") was not obtained (" << window.first
1500 << ")");
1501 NS_TEST_EXPECT_MSG_EQ(window.second,
1502 windowRef.second,
1503 "The expected stop time (" << windowRef.second
1504 << ") was not obtained (" << window.second
1505 << ")");
1507 modeRef,
1508 "The expected mode (" << modeRef << ") was not obtained (" << mode
1509 << ")");
1510 ++itObtained;
1511 ++itExpected;
1512 }
1513}
1514
1515void
1517{
1518 Time ppduStart = Seconds(1.0);
1519 Ptr<PhyEntity> phyEntity;
1521 WifiTxVector txVector;
1522 WifiMode nonHtMode;
1523
1524 // ==================================================================================
1525 // 11b (HR/DSSS)
1526 phyEntity = Create<DsssPhy>();
1528 txVector.SetChannelWidth(22);
1529
1530 // -> long PPDU format
1532 nonHtMode = DsssPhy::GetDsssRate1Mbps();
1533 sections = {
1534 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(144)}, nonHtMode}},
1536 {{ppduStart + MicroSeconds(144), ppduStart + MicroSeconds(192)}, nonHtMode}},
1537 };
1538 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1539
1540 // -> long PPDU format if data rate is 1 Mbps (even if preamble is tagged short)
1542 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1543
1544 // -> short PPDU format
1546 nonHtMode = DsssPhy::GetDsssRate2Mbps();
1548 sections = {
1549 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(72)}, nonHtMode}},
1551 {{ppduStart + MicroSeconds(72), ppduStart + MicroSeconds(96)}, nonHtMode}},
1552 };
1553 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1554
1555 // ==================================================================================
1556 // 11a (OFDM)
1558
1559 // -> one iteration per variant: default, 10 MHz, and 5 MHz
1560 std::map<OfdmPhyVariant, std::size_t> variants{
1561 // number to use to deduce rate and BW info for each variant
1562 {OFDM_PHY_DEFAULT, 1},
1563 {OFDM_PHY_10_MHZ, 2},
1564 {OFDM_PHY_5_MHZ, 4},
1565 };
1566 for (auto variant : variants)
1567 {
1568 phyEntity = Create<OfdmPhy>(variant.first);
1569 std::size_t ratio = variant.second;
1570 uint16_t bw = 20 / ratio; // MHz
1571 txVector.SetChannelWidth(bw);
1572 txVector.SetMode(OfdmPhy::GetOfdmRate(12000000 / ratio, bw));
1573 nonHtMode = OfdmPhy::GetOfdmRate(6000000 / ratio, bw);
1574 sections = {
1576 {{ppduStart, ppduStart + MicroSeconds(16 * ratio)}, nonHtMode}},
1578 {{ppduStart + MicroSeconds(16 * ratio), ppduStart + MicroSeconds(20 * ratio)},
1579 nonHtMode}},
1580 };
1581 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1582 }
1583
1584 // ==================================================================================
1585 // 11g (ERP-OFDM)
1586 phyEntity = Create<ErpOfdmPhy>();
1587 txVector.SetChannelWidth(20);
1588 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(54000000));
1589 nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps();
1590 sections = {
1591 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1593 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1594 };
1595 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1596
1597 // ==================================================================================
1598 // 11n (HT)
1599 phyEntity = Create<HtPhy>(4);
1600 txVector.SetChannelWidth(20);
1601 txVector.SetMode(HtPhy::GetHtMcs6());
1602 nonHtMode = OfdmPhy::GetOfdmRate6Mbps();
1603 WifiMode htSigMode = nonHtMode;
1604
1605 // -> HT-mixed format for 2 SS and no ESS
1607 txVector.SetNss(2);
1608 txVector.SetNess(0);
1609 sections = {
1610 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1612 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1614 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, htSigMode}},
1616 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(40)}, // 1 HT-STF + 2 HT-LTFs
1617 htSigMode}},
1618 };
1619 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1620 txVector.SetChannelWidth(20); // shouldn't have any impact
1621 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1622
1623 // -> HT-mixed format for 3 SS and 1 ESS
1624 txVector.SetNss(3);
1625 txVector.SetNess(1);
1626 sections[WIFI_PPDU_FIELD_TRAINING] = {
1627 {ppduStart + MicroSeconds(28),
1628 ppduStart + MicroSeconds(52)}, // 1 HT-STF + 5 HT-LTFs (4 data + 1 extension)
1629 htSigMode};
1630 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1631
1632 // ==================================================================================
1633 // 11ac (VHT)
1634 phyEntity = Create<VhtPhy>();
1635 txVector.SetChannelWidth(20);
1636 txVector.SetNess(0);
1637 txVector.SetMode(VhtPhy::GetVhtMcs7());
1638 WifiMode sigAMode = nonHtMode;
1639 WifiMode sigBMode = VhtPhy::GetVhtMcs0();
1640
1641 // -> VHT SU format for 5 SS
1643 txVector.SetNss(5);
1644 sections = {
1645 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1647 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1649 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, sigAMode}},
1651 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(56)}, // 1 VHT-STF + 6 VHT-LTFs
1652 sigAMode}},
1653 };
1654 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1655
1656 // -> VHT SU format for 7 SS
1657 txVector.SetNss(7);
1658 sections[WIFI_PPDU_FIELD_TRAINING] = {
1659 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(64)}, // 1 VHT-STF + 8 VHT-LTFs
1660 sigAMode};
1661 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1662
1663 // -> VHT MU format for 3 SS
1665 txVector.SetNss(3);
1666 sections[WIFI_PPDU_FIELD_TRAINING] = {
1667 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(48)}, // 1 VHT-STF + 4 VHT-LTFs
1668 sigAMode};
1669 sections[WIFI_PPDU_FIELD_SIG_B] = {{ppduStart + MicroSeconds(48), ppduStart + MicroSeconds(52)},
1670 sigBMode};
1671 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1672 txVector.SetChannelWidth(80); // shouldn't have any impact
1673 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1674
1675 // ==================================================================================
1676 // 11ax (HE)
1677 phyEntity = Create<HePhy>();
1678 txVector.SetChannelWidth(20);
1679 txVector.SetNss(2); // HE-LTF duration assumed to be always 8 us for the time being (see note in
1680 // HePhy::GetTrainingDuration)
1681 txVector.SetMode(HePhy::GetHeMcs9());
1682 std::map<uint16_t, HeMuUserInfo> userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1683 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1684 sigAMode = HePhy::GetVhtMcs0();
1685 sigBMode = HePhy::GetVhtMcs4(); // because of first user info map
1686
1687 // -> HE SU format
1689 sections = {
1690 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1692 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(24)}, // L-SIG + RL-SIG
1693 nonHtMode}},
1695 {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)}, sigAMode}},
1697 {{ppduStart + MicroSeconds(32),
1698 ppduStart + MicroSeconds(52)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1699 sigAMode}},
1700 };
1701 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1702
1703 // -> HE ER SU format
1705 sections[WIFI_PPDU_FIELD_SIG_A] = {
1706 {ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(40)}, // 16 us HE-SIG-A
1707 sigAMode};
1708 sections[WIFI_PPDU_FIELD_TRAINING] = {
1709 {ppduStart + MicroSeconds(40),
1710 ppduStart + MicroSeconds(60)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1711 sigAMode};
1712 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1713
1714 // -> HE TB format
1716 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1717 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1718 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1719 sigAMode};
1720 sections[WIFI_PPDU_FIELD_TRAINING] = {
1721 {ppduStart + MicroSeconds(32),
1722 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 8 us) + 2 HE-LTFs (@ 8 us)
1723 sigAMode};
1724 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1725
1726 // -> HE MU format
1728 txVector.SetSigBMode(sigBMode);
1729 txVector.SetRuAllocation({96}, 0);
1730 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1731 sigAMode};
1732 sections[WIFI_PPDU_FIELD_SIG_B] = {
1733 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1734 sigBMode};
1735 sections[WIFI_PPDU_FIELD_TRAINING] = {
1736 {ppduStart + MicroSeconds(36),
1737 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1738 sigBMode};
1739 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1740 txVector.SetChannelWidth(160); // shouldn't have any impact
1741 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113}, 0);
1742
1743 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1744
1745 // ==================================================================================
1746 // 11be (EHT)
1747 sections.erase(WIFI_PPDU_FIELD_SIG_A); // FIXME: do we keep using separate type for 11be?
1748 sections.erase(WIFI_PPDU_FIELD_SIG_B); // FIXME: do we keep using separate type for 11be?
1749 phyEntity = Create<EhtPhy>();
1750 txVector.SetChannelWidth(20);
1751 txVector.SetNss(2); // EHT-LTF duration assumed to be always 8 us for the time being (see note
1752 // in HePhy::GetTrainingDuration)
1753 txVector.SetMode(EhtPhy::GetEhtMcs9());
1754 userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1755 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1756 WifiMode uSigMode = EhtPhy::GetVhtMcs0();
1757 WifiMode ehtSigMode = EhtPhy::GetVhtMcs4(); // because of first user info map
1758
1759 // -> EHT TB format
1761 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1762 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1763 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1764 uSigMode};
1765 sections[WIFI_PPDU_FIELD_TRAINING] = {
1766 {ppduStart + MicroSeconds(32),
1767 ppduStart + MicroSeconds(56)}, // 1 EHT-STF (@ 8 us) + 2 EHT-LTFs (@ 8 us)
1768 uSigMode};
1769 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1770
1771 // -> EHT MU format
1773 txVector.SetEhtPpduType(0); // EHT MU transmission
1774 txVector.SetRuAllocation({96}, 0);
1775 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1776 uSigMode};
1777 sections[WIFI_PPDU_FIELD_EHT_SIG] = {
1778 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1779 ehtSigMode};
1780 sections[WIFI_PPDU_FIELD_TRAINING] = {
1781 {ppduStart + MicroSeconds(36),
1782 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1783 ehtSigMode};
1784 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1785 txVector.SetChannelWidth(160); // shouldn't have any impact
1786 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113}, 0);
1787
1788 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1789}
1790
1791/**
1792 * \ingroup wifi-test
1793 * \ingroup tests
1794 *
1795 * \brief Tx Duration Test Suite
1796 */
1798{
1799 public:
1801};
1802
1804 : TestSuite("wifi-devices-tx-duration", Type::UNIT)
1805{
1806 AddTestCase(new TxDurationTest, TestCase::Duration::QUICK);
1807
1808 AddTestCase(new PhyHeaderSectionsTest, TestCase::Duration::QUICK);
1809
1810 // 20 MHz band, HeSigBDurationTest::OFDMA, even number of users per HE-SIG-B content channel
1812 {{{HeRu::RU_106_TONE, 1, true}, 11, 1}, {{HeRu::RU_106_TONE, 2, true}, 10, 4}},
1814 20,
1816 {96},
1817 std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
1818 MicroSeconds(4)), // one OFDM symbol;
1819 TestCase::Duration::QUICK);
1820
1821 // 40 MHz band, HeSigBDurationTest::OFDMA, even number of users per HE-SIG-B content channel
1823 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1824 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1825 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1826 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1827 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1828 {{HeRu::RU_52_TONE, 8, true}, 6, 2}},
1830 40,
1832 {96, 112},
1833 std::make_pair(2, 4), // two users in HE-SIG-B content channel 1 and
1834 // four users in HE-SIG-B content channel 2
1835 MicroSeconds(4)), // one OFDM symbol;
1836 TestCase::Duration::QUICK);
1837
1838 // 40 MHz band, HeSigBDurationTest::OFDMA, odd number of users per HE-SIG-B content channel
1840 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1841 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1842 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1843 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1844 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1845 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1846 {{HeRu::RU_26_TONE, 14, true}, 3, 1}},
1848 40,
1850 {96, 15},
1851 std::make_pair(2, 5), // two users in HE-SIG-B content channel 1 and
1852 // five users in HE-SIG-B content channel 2
1853 MicroSeconds(8)), // two OFDM symbols
1854 TestCase::Duration::QUICK);
1855
1856 // 80 MHz band, OFDMA
1858 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1859 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1860 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1861 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1862 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1863 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1864 {{HeRu::RU_26_TONE, 14, true}, 3, 1},
1865 {{HeRu::RU_242_TONE, 3, true}, 1, 1},
1866 {{HeRu::RU_242_TONE, 4, true}, 4, 1}},
1868 80,
1870 {96, 15, 192, 192},
1871 std::make_pair(3, 6), // three users in HE-SIG-B content channel 1
1872 // and six users in HE-SIG-B content channel 2
1873 MicroSeconds(16)), // four OFDM symbols
1874 TestCase::Duration::QUICK);
1875
1876 // 160 MHz band, OFDMA
1878 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1879 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1880 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1881 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1882 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1883 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1884 {{HeRu::RU_26_TONE, 14, true}, 3, 1},
1885 {{HeRu::RU_242_TONE, 3, true}, 1, 1},
1886 {{HeRu::RU_242_TONE, 4, true}, 4, 1},
1887 {{HeRu::RU_996_TONE, 1, false}, 1, 1}},
1889 160,
1891 {96, 15, 192, 192, 208, 208, 208, 208},
1892 std::make_pair(4, 7), // four users in HE-SIG-B content channel 1 and
1893 // seven users in HE-SIG-B content channel 2
1894 MicroSeconds(20)), // five OFDM symbols
1895 TestCase::Duration::QUICK);
1896
1897 // 20 MHz band, HeSigBDurationTest::OFDMA, one unallocated RU at the middle
1899 new HeSigBDurationTest({{{HeRu::RU_26_TONE, 1, true}, 11, 1},
1900 {{HeRu::RU_26_TONE, 2, true}, 11, 1},
1901 {{HeRu::RU_26_TONE, 3, true}, 11, 1},
1902 {{HeRu::RU_26_TONE, 4, true}, 11, 1},
1903 {{HeRu::RU_26_TONE, 6, true}, 11, 1},
1904 {{HeRu::RU_26_TONE, 7, true}, 11, 1},
1905 {{HeRu::RU_26_TONE, 8, true}, 11, 1},
1906 {{HeRu::RU_26_TONE, 9, true}, 11, 1}},
1908 20,
1910 {0},
1911 std::make_pair(9, 0), // 9 users in HE-SIG-B content channel 1
1912 MicroSeconds(8)), // two OFDM symbols
1913 TestCase::Duration::QUICK);
1914
1915 // 40 MHz band, HeSigBDurationTest::OFDMA, unallocated RUs at the begin and at the end of the
1916 // first 20 MHz subband and in the middle of the second 20 MHz subband
1918 new HeSigBDurationTest({{{HeRu::RU_52_TONE, 2, true}, 10, 1},
1919 {{HeRu::RU_52_TONE, 3, true}, 10, 2},
1920 {{HeRu::RU_52_TONE, 5, true}, 11, 1},
1921 {{HeRu::RU_52_TONE, 8, true}, 11, 2}},
1923 40,
1925 {112, 112},
1926 std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
1927 MicroSeconds(4)), // two OFDM symbols
1928 TestCase::Duration::QUICK);
1929
1930 // 40 MHz band, HeSigBDurationTest::OFDMA, one unallocated RUs in the first 20 MHz subband and
1931 // two unallocated RUs in second 20 MHz subband
1933 new HeSigBDurationTest({{{HeRu::RU_52_TONE, 1, true}, 10, 1},
1934 {{HeRu::RU_52_TONE, 2, true}, 10, 2},
1935 {{HeRu::RU_52_TONE, 3, true}, 11, 1},
1936 {{HeRu::RU_52_TONE, 5, true}, 11, 2},
1937 {{HeRu::RU_52_TONE, 6, true}, 11, 3}},
1939 40,
1941 {112, 112},
1942 std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
1943 MicroSeconds(4)), // two OFDM symbols
1944 TestCase::Duration::QUICK);
1945
1946 // 20 MHz band, MU-MIMO, 2 users
1948 {{{HeRu::RU_242_TONE, 1, true}, 11, 1}, {{HeRu::RU_242_TONE, 1, true}, 10, 4}},
1950 20,
1952 {192},
1953 std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
1954 MicroSeconds(4)), // one OFDM symbol
1955 TestCase::Duration::QUICK);
1956
1957 // 20 MHz band, MU-MIMO, 3 users
1959 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 3},
1960 {{HeRu::RU_242_TONE, 1, true}, 5, 2},
1961 {{HeRu::RU_242_TONE, 1, true}, 6, 1}},
1963 20,
1965 {192},
1966 std::make_pair(3, 0), // all users in HE-SIG-B content channel 1
1967 MicroSeconds(4)), // one OFDM symbol
1968 TestCase::Duration::QUICK);
1969
1970 // 20 MHz band, MU-MIMO, 4 users
1972 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
1973 {{HeRu::RU_242_TONE, 1, true}, 5, 2},
1974 {{HeRu::RU_242_TONE, 1, true}, 6, 3},
1975 {{HeRu::RU_242_TONE, 1, true}, 7, 2}},
1977 20,
1979 {192},
1980 std::make_pair(4, 0), // all users in HE-SIG-B content channel 1
1981 MicroSeconds(4)), // one OFDM symbol
1982 TestCase::Duration::QUICK);
1983
1984 // 20 MHz band, MU-MIMO, 6 users
1986 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
1987 {{HeRu::RU_242_TONE, 1, true}, 5, 1},
1988 {{HeRu::RU_242_TONE, 1, true}, 6, 2},
1989 {{HeRu::RU_242_TONE, 1, true}, 7, 2},
1990 {{HeRu::RU_242_TONE, 1, true}, 8, 1},
1991 {{HeRu::RU_242_TONE, 1, true}, 9, 1}},
1993 20,
1995 {192},
1996 std::make_pair(6, 0), // all users in HE-SIG-B content channel 1
1997 MicroSeconds(4)), // one OFDM symbol
1998 TestCase::Duration::QUICK);
1999
2000 // 20 MHz band, MU-MIMO, 8 users
2002 new HeSigBDurationTest({{{HeRu::RU_242_TONE, 1, true}, 4, 1},
2003 {{HeRu::RU_242_TONE, 1, true}, 5, 1},
2004 {{HeRu::RU_242_TONE, 1, true}, 6, 1},
2005 {{HeRu::RU_242_TONE, 1, true}, 7, 1},
2006 {{HeRu::RU_242_TONE, 1, true}, 8, 1},
2007 {{HeRu::RU_242_TONE, 1, true}, 9, 1},
2008 {{HeRu::RU_242_TONE, 1, true}, 10, 1},
2009 {{HeRu::RU_242_TONE, 1, true}, 11, 1}},
2011 20,
2013 {192},
2014 std::make_pair(8, 0), // all users in HE-SIG-B content channel 1
2015 MicroSeconds(8)), // two OFDM symbols
2016 TestCase::Duration::QUICK);
2017
2018 // 40 MHz band, MU-MIMO, 2 users
2020 {{{HeRu::RU_484_TONE, 1, true}, 11, 1}, {{HeRu::RU_484_TONE, 1, true}, 10, 4}},
2022 40,
2024 {200, 200},
2025 std::make_pair(1, 1), // users equally split between the two content channels
2026 MicroSeconds(4)), // one OFDM symbol
2027 TestCase::Duration::QUICK);
2028
2029 // 40 MHz band, MU-MIMO, 3 users
2032 {{{HeRu::RU_484_TONE, 1, true}, 4, 3},
2033 {{HeRu::RU_484_TONE, 1, true}, 5, 2},
2034 {{HeRu::RU_484_TONE, 1, true}, 6, 1}},
2036 40,
2038 {200, 200},
2039 std::make_pair(2, 1), // 2 users in content channel 1 and 1 user in content channel 2
2040 MicroSeconds(4)), // one OFDM symbol
2041 TestCase::Duration::QUICK);
2042
2043 // 40 MHz band, MU-MIMO, 4 users
2045 {{{HeRu::RU_484_TONE, 1, true}, 4, 1},
2046 {{HeRu::RU_484_TONE, 1, true}, 5, 2},
2047 {{HeRu::RU_484_TONE, 1, true}, 6, 3},
2048 {{HeRu::RU_484_TONE, 1, true}, 7, 2}},
2050 40,
2052 {200, 200},
2053 std::make_pair(2, 2), // users equally split between the two content channels
2054 MicroSeconds(4)), // one OFDM symbol
2055 TestCase::Duration::QUICK);
2056
2057 // 40 MHz band, MU-MIMO, 6 users
2059 {{{HeRu::RU_484_TONE, 1, true}, 4, 1},
2060 {{HeRu::RU_484_TONE, 1, true}, 5, 1},
2061 {{HeRu::RU_484_TONE, 1, true}, 6, 2},
2062 {{HeRu::RU_484_TONE, 1, true}, 7, 2},
2063 {{HeRu::RU_484_TONE, 1, true}, 8, 1},
2064 {{HeRu::RU_484_TONE, 1, true}, 9, 1}},
2066 40,
2068 {200, 200},
2069 std::make_pair(3, 3), // users equally split between the two content channels
2070 MicroSeconds(4)), // one OFDM symbol
2071 TestCase::Duration::QUICK);
2072
2073 // 40 MHz band, MU-MIMO, 8 users
2075 {{{HeRu::RU_484_TONE, 1, true}, 4, 1},
2076 {{HeRu::RU_484_TONE, 1, true}, 5, 1},
2077 {{HeRu::RU_484_TONE, 1, true}, 6, 1},
2078 {{HeRu::RU_484_TONE, 1, true}, 7, 1},
2079 {{HeRu::RU_484_TONE, 1, true}, 8, 1},
2080 {{HeRu::RU_484_TONE, 1, true}, 9, 1},
2081 {{HeRu::RU_484_TONE, 1, true}, 10, 1},
2082 {{HeRu::RU_484_TONE, 1, true}, 11, 1}},
2084 40,
2086 {200, 200},
2087 std::make_pair(4, 4), // users equally split between the two content channels
2088 MicroSeconds(4)), // one OFDM symbol
2089 TestCase::Duration::QUICK);
2090
2091 // 80 MHz band, MU-MIMO, 2 users
2093 {{{HeRu::RU_996_TONE, 1, true}, 11, 1}, {{HeRu::RU_996_TONE, 1, true}, 10, 4}},
2095 80,
2097 {208, 208, 208, 208},
2098 std::make_pair(1, 1), // users equally split between the two content channels
2099 MicroSeconds(4)), // one OFDM symbol
2100 TestCase::Duration::QUICK);
2101
2102 // 80 MHz band, MU-MIMO, 3 users
2105 {{{HeRu::RU_996_TONE, 1, true}, 4, 3},
2106 {{HeRu::RU_996_TONE, 1, true}, 5, 2},
2107 {{HeRu::RU_996_TONE, 1, true}, 6, 1}},
2109 80,
2111 {208, 208, 208, 208},
2112 std::make_pair(2, 1), // 2 users in content channel 1 and 1 user in content channel 2
2113 MicroSeconds(4)), // one OFDM symbol
2114 TestCase::Duration::QUICK);
2115
2116 // 80 MHz band, MU-MIMO, 4 users
2118 {{{HeRu::RU_996_TONE, 1, true}, 4, 1},
2119 {{HeRu::RU_996_TONE, 1, true}, 5, 2},
2120 {{HeRu::RU_996_TONE, 1, true}, 6, 3},
2121 {{HeRu::RU_996_TONE, 1, true}, 7, 2}},
2123 80,
2125 {208, 208, 208, 208},
2126 std::make_pair(2, 2), // users equally split between the two content channels
2127 MicroSeconds(4)), // one OFDM symbol
2128 TestCase::Duration::QUICK);
2129
2130 // 80 MHz band, MU-MIMO, 6 users
2132 {{{HeRu::RU_996_TONE, 1, true}, 4, 1},
2133 {{HeRu::RU_996_TONE, 1, true}, 5, 1},
2134 {{HeRu::RU_996_TONE, 1, true}, 6, 2},
2135 {{HeRu::RU_996_TONE, 1, true}, 7, 2},
2136 {{HeRu::RU_996_TONE, 1, true}, 8, 1},
2137 {{HeRu::RU_996_TONE, 1, true}, 9, 1}},
2139 80,
2141 {208, 208, 208, 208},
2142 std::make_pair(3, 3), // users equally split between the two content channels
2143 MicroSeconds(4)), // one OFDM symbol
2144 TestCase::Duration::QUICK);
2145
2146 // 80 MHz band, MU-MIMO, 8 users
2148 {{{HeRu::RU_996_TONE, 1, true}, 4, 1},
2149 {{HeRu::RU_996_TONE, 1, true}, 5, 1},
2150 {{HeRu::RU_996_TONE, 1, true}, 6, 1},
2151 {{HeRu::RU_996_TONE, 1, true}, 7, 1},
2152 {{HeRu::RU_996_TONE, 1, true}, 8, 1},
2153 {{HeRu::RU_996_TONE, 1, true}, 9, 1},
2154 {{HeRu::RU_996_TONE, 1, true}, 10, 1},
2155 {{HeRu::RU_996_TONE, 1, true}, 11, 1}},
2157 80,
2159 {208, 208, 208, 208},
2160 std::make_pair(4, 4), // users equally split between the two content channels
2161 MicroSeconds(4)), // one OFDM symbol
2162 TestCase::Duration::QUICK);
2163
2164 // 160 MHz band, MU-MIMO, 2 users
2167 {{{HeRu::RU_2x996_TONE, 1, true}, 11, 1}, {{HeRu::RU_2x996_TONE, 1, true}, 10, 4}},
2169 160,
2171 {208, 208, 208, 208, 208, 208, 208, 208},
2172 std::make_pair(1, 1), // users equally split between the two content channels
2173 MicroSeconds(4)), // one OFDM symbol
2174 TestCase::Duration::QUICK);
2175
2176 // 160 MHz band, MU-MIMO, 3 users
2179 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 3},
2180 {{HeRu::RU_2x996_TONE, 1, true}, 5, 2},
2181 {{HeRu::RU_2x996_TONE, 1, true}, 6, 1}},
2183 160,
2185 {208, 208, 208, 208, 208, 208, 208, 208},
2186 std::make_pair(2, 1), // 2 users in content channel 1 and 1 user in content channel 2
2187 MicroSeconds(4)), // one OFDM symbol
2188 TestCase::Duration::QUICK);
2189
2190 // 160 MHz band, MU-MIMO, 4 users
2192 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
2193 {{HeRu::RU_2x996_TONE, 1, true}, 5, 2},
2194 {{HeRu::RU_2x996_TONE, 1, true}, 6, 3},
2195 {{HeRu::RU_2x996_TONE, 1, true}, 7, 2}},
2197 160,
2199 {208, 208, 208, 208, 208, 208, 208, 208},
2200 std::make_pair(2, 2), // users equally split between the two content channels
2201 MicroSeconds(4)), // one OFDM symbol
2202 TestCase::Duration::QUICK);
2203
2204 // 160 MHz band, MU-MIMO, 6 users
2206 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
2207 {{HeRu::RU_2x996_TONE, 1, true}, 5, 1},
2208 {{HeRu::RU_2x996_TONE, 1, true}, 6, 2},
2209 {{HeRu::RU_2x996_TONE, 1, true}, 7, 2},
2210 {{HeRu::RU_2x996_TONE, 1, true}, 8, 1},
2211 {{HeRu::RU_2x996_TONE, 1, true}, 9, 1}},
2213 160,
2215 {208, 208, 208, 208, 208, 208, 208, 208},
2216 std::make_pair(3, 3), // users equally split between the two content channels
2217 MicroSeconds(4)), // one OFDM symbol
2218 TestCase::Duration::QUICK);
2219
2220 // 160 MHz band, MU-MIMO, 8 users
2222 {{{HeRu::RU_2x996_TONE, 1, true}, 4, 1},
2223 {{HeRu::RU_2x996_TONE, 1, true}, 5, 1},
2224 {{HeRu::RU_2x996_TONE, 1, true}, 6, 1},
2225 {{HeRu::RU_2x996_TONE, 1, true}, 7, 1},
2226 {{HeRu::RU_2x996_TONE, 1, true}, 8, 1},
2227 {{HeRu::RU_2x996_TONE, 1, true}, 9, 1},
2228 {{HeRu::RU_2x996_TONE, 1, true}, 10, 1},
2229 {{HeRu::RU_2x996_TONE, 1, true}, 11, 1}},
2231 160,
2233 {208, 208, 208, 208, 208, 208, 208, 208},
2234 std::make_pair(4, 4), // users equally split between the two content channels
2235 MicroSeconds(4)), // one OFDM symbol
2236 TestCase::Duration::QUICK);
2237}
2238
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)
HeSigBDurationTest(const std::list< HeMuUserInfo > &userInfos, const WifiMode &sigBMode, uint16_t channelWidth, MuType expectedMuType, const RuAllocation &expectedRuAllocation, const std::pair< std::size_t, std::size_t > &expectedNumUsersPerCc, Time expectedSigBDuration)
Constructor.
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.
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.
uint16_t m_channelWidth
Channel width in MHz.
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.
static bool CheckMuTxDuration(std::list< uint32_t > sizes, std::list< HeMuUserInfo > userInfos, uint16_t channelWidth, uint16_t guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the overall Tx duration returned by WifiPhy for a MU PPDU corresponds to a known value.
bool CheckTxDuration(uint32_t size, WifiMode payloadMode, uint16_t channelWidth, uint16_t guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the overall tx duration returned by InterferenceHelper corresponds to a known value.
bool CheckPayloadDuration(uint32_t size, WifiMode payloadMode, uint16_t channelWidth, uint16_t guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the payload tx duration returned by InterferenceHelper corresponds to a known value.
void DoRun() override
Implementation to actually run this TestCase.
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 std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel(uint16_t channelWidth, const RuAllocation &ruAllocation, bool sigBCompression, uint8_t numMuMimoUsers)
Get the number of STAs per HE-SIG-B content channel.
Definition: he-ppdu.cc:486
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:554
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:454
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:763
@ RU_26_TONE
Definition: he-ru.h:42
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_52_TONE
Definition: he-ru.h:43
@ RU_242_TONE
Definition: he-ru.h:45
@ RU_2x996_TONE
Definition: he-ru.h:48
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 GetOfdmRate54Mbps()
Return a WifiMode for OFDM at 54 Mbps.
static WifiMode GetOfdmRate(uint64_t rate, uint16_t bw=20)
Return a WifiMode for OFDM corresponding to the provided rate and the channel bandwidth (20,...
Definition: ofdm-phy.cc:414
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:326
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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:51
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:185
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1529
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:725
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 SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t 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.
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:66
#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:86
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
Definition: wifi-phy-band.h:33
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.
Definition: wifi-phy-band.h:39
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ 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:46
@ OFDM_PHY_DEFAULT
Definition: ofdm-phy.h:45
@ OFDM_PHY_5_MHZ
Definition: ofdm-phy.h:47
@ 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:35
HE MU specific user transmission parameters.
HeRu::RuSpec ru
RU specification.
static TxDurationTestSuite g_txDurationTestSuite
the test suite