A Discrete-Event Network Simulator
API
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/erp-ofdm-phy.h"
24#include "ns3/he-ru.h"
25#include "ns3/log.h"
26#include "ns3/packet.h"
27#include "ns3/simulator.h"
28#include "ns3/test.h"
29#include "ns3/wifi-psdu.h"
30#include "ns3/yans-wifi-phy.h"
31
32#include <numeric>
33
34using namespace ns3;
35
36NS_LOG_COMPONENT_DEFINE("InterferenceHelperTxDurationTest");
37
45{
46 public:
48 ~TxDurationTest() override;
49 void DoRun() override;
50
51 private:
66 WifiMode payloadMode,
67 uint16_t channelWidth,
68 uint16_t guardInterval,
69 WifiPreamble preamble,
70 Time knownDuration);
71
85 bool CheckTxDuration(uint32_t size,
86 WifiMode payloadMode,
87 uint16_t channelWidth,
88 uint16_t guardInterval,
89 WifiPreamble preamble,
90 Time knownDuration);
91
105 static bool CheckMuTxDuration(std::list<uint32_t> sizes,
106 std::list<HeMuUserInfo> userInfos,
107 uint16_t channelWidth,
108 uint16_t guardInterval,
109 WifiPreamble preamble,
110 Time knownDuration);
111
126 static Time CalculateTxDurationUsingList(std::list<uint32_t> sizes,
127 std::list<uint16_t> staIds,
128 WifiTxVector txVector,
129 WifiPhyBand band);
130};
131
133 : TestCase("Wifi TX Duration")
134{
135}
136
138{
139}
140
141bool
143 WifiMode payloadMode,
144 uint16_t channelWidth,
145 uint16_t guardInterval,
146 WifiPreamble preamble,
147 Time knownDuration)
148{
149 WifiTxVector txVector;
150 txVector.SetMode(payloadMode);
151 txVector.SetPreambleType(preamble);
152 txVector.SetChannelWidth(channelWidth);
153 txVector.SetGuardInterval(guardInterval);
154 txVector.SetNss(1);
155 txVector.SetStbc(0);
156 txVector.SetNess(0);
157 std::list<WifiPhyBand> testedBands;
158 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
159 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
160 {
161 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
162 }
163 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
164 {
165 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
166 }
167 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
168 {
169 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
170 }
171 for (auto& testedBand : testedBands)
172 {
173 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
174 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
175 {
176 knownDuration +=
177 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
178 }
179 Time calculatedDuration = phy->GetPayloadDuration(size, txVector, testedBand);
180 if (calculatedDuration != knownDuration)
181 {
182 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
183 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
184 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
185 << " known=" << knownDuration << " calculated=" << calculatedDuration
186 << std::endl;
187 return false;
188 }
189 }
190 return true;
191}
192
193bool
195 WifiMode payloadMode,
196 uint16_t channelWidth,
197 uint16_t guardInterval,
198 WifiPreamble preamble,
199 Time knownDuration)
200{
201 WifiTxVector txVector;
202 txVector.SetMode(payloadMode);
203 txVector.SetPreambleType(preamble);
204 txVector.SetChannelWidth(channelWidth);
205 txVector.SetGuardInterval(guardInterval);
206 txVector.SetNss(1);
207 txVector.SetStbc(0);
208 txVector.SetNess(0);
209 std::list<WifiPhyBand> testedBands;
210 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
211 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM)
212 {
213 testedBands.push_back(WIFI_PHY_BAND_5GHZ);
214 }
215 if (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_HE)
216 {
217 testedBands.push_back(WIFI_PHY_BAND_6GHZ);
218 }
219 if (payloadMode.GetModulationClass() != WIFI_MOD_CLASS_VHT)
220 {
221 testedBands.push_back(WIFI_PHY_BAND_2_4GHZ);
222 }
223 for (auto& testedBand : testedBands)
224 {
225 if ((testedBand == WIFI_PHY_BAND_2_4GHZ) &&
226 (payloadMode.GetModulationClass() >= WIFI_MOD_CLASS_OFDM))
227 {
228 knownDuration +=
229 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
230 }
231 Time calculatedDuration = phy->CalculateTxDuration(size, txVector, testedBand);
232 Time calculatedDurationUsingList =
233 CalculateTxDurationUsingList(std::list<uint32_t>{size},
234 std::list<uint16_t>{SU_STA_ID},
235 txVector,
236 testedBand);
237 if (calculatedDuration != knownDuration ||
238 calculatedDuration != calculatedDurationUsingList)
239 {
240 std::cerr << "size=" << size << " band=" << testedBand << " mode=" << payloadMode
241 << " channelWidth=" << +channelWidth << " guardInterval=" << guardInterval
242 << " datarate=" << payloadMode.GetDataRate(channelWidth, guardInterval, 1)
243 << " preamble=" << preamble << " known=" << knownDuration
244 << " calculated=" << calculatedDuration
245 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
246 return false;
247 }
248 }
249 return true;
250}
251
252bool
253TxDurationTest::CheckMuTxDuration(std::list<uint32_t> sizes,
254 std::list<HeMuUserInfo> userInfos,
255 uint16_t channelWidth,
256 uint16_t guardInterval,
257 WifiPreamble preamble,
258 Time knownDuration)
259{
260 NS_ASSERT(sizes.size() == userInfos.size() && sizes.size() > 1);
262 channelWidth < std::accumulate(
263 std::begin(userInfos),
264 std::end(userInfos),
265 0,
266 [](const uint16_t prevBw, const HeMuUserInfo& info) {
267 return prevBw + HeRu::GetBandwidth(info.ru.GetRuType());
268 }),
269 "Cannot accommodate all the RUs in the provided band"); // MU-MIMO (for which allocations
270 // use the same RU) is not supported
271 WifiTxVector txVector;
272 txVector.SetPreambleType(preamble);
273 txVector.SetChannelWidth(channelWidth);
274 txVector.SetGuardInterval(guardInterval);
275 txVector.SetStbc(0);
276 txVector.SetNess(0);
277 if (IsEht(preamble))
278 {
279 txVector.SetEhtPpduType(0);
280 }
281 std::list<uint16_t> staIds;
282
283 uint16_t staId = 1;
284 for (const auto& userInfo : userInfos)
285 {
286 txVector.SetHeMuUserInfo(staId, userInfo);
287 staIds.push_back(staId++);
288 }
289 txVector.SetSigBMode(VhtPhy::GetVhtMcs0());
290 txVector.SetRuAllocation({192, 192});
291
292 Ptr<YansWifiPhy> phy = CreateObject<YansWifiPhy>();
293 std::list<WifiPhyBand> testedBands{
296 WIFI_PHY_BAND_2_4GHZ}; // Durations vary depending on frequency; test also 2.4 GHz (bug
297 // 1971)
298 for (auto& testedBand : testedBands)
299 {
300 if (testedBand == WIFI_PHY_BAND_2_4GHZ)
301 {
302 knownDuration +=
303 MicroSeconds(6); // 2.4 GHz band should be at the end of the bands to test
304 }
305 Time calculatedDuration = NanoSeconds(0);
306 uint32_t longuestSize = 0;
307 auto iterStaId = staIds.begin();
308 for (auto& size : sizes)
309 {
310 Time ppduDurationForSta =
311 phy->CalculateTxDuration(size, txVector, testedBand, *iterStaId);
312 if (ppduDurationForSta > calculatedDuration)
313 {
314 calculatedDuration = ppduDurationForSta;
315 staId = *iterStaId;
316 longuestSize = size;
317 }
318 ++iterStaId;
319 }
320 Time calculatedDurationUsingList =
321 CalculateTxDurationUsingList(sizes, staIds, txVector, testedBand);
322 if (calculatedDuration != knownDuration ||
323 calculatedDuration != calculatedDurationUsingList)
324 {
325 std::cerr << "size=" << longuestSize << " band=" << testedBand << " staId=" << staId
326 << " nss=" << +txVector.GetNss(staId) << " mode=" << txVector.GetMode(staId)
327 << " channelWidth=" << channelWidth << " guardInterval=" << guardInterval
328 << " datarate="
329 << txVector.GetMode(staId).GetDataRate(channelWidth,
330 guardInterval,
331 txVector.GetNss(staId))
332 << " known=" << knownDuration << " calculated=" << calculatedDuration
333 << " calculatedUsingList=" << calculatedDurationUsingList << std::endl;
334 return false;
335 }
336 }
337 return true;
338}
339
340Time
342 std::list<uint16_t> staIds,
343 WifiTxVector txVector,
344 WifiPhyBand band)
345{
346 NS_ASSERT(sizes.size() == staIds.size());
347 WifiConstPsduMap psduMap;
348 auto itStaId = staIds.begin();
349 WifiMacHeader hdr;
350 hdr.SetType(WIFI_MAC_CTL_ACK); // so that size may not be empty while being as short as possible
351 for (auto& size : sizes)
352 {
353 // MAC header and FCS are to deduce from size
354 psduMap[*itStaId++] =
355 Create<WifiPsdu>(Create<Packet>(size - hdr.GetSerializedSize() - 4), hdr);
356 }
357 return WifiPhy::CalculateTxDuration(psduMap, txVector, band);
358}
359
360void
362{
363 bool retval = true;
364
365 // IEEE Std 802.11-2007 Table 18-2 "Example of LENGTH calculations for CCK"
366 retval = retval &&
368 DsssPhy::GetDsssRate11Mbps(),
369 22,
370 800,
372 MicroSeconds(744)) &&
374 DsssPhy::GetDsssRate11Mbps(),
375 22,
376 800,
378 MicroSeconds(745)) &&
380 DsssPhy::GetDsssRate11Mbps(),
381 22,
382 800,
384 MicroSeconds(746)) &&
386 DsssPhy::GetDsssRate11Mbps(),
387 22,
388 800,
390 MicroSeconds(747));
391
392 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b CCK duration failed");
393
394 // Similar, but we add PHY preamble and header durations
395 // and we test different rates.
396 // The payload durations for modes other than 11mbb have been
397 // calculated by hand according to IEEE Std 802.11-2007 18.2.3.5
398 retval = retval &&
399 CheckTxDuration(1023,
400 DsssPhy::GetDsssRate11Mbps(),
401 22,
402 800,
404 MicroSeconds(744 + 96)) &&
405 CheckTxDuration(1024,
406 DsssPhy::GetDsssRate11Mbps(),
407 22,
408 800,
410 MicroSeconds(745 + 96)) &&
411 CheckTxDuration(1025,
412 DsssPhy::GetDsssRate11Mbps(),
413 22,
414 800,
416 MicroSeconds(746 + 96)) &&
417 CheckTxDuration(1026,
418 DsssPhy::GetDsssRate11Mbps(),
419 22,
420 800,
422 MicroSeconds(747 + 96)) &&
423 CheckTxDuration(1023,
424 DsssPhy::GetDsssRate11Mbps(),
425 22,
426 800,
428 MicroSeconds(744 + 192)) &&
429 CheckTxDuration(1024,
430 DsssPhy::GetDsssRate11Mbps(),
431 22,
432 800,
434 MicroSeconds(745 + 192)) &&
435 CheckTxDuration(1025,
436 DsssPhy::GetDsssRate11Mbps(),
437 22,
438 800,
440 MicroSeconds(746 + 192)) &&
441 CheckTxDuration(1026,
442 DsssPhy::GetDsssRate11Mbps(),
443 22,
444 800,
446 MicroSeconds(747 + 192)) &&
447 CheckTxDuration(1023,
448 DsssPhy::GetDsssRate5_5Mbps(),
449 22,
450 800,
452 MicroSeconds(1488 + 96)) &&
453 CheckTxDuration(1024,
454 DsssPhy::GetDsssRate5_5Mbps(),
455 22,
456 800,
458 MicroSeconds(1490 + 96)) &&
459 CheckTxDuration(1025,
460 DsssPhy::GetDsssRate5_5Mbps(),
461 22,
462 800,
464 MicroSeconds(1491 + 96)) &&
465 CheckTxDuration(1026,
466 DsssPhy::GetDsssRate5_5Mbps(),
467 22,
468 800,
470 MicroSeconds(1493 + 96)) &&
471 CheckTxDuration(1023,
472 DsssPhy::GetDsssRate5_5Mbps(),
473 22,
474 800,
476 MicroSeconds(1488 + 192)) &&
477 CheckTxDuration(1024,
478 DsssPhy::GetDsssRate5_5Mbps(),
479 22,
480 800,
482 MicroSeconds(1490 + 192)) &&
483 CheckTxDuration(1025,
484 DsssPhy::GetDsssRate5_5Mbps(),
485 22,
486 800,
488 MicroSeconds(1491 + 192)) &&
489 CheckTxDuration(1026,
490 DsssPhy::GetDsssRate5_5Mbps(),
491 22,
492 800,
494 MicroSeconds(1493 + 192)) &&
495 CheckTxDuration(1023,
496 DsssPhy::GetDsssRate2Mbps(),
497 22,
498 800,
500 MicroSeconds(4092 + 96)) &&
501 CheckTxDuration(1024,
502 DsssPhy::GetDsssRate2Mbps(),
503 22,
504 800,
506 MicroSeconds(4096 + 96)) &&
507 CheckTxDuration(1025,
508 DsssPhy::GetDsssRate2Mbps(),
509 22,
510 800,
512 MicroSeconds(4100 + 96)) &&
513 CheckTxDuration(1026,
514 DsssPhy::GetDsssRate2Mbps(),
515 22,
516 800,
518 MicroSeconds(4104 + 96)) &&
519 CheckTxDuration(1023,
520 DsssPhy::GetDsssRate2Mbps(),
521 22,
522 800,
524 MicroSeconds(4092 + 192)) &&
525 CheckTxDuration(1024,
526 DsssPhy::GetDsssRate2Mbps(),
527 22,
528 800,
530 MicroSeconds(4096 + 192)) &&
531 CheckTxDuration(1025,
532 DsssPhy::GetDsssRate2Mbps(),
533 22,
534 800,
536 MicroSeconds(4100 + 192)) &&
537 CheckTxDuration(1026,
538 DsssPhy::GetDsssRate2Mbps(),
539 22,
540 800,
542 MicroSeconds(4104 + 192)) &&
543 CheckTxDuration(1023,
544 DsssPhy::GetDsssRate1Mbps(),
545 22,
546 800,
548 MicroSeconds(8184 + 192)) &&
549 CheckTxDuration(1024,
550 DsssPhy::GetDsssRate1Mbps(),
551 22,
552 800,
554 MicroSeconds(8192 + 192)) &&
555 CheckTxDuration(1025,
556 DsssPhy::GetDsssRate1Mbps(),
557 22,
558 800,
560 MicroSeconds(8200 + 192)) &&
561 CheckTxDuration(1026,
562 DsssPhy::GetDsssRate1Mbps(),
563 22,
564 800,
566 MicroSeconds(8208 + 192)) &&
567 CheckTxDuration(1023,
568 DsssPhy::GetDsssRate1Mbps(),
569 22,
570 800,
572 MicroSeconds(8184 + 192)) &&
573 CheckTxDuration(1024,
574 DsssPhy::GetDsssRate1Mbps(),
575 22,
576 800,
578 MicroSeconds(8192 + 192)) &&
579 CheckTxDuration(1025,
580 DsssPhy::GetDsssRate1Mbps(),
581 22,
582 800,
584 MicroSeconds(8200 + 192)) &&
585 CheckTxDuration(1026,
586 DsssPhy::GetDsssRate1Mbps(),
587 22,
588 800,
590 MicroSeconds(8208 + 192));
591
592 // values from http://mailman.isi.edu/pipermail/ns-developers/2009-July/006226.html
593 retval = retval && CheckTxDuration(14,
594 DsssPhy::GetDsssRate1Mbps(),
595 22,
596 800,
598 MicroSeconds(304));
599
600 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
601 retval = retval &&
602 CheckTxDuration(1536,
603 DsssPhy::GetDsssRate11Mbps(),
604 22,
605 800,
607 MicroSeconds(1310)) &&
609 DsssPhy::GetDsssRate11Mbps(),
610 22,
611 800,
613 MicroSeconds(248)) &&
615 DsssPhy::GetDsssRate11Mbps(),
616 22,
617 800,
619 MicroSeconds(203));
620
621 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11b duration failed");
622
623 // 802.11a durations
624 // values from http://www.oreillynet.com/pub/a/wireless/2003/08/08/wireless_throughput.html
625 retval = retval &&
626 CheckTxDuration(1536,
627 OfdmPhy::GetOfdmRate54Mbps(),
628 20,
629 800,
631 MicroSeconds(248)) &&
633 OfdmPhy::GetOfdmRate54Mbps(),
634 20,
635 800,
637 MicroSeconds(32)) &&
639 OfdmPhy::GetOfdmRate54Mbps(),
640 20,
641 800,
643 MicroSeconds(24));
644
645 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11a duration failed");
646
647 // 802.11g durations are same as 802.11a durations but with 6 us signal extension
648 retval = retval &&
649 CheckTxDuration(1536,
650 ErpOfdmPhy::GetErpOfdmRate54Mbps(),
651 20,
652 800,
654 MicroSeconds(254)) &&
656 ErpOfdmPhy::GetErpOfdmRate54Mbps(),
657 20,
658 800,
660 MicroSeconds(38)) &&
662 ErpOfdmPhy::GetErpOfdmRate54Mbps(),
663 20,
664 800,
666 MicroSeconds(30));
667
668 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11g duration failed");
669
670 // 802.11n durations
671 retval =
672 retval &&
673 CheckTxDuration(1536,
674 HtPhy::GetHtMcs7(),
675 20,
676 800,
678 MicroSeconds(228)) &&
679 CheckTxDuration(76, HtPhy::GetHtMcs7(), 20, 800, WIFI_PREAMBLE_HT_MF, MicroSeconds(48)) &&
680 CheckTxDuration(14, HtPhy::GetHtMcs7(), 20, 800, WIFI_PREAMBLE_HT_MF, MicroSeconds(40)) &&
681 CheckTxDuration(1536,
682 HtPhy::GetHtMcs0(),
683 20,
684 400,
686 NanoSeconds(1742400)) &&
687 CheckTxDuration(76, HtPhy::GetHtMcs0(), 20, 400, WIFI_PREAMBLE_HT_MF, MicroSeconds(126)) &&
688 CheckTxDuration(14, HtPhy::GetHtMcs0(), 20, 400, WIFI_PREAMBLE_HT_MF, NanoSeconds(57600)) &&
689 CheckTxDuration(1536,
690 HtPhy::GetHtMcs6(),
691 20,
692 400,
694 NanoSeconds(226800)) &&
695 CheckTxDuration(76, HtPhy::GetHtMcs6(), 20, 400, WIFI_PREAMBLE_HT_MF, NanoSeconds(46800)) &&
696 CheckTxDuration(14, HtPhy::GetHtMcs6(), 20, 400, WIFI_PREAMBLE_HT_MF, NanoSeconds(39600)) &&
697 CheckTxDuration(1536,
698 HtPhy::GetHtMcs7(),
699 40,
700 800,
702 MicroSeconds(128)) &&
703 CheckTxDuration(76, HtPhy::GetHtMcs7(), 40, 800, WIFI_PREAMBLE_HT_MF, MicroSeconds(44)) &&
704 CheckTxDuration(14, HtPhy::GetHtMcs7(), 40, 800, WIFI_PREAMBLE_HT_MF, MicroSeconds(40)) &&
705 CheckTxDuration(1536,
706 HtPhy::GetHtMcs7(),
707 40,
708 400,
710 NanoSeconds(118800)) &&
711 CheckTxDuration(76, HtPhy::GetHtMcs7(), 40, 400, WIFI_PREAMBLE_HT_MF, NanoSeconds(43200)) &&
712 CheckTxDuration(14, HtPhy::GetHtMcs7(), 40, 400, WIFI_PREAMBLE_HT_MF, NanoSeconds(39600));
713
714 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11n duration failed");
715
716 // 802.11ac durations
717 retval = retval &&
718 CheckTxDuration(1536,
719 VhtPhy::GetVhtMcs8(),
720 20,
721 800,
723 MicroSeconds(196)) &&
725 VhtPhy::GetVhtMcs8(),
726 20,
727 800,
729 MicroSeconds(48)) &&
731 VhtPhy::GetVhtMcs8(),
732 20,
733 800,
735 MicroSeconds(40)) &&
736 CheckTxDuration(1536,
737 VhtPhy::GetVhtMcs8(),
738 20,
739 400,
741 MicroSeconds(180)) &&
743 VhtPhy::GetVhtMcs8(),
744 20,
745 400,
747 NanoSeconds(46800)) &&
749 VhtPhy::GetVhtMcs8(),
750 20,
751 400,
753 NanoSeconds(39600)) &&
754 CheckTxDuration(1536,
755 VhtPhy::GetVhtMcs9(),
756 40,
757 800,
759 MicroSeconds(108)) &&
761 VhtPhy::GetVhtMcs9(),
762 40,
763 800,
765 MicroSeconds(40)) &&
767 VhtPhy::GetVhtMcs9(),
768 40,
769 800,
771 MicroSeconds(40)) &&
772 CheckTxDuration(1536,
773 VhtPhy::GetVhtMcs9(),
774 40,
775 400,
777 NanoSeconds(100800)) &&
779 VhtPhy::GetVhtMcs9(),
780 40,
781 400,
783 NanoSeconds(39600)) &&
785 VhtPhy::GetVhtMcs9(),
786 40,
787 400,
789 NanoSeconds(39600)) &&
790 CheckTxDuration(1536,
791 VhtPhy::GetVhtMcs0(),
792 80,
793 800,
795 MicroSeconds(460)) &&
797 VhtPhy::GetVhtMcs0(),
798 80,
799 800,
801 MicroSeconds(60)) &&
803 VhtPhy::GetVhtMcs0(),
804 80,
805 800,
807 MicroSeconds(44)) &&
808 CheckTxDuration(1536,
809 VhtPhy::GetVhtMcs0(),
810 80,
811 400,
813 NanoSeconds(417600)) &&
815 VhtPhy::GetVhtMcs0(),
816 80,
817 400,
819 NanoSeconds(57600)) &&
821 VhtPhy::GetVhtMcs0(),
822 80,
823 400,
825 NanoSeconds(43200)) &&
826 CheckTxDuration(1536,
827 VhtPhy::GetVhtMcs9(),
828 80,
829 800,
831 MicroSeconds(68)) &&
833 VhtPhy::GetVhtMcs9(),
834 80,
835 800,
837 MicroSeconds(40)) &&
839 VhtPhy::GetVhtMcs9(),
840 80,
841 800,
843 MicroSeconds(40)) &&
844 CheckTxDuration(1536,
845 VhtPhy::GetVhtMcs9(),
846 80,
847 400,
849 NanoSeconds(64800)) &&
851 VhtPhy::GetVhtMcs9(),
852 80,
853 400,
855 NanoSeconds(39600)) &&
857 VhtPhy::GetVhtMcs9(),
858 80,
859 400,
861 NanoSeconds(39600)) &&
862 CheckTxDuration(1536,
863 VhtPhy::GetVhtMcs8(),
864 160,
865 800,
867 MicroSeconds(56)) &&
869 VhtPhy::GetVhtMcs8(),
870 160,
871 800,
873 MicroSeconds(40)) &&
875 VhtPhy::GetVhtMcs8(),
876 160,
877 800,
879 MicroSeconds(40)) &&
880 CheckTxDuration(1536,
881 VhtPhy::GetVhtMcs8(),
882 160,
883 400,
885 MicroSeconds(54)) &&
887 VhtPhy::GetVhtMcs8(),
888 160,
889 400,
891 NanoSeconds(39600)) &&
893 VhtPhy::GetVhtMcs8(),
894 160,
895 400,
897 NanoSeconds(39600));
898
899 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ac duration failed");
900
901 // 802.11ax SU durations
902 retval =
903 retval &&
904 CheckTxDuration(1536,
905 HePhy::GetHeMcs0(),
906 20,
907 800,
909 NanoSeconds(1485600)) &&
911 HePhy::GetHeMcs0(),
912 20,
913 800,
915 NanoSeconds(125600)) &&
916 CheckTxDuration(14, HePhy::GetHeMcs0(), 20, 800, WIFI_PREAMBLE_HE_SU, NanoSeconds(71200)) &&
917 CheckTxDuration(1536,
918 HePhy::GetHeMcs0(),
919 40,
920 800,
922 NanoSeconds(764800)) &&
923 CheckTxDuration(76, HePhy::GetHeMcs0(), 40, 800, WIFI_PREAMBLE_HE_SU, NanoSeconds(84800)) &&
924 CheckTxDuration(14, HePhy::GetHeMcs0(), 40, 800, WIFI_PREAMBLE_HE_SU, NanoSeconds(57600)) &&
925 CheckTxDuration(1536,
926 HePhy::GetHeMcs0(),
927 80,
928 800,
930 NanoSeconds(397600)) &&
931 CheckTxDuration(76, HePhy::GetHeMcs0(), 80, 800, WIFI_PREAMBLE_HE_SU, NanoSeconds(71200)) &&
932 CheckTxDuration(14, HePhy::GetHeMcs0(), 80, 800, WIFI_PREAMBLE_HE_SU, NanoSeconds(57600)) &&
933 CheckTxDuration(1536,
934 HePhy::GetHeMcs0(),
935 160,
936 800,
938 NanoSeconds(220800)) &&
940 HePhy::GetHeMcs0(),
941 160,
942 800,
944 NanoSeconds(57600)) &&
946 HePhy::GetHeMcs0(),
947 160,
948 800,
950 NanoSeconds(57600)) &&
951 CheckTxDuration(1536,
952 HePhy::GetHeMcs0(),
953 20,
954 1600,
956 NanoSeconds(1570400)) &&
958 HePhy::GetHeMcs0(),
959 20,
960 1600,
962 NanoSeconds(130400)) &&
964 HePhy::GetHeMcs0(),
965 20,
966 1600,
968 NanoSeconds(72800)) &&
969 CheckTxDuration(1536,
970 HePhy::GetHeMcs0(),
971 40,
972 1600,
974 NanoSeconds(807200)) &&
976 HePhy::GetHeMcs0(),
977 40,
978 1600,
980 NanoSeconds(87200)) &&
982 HePhy::GetHeMcs0(),
983 40,
984 1600,
986 NanoSeconds(58400)) &&
987 CheckTxDuration(1536,
988 HePhy::GetHeMcs0(),
989 80,
990 1600,
992 NanoSeconds(418400)) &&
994 HePhy::GetHeMcs0(),
995 80,
996 1600,
998 NanoSeconds(72800)) &&
1000 HePhy::GetHeMcs0(),
1001 80,
1002 1600,
1004 NanoSeconds(58400)) &&
1005 CheckTxDuration(1536,
1006 HePhy::GetHeMcs0(),
1007 160,
1008 1600,
1010 NanoSeconds(231200)) &&
1011 CheckTxDuration(76,
1012 HePhy::GetHeMcs0(),
1013 160,
1014 1600,
1016 NanoSeconds(58400)) &&
1017 CheckTxDuration(14,
1018 HePhy::GetHeMcs0(),
1019 160,
1020 1600,
1022 NanoSeconds(58400)) &&
1023 CheckTxDuration(1536,
1024 HePhy::GetHeMcs0(),
1025 20,
1026 3200,
1028 MicroSeconds(1740)) &&
1029 CheckTxDuration(76, HePhy::GetHeMcs0(), 20, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(140)) &&
1030 CheckTxDuration(14, HePhy::GetHeMcs0(), 20, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(76)) &&
1031 CheckTxDuration(1536,
1032 HePhy::GetHeMcs0(),
1033 40,
1034 3200,
1036 MicroSeconds(892)) &&
1037 CheckTxDuration(76, HePhy::GetHeMcs0(), 40, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(92)) &&
1038 CheckTxDuration(14, HePhy::GetHeMcs0(), 40, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1039 CheckTxDuration(1536,
1040 HePhy::GetHeMcs0(),
1041 80,
1042 3200,
1044 MicroSeconds(460)) &&
1045 CheckTxDuration(76, HePhy::GetHeMcs0(), 80, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(76)) &&
1046 CheckTxDuration(14, HePhy::GetHeMcs0(), 80, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1047 CheckTxDuration(1536,
1048 HePhy::GetHeMcs0(),
1049 160,
1050 3200,
1052 MicroSeconds(252)) &&
1053 CheckTxDuration(76, HePhy::GetHeMcs0(), 160, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1054 CheckTxDuration(14, HePhy::GetHeMcs0(), 160, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1055 CheckTxDuration(1536,
1056 HePhy::GetHeMcs11(),
1057 20,
1058 800,
1060 NanoSeconds(139200)) &&
1061 CheckTxDuration(76,
1062 HePhy::GetHeMcs11(),
1063 20,
1064 800,
1066 NanoSeconds(57600)) &&
1067 CheckTxDuration(14,
1068 HePhy::GetHeMcs11(),
1069 20,
1070 800,
1072 NanoSeconds(57600)) &&
1073 CheckTxDuration(1536,
1074 HePhy::GetHeMcs11(),
1075 40,
1076 800,
1078 NanoSeconds(98400)) &&
1079 CheckTxDuration(76,
1080 HePhy::GetHeMcs11(),
1081 40,
1082 800,
1084 NanoSeconds(57600)) &&
1085 CheckTxDuration(14,
1086 HePhy::GetHeMcs11(),
1087 40,
1088 800,
1090 NanoSeconds(57600)) &&
1091 CheckTxDuration(1536,
1092 HePhy::GetHeMcs11(),
1093 80,
1094 800,
1096 NanoSeconds(71200)) &&
1097 CheckTxDuration(76,
1098 HePhy::GetHeMcs11(),
1099 80,
1100 800,
1102 NanoSeconds(57600)) &&
1103 CheckTxDuration(14,
1104 HePhy::GetHeMcs11(),
1105 80,
1106 800,
1108 NanoSeconds(57600)) &&
1109 CheckTxDuration(1536,
1110 HePhy::GetHeMcs11(),
1111 160,
1112 800,
1114 NanoSeconds(57600)) &&
1115 CheckTxDuration(76,
1116 HePhy::GetHeMcs11(),
1117 160,
1118 800,
1120 NanoSeconds(57600)) &&
1121 CheckTxDuration(14,
1122 HePhy::GetHeMcs11(),
1123 160,
1124 800,
1126 NanoSeconds(57600)) &&
1127 CheckTxDuration(1536,
1128 HePhy::GetHeMcs11(),
1129 20,
1130 1600,
1132 NanoSeconds(144800)) &&
1133 CheckTxDuration(76,
1134 HePhy::GetHeMcs11(),
1135 20,
1136 1600,
1138 NanoSeconds(58400)) &&
1139 CheckTxDuration(14,
1140 HePhy::GetHeMcs11(),
1141 20,
1142 1600,
1144 NanoSeconds(58400)) &&
1145 CheckTxDuration(1536,
1146 HePhy::GetHeMcs11(),
1147 40,
1148 1600,
1150 NanoSeconds(101600)) &&
1151 CheckTxDuration(76,
1152 HePhy::GetHeMcs11(),
1153 40,
1154 1600,
1156 NanoSeconds(58400)) &&
1157 CheckTxDuration(14,
1158 HePhy::GetHeMcs11(),
1159 40,
1160 1600,
1162 NanoSeconds(58400)) &&
1163 CheckTxDuration(1536,
1164 HePhy::GetHeMcs11(),
1165 80,
1166 1600,
1168 NanoSeconds(72800)) &&
1169 CheckTxDuration(76,
1170 HePhy::GetHeMcs11(),
1171 80,
1172 1600,
1174 NanoSeconds(58400)) &&
1175 CheckTxDuration(14,
1176 HePhy::GetHeMcs11(),
1177 80,
1178 1600,
1180 NanoSeconds(58400)) &&
1181 CheckTxDuration(1536,
1182 HePhy::GetHeMcs11(),
1183 160,
1184 1600,
1186 NanoSeconds(58400)) &&
1187 CheckTxDuration(76,
1188 HePhy::GetHeMcs11(),
1189 160,
1190 1600,
1192 NanoSeconds(58400)) &&
1193 CheckTxDuration(14,
1194 HePhy::GetHeMcs11(),
1195 160,
1196 1600,
1198 NanoSeconds(58400)) &&
1199 CheckTxDuration(1536,
1200 HePhy::GetHeMcs11(),
1201 20,
1202 3200,
1204 MicroSeconds(156)) &&
1205 CheckTxDuration(76, HePhy::GetHeMcs11(), 20, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1206 CheckTxDuration(14, HePhy::GetHeMcs11(), 20, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1207 CheckTxDuration(1536,
1208 HePhy::GetHeMcs11(),
1209 40,
1210 3200,
1212 MicroSeconds(108)) &&
1213 CheckTxDuration(76, HePhy::GetHeMcs11(), 40, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1214 CheckTxDuration(14, HePhy::GetHeMcs11(), 40, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1215 CheckTxDuration(1536,
1216 HePhy::GetHeMcs11(),
1217 80,
1218 3200,
1220 MicroSeconds(76)) &&
1221 CheckTxDuration(76, HePhy::GetHeMcs11(), 80, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1222 CheckTxDuration(14, HePhy::GetHeMcs11(), 80, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60)) &&
1223 CheckTxDuration(1536,
1224 HePhy::GetHeMcs11(),
1225 160,
1226 3200,
1228 MicroSeconds(60)) &&
1229 CheckTxDuration(76,
1230 HePhy::GetHeMcs11(),
1231 160,
1232 3200,
1234 MicroSeconds(60)) &&
1235 CheckTxDuration(14, HePhy::GetHeMcs11(), 160, 3200, WIFI_PREAMBLE_HE_SU, MicroSeconds(60));
1236
1237 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax SU duration failed");
1238
1239 // 802.11ax MU durations
1240 retval = retval &&
1242 std::list<uint32_t>{1536, 1536},
1243 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1244 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1245 40,
1246 800,
1249 1493600)) // equivalent to HE_SU for 20 MHz with 2 extra HE-SIG-B (i.e. 8 us)
1250 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1251 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1252 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1253 40,
1254 800,
1256 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1257 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1258 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1259 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1260 40,
1261 800,
1263 NanoSeconds(1493600));
1264
1265 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11ax MU duration failed");
1266
1267 // 802.11be MU durations
1268 retval = retval &&
1269 CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1270 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1271 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1272 40,
1273 800,
1275 NanoSeconds(1493600)) // equivalent to 802.11ax MU
1276 && CheckMuTxDuration(std::list<uint32_t>{1536, 1536},
1277 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 1, 1},
1278 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1279 40,
1280 800,
1282 NanoSeconds(1493600)) // shouldn't change if first PSDU is shorter
1283 && CheckMuTxDuration(std::list<uint32_t>{1536, 76},
1284 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1, true}, 0, 1},
1285 {{HeRu::RU_242_TONE, 2, true}, 0, 1}},
1286 40,
1287 800,
1289 NanoSeconds(1493600));
1290
1291 NS_TEST_EXPECT_MSG_EQ(retval, true, "an 802.11be MU duration failed");
1292
1293 Simulator::Destroy();
1294}
1295
1303{
1304 public:
1306 ~HeSigBDurationTest() override;
1307 void DoRun() override;
1308
1309 private:
1318 static WifiTxVector BuildTxVector(uint16_t bw, std::list<HeMuUserInfo> userInfos);
1319};
1320
1322 : TestCase("Check HE-SIG-B duration computation")
1323{
1324}
1325
1327{
1328}
1329
1331HeSigBDurationTest::BuildTxVector(uint16_t bw, std::list<HeMuUserInfo> userInfos)
1332{
1333 WifiTxVector txVector;
1335 txVector.SetChannelWidth(bw);
1336 txVector.SetGuardInterval(3200);
1337 txVector.SetStbc(0);
1338 txVector.SetNess(0);
1339 std::list<uint16_t> staIds;
1340 uint16_t staId = 1;
1341 for (const auto& userInfo : userInfos)
1342 {
1343 txVector.SetHeMuUserInfo(staId, userInfo);
1344 staIds.push_back(staId++);
1345 }
1346 return txVector;
1347}
1348
1349void
1351{
1352 const auto& hePhy = WifiPhy::GetStaticPhyEntity(WIFI_MOD_CLASS_HE);
1353
1354 // 20 MHz band
1355 std::list<HeMuUserInfo> userInfos;
1356 userInfos.push_back({{HeRu::RU_106_TONE, 1, true}, 11, 1});
1357 userInfos.push_back({{HeRu::RU_106_TONE, 2, true}, 10, 4});
1358 WifiTxVector txVector = BuildTxVector(20, userInfos);
1359 txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
1360 txVector.SetRuAllocation({96});
1361 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1362 VhtPhy::GetVhtMcs5(),
1363 "HE-SIG-B should be sent at MCS 5");
1364 std::pair<std::size_t, std::size_t> numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
1365 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1366 2,
1367 "Both users should be on HE-SIG-B content channel 1");
1368 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1369 0,
1370 "Both users should be on HE-SIG-B content channel 2");
1371 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1372 MicroSeconds(4),
1373 "HE-SIG-B should only last one OFDM symbol");
1374
1375 // 40 MHz band, even number of users per HE-SIG-B content channel
1376 userInfos.push_back({{HeRu::RU_52_TONE, 5, true}, 4, 1});
1377 userInfos.push_back({{HeRu::RU_52_TONE, 6, true}, 6, 2});
1378 userInfos.push_back({{HeRu::RU_52_TONE, 7, true}, 5, 3});
1379 userInfos.push_back({{HeRu::RU_52_TONE, 8, true}, 6, 2});
1380 txVector = BuildTxVector(40, userInfos);
1381 txVector.SetSigBMode(VhtPhy::GetVhtMcs4());
1382 txVector.SetRuAllocation({96, 112});
1383 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1384 VhtPhy::GetVhtMcs4(),
1385 "HE-SIG-B should be sent at MCS 4");
1386 numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
1387 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1388 2,
1389 "Two users should be on HE-SIG-B content channel 1");
1390 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1391 4,
1392 "Four users should be on HE-SIG-B content channel 2");
1393 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1394 MicroSeconds(4),
1395 "HE-SIG-B should only last one OFDM symbol");
1396
1397 // 40 MHz band, odd number of users per HE-SIG-B content channel
1398 userInfos.push_back({{HeRu::RU_26_TONE, 14, true}, 3, 1});
1399 txVector = BuildTxVector(40, userInfos);
1400 txVector.SetSigBMode(VhtPhy::GetVhtMcs3());
1401 txVector.SetRuAllocation({96, 15});
1402 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1403 VhtPhy::GetVhtMcs3(),
1404 "HE-SIG-B should be sent at MCS 3");
1405 numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
1406 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1407 2,
1408 "Two users should be on HE-SIG-B content channel 1");
1409 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1410 5,
1411 "Five users should be on HE-SIG-B content channel 2");
1412 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1413 MicroSeconds(8),
1414 "HE-SIG-B should last two OFDM symbols");
1415
1416 // 80 MHz band
1417 userInfos.push_back({{HeRu::RU_242_TONE, 3, true}, 1, 1});
1418 userInfos.push_back({{HeRu::RU_242_TONE, 4, true}, 4, 1});
1419 txVector = BuildTxVector(80, userInfos);
1420 txVector.SetSigBMode(VhtPhy::GetVhtMcs1());
1421 txVector.SetRuAllocation({96, 15, 192, 192});
1422 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1423 VhtPhy::GetVhtMcs1(),
1424 "HE-SIG-B should be sent at MCS 1");
1425 numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
1426 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1427 3,
1428 "Three users should be on HE-SIG-B content channel 1");
1429 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1430 6,
1431 "Six users should be on HE-SIG-B content channel 2");
1432 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1433 MicroSeconds(16),
1434 "HE-SIG-B should last four OFDM symbols");
1435
1436 // 160 MHz band
1437 userInfos.push_back({{HeRu::RU_996_TONE, 1, false}, 1, 1});
1438 txVector = BuildTxVector(160, userInfos);
1439 txVector.SetSigBMode(VhtPhy::GetVhtMcs1());
1440 txVector.SetRuAllocation({96, 15, 192, 192, 208, 208, 208, 208});
1441 NS_TEST_EXPECT_MSG_EQ(hePhy->GetSigMode(WIFI_PPDU_FIELD_SIG_B, txVector),
1442 VhtPhy::GetVhtMcs1(),
1443 "HE-SIG-B should be sent at MCS 1");
1444 numUsersPerCc = txVector.GetNumRusPerHeSigBContentChannel();
1445 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.first,
1446 4,
1447 "Four users should be on HE-SIG-B content channel 1");
1448 NS_TEST_EXPECT_MSG_EQ(numUsersPerCc.second,
1449 7,
1450 "Seven users should be on HE-SIG-B content channel 2");
1451 NS_TEST_EXPECT_MSG_EQ(hePhy->GetDuration(WIFI_PPDU_FIELD_SIG_B, txVector),
1452 MicroSeconds(20),
1453 "HE-SIG-B should last five OFDM symbols");
1454}
1455
1463{
1464 public:
1466 ~PhyHeaderSectionsTest() override;
1467 void DoRun() override;
1468
1469 private:
1479};
1480
1482 : TestCase("PHY header sections consistency")
1483{
1484}
1485
1487{
1488}
1489
1490void
1493{
1494 NS_ASSERT_MSG(obtained.size() == expected.size(),
1495 "The expected map size (" << expected.size() << ") was not obtained ("
1496 << obtained.size() << ")");
1497
1498 auto itObtained = obtained.begin();
1499 auto itExpected = expected.begin();
1500 for (; itObtained != obtained.end() || itExpected != expected.end();)
1501 {
1502 WifiPpduField field = itObtained->first;
1503 auto window = itObtained->second.first;
1504 auto mode = itObtained->second.second;
1505
1506 WifiPpduField fieldRef = itExpected->first;
1507 auto windowRef = itExpected->second.first;
1508 auto modeRef = itExpected->second.second;
1509
1511 fieldRef,
1512 "The expected PPDU field (" << fieldRef << ") was not obtained ("
1513 << field << ")");
1515 windowRef.first,
1516 "The expected start time (" << windowRef.first
1517 << ") was not obtained (" << window.first
1518 << ")");
1520 windowRef.second,
1521 "The expected stop time (" << windowRef.second
1522 << ") was not obtained (" << window.second
1523 << ")");
1525 modeRef,
1526 "The expected mode (" << modeRef << ") was not obtained (" << mode
1527 << ")");
1528 ++itObtained;
1529 ++itExpected;
1530 }
1531}
1532
1533void
1535{
1536 Time ppduStart = Seconds(1.0);
1537 Ptr<PhyEntity> phyEntity;
1539 WifiTxVector txVector;
1540 WifiMode nonHtMode;
1541
1542 // ==================================================================================
1543 // 11b (HR/DSSS)
1544 phyEntity = Create<DsssPhy>();
1545 txVector.SetMode(DsssPhy::GetDsssRate1Mbps());
1546 txVector.SetChannelWidth(22);
1547
1548 // -> long PPDU format
1550 nonHtMode = DsssPhy::GetDsssRate1Mbps();
1551 sections = {
1552 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(144)}, nonHtMode}},
1554 {{ppduStart + MicroSeconds(144), ppduStart + MicroSeconds(192)}, nonHtMode}},
1555 };
1556 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1557
1558 // -> long PPDU format if data rate is 1 Mbps (even if preamble is tagged short)
1560 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1561
1562 // -> short PPDU format
1563 txVector.SetMode(DsssPhy::GetDsssRate11Mbps());
1564 nonHtMode = DsssPhy::GetDsssRate2Mbps();
1566 sections = {
1567 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(72)}, nonHtMode}},
1569 {{ppduStart + MicroSeconds(72), ppduStart + MicroSeconds(96)}, nonHtMode}},
1570 };
1571 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1572
1573 // ==================================================================================
1574 // 11a (OFDM)
1576
1577 // -> one iteration per variant: default, 10 MHz, and 5 MHz
1578 std::map<OfdmPhyVariant, std::size_t> variants{
1579 // number to use to deduce rate and BW info for each variant
1580 {OFDM_PHY_DEFAULT, 1},
1581 {OFDM_PHY_10_MHZ, 2},
1582 {OFDM_PHY_5_MHZ, 4},
1583 };
1584 for (auto variant : variants)
1585 {
1586 phyEntity = Create<OfdmPhy>(variant.first);
1587 std::size_t ratio = variant.second;
1588 uint16_t bw = 20 / ratio; // MHz
1589 txVector.SetChannelWidth(bw);
1590 txVector.SetMode(OfdmPhy::GetOfdmRate(12000000 / ratio, bw));
1591 nonHtMode = OfdmPhy::GetOfdmRate(6000000 / ratio, bw);
1592 sections = {
1594 {{ppduStart, ppduStart + MicroSeconds(16 * ratio)}, nonHtMode}},
1596 {{ppduStart + MicroSeconds(16 * ratio), ppduStart + MicroSeconds(20 * ratio)},
1597 nonHtMode}},
1598 };
1599 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1600 }
1601
1602 // ==================================================================================
1603 // 11g (ERP-OFDM)
1604 phyEntity = Create<ErpOfdmPhy>();
1605 txVector.SetChannelWidth(20);
1606 txVector.SetMode(ErpOfdmPhy::GetErpOfdmRate(54000000));
1607 nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps();
1608 sections = {
1609 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1611 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1612 };
1613 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1614
1615 // ==================================================================================
1616 // 11n (HT)
1617 phyEntity = Create<HtPhy>(4);
1618 txVector.SetChannelWidth(20);
1619 txVector.SetMode(HtPhy::GetHtMcs6());
1620 nonHtMode = OfdmPhy::GetOfdmRate6Mbps();
1621 WifiMode htSigMode = nonHtMode;
1622
1623 // -> HT-mixed format for 2 SS and no ESS
1625 txVector.SetNss(2);
1626 txVector.SetNess(0);
1627 sections = {
1628 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1630 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1632 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, htSigMode}},
1634 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(40)}, // 1 HT-STF + 2 HT-LTFs
1635 htSigMode}},
1636 };
1637 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1638 txVector.SetChannelWidth(20); // shouldn't have any impact
1639 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1640
1641 // -> HT-mixed format for 3 SS and 1 ESS
1642 txVector.SetNss(3);
1643 txVector.SetNess(1);
1644 sections[WIFI_PPDU_FIELD_TRAINING] = {
1645 {ppduStart + MicroSeconds(28),
1646 ppduStart + MicroSeconds(52)}, // 1 HT-STF + 5 HT-LTFs (4 data + 1 extension)
1647 htSigMode};
1648 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1649
1650 // ==================================================================================
1651 // 11ac (VHT)
1652 phyEntity = Create<VhtPhy>();
1653 txVector.SetChannelWidth(20);
1654 txVector.SetNess(0);
1655 txVector.SetMode(VhtPhy::GetVhtMcs7());
1656 WifiMode sigAMode = nonHtMode;
1657 WifiMode sigBMode = VhtPhy::GetVhtMcs0();
1658
1659 // -> VHT SU format for 5 SS
1661 txVector.SetNss(5);
1662 sections = {
1663 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1665 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(20)}, nonHtMode}},
1667 {{ppduStart + MicroSeconds(20), ppduStart + MicroSeconds(28)}, sigAMode}},
1669 {{ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(56)}, // 1 VHT-STF + 6 VHT-LTFs
1670 sigAMode}},
1671 };
1672 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1673
1674 // -> VHT SU format for 7 SS
1675 txVector.SetNss(7);
1676 sections[WIFI_PPDU_FIELD_TRAINING] = {
1677 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(64)}, // 1 VHT-STF + 8 VHT-LTFs
1678 sigAMode};
1679 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1680
1681 // -> VHT MU format for 3 SS
1683 txVector.SetNss(3);
1684 sections[WIFI_PPDU_FIELD_TRAINING] = {
1685 {ppduStart + MicroSeconds(28), ppduStart + MicroSeconds(48)}, // 1 VHT-STF + 4 VHT-LTFs
1686 sigAMode};
1687 sections[WIFI_PPDU_FIELD_SIG_B] = {{ppduStart + MicroSeconds(48), ppduStart + MicroSeconds(52)},
1688 sigBMode};
1689 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1690 txVector.SetChannelWidth(80); // shouldn't have any impact
1691 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1692
1693 // ==================================================================================
1694 // 11ax (HE)
1695 phyEntity = Create<HePhy>();
1696 txVector.SetChannelWidth(20);
1697 txVector.SetNss(2); // HE-LTF duration assumed to be always 8 us for the time being (see note in
1698 // HePhy::GetTrainingDuration)
1699 txVector.SetMode(HePhy::GetHeMcs9());
1700 std::map<uint16_t, HeMuUserInfo> userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1701 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1702 sigAMode = HePhy::GetVhtMcs0();
1703 sigBMode = HePhy::GetVhtMcs4(); // because of first user info map
1704
1705 // -> HE SU format
1707 sections = {
1708 {WIFI_PPDU_FIELD_PREAMBLE, {{ppduStart, ppduStart + MicroSeconds(16)}, nonHtMode}},
1710 {{ppduStart + MicroSeconds(16), ppduStart + MicroSeconds(24)}, // L-SIG + RL-SIG
1711 nonHtMode}},
1713 {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)}, sigAMode}},
1715 {{ppduStart + MicroSeconds(32),
1716 ppduStart + MicroSeconds(52)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1717 sigAMode}},
1718 };
1719 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1720
1721 // -> HE ER SU format
1723 sections[WIFI_PPDU_FIELD_SIG_A] = {
1724 {ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(40)}, // 16 us HE-SIG-A
1725 sigAMode};
1726 sections[WIFI_PPDU_FIELD_TRAINING] = {
1727 {ppduStart + MicroSeconds(40),
1728 ppduStart + MicroSeconds(60)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1729 sigAMode};
1730 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1731
1732 // -> HE TB format
1734 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1735 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1736 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1737 sigAMode};
1738 sections[WIFI_PPDU_FIELD_TRAINING] = {
1739 {ppduStart + MicroSeconds(32),
1740 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 8 us) + 2 HE-LTFs (@ 8 us)
1741 sigAMode};
1742 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1743
1744 // -> HE MU format
1746 txVector.SetSigBMode(sigBMode);
1747 txVector.SetRuAllocation({96});
1748 sections[WIFI_PPDU_FIELD_SIG_A] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1749 sigAMode};
1750 sections[WIFI_PPDU_FIELD_SIG_B] = {
1751 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1752 sigBMode};
1753 sections[WIFI_PPDU_FIELD_TRAINING] = {
1754 {ppduStart + MicroSeconds(36),
1755 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1756 sigBMode};
1757 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1758 txVector.SetChannelWidth(160); // shouldn't have any impact
1759 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113});
1760
1761 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1762
1763 // ==================================================================================
1764 // 11be (EHT)
1765 sections.erase(WIFI_PPDU_FIELD_SIG_A); // FIXME: do we keep using separate type for 11be?
1766 sections.erase(WIFI_PPDU_FIELD_SIG_B); // FIXME: do we keep using separate type for 11be?
1767 phyEntity = Create<EhtPhy>();
1768 txVector.SetChannelWidth(20);
1769 txVector.SetNss(2); // EHT-LTF duration assumed to be always 8 us for the time being (see note
1770 // in HePhy::GetTrainingDuration)
1771 txVector.SetMode(EhtPhy::GetEhtMcs9());
1772 userInfoMap = {{1, {{HeRu::RU_106_TONE, 1, true}, 4, 2}},
1773 {2, {{HeRu::RU_106_TONE, 1, true}, 9, 1}}};
1774 WifiMode uSigMode = EhtPhy::GetVhtMcs0();
1775 WifiMode ehtSigMode = EhtPhy::GetVhtMcs4(); // because of first user info map
1776
1777 // -> EHT TB format
1779 txVector.SetHeMuUserInfo(1, userInfoMap.at(1));
1780 txVector.SetHeMuUserInfo(2, userInfoMap.at(2));
1781 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1782 uSigMode};
1783 sections[WIFI_PPDU_FIELD_TRAINING] = {
1784 {ppduStart + MicroSeconds(32),
1785 ppduStart + MicroSeconds(56)}, // 1 EHT-STF (@ 8 us) + 2 EHT-LTFs (@ 8 us)
1786 uSigMode};
1787 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1788
1789 // -> EHT MU format
1791 txVector.SetEhtPpduType(0); // EHT MU transmission
1792 txVector.SetRuAllocation({96});
1793 sections[WIFI_PPDU_FIELD_U_SIG] = {{ppduStart + MicroSeconds(24), ppduStart + MicroSeconds(32)},
1794 uSigMode};
1795 sections[WIFI_PPDU_FIELD_EHT_SIG] = {
1796 {ppduStart + MicroSeconds(32), ppduStart + MicroSeconds(36)}, // only one symbol
1797 ehtSigMode};
1798 sections[WIFI_PPDU_FIELD_TRAINING] = {
1799 {ppduStart + MicroSeconds(36),
1800 ppduStart + MicroSeconds(56)}, // 1 HE-STF (@ 4 us) + 2 HE-LTFs (@ 8 us)
1801 ehtSigMode};
1802 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1803 txVector.SetChannelWidth(160); // shouldn't have any impact
1804 txVector.SetRuAllocation({96, 113, 113, 113, 113, 113, 113, 113});
1805
1806 CheckPhyHeaderSections(phyEntity->GetPhyHeaderSections(txVector, ppduStart), sections);
1807}
1808
1816{
1817 public:
1819};
1820
1822 : TestSuite("wifi-devices-tx-duration", UNIT)
1823{
1824 AddTestCase(new HeSigBDurationTest, TestCase::QUICK);
1825 AddTestCase(new TxDurationTest, TestCase::QUICK);
1826 AddTestCase(new PhyHeaderSectionsTest, TestCase::QUICK);
1827}
1828
HE-SIG-B duration test.
static WifiTxVector BuildTxVector(uint16_t bw, std::list< HeMuUserInfo > userInfos)
Build a TXVECTOR for HE MU with the given bandwidth and user information.
void DoRun() override
Implementation to actually run this TestCase.
~HeSigBDurationTest() override
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.
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:435
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
Definition: phy-entity.h:327
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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:50
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
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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.
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
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.
std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel() const
Get the number of RUs per HE-SIG-B content channel.
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
phy
Definition: third.py:82
HE MU specific user transmission parameters.
HeRu::RuSpec ru
RU specification.
static TxDurationTestSuite g_txDurationTestSuite
the test suite
#define SU_STA_ID
Definition: wifi-mode.h:34