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 <numeric>
34
35using namespace ns3;
36
37NS_LOG_COMPONENT_DEFINE("InterferenceHelperTxDurationTest");
38
46{
47 public:
49 ~TxDurationTest() override;
50 void DoRun() override;
51
52 private:
67 WifiMode payloadMode,
68 uint16_t channelWidth,
69 uint16_t guardInterval,
70 WifiPreamble preamble,
71 Time knownDuration);
72
86 bool CheckTxDuration(uint32_t size,
87 WifiMode payloadMode,
88 uint16_t channelWidth,
89 uint16_t guardInterval,
90 WifiPreamble preamble,
91 Time knownDuration);
92
106 static bool CheckMuTxDuration(std::list<uint32_t> sizes,
107 std::list<HeMuUserInfo> userInfos,
108 uint16_t channelWidth,
109 uint16_t guardInterval,
110 WifiPreamble preamble,
111 Time knownDuration);
112
127 static Time CalculateTxDurationUsingList(std::list<uint32_t> sizes,
128 std::list<uint16_t> staIds,
129 WifiTxVector txVector,
130 WifiPhyBand band);
131};
132
134 : TestCase("Wifi TX Duration")
135{
136}
137
139{
140}
141
142bool
144 WifiMode payloadMode,
145 uint16_t channelWidth,
146 uint16_t guardInterval,
147 WifiPreamble preamble,
148 Time knownDuration)
149{
150 WifiTxVector txVector;
151 txVector.SetMode(payloadMode);
152 txVector.SetPreambleType(preamble);
153 txVector.SetChannelWidth(channelWidth);
154 txVector.SetGuardInterval(guardInterval);
155 txVector.SetNss(1);
156 txVector.SetStbc(0);
157 txVector.SetNess(0);
158 std::list<WifiPhyBand> testedBands;
159 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
160 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
161 {
162 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
163 }
164 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
165 {
166 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
167 }
168 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
169 {
170 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
171 }
172 for (auto& testedBand : testedBands)
173 {
174 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
175 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
176 {
177 knownDuration +=
178 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
179 }
180 Time calculatedDuration = phy->GetPayloadDuration(size, txVector, testedBand);
181 if (calculatedDuration != knownDuration)
182 {
183 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
184 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
185 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
186 << " known=" << knownDuration << " calculated=" << calculatedDuration
187 << std::endl;
188 return false;
189 }
190 }
191 return true;
192}
193
194bool
196 WifiMode payloadMode,
197 uint16_t channelWidth,
198 uint16_t guardInterval,
199 WifiPreamble preamble,
200 Time knownDuration)
201{
202 WifiTxVector txVector;
203 txVector.SetMode(payloadMode);
204 txVector.SetPreambleType(preamble);
205 txVector.SetChannelWidth(channelWidth);
206 txVector.SetGuardInterval(guardInterval);
207 txVector.SetNss(1);
208 txVector.SetStbc(0);
209 txVector.SetNess(0);
210 std::list<WifiPhyBand> testedBands;
211 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
212 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
213 {
214 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
215 }
216 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
217 {
218 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
219 }
220 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
221 {
222 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
223 }
224 for (auto& testedBand : testedBands)
225 {
226 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
227 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
228 {
229 knownDuration +=
230 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
231 }
232 Time calculatedDuration = phy->CalculateTxDuration(size, txVector, testedBand);
233 Time calculatedDurationUsingList =
234 CalculateTxDurationUsingList(std::list<uint32_t>{size},
235 std::list<uint16_t>{SU_STA_ID},
236 txVector,
237 testedBand);
238 if (calculatedDuration != knownDuration ||
239 calculatedDuration != calculatedDurationUsingList)
240 {
241 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
242 << " channelWidth=" << +channelWidth << " guardInterval=" << guardInterval
243 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
244 << " preamble=" << preamble << " known=" << knownDuration
245 << " calculated=" << calculatedDuration
246 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
247 return false;
248 }
249 }
250 return true;
251}
252
253bool
254TxDurationTest::CheckMuTxDuration(std::list<uint32_t> sizes,
255 std::list<HeMuUserInfo> userInfos,
256 uint16_t channelWidth,
257 uint16_t guardInterval,
258 WifiPreamble preamble,
259 Time knownDuration)
260{
261 NS_ASSERT(sizes.size() == userInfos.size() && sizes.size() > 1);
263 channelWidth < std::accumulate(
264 std::begin(userInfos),
265 std::end(userInfos),
266 0,
267 [](const uint16_t prevBw, const HeMuUserInfo& info) {
268 return prevBw + HeRu::GetBandwidth(info.ru.GetRuType());
269 }),
270 "Cannot accommodate all the RUs in the provided band"); // MU-MIMO (for which allocations
271 // use the same RU) is not supported
272 WifiTxVector txVector;
273 txVector.SetPreambleType(preamble);
274 txVector.SetChannelWidth(channelWidth);
275 txVector.SetGuardInterval(guardInterval);
276 txVector.SetStbc(0);
277 txVector.SetNess(0);
278 if (IsEht(preamble))
279 {
280 txVector.SetEhtPpduType(0);
281 }
282 std::list<uint16_t> staIds;
283
284 uint16_t staId = 1;
285 for (const auto& userInfo : userInfos)
286 {
287 txVector.SetHeMuUserInfo(staId, userInfo);
288 staIds.push_back(staId++);
289 }
291 txVector.SetRuAllocation({192, 192}, 0);
292
293 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
294 std::list<WifiPhyBand> testedBands{
297 WIFI_PHY_BAND_2_4GHZ}; // Durations vary depending on frequency; test also 2.4 GHz (bug
298 // 1971)
299 for (auto& testedBand : testedBands)
300 {
301 if (testedBand == WIFI_PHY_BAND_2_4GHZ)
302 {
303 knownDuration +=
304 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
305 }
306 Time calculatedDuration = NanoSeconds(0);
307 uint32_t longestSize = 0;
308 auto iterStaId = staIds.begin();
309 for (auto& size : sizes)
310 {
311 Time ppduDurationForSta =
312 phy->CalculateTxDuration(size, txVector, testedBand, *iterStaId);
313 if (ppduDurationForSta > calculatedDuration)
314 {
315 calculatedDuration = ppduDurationForSta;
316 staId = *iterStaId;
317 longestSize = size;
318 }
319 ++iterStaId;
320 }
321 Time calculatedDurationUsingList =
322 CalculateTxDurationUsingList(sizes, staIds, txVector, testedBand);
323 if (calculatedDuration != knownDuration ||
324 calculatedDuration != calculatedDurationUsingList)
325 {
326 std::cerr << "size=" << longestSize << " band=" << testedBand << " staId=" << staId
327 << " nss=" << +txVector.GetNss(staId) << " mode=" << txVector.GetMode(staId)
328 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
329 << " datarate="
330 << txVector.GetMode(staId).GetDataRate(channelWidth,
331 guardInterval,
332 txVector.GetNss(staId))
333 << " known=" << knownDuration << " calculated=" << calculatedDuration
334 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
335 return false;
336 }
337 }
338 return true;
339}
340
341Time
343 std::list<uint16_t> staIds,
344 WifiTxVector txVector,
345 WifiPhyBand band)
346{
347 NS_ASSERT(sizes.size() == staIds.size());
348 WifiConstPsduMap psduMap;
349 auto itStaId = staIds.begin();
350 WifiMacHeader hdr;
351 hdr.SetType(WIFI_MAC_CTL_ACK); // so that size may not be empty while being as short as possible
352 for (auto& size : sizes)
353 {
354 // MAC header and FCS are to deduce from size
355 psduMap[*itStaId++] =
356 Create<WifiPsdu>(Create<Packet>(size - hdr.GetSerializedSize() - 4), hdr);
357 }
358 return WifiPhy::CalculateTxDuration(psduMap, txVector, band);
359}
360
361void
363{
364 bool retval = true;
365
366 // IEEE Std 802.11-2007 Table 18-2 "Example of LENGTH calculations for CCK"
367 retval = retval &&
370 22,
371 800,
373 MicroSeconds(744)) &&
376 22,
377 800,
379 MicroSeconds(745)) &&
382 22,
383 800,
385 MicroSeconds(746)) &&
388 22,
389 800,
391 MicroSeconds(747));
392
393 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b CCK duration failed");
394
395 // Similar, but we add PHY preamble and header durations
396 // and we test different rates.
397 // The payload durations for modes other than 11mbb have been
398 // calculated by hand according to IEEE Std 802.11-2007 18.2.3.5
399 retval = retval &&
400 CheckTxDuration(1023,
402 22,
403 800,
405 MicroSeconds(744 + 96)) &&
406 CheckTxDuration(1024,
408 22,
409 800,
411 MicroSeconds(745 + 96)) &&
412 CheckTxDuration(1025,
414 22,
415 800,
417 MicroSeconds(746 + 96)) &&
418 CheckTxDuration(1026,
420 22,
421 800,
423 MicroSeconds(747 + 96)) &&
424 CheckTxDuration(1023,
426 22,
427 800,
429 MicroSeconds(744 + 192)) &&
430 CheckTxDuration(1024,
432 22,
433 800,
435 MicroSeconds(745 + 192)) &&
436 CheckTxDuration(1025,
438 22,
439 800,
441 MicroSeconds(746 + 192)) &&
442 CheckTxDuration(1026,
444 22,
445 800,
447 MicroSeconds(747 + 192)) &&
448 CheckTxDuration(1023,
450 22,
451 800,
453 MicroSeconds(1488 + 96)) &&
454 CheckTxDuration(1024,
456 22,
457 800,
459 MicroSeconds(1490 + 96)) &&
460 CheckTxDuration(1025,
462 22,
463 800,
465 MicroSeconds(1491 + 96)) &&
466 CheckTxDuration(1026,
468 22,
469 800,
471 MicroSeconds(1493 + 96)) &&
472 CheckTxDuration(1023,
474 22,
475 800,
477 MicroSeconds(1488 + 192)) &&
478 CheckTxDuration(1024,
480 22,
481 800,
483 MicroSeconds(1490 + 192)) &&
484 CheckTxDuration(1025,
486 22,
487 800,
489 MicroSeconds(1491 + 192)) &&
490 CheckTxDuration(1026,
492 22,
493 800,
495 MicroSeconds(1493 + 192)) &&
496 CheckTxDuration(1023,
498 22,
499 800,
501 MicroSeconds(4092 + 96)) &&
502 CheckTxDuration(1024,
504 22,
505 800,
507 MicroSeconds(4096 + 96)) &&
508 CheckTxDuration(1025,
510 22,
511 800,
513 MicroSeconds(4100 + 96)) &&
514 CheckTxDuration(1026,
516 22,
517 800,
519 MicroSeconds(4104 + 96)) &&
520 CheckTxDuration(1023,
522 22,
523 800,
525 MicroSeconds(4092 + 192)) &&
526 CheckTxDuration(1024,
528 22,
529 800,
531 MicroSeconds(4096 + 192)) &&
532 CheckTxDuration(1025,
534 22,
535 800,
537 MicroSeconds(4100 + 192)) &&
538 CheckTxDuration(1026,
540 22,
541 800,
543 MicroSeconds(4104 + 192)) &&
544 CheckTxDuration(1023,
546 22,
547 800,
549 MicroSeconds(8184 + 192)) &&
550 CheckTxDuration(1024,
552 22,
553 800,
555 MicroSeconds(8192 + 192)) &&
556 CheckTxDuration(1025,
558 22,
559 800,
561 MicroSeconds(8200 + 192)) &&
562 CheckTxDuration(1026,
564 22,
565 800,
567 MicroSeconds(8208 + 192)) &&
568 CheckTxDuration(1023,
570 22,
571 800,
573 MicroSeconds(8184 + 192)) &&
574 CheckTxDuration(1024,
576 22,
577 800,
579 MicroSeconds(8192 + 192)) &&
580 CheckTxDuration(1025,
582 22,
583 800,
585 MicroSeconds(8200 + 192)) &&
586 CheckTxDuration(1026,
588 22,
589 800,
591 MicroSeconds(8208 + 192));
592
593 // values from http://mailman.isi.edu/pipermail/ns-developers/2009-July/006226.html
594 retval = retval && CheckTxDuration(14,
596 22,
597 800,
599 MicroSeconds(304));
600
601 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
602 retval = retval &&
603 CheckTxDuration(1536,
605 22,
606 800,
608 MicroSeconds(1310)) &&
611 22,
612 800,
614 MicroSeconds(248)) &&
617 22,
618 800,
620 MicroSeconds(203));
621
622 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b duration failed");
623
624 // 802.11a durations
625 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
626 retval = retval &&
627 CheckTxDuration(1536,
629 20,
630 800,
632 MicroSeconds(248)) &&
635 20,
636 800,
638 MicroSeconds(32)) &&
641 20,
642 800,
644 MicroSeconds(24));
645
646 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11a duration failed");
647
648 // 802.11g durations are same as 802.11a durations but with 6 us signal extension
649 retval = retval &&
650 CheckTxDuration(1536,
652 20,
653 800,
655 MicroSeconds(254)) &&
658 20,
659 800,
661 MicroSeconds(38)) &&
664 20,
665 800,
667 MicroSeconds(30));
668
669 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11g duration failed");
670
671 // 802.11n durations
672 retval =
673 retval &&
674 CheckTxDuration(1536,
676 20,
677 800,
679 MicroSeconds(228)) &&
682 CheckTxDuration(1536,
684 20,
685 400,
687 NanoSeconds(1742400)) &&
690 CheckTxDuration(1536,
692 20,
693 400,
695 NanoSeconds(226800)) &&
698 CheckTxDuration(1536,
700 40,
701 800,
703 MicroSeconds(128)) &&
706 CheckTxDuration(1536,
708 40,
709 400,
711 NanoSeconds(118800)) &&
714
715 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11n duration failed");
716
717 // 802.11ac durations
718 retval = retval &&
719 CheckTxDuration(1536,
721 20,
722 800,
724 MicroSeconds(196)) &&
727 20,
728 800,
730 MicroSeconds(48)) &&
733 20,
734 800,
736 MicroSeconds(40)) &&
737 CheckTxDuration(1536,
739 20,
740 400,
742 MicroSeconds(180)) &&
745 20,
746 400,
748 NanoSeconds(46800)) &&
751 20,
752 400,
754 NanoSeconds(39600)) &&
755 CheckTxDuration(1536,
757 40,
758 800,
760 MicroSeconds(108)) &&
763 40,
764 800,
766 MicroSeconds(40)) &&
769 40,
770 800,
772 MicroSeconds(40)) &&
773 CheckTxDuration(1536,
775 40,
776 400,
778 NanoSeconds(100800)) &&
781 40,
782 400,
784 NanoSeconds(39600)) &&
787 40,
788 400,
790 NanoSeconds(39600)) &&
791 CheckTxDuration(1536,
793 80,
794 800,
796 MicroSeconds(460)) &&
799 80,
800 800,
802 MicroSeconds(60)) &&
805 80,
806 800,
808 MicroSeconds(44)) &&
809 CheckTxDuration(1536,
811 80,
812 400,
814 NanoSeconds(417600)) &&
817 80,
818 400,
820 NanoSeconds(57600)) &&
823 80,
824 400,
826 NanoSeconds(43200)) &&
827 CheckTxDuration(1536,
829 80,
830 800,
832 MicroSeconds(68)) &&
835 80,
836 800,
838 MicroSeconds(40)) &&
841 80,
842 800,
844 MicroSeconds(40)) &&
845 CheckTxDuration(1536,
847 80,
848 400,
850 NanoSeconds(64800)) &&
853 80,
854 400,
856 NanoSeconds(39600)) &&
859 80,
860 400,
862 NanoSeconds(39600)) &&
863 CheckTxDuration(1536,
865 160,
866 800,
868 MicroSeconds(56)) &&
871 160,
872 800,
874 MicroSeconds(40)) &&
877 160,
878 800,
880 MicroSeconds(40)) &&
881 CheckTxDuration(1536,
883 160,
884 400,
886 MicroSeconds(54)) &&
889 160,
890 400,
892 NanoSeconds(39600)) &&
895 160,
896 400,
898 NanoSeconds(39600));
899
900 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ac duration failed");
901
902 // 802.11ax SU durations
903 retval =
904 retval &&
905 CheckTxDuration(1536,
907 20,
908 800,
910 NanoSeconds(1485600)) &&
913 20,
914 800,
916 NanoSeconds(125600)) &&
918 CheckTxDuration(1536,
920 40,
921 800,
923 NanoSeconds(764800)) &&
926 CheckTxDuration(1536,
928 80,
929 800,
931 NanoSeconds(397600)) &&
934 CheckTxDuration(1536,
936 160,
937 800,
939 NanoSeconds(220800)) &&
942 160,
943 800,
945 NanoSeconds(57600)) &&
948 160,
949 800,
951 NanoSeconds(57600)) &&
952 CheckTxDuration(1536,
954 20,
955 1600,
957 NanoSeconds(1570400)) &&
960 20,
961 1600,
963 NanoSeconds(130400)) &&
966 20,
967 1600,
969 NanoSeconds(72800)) &&
970 CheckTxDuration(1536,
972 40,
973 1600,
975 NanoSeconds(807200)) &&
978 40,
979 1600,
981 NanoSeconds(87200)) &&
984 40,
985 1600,
987 NanoSeconds(58400)) &&
988 CheckTxDuration(1536,
990 80,
991 1600,
993 NanoSeconds(418400)) &&
996 80,
997 1600,
999 NanoSeconds(72800)) &&
1000 CheckTxDuration(14,
1002 80,
1003 1600,
1005 NanoSeconds(58400)) &&
1006 CheckTxDuration(1536,
1008 160,
1009 1600,
1011 NanoSeconds(231200)) &&
1012 CheckTxDuration(76,
1014 160,
1015 1600,
1017 NanoSeconds(58400)) &&
1018 CheckTxDuration(14,
1020 160,
1021 1600,
1023 NanoSeconds(58400)) &&
1024 CheckTxDuration(1536,
1026 20,
1027 3200,
1029 MicroSeconds(1740)) &&
1032 CheckTxDuration(1536,
1034 40,
1035 3200,
1037 MicroSeconds(892)) &&
1040 CheckTxDuration(1536,
1042 80,
1043 3200,
1045 MicroSeconds(460)) &&
1048 CheckTxDuration(1536,
1050 160,
1051 3200,
1053 MicroSeconds(252)) &&
1056 CheckTxDuration(1536,
1058 20,
1059 800,
1061 NanoSeconds(139200)) &&
1062 CheckTxDuration(76,
1064 20,
1065 800,
1067 NanoSeconds(57600)) &&
1068 CheckTxDuration(14,
1070 20,
1071 800,
1073 NanoSeconds(57600)) &&
1074 CheckTxDuration(1536,
1076 40,
1077 800,
1079 NanoSeconds(98400)) &&
1080 CheckTxDuration(76,
1082 40,
1083 800,
1085 NanoSeconds(57600)) &&
1086 CheckTxDuration(14,
1088 40,
1089 800,
1091 NanoSeconds(57600)) &&
1092 CheckTxDuration(1536,
1094 80,
1095 800,
1097 NanoSeconds(71200)) &&
1098 CheckTxDuration(76,
1100 80,
1101 800,
1103 NanoSeconds(57600)) &&
1104 CheckTxDuration(14,
1106 80,
1107 800,
1109 NanoSeconds(57600)) &&
1110 CheckTxDuration(1536,
1112 160,
1113 800,
1115 NanoSeconds(57600)) &&
1116 CheckTxDuration(76,
1118 160,
1119 800,
1121 NanoSeconds(57600)) &&
1122 CheckTxDuration(14,
1124 160,
1125 800,
1127 NanoSeconds(57600)) &&
1128 CheckTxDuration(1536,
1130 20,
1131 1600,
1133 NanoSeconds(144800)) &&
1134 CheckTxDuration(76,
1136 20,
1137 1600,
1139 NanoSeconds(58400)) &&
1140 CheckTxDuration(14,
1142 20,
1143 1600,
1145 NanoSeconds(58400)) &&
1146 CheckTxDuration(1536,
1148 40,
1149 1600,
1151 NanoSeconds(101600)) &&
1152 CheckTxDuration(76,
1154 40,
1155 1600,
1157 NanoSeconds(58400)) &&
1158 CheckTxDuration(14,
1160 40,
1161 1600,
1163 NanoSeconds(58400)) &&
1164 CheckTxDuration(1536,
1166 80,
1167 1600,
1169 NanoSeconds(72800)) &&
1170 CheckTxDuration(76,
1172 80,
1173 1600,
1175 NanoSeconds(58400)) &&
1176 CheckTxDuration(14,
1178 80,
1179 1600,
1181 NanoSeconds(58400)) &&
1182 CheckTxDuration(1536,
1184 160,
1185 1600,
1187 NanoSeconds(58400)) &&
1188 CheckTxDuration(76,
1190 160,
1191 1600,
1193 NanoSeconds(58400)) &&
1194 CheckTxDuration(14,
1196 160,
1197 1600,
1199 NanoSeconds(58400)) &&
1200 CheckTxDuration(1536,
1202 20,
1203 3200,
1205 MicroSeconds(156)) &&
1208 CheckTxDuration(1536,
1210 40,
1211 3200,
1213 MicroSeconds(108)) &&
1216 CheckTxDuration(1536,
1218 80,
1219 3200,
1221 MicroSeconds(76)) &&
1224 CheckTxDuration(1536,
1226 160,
1227 3200,
1229 MicroSeconds(60)) &&
1230 CheckTxDuration(76,
1232 160,
1233 3200,
1235 MicroSeconds(60)) &&
1237
1238 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax SU duration failed");
1239
1240 // 802.11ax MU durations
1241 retval = retval &&
1243 std::list<uint32_t>{1536, 1536},
1244 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1245 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1246 40,
1247 800,
1250 1493600)) // equivalent to HE_SU for 20 MHz with 2 extra HE-SIG-B (i.e. 8 us)
1251 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1252 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1253 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1254 40,
1255 800,
1257 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1258 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1259 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1260 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1261 40,
1262 800,
1264 NanoSeconds(1493600));
1265
1266 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax MU duration failed");
1267
1268 // 802.11be MU durations
1269 retval = retval &&
1270 CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1271 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1272 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1273 40,
1274 800,
1276 NanoSeconds(1493600)) // equivalent to 802.11ax MU
1277 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1278 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1279 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1280 40,
1281 800,
1283 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1284 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1285 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1286 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1287 40,
1288 800,
1290 NanoSeconds(1493600));
1291
1292 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11be MU duration failed");
1293
1295}
1296
1304{
1305 public:
1316 HeSigBDurationTest(const std::list<HeMuUserInfo>& userInfos,
1317 const WifiMode& sigBMode,
1318 uint16_t channelWidth,
1319 const RuAllocation& expectedRuAllocation,
1320 const std::pair<std::size_t, std::size_t>& expectedNumUsersPerCc,
1321 Time expectedSigBDuration);
1322
1323 private:
1324 void DoRun() override;
1325
1332
1333 std::list<HeMuUserInfo> m_userInfos;
1337 std::pair<std::size_t, std::size_t>
1340};
1341
1343 const std::list<HeMuUserInfo>& userInfos,
1344 const WifiMode& sigBMode,
1345 uint16_t channelWidth,
1346 const RuAllocation& expectedRuAllocation,
1347 const std::pair<std::size_t, std::size_t>& expectedNumUsersPerCc,
1348 Time expectedSigBDuration)
1349 : TestCase{"Check HE-SIG-B duration computation"},
1350 m_userInfos{userInfos},
1351 m_sigBMode{sigBMode},
1352 m_channelWidth{channelWidth},
1353 m_expectedRuAllocation{expectedRuAllocation},
1354 m_expectedNumUsersPerCc{expectedNumUsersPerCc},
1355 m_expectedSigBDuration{expectedSigBDuration}
1356{
1357}
1358
1361{
1362 WifiTxVector txVector;
1365 txVector.SetGuardInterval(3200);
1366 txVector.SetStbc(0);
1367 txVector.SetNess(0);
1368 std::list<uint16_t> staIds;
1369 uint16_t staId = 1;
1370 for (const auto& userInfo : m_userInfos)
1371 {
1372 txVector.SetHeMuUserInfo(staId, userInfo);
1373 staIds.push_back(staId++);
1374 }
1375 txVector.SetSigBMode(m_sigBMode);
1376 return txVector;
1377}
1378
1379void
1381{
1383 const auto& txVector = BuildTxVector();
1384
1385 // Verify mode for HE-SIG-B field
1386 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1387 m_sigBMode,
1388 "Incorrect mode used to send HE-SIG-B");
1389
1390 // Verify RU_ALLOCATION in TXVECTOR
1391 NS_TEST_EXPECT_MSG_EQ((txVector.GetRuAllocation(0) == m_expectedRuAllocation),
1392 true,
1393 "Incorrect RU_ALLOCATION");
1394
1395 // Verify number of users for content channels 1 and 2
1396 const auto& numUsersPerCc =
1397 HePpdu::GetNumRusPerHeSigBContentChannel(txVector.GetChannelWidth(),
1398 txVector.GetRuAllocation(0));
1399 const auto contentChannels = HePpdu::GetHeSigBContentChannels(txVector, 0);
1400 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1402 "Incorrect number of users in HE-SIG-B content channel 1");
1403 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1405 "Incorrect number of users in HE-SIG-B content channel 2");
1406 NS_TEST_EXPECT_MSG_EQ(contentChannels.at(0).size(),
1408 "Incorrect number of users in HE-SIG-B content channel 1");
1409 NS_TEST_EXPECT_MSG_EQ((contentChannels.size() > 1 ? contentChannels.at(1).size() : 0),
1411 "Incorrect number of users in HE-SIG-B content channel 2");
1412
1413 // Verify total HE-SIG-B duration
1414 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1416 "Incorrect duration for HE-SIG-B");
1417}
1418
1426{
1427 public:
1429 ~PhyHeaderSectionsTest() override;
1430 void DoRun() override;
1431
1432 private:
1442};
1443
1445 : TestCase("PHY header sections consistency")
1446{
1447}
1448
1450{
1451}
1452
1453void
1456{
1457 NS_ASSERT_MSG(obtained.size() == expected.size(),
1458 "The expected map size (" << expected.size() << ") was not obtained ("
1459 << obtained.size() << ")");
1460
1461 auto itObtained = obtained.begin();
1462 auto itExpected = expected.begin();
1463 for (; itObtained != obtained.end() || itExpected != expected.end();)
1464 {
1465 WifiPpduField field = itObtained->first;
1466 auto window = itObtained->second.first;
1467 auto mode = itObtained->second.second;
1468
1469 WifiPpduField fieldRef = itExpected->first;
1470 auto windowRef = itExpected->second.first;
1471 auto modeRef = itExpected->second.second;
1472
1474 fieldRef,
1475 "The expected PPDU field (" << fieldRef << ") was not obtained ("
1476 << field << ")");
1477 NS_TEST_EXPECT_MSG_EQ(window.first,
1478 windowRef.first,
1479 "The expected start time (" << windowRef.first
1480 << ") was not obtained (" << window.first
1481 << ")");
1482 NS_TEST_EXPECT_MSG_EQ(window.second,
1483 windowRef.second,
1484 "The expected stop time (" << windowRef.second
1485 << ") was not obtained (" << window.second
1486 << ")");
1488 modeRef,
1489 "The expected mode (" << modeRef << ") was not obtained (" << mode
1490 << ")");
1491 ++itObtained;
1492 ++itExpected;
1493 }
1494}
1495
1496void
1498{
1499 Time ppduStart = Seconds(1.0);
1500 Ptr<PhyEntity> phyEntity;
1502 WifiTxVector txVector;
1503 WifiMode nonHtMode;
1504
1505 // ==================================================================================
1506 // 11b (HR/DSSS)
1507 phyEntity = Create<DsssPhy>();
1509 txVector.SetChannelWidth(22);
1510
1511 // -> long PPDU format
1513 nonHtMode = DsssPhy::GetDsssRate1Mbps();
1514 sections = {
1515 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(144)}, nonHtMode}},
1517 {{ppduStart + MicroSeconds(144), ppduStart + MicroSeconds(192)}, nonHtMode}},
1518 };
1519 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1520
1521 // -> long PPDU format if data rate is 1 Mbps (even if preamble is tagged short)
1523 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1524
1525 // -> short PPDU format
1527 nonHtMode = DsssPhy::GetDsssRate2Mbps();
1529 sections = {
1530 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(72)}, nonHtMode}},
1532 {{ppduStart + MicroSeconds(72), ppduStart + MicroSeconds(96)}, nonHtMode}},
1533 };
1534 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1535
1536 // ==================================================================================
1537 // 11a (OFDM)
1539
1540 // -> one iteration per variant: default, 10 MHz, and 5 MHz
1541 std::map<OfdmPhyVariant, std::size_t> variants{
1542 // number to use to deduce rate and BW info for each variant
1543 {OFDM_PHY_DEFAULT, 1},
1544 {OFDM_PHY_10_MHZ, 2},
1545 {OFDM_PHY_5_MHZ, 4},
1546 };
1547 for (auto variant : variants)
1548 {
1549 phyEntity = Create<OfdmPhy>(variant.first);
1550 std::size_t ratio = variant.second;
1551 uint16_t bw = 20 / ratio; // MHz
1552 txVector.SetChannelWidth(bw);
1553 txVector.SetMode(OfdmPhy::GetOfdmRate(12000000 / ratio, bw));
1554 nonHtMode = OfdmPhy::GetOfdmRate(6000000 / ratio, bw);
1555 sections = {
1557 {{ppduStart, ppduStart + MicroSeconds(16 * ratio)}, nonHtMode}},
1559 {{ppduStart + MicroSeconds(16 * ratio), ppduStart + MicroSeconds(20 * ratio)},
1560 nonHtMode}},
1561 };
1562 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1563 }
1564
1565 // ==================================================================================
1566 // 11g (ERP-OFDM)
1567 phyEntity = Create<ErpOfdmPhy>();
1568 txVector.SetChannelWidth(20);
1569 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(54000000));
1570 nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps();
1571 sections = {
1572 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1574 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1575 };
1576 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1577
1578 // ==================================================================================
1579 // 11n (HT)
1580 phyEntity = Create<HtPhy>(4);
1581 txVector.SetChannelWidth(20);
1582 txVector.SetMode(HtPhy::GetHtMcs6());
1583 nonHtMode = OfdmPhy::GetOfdmRate6Mbps();
1584 WifiMode htSigMode = nonHtMode;
1585
1586 // -> HT-mixed format for 2 SS and no ESS
1588 txVector.SetNss(2);
1589 txVector.SetNess(0);
1590 sections = {
1591 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1593 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1595 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, htSigMode}},
1597 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(40)}, // 1 HT-STF + 2 HT-LTFs
1598 htSigMode}},
1599 };
1600 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1601 txVector.SetChannelWidth(20); // shouldn't have any impact
1602 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1603
1604 // -> HT-mixed format for 3 SS and 1 ESS
1605 txVector.SetNss(3);
1606 txVector.SetNess(1);
1607 sections[WIFI_PPDU_FIELD_TRAINING] = {
1608 {ppduStart + MicroSeconds(28),
1609 ppduStart + MicroSeconds(52)}, // 1 HT-STF + 5 HT-LTFs (4 data + 1 extension)
1610 htSigMode};
1611 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1612
1613 // ==================================================================================
1614 // 11ac (VHT)
1615 phyEntity = Create<VhtPhy>();
1616 txVector.SetChannelWidth(20);
1617 txVector.SetNess(0);
1618 txVector.SetMode(VhtPhy::GetVhtMcs7());
1619 WifiMode sigAMode = nonHtMode;
1620 WifiMode sigBMode = VhtPhy::GetVhtMcs0();
1621
1622 // -> VHT SU format for 5 SS
1624 txVector.SetNss(5);
1625 sections = {
1626 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1628 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1630 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, sigAMode}},
1632 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(56)}, // 1 VHT-STF + 6 VHT-LTFs
1633 sigAMode}},
1634 };
1635 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1636
1637 // -> VHT SU format for 7 SS
1638 txVector.SetNss(7);
1639 sections[WIFI_PPDU_FIELD_TRAINING] = {
1640 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(64)}, // 1 VHT-STF + 8 VHT-LTFs
1641 sigAMode};
1642 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1643
1644 // -> VHT MU format for 3 SS
1646 txVector.SetNss(3);
1647 sections[WIFI_PPDU_FIELD_TRAINING] = {
1648 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(48)}, // 1 VHT-STF + 4 VHT-LTFs
1649 sigAMode};
1650 sections[WIFI_PPDU_FIELD_SIG_B] = {{ppduStart + MicroSeconds(48), ppduStart + MicroSeconds(52)},
1651 sigBMode};
1652 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1653 txVector.SetChannelWidth(80); // shouldn't have any impact
1654 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1655
1656 // ==================================================================================
1657 // 11ax (HE)
1658 phyEntity = Create<HePhy>();
1659 txVector.SetChannelWidth(20);
1660 txVector.SetNss(2); // HE-LTF duration assumed to be always 8 us for the time being (see note in
1661 // HePhy::GetTrainingDuration)
1662 txVector.SetMode(HePhy::GetHeMcs9());
1663 std::map<uint16_t, HeMuUserInfo> userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1664 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1665 sigAMode = HePhy::GetVhtMcs0();
1666 sigBMode = HePhy::GetVhtMcs4(); // because of first user info map
1667
1668 // -> HE SU format
1670 sections = {
1671 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1673 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(24)}, // L-SIG + RL-SIG
1674 nonHtMode}},
1676 {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)}, sigAMode}},
1678 {{ppduStart + MicroSeconds(32),
1679 ppduStart + MicroSeconds(52)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1680 sigAMode}},
1681 };
1682 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1683
1684 // -> HE ER SU format
1686 sections[WIFI_PPDU_FIELD_SIG_A] = {
1687 {ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(40)}, // 16 us HE-SIG-A
1688 sigAMode};
1689 sections[WIFI_PPDU_FIELD_TRAINING] = {
1690 {ppduStart + MicroSeconds(40),
1691 ppduStart + MicroSeconds(60)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1692 sigAMode};
1693 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1694
1695 // -> HE TB format
1697 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1698 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1699 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1700 sigAMode};
1701 sections[WIFI_PPDU_FIELD_TRAINING] = {
1702 {ppduStart + MicroSeconds(32),
1703 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 8 us) + 2 HE-LTFs (@ 8 us)
1704 sigAMode};
1705 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1706
1707 // -> HE MU format
1709 txVector.SetSigBMode(sigBMode);
1710 txVector.SetRuAllocation({96}, 0);
1711 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1712 sigAMode};
1713 sections[WIFI_PPDU_FIELD_SIG_B] = {
1714 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1715 sigBMode};
1716 sections[WIFI_PPDU_FIELD_TRAINING] = {
1717 {ppduStart + MicroSeconds(36),
1718 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1719 sigBMode};
1720 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1721 txVector.SetChannelWidth(160); // shouldn't have any impact
1722 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113}, 0);
1723
1724 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1725
1726 // ==================================================================================
1727 // 11be (EHT)
1728 sections.erase(WIFI_PPDU_FIELD_SIG_A); // FIXME: do we keep using separate type for 11be?
1729 sections.erase(WIFI_PPDU_FIELD_SIG_B); // FIXME: do we keep using separate type for 11be?
1730 phyEntity = Create<EhtPhy>();
1731 txVector.SetChannelWidth(20);
1732 txVector.SetNss(2); // EHT-LTF duration assumed to be always 8 us for the time being (see note
1733 // in HePhy::GetTrainingDuration)
1734 txVector.SetMode(EhtPhy::GetEhtMcs9());
1735 userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1736 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1737 WifiMode uSigMode = EhtPhy::GetVhtMcs0();
1738 WifiMode ehtSigMode = EhtPhy::GetVhtMcs4(); // because of first user info map
1739
1740 // -> EHT TB format
1742 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1743 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1744 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1745 uSigMode};
1746 sections[WIFI_PPDU_FIELD_TRAINING] = {
1747 {ppduStart + MicroSeconds(32),
1748 ppduStart + MicroSeconds(56)}, // 1 EHT-STF (@ 8 us) + 2 EHT-LTFs (@ 8 us)
1749 uSigMode};
1750 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1751
1752 // -> EHT MU format
1754 txVector.SetEhtPpduType(0); // EHT MU transmission
1755 txVector.SetRuAllocation({96}, 0);
1756 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1757 uSigMode};
1758 sections[WIFI_PPDU_FIELD_EHT_SIG] = {
1759 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1760 ehtSigMode};
1761 sections[WIFI_PPDU_FIELD_TRAINING] = {
1762 {ppduStart + MicroSeconds(36),
1763 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1764 ehtSigMode};
1765 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1766 txVector.SetChannelWidth(160); // shouldn't have any impact
1767 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113}, 0);
1768
1769 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1770}
1771
1779{
1780 public:
1782};
1783
1785 : TestSuite("wifi-devices-tx-duration", UNIT)
1786{
1788
1790
1791 // 20 MHz band, even number of users per HE-SIG-B content channel
1793 {{{HeRu::RU_106_TONE, 1, true}, 11, 1}, {{HeRu::RU_106_TONE, 2, true}, 10, 4}},
1795 20,
1796 {96},
1797 std::make_pair(2, 0), // both users in HE-SIG-B content channel 1
1798 MicroSeconds(4)), // one OFDM symbol;
1800
1801 // 40 MHz band, even number of users per HE-SIG-B content channel
1803 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1804 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1805 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1806 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1807 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1808 {{HeRu::RU_52_TONE, 8, true}, 6, 2}},
1810 40,
1811 {96, 112},
1812 std::make_pair(2, 4), // two users in HE-SIG-B content channel 1 and
1813 // four users in HE-SIG-B content channel 2
1814 MicroSeconds(4)), // one OFDM symbol;
1816
1817 // 40 MHz band, odd number of users per HE-SIG-B content channel
1819 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1820 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1821 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1822 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1823 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1824 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1825 {{HeRu::RU_26_TONE, 14, true}, 3, 1}},
1827 40,
1828 {96, 15},
1829 std::make_pair(2, 5), // two users in HE-SIG-B content channel 1 and
1830 // five users in HE-SIG-B content channel 2
1831 MicroSeconds(8)), // two OFDM symbols
1833
1834 // 80 MHz band
1836 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1837 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1838 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1839 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1840 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1841 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1842 {{HeRu::RU_26_TONE, 14, true}, 3, 1},
1843 {{HeRu::RU_242_TONE, 3, true}, 1, 1},
1844 {{HeRu::RU_242_TONE, 4, true}, 4, 1}},
1846 80,
1847 {96, 15, 192, 192},
1848 std::make_pair(3, 6), // three users in HE-SIG-B content channel 1
1849 // and six users in HE-SIG-B content channel 2
1850 MicroSeconds(16)), // four OFDM symbols
1852
1853 // 160 MHz band
1855 new HeSigBDurationTest({{{HeRu::RU_106_TONE, 1, true}, 11, 1},
1856 {{HeRu::RU_106_TONE, 2, true}, 10, 4},
1857 {{HeRu::RU_52_TONE, 5, true}, 4, 1},
1858 {{HeRu::RU_52_TONE, 6, true}, 6, 2},
1859 {{HeRu::RU_52_TONE, 7, true}, 5, 3},
1860 {{HeRu::RU_52_TONE, 8, true}, 6, 2},
1861 {{HeRu::RU_26_TONE, 14, true}, 3, 1},
1862 {{HeRu::RU_242_TONE, 3, true}, 1, 1},
1863 {{HeRu::RU_242_TONE, 4, true}, 4, 1},
1864 {{HeRu::RU_996_TONE, 1, false}, 1, 1}},
1866 160,
1867 {96, 15, 192, 192, 208, 208, 208, 208},
1868 std::make_pair(4, 7), // four users in HE-SIG-B content channel 1 and
1869 // seven users in HE-SIG-B content channel 2
1870 MicroSeconds(20)), // five OFDM symbols
1872
1873 // 20 MHz band, one unallocated RU at the middle
1875 new HeSigBDurationTest({{{HeRu::RU_26_TONE, 1, true}, 11, 1},
1876 {{HeRu::RU_26_TONE, 2, true}, 11, 1},
1877 {{HeRu::RU_26_TONE, 3, true}, 11, 1},
1878 {{HeRu::RU_26_TONE, 4, true}, 11, 1},
1879 {{HeRu::RU_26_TONE, 6, true}, 11, 1},
1880 {{HeRu::RU_26_TONE, 7, true}, 11, 1},
1881 {{HeRu::RU_26_TONE, 8, true}, 11, 1},
1882 {{HeRu::RU_26_TONE, 9, true}, 11, 1}},
1884 20,
1885 {0},
1886 std::make_pair(9, 0), // 9 users in HE-SIG-B content channel 1
1887 MicroSeconds(8)), // two OFDM symbols;
1889
1890 // 40 MHz band, unallocated RUs at the begin and at the end of the first 20 MHz subband and in
1891 // the middle of the second 20 MHz subband
1893 new HeSigBDurationTest({{{HeRu::RU_52_TONE, 2, true}, 10, 1},
1894 {{HeRu::RU_52_TONE, 3, true}, 10, 2},
1895 {{HeRu::RU_52_TONE, 5, true}, 11, 1},
1896 {{HeRu::RU_52_TONE, 8, true}, 11, 2}},
1898 40,
1899 {112, 112},
1900 std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
1901 MicroSeconds(4)), // two OFDM symbols;
1903
1904 // 40 MHz band, one unallocated RUs in the first 20 MHz subband and two unallocated RUs in
1905 // second 20 MHz subband
1907 new HeSigBDurationTest({{{HeRu::RU_52_TONE, 1, true}, 10, 1},
1908 {{HeRu::RU_52_TONE, 2, true}, 10, 2},
1909 {{HeRu::RU_52_TONE, 3, true}, 11, 1},
1910 {{HeRu::RU_52_TONE, 5, true}, 11, 2},
1911 {{HeRu::RU_52_TONE, 6, true}, 11, 3}},
1913 40,
1914 {112, 112},
1915 std::make_pair(4, 4), // 4 users in both HE-SIG-B content channels
1916 MicroSeconds(4)), // two OFDM symbols;
1918}
1919
HE-SIG-B duration test.
std::list< HeMuUserInfo > m_userInfos
HE MU specific per-user information.
HeSigBDurationTest(const std::list< HeMuUserInfo > &userInfos, const WifiMode &sigBMode, uint16_t channelWidth, 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)
Get the number of RUs per HE-SIG-B content channel.
Definition: he-ppdu.cc:449
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:497
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:453
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:762
@ RU_26_TONE
Definition: he-ru.h:42
@ 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
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:411
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:327
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
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
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:1496
static const Ptr< const PhyEntity > GetStaticPhyEntity(WifiModulationClass modulation)
Get the implemented PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:704
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.
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.
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:251
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
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