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