A Discrete-Event Network Simulator
API
wifi-mode.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006,2007 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  * Sébastien Deronne <sebastien.deronne@gmail.com>
20  */
21 
22 #include "wifi-mode.h"
23 #include "wifi-tx-vector.h"
24 #include "ns3/simulator.h"
25 #include "ns3/assert.h"
26 #include "ns3/log.h"
27 #include <cmath>
28 
29 namespace ns3 {
30 
40 bool operator == (const WifiMode &a, const WifiMode &b)
41 {
42  return a.GetUid () == b.GetUid ();
43 }
52 std::ostream & operator << (std::ostream & os, const WifiMode &mode)
53 {
54  os << mode.GetUniqueName ();
55  return os;
56 }
65 std::istream & operator >> (std::istream &is, WifiMode &mode)
66 {
67  std::string str;
68  is >> str;
69  mode = WifiModeFactory::GetFactory ()->Search (str);
70  return is;
71 }
72 
73 uint64_t
74 WifiMode::GetPhyRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
75 {
76  //TODO: nss > 4 not supported yet
77  NS_ASSERT (nss <= 4);
78  uint32_t dataRate, phyRate;
79  dataRate = GetDataRate (channelWidth, isShortGuardInterval, nss);
80  switch (GetCodeRate ())
81  {
82  case WIFI_CODE_RATE_5_6:
83  phyRate = dataRate * 6 / 5;
84  break;
85  case WIFI_CODE_RATE_3_4:
86  phyRate = dataRate * 4 / 3;
87  break;
88  case WIFI_CODE_RATE_2_3:
89  phyRate = dataRate * 3 / 2;
90  break;
91  case WIFI_CODE_RATE_1_2:
92  phyRate = dataRate * 2 / 1;
93  break;
95  default:
96  phyRate = dataRate;
97  break;
98  }
99  return phyRate;
100 }
101 
102 uint64_t
104 {
105  return GetPhyRate (txVector.GetChannelWidth (), txVector.IsShortGuardInterval (), txVector.GetNss ());
106 }
107 
108 uint64_t
109 WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
110 {
111  //TODO: nss > 4 not supported yet
112  NS_ASSERT (nss <= 4);
114  uint64_t dataRate = 0;
115  if (item->modClass == WIFI_MOD_CLASS_DSSS)
116  {
117  dataRate = (11000000 / 11) * log2 (GetConstellationSize ());
118  }
119  else if (item->modClass == WIFI_MOD_CLASS_HR_DSSS)
120  {
121  dataRate = (11000000 / 8) * log2 (GetConstellationSize ());
122  }
123  else if (item->modClass == WIFI_MOD_CLASS_OFDM || item->modClass == WIFI_MOD_CLASS_ERP_OFDM)
124  {
125  double symbolRate = (1 / 4.0) * 1e6;
126 
127  uint32_t usableSubCarriers;
128  switch (channelWidth)
129  {
130  case 20:
131  default:
132  usableSubCarriers = 48;
133  break;
134  case 10:
135  usableSubCarriers = 24;
136  break;
137  case 5:
138  usableSubCarriers = 12;
139  break;
140  }
141 
142  double codingRate;
143  switch (GetCodeRate ())
144  {
145  case WIFI_CODE_RATE_3_4:
146  codingRate = (3.0 / 4.0);
147  break;
148  case WIFI_CODE_RATE_2_3:
149  codingRate = (2.0 / 3.0);
150  break;
151  case WIFI_CODE_RATE_1_2:
152  codingRate = (1.0 / 2.0);
153  break;
155  default:
156  NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined");
157  break;
158  }
159 
160  uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize ());
161 
162  dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
163  }
164  else if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
165  {
166  if (item->modClass == WIFI_MOD_CLASS_VHT && item->mcsValue == 9 && nss != 3)
167  {
168  //VHT MCS 9 forbidden at 20 MHz (only allowed when NSS = 3)
169  NS_ASSERT (channelWidth != 20);
170  }
171  if (item->modClass == WIFI_MOD_CLASS_VHT && item->mcsValue == 6 && nss == 3)
172  {
173  //VHT MCS 6 forbidden at 80 MHz when NSS = 3
174  NS_ASSERT (channelWidth != 80);
175  }
176  double symbolRate;
177  if (!isShortGuardInterval)
178  {
179  symbolRate = (1 / 4.0) * 1e6;
180  }
181  else
182  {
183  symbolRate = (1 / 3.6) * 1e6;
184  }
185 
186  uint32_t usableSubCarriers;
187  switch (channelWidth)
188  {
189  case 20:
190  default:
191  usableSubCarriers = 52;
192  break;
193  case 40:
194  usableSubCarriers = 108;
195  break;
196  case 80:
197  usableSubCarriers = 234;
198  break;
199  case 160:
200  usableSubCarriers = 468;
201  break;
202  }
203 
204  double codingRate;
205  switch (GetCodeRate ())
206  {
207  case WIFI_CODE_RATE_5_6:
208  codingRate = (5.0 / 6.0);
209  break;
210  case WIFI_CODE_RATE_3_4:
211  codingRate = (3.0 / 4.0);
212  break;
213  case WIFI_CODE_RATE_2_3:
214  codingRate = (2.0 / 3.0);
215  break;
216  case WIFI_CODE_RATE_1_2:
217  codingRate = (1.0 / 2.0);
218  break;
220  default:
221  NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined with nss: " << (uint16_t) nss);
222  break;
223  }
224 
225  uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize ());
226 
227  dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
228  }
229  else
230  {
231  NS_ASSERT ("undefined datarate for the modulation class!");
232  }
233  dataRate *= nss; // number of spatial streams
234  return dataRate;
235 }
236 
237 uint64_t
239 {
240  return GetDataRate (txVector.GetChannelWidth (), txVector.IsShortGuardInterval (), txVector.GetNss ());
241 }
242 
243 enum WifiCodeRate
245 {
247  if (item->modClass == WIFI_MOD_CLASS_HT)
248  {
249  switch (item->mcsValue % 8)
250  {
251  case 0:
252  case 1:
253  case 3:
254  return WIFI_CODE_RATE_1_2;
255  case 2:
256  case 4:
257  case 6:
258  return WIFI_CODE_RATE_3_4;
259  case 5:
260  return WIFI_CODE_RATE_2_3;
261  case 7:
262  return WIFI_CODE_RATE_5_6;
263  default:
265  }
266  }
267  else if (item->modClass == WIFI_MOD_CLASS_VHT)
268  {
269  switch (item->mcsValue)
270  {
271  case 0:
272  case 1:
273  case 3:
274  return WIFI_CODE_RATE_1_2;
275  case 2:
276  case 4:
277  case 6:
278  case 8:
279  return WIFI_CODE_RATE_3_4;
280  case 5:
281  return WIFI_CODE_RATE_2_3;
282  case 7:
283  case 9:
284  return WIFI_CODE_RATE_5_6;
285  default:
287  }
288  }
289  else
290  {
291  return item->codingRate;
292  }
293 }
294 
295 uint16_t
297 {
299  if (item->modClass == WIFI_MOD_CLASS_HT)
300  {
301  switch (item->mcsValue % 8)
302  {
303  case 0:
304  return 2;
305  case 1:
306  case 2:
307  return 4;
308  case 3:
309  case 4:
310  return 16;
311  case 5:
312  case 6:
313  case 7:
314  return 64;
315  default:
316  return 0;
317  }
318  }
319  else if (item->modClass == WIFI_MOD_CLASS_VHT)
320  {
321  switch (item->mcsValue)
322  {
323  case 0:
324  return 2;
325  case 1:
326  case 2:
327  return 4;
328  case 3:
329  case 4:
330  return 16;
331  case 5:
332  case 6:
333  case 7:
334  return 64;
335  case 8:
336  case 9:
337  return 256;
338  default:
339  return 0;
340  }
341  }
342  else
343  {
344  return item->constellationSize;
345  }
346 }
347 
348 std::string
350 {
351  //needed for ostream printing of the invalid mode
353  return item->uniqueUid;
354 }
355 
356 bool
358 {
360  return item->isMandatory;
361 }
362 
363 uint8_t
365 {
367  if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
368  {
369  return item->mcsValue;
370  }
371  else
372  {
373  //We should not go here!
374  NS_ASSERT (false);
375  return 0;
376  }
377 }
378 
379 uint32_t
380 WifiMode::GetUid (void) const
381 {
382  return m_uid;
383 }
384 
387 {
389  return item->modClass;
390 }
391 
392 uint64_t
394 {
395  uint64_t dataRate;
397  if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
398  {
399  WifiCodeRate codeRate = GetCodeRate();
400  switch(GetConstellationSize())
401  {
402  case 2:
403  if (codeRate == WIFI_CODE_RATE_1_2)
404  dataRate = 6000000;
405  else if (codeRate == WIFI_CODE_RATE_3_4)
406  dataRate = 9000000;
407  else
408  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
409  break;
410  case 4:
411  if (codeRate == WIFI_CODE_RATE_1_2)
412  dataRate = 12000000;
413  else if (codeRate == WIFI_CODE_RATE_3_4)
414  dataRate = 18000000;
415  else
416  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
417  break;
418  case 16:
419  if (codeRate == WIFI_CODE_RATE_1_2)
420  dataRate = 24000000;
421  else if (codeRate == WIFI_CODE_RATE_3_4)
422  dataRate = 36000000;
423  else
424  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
425  break;
426  case 64:
427  if (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3)
428  dataRate = 48000000;
429  else if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
430  dataRate = 54000000;
431  else
432  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
433  break;
434  case 256:
435  if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
436  dataRate = 54000000;
437  else
438  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
439  break;
440  default:
441  NS_FATAL_ERROR ("Wrong constellation size");
442  }
443  }
444  else
445  {
446  NS_FATAL_ERROR ("Trying to get reference rate for a non-HT rate");
447  }
448  return dataRate;
449 }
450 
451 bool
453 {
454  WifiCodeRate codeRate = mode.GetCodeRate ();
455  switch (GetCodeRate ())
456  {
457  case WIFI_CODE_RATE_1_2:
458  return false; //This is the smallest code rate.
459  case WIFI_CODE_RATE_2_3:
460  return (codeRate == WIFI_CODE_RATE_1_2);
461  case WIFI_CODE_RATE_3_4:
462  return (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3);
463  case WIFI_CODE_RATE_5_6:
464  return (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3 || codeRate == WIFI_CODE_RATE_3_4);
465  default:
466  NS_FATAL_ERROR ("Wifi Code Rate not defined");
467  return false;
468  }
469 }
470 
471 bool
473 {
475  switch(item->modClass)
476  {
477  case WIFI_MOD_CLASS_DSSS:
479  {
480  return (GetConstellationSize () > mode.GetConstellationSize ());
481  }
482  else
483  {
484  return false;
485  }
488  {
489  return true;
490  }
491  else
492  {
493  return (GetConstellationSize () > mode.GetConstellationSize ());
494  }
496  case WIFI_MOD_CLASS_OFDM:
497  case WIFI_MOD_CLASS_HT:
498  case WIFI_MOD_CLASS_VHT:
500  {
501  return true;
502  }
503  else if (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)
504  {
505  return (mode.GetConstellationSize () > GetConstellationSize ());
506  }
507  else
508  {
510  {
511  return true;
512  }
513  else if (GetConstellationSize () == mode.GetConstellationSize ())
514  {
515  return IsHigherCodeRate (mode);
516  }
517  else
518  {
519  return false;
520  }
521  }
522  default:
523  NS_FATAL_ERROR ("Modulation class not defined");
524  return false;
525  }
526 }
527 
529  : m_uid (0)
530 {
531 }
532 
533 WifiMode::WifiMode (uint32_t uid)
534  : m_uid (uid)
535 {
536 }
537 
538 WifiMode::WifiMode (std::string name)
539 {
540  *this = WifiModeFactory::GetFactory ()->Search (name);
541 }
542 
544 
546 {
547 }
548 
549 WifiMode
550 WifiModeFactory::CreateWifiMode (std::string uniqueName,
551  enum WifiModulationClass modClass,
552  bool isMandatory,
553  enum WifiCodeRate codingRate,
554  uint16_t constellationSize)
555 {
556  WifiModeFactory *factory = GetFactory ();
557  uint32_t uid = factory->AllocateUid (uniqueName);
558  WifiModeItem *item = factory->Get (uid);
559  item->uniqueUid = uniqueName;
560  item->modClass = modClass;
561  //The modulation class for this WifiMode must be valid.
562  NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN);
563  item->codingRate = codingRate;
564 
565  //Check for compatibility between modulation class and coding
566  //rate. If modulation class is DSSS then coding rate must be
567  //undefined, and vice versa. I could have done this with an
568  //assertion, but it seems better to always give the error (i.e.,
569  //not only in non-optimised builds) and the cycles that extra test
570  //here costs are only suffered at simulation setup.
571  if ((codingRate == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS && modClass != WIFI_MOD_CLASS_HR_DSSS)
572  {
573  NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl
574  << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is WIFI_MOD_CLASS_DSSS or WIFI_MOD_CLASS_HR_DSSS");
575  }
576 
577  item->constellationSize = constellationSize;
578  item->isMandatory = isMandatory;
579 
580  NS_ASSERT (modClass != WIFI_MOD_CLASS_HT && modClass != WIFI_MOD_CLASS_VHT);
581  //fill unused mcs item with a dummy value
582  item->mcsValue = 0;
583 
584  return WifiMode (uid);
585 }
586 
587 WifiMode
588 WifiModeFactory::CreateWifiMcs (std::string uniqueName,
589  uint8_t mcsValue,
590  enum WifiModulationClass modClass)
591 {
592  WifiModeFactory *factory = GetFactory ();
593  uint32_t uid = factory->AllocateUid (uniqueName);
594  WifiModeItem *item = factory->Get (uid);
595  item->uniqueUid = uniqueName;
596  item->modClass = modClass;
597 
598  //The modulation class must be either HT or VHT
599  NS_ASSERT (modClass == WIFI_MOD_CLASS_HT || modClass == WIFI_MOD_CLASS_VHT);
600 
601  item->mcsValue = mcsValue;
602  //fill unused items with dummy values
603  item->constellationSize = 0;
605  item->isMandatory = false;
606 
607  return WifiMode (uid);
608 }
609 
610 WifiMode
611 WifiModeFactory::Search (std::string name)
612 {
613  WifiModeItemList::const_iterator i;
614  uint32_t j = 0;
615  for (i = m_itemList.begin (); i != m_itemList.end (); i++)
616  {
617  if (i->uniqueUid == name)
618  {
619  return WifiMode (j);
620  }
621  j++;
622  }
623 
624  //If we get here then a matching WifiMode was not found above. This
625  //is a fatal problem, but we try to be helpful by displaying the
626  //list of WifiModes that are supported.
627  NS_LOG_UNCOND ("Could not find match for WifiMode named \""
628  << name << "\". Valid options are:");
629  for (i = m_itemList.begin (); i != m_itemList.end (); i++)
630  {
631  NS_LOG_UNCOND (" " << i->uniqueUid);
632  }
633  //Empty fatal error to die. We've already unconditionally logged
634  //the helpful information.
635  NS_FATAL_ERROR ("");
636 
637  //This next line is unreachable because of the fatal error
638  //immediately above, and that is fortunate, because we have no idea
639  //what is in WifiMode (0), but we do know it is not what our caller
640  //has requested by name. It's here only because it's the safest
641  //thing that'll give valid code.
642  return WifiMode (0);
643 }
644 
645 uint32_t
646 WifiModeFactory::AllocateUid (std::string uniqueUid)
647 {
648  uint32_t j = 0;
649  for (WifiModeItemList::const_iterator i = m_itemList.begin ();
650  i != m_itemList.end (); i++)
651  {
652  if (i->uniqueUid == uniqueUid)
653  {
654  return j;
655  }
656  j++;
657  }
658  uint32_t uid = m_itemList.size ();
659  m_itemList.push_back (WifiModeItem ());
660  return uid;
661 }
662 
664 WifiModeFactory::Get (uint32_t uid)
665 {
666  NS_ASSERT (uid < m_itemList.size ());
667  return &m_itemList[uid];
668 }
669 
672 {
673  static bool isFirstTime = true;
674  static WifiModeFactory factory;
675  if (isFirstTime)
676  {
677  uint32_t uid = factory.AllocateUid ("Invalid-WifiMode");
678  WifiModeItem *item = factory.Get (uid);
679  item->uniqueUid = "Invalid-WifiMode";
681  item->constellationSize = 0;
683  item->isMandatory = false;
684  item->mcsValue = 0;
685  isFirstTime = false;
686  }
687  return &factory;
688 }
689 
690 } //namespace ns3
std::istream & operator>>(std::istream &is, Angles &a)
initialize a struct Angles from input
Definition: angles.cc:48
WifiMode()
Create an invalid WifiMode.
Definition: wifi-mode.cc:528
ERP-OFDM PHY (19.5)
Definition: wifi-mode.h:58
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
WifiCodeRate
This enumeration defines the various convolutional coding rates used for the OFDM transmission modes ...
Definition: wifi-mode.h:74
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type.
enum WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:386
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
bool IsShortGuardInterval(void) const
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:145
VHT PHY (Clause 22)
Definition: wifi-mode.h:64
HR/DSSS PHY (Clause 18)
Definition: wifi-mode.h:52
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:99
bool IsMandatory(void) const
Definition: wifi-mode.cc:357
static WifiMode CreateWifiMcs(std::string uniqueName, uint8_t mcsValue, enum WifiModulationClass modClass)
Definition: wifi-mode.cc:588
Modulation class unknown or unspecified.
Definition: wifi-mode.h:44
WifiModeItem * Get(uint32_t uid)
Return a WifiModeItem at the given uid index.
Definition: wifi-mode.cc:664
uint64_t GetPhyRate(uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
Definition: wifi-mode.cc:74
uint16_t GetConstellationSize(void) const
Definition: wifi-mode.cc:296
bool IsHigherDataRate(WifiMode mode) const
Definition: wifi-mode.cc:472
uint32_t m_uid
Definition: wifi-mode.h:218
enum WifiCodeRate GetCodeRate(void) const
Definition: wifi-mode.cc:244
uint32_t GetChannelWidth(void) const
HT PHY (Clause 20)
Definition: wifi-mode.h:62
uint8_t GetMcsValue(void) const
Definition: wifi-mode.cc:364
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:349
WifiModeItemList m_itemList
Definition: wifi-mode.h:341
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
Every class exported by the ns3 library is enclosed in the ns3 namespace.
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionaly.
uint64_t GetDataRate(uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
Definition: wifi-mode.cc:109
friend class WifiMode
Definition: wifi-mode.h:286
uint64_t GetNonHtReferenceRate(void) const
Definition: wifi-mode.cc:393
static WifiMode CreateWifiMode(std::string uniqueName, enum WifiModulationClass modClass, bool isMandatory, enum WifiCodeRate codingRate, uint16_t constellationSize)
Definition: wifi-mode.cc:550
No explicit coding (e.g., DSSS rates)
Definition: wifi-mode.h:77
create WifiMode class instances and keep track of them.
Definition: wifi-mode.h:245
uint8_t GetNss(void) const
WifiModulationClass
This enumeration defines the modulation classes per (Table 9-4 "Modulation classes"; IEEE 802...
Definition: wifi-mode.h:40
bool IsHigherCodeRate(WifiMode mode) const
Definition: wifi-mode.cc:452
OFDM PHY (Clause 17)
Definition: wifi-mode.h:60
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.cc:95
static WifiModeFactory * GetFactory()
Return a WifiModeFactory.
Definition: wifi-mode.cc:671
uint32_t AllocateUid(std::string uniqueUid)
Allocate a WifiModeItem from a given uniqueUid.
Definition: wifi-mode.cc:646
enum WifiModulationClass modClass
Definition: wifi-mode.h:305
uint32_t GetUid(void) const
Definition: wifi-mode.cc:380
WifiMode Search(std::string name)
Search and return WifiMode from a given name.
Definition: wifi-mode.cc:611
This is the data associated to a unique WifiMode.
Definition: wifi-mode.h:302
DSSS PHY (Clause 15)
Definition: wifi-mode.h:50