A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  NS_ASSERT_MSG (channelWidth != 20, "VHT MCS 9 forbidden at 20 MHz (only allowed when NSS = 3)");
169  }
170  if (item->modClass == WIFI_MOD_CLASS_VHT && item->mcsValue == 6 && nss == 3)
171  {
172  NS_ASSERT_MSG (channelWidth != 80, "VHT MCS 6 forbidden at 80 MHz when NSS = 3");
173  }
174  double symbolRate;
175  if (!isShortGuardInterval)
176  {
177  symbolRate = (1 / 4.0) * 1e6;
178  }
179  else
180  {
181  symbolRate = (1 / 3.6) * 1e6;
182  }
183 
184  uint32_t usableSubCarriers;
185  switch (channelWidth)
186  {
187  case 20:
188  default:
189  usableSubCarriers = 52;
190  break;
191  case 40:
192  usableSubCarriers = 108;
193  break;
194  case 80:
195  usableSubCarriers = 234;
196  break;
197  case 160:
198  usableSubCarriers = 468;
199  break;
200  }
201 
202  double codingRate;
203  switch (GetCodeRate ())
204  {
205  case WIFI_CODE_RATE_5_6:
206  codingRate = (5.0 / 6.0);
207  break;
208  case WIFI_CODE_RATE_3_4:
209  codingRate = (3.0 / 4.0);
210  break;
211  case WIFI_CODE_RATE_2_3:
212  codingRate = (2.0 / 3.0);
213  break;
214  case WIFI_CODE_RATE_1_2:
215  codingRate = (1.0 / 2.0);
216  break;
218  default:
219  NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined with nss: " << (uint16_t) nss);
220  break;
221  }
222 
223  uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize ());
224 
225  dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
226  }
227  else
228  {
229  NS_ASSERT ("undefined datarate for the modulation class!");
230  }
231  dataRate *= nss; // number of spatial streams
232  return dataRate;
233 }
234 
235 uint64_t
237 {
238  return GetDataRate (txVector.GetChannelWidth (), txVector.IsShortGuardInterval (), txVector.GetNss ());
239 }
240 
241 enum WifiCodeRate
243 {
245  if (item->modClass == WIFI_MOD_CLASS_HT)
246  {
247  switch (item->mcsValue % 8)
248  {
249  case 0:
250  case 1:
251  case 3:
252  return WIFI_CODE_RATE_1_2;
253  case 2:
254  case 4:
255  case 6:
256  return WIFI_CODE_RATE_3_4;
257  case 5:
258  return WIFI_CODE_RATE_2_3;
259  case 7:
260  return WIFI_CODE_RATE_5_6;
261  default:
263  }
264  }
265  else if (item->modClass == WIFI_MOD_CLASS_VHT)
266  {
267  switch (item->mcsValue)
268  {
269  case 0:
270  case 1:
271  case 3:
272  return WIFI_CODE_RATE_1_2;
273  case 2:
274  case 4:
275  case 6:
276  case 8:
277  return WIFI_CODE_RATE_3_4;
278  case 5:
279  return WIFI_CODE_RATE_2_3;
280  case 7:
281  case 9:
282  return WIFI_CODE_RATE_5_6;
283  default:
285  }
286  }
287  else
288  {
289  return item->codingRate;
290  }
291 }
292 
293 uint16_t
295 {
297  if (item->modClass == WIFI_MOD_CLASS_HT)
298  {
299  switch (item->mcsValue % 8)
300  {
301  case 0:
302  return 2;
303  case 1:
304  case 2:
305  return 4;
306  case 3:
307  case 4:
308  return 16;
309  case 5:
310  case 6:
311  case 7:
312  return 64;
313  default:
314  return 0;
315  }
316  }
317  else if (item->modClass == WIFI_MOD_CLASS_VHT)
318  {
319  switch (item->mcsValue)
320  {
321  case 0:
322  return 2;
323  case 1:
324  case 2:
325  return 4;
326  case 3:
327  case 4:
328  return 16;
329  case 5:
330  case 6:
331  case 7:
332  return 64;
333  case 8:
334  case 9:
335  return 256;
336  default:
337  return 0;
338  }
339  }
340  else
341  {
342  return item->constellationSize;
343  }
344 }
345 
346 std::string
348 {
349  //needed for ostream printing of the invalid mode
351  return item->uniqueUid;
352 }
353 
354 bool
356 {
358  return item->isMandatory;
359 }
360 
361 uint8_t
363 {
365  if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
366  {
367  return item->mcsValue;
368  }
369  else
370  {
371  //We should not go here!
372  NS_ASSERT (false);
373  return 0;
374  }
375 }
376 
377 uint32_t
378 WifiMode::GetUid (void) const
379 {
380  return m_uid;
381 }
382 
385 {
387  return item->modClass;
388 }
389 
390 uint64_t
392 {
393  uint64_t dataRate;
395  if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
396  {
397  WifiCodeRate codeRate = GetCodeRate();
398  switch(GetConstellationSize())
399  {
400  case 2:
401  if (codeRate == WIFI_CODE_RATE_1_2)
402  dataRate = 6000000;
403  else if (codeRate == WIFI_CODE_RATE_3_4)
404  dataRate = 9000000;
405  else
406  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
407  break;
408  case 4:
409  if (codeRate == WIFI_CODE_RATE_1_2)
410  dataRate = 12000000;
411  else if (codeRate == WIFI_CODE_RATE_3_4)
412  dataRate = 18000000;
413  else
414  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
415  break;
416  case 16:
417  if (codeRate == WIFI_CODE_RATE_1_2)
418  dataRate = 24000000;
419  else if (codeRate == WIFI_CODE_RATE_3_4)
420  dataRate = 36000000;
421  else
422  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
423  break;
424  case 64:
425  if (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3)
426  dataRate = 48000000;
427  else if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
428  dataRate = 54000000;
429  else
430  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
431  break;
432  case 256:
433  if (codeRate == WIFI_CODE_RATE_3_4 || codeRate == WIFI_CODE_RATE_5_6)
434  dataRate = 54000000;
435  else
436  NS_FATAL_ERROR ("Trying to get reference rate for a MCS with wrong combination of coding rate and modulation");
437  break;
438  default:
439  NS_FATAL_ERROR ("Wrong constellation size");
440  }
441  }
442  else
443  {
444  NS_FATAL_ERROR ("Trying to get reference rate for a non-HT rate");
445  }
446  return dataRate;
447 }
448 
449 bool
451 {
452  WifiCodeRate codeRate = mode.GetCodeRate ();
453  switch (GetCodeRate ())
454  {
455  case WIFI_CODE_RATE_1_2:
456  return false; //This is the smallest code rate.
457  case WIFI_CODE_RATE_2_3:
458  return (codeRate == WIFI_CODE_RATE_1_2);
459  case WIFI_CODE_RATE_3_4:
460  return (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3);
461  case WIFI_CODE_RATE_5_6:
462  return (codeRate == WIFI_CODE_RATE_1_2 || codeRate == WIFI_CODE_RATE_2_3 || codeRate == WIFI_CODE_RATE_3_4);
463  default:
464  NS_FATAL_ERROR ("Wifi Code Rate not defined");
465  return false;
466  }
467 }
468 
469 bool
471 {
473  switch(item->modClass)
474  {
475  case WIFI_MOD_CLASS_DSSS:
477  {
478  return (GetConstellationSize () > mode.GetConstellationSize ());
479  }
480  else
481  {
482  return false;
483  }
486  {
487  return true;
488  }
489  else
490  {
491  return (GetConstellationSize () > mode.GetConstellationSize ());
492  }
494  case WIFI_MOD_CLASS_OFDM:
495  case WIFI_MOD_CLASS_HT:
496  case WIFI_MOD_CLASS_VHT:
498  {
499  return true;
500  }
501  else if (mode.GetModulationClass () == WIFI_MOD_CLASS_HR_DSSS)
502  {
503  return (mode.GetConstellationSize () > GetConstellationSize ());
504  }
505  else
506  {
508  {
509  return true;
510  }
511  else if (GetConstellationSize () == mode.GetConstellationSize ())
512  {
513  return IsHigherCodeRate (mode);
514  }
515  else
516  {
517  return false;
518  }
519  }
520  default:
521  NS_FATAL_ERROR ("Modulation class not defined");
522  return false;
523  }
524 }
525 
527  : m_uid (0)
528 {
529 }
530 
531 WifiMode::WifiMode (uint32_t uid)
532  : m_uid (uid)
533 {
534 }
535 
536 WifiMode::WifiMode (std::string name)
537 {
538  *this = WifiModeFactory::GetFactory ()->Search (name);
539 }
540 
542 
544 {
545 }
546 
547 WifiMode
548 WifiModeFactory::CreateWifiMode (std::string uniqueName,
549  enum WifiModulationClass modClass,
550  bool isMandatory,
551  enum WifiCodeRate codingRate,
552  uint16_t constellationSize)
553 {
554  WifiModeFactory *factory = GetFactory ();
555  uint32_t uid = factory->AllocateUid (uniqueName);
556  WifiModeItem *item = factory->Get (uid);
557  item->uniqueUid = uniqueName;
558  item->modClass = modClass;
559  //The modulation class for this WifiMode must be valid.
560  NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN);
561  item->codingRate = codingRate;
562 
563  //Check for compatibility between modulation class and coding
564  //rate. If modulation class is DSSS then coding rate must be
565  //undefined, and vice versa. I could have done this with an
566  //assertion, but it seems better to always give the error (i.e.,
567  //not only in non-optimised builds) and the cycles that extra test
568  //here costs are only suffered at simulation setup.
569  if ((codingRate == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS && modClass != WIFI_MOD_CLASS_HR_DSSS)
570  {
571  NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl
572  << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is WIFI_MOD_CLASS_DSSS or WIFI_MOD_CLASS_HR_DSSS");
573  }
574 
575  item->constellationSize = constellationSize;
576  item->isMandatory = isMandatory;
577 
578  NS_ASSERT (modClass != WIFI_MOD_CLASS_HT && modClass != WIFI_MOD_CLASS_VHT);
579  //fill unused mcs item with a dummy value
580  item->mcsValue = 0;
581 
582  return WifiMode (uid);
583 }
584 
585 WifiMode
586 WifiModeFactory::CreateWifiMcs (std::string uniqueName,
587  uint8_t mcsValue,
588  enum WifiModulationClass modClass)
589 {
590  WifiModeFactory *factory = GetFactory ();
591  uint32_t uid = factory->AllocateUid (uniqueName);
592  WifiModeItem *item = factory->Get (uid);
593  item->uniqueUid = uniqueName;
594  item->modClass = modClass;
595 
596  //The modulation class must be either HT or VHT
597  NS_ASSERT (modClass == WIFI_MOD_CLASS_HT || modClass == WIFI_MOD_CLASS_VHT);
598 
599  item->mcsValue = mcsValue;
600  //fill unused items with dummy values
601  item->constellationSize = 0;
603  item->isMandatory = false;
604 
605  return WifiMode (uid);
606 }
607 
608 WifiMode
609 WifiModeFactory::Search (std::string name)
610 {
611  WifiModeItemList::const_iterator i;
612  uint32_t j = 0;
613  for (i = m_itemList.begin (); i != m_itemList.end (); i++)
614  {
615  if (i->uniqueUid == name)
616  {
617  return WifiMode (j);
618  }
619  j++;
620  }
621 
622  //If we get here then a matching WifiMode was not found above. This
623  //is a fatal problem, but we try to be helpful by displaying the
624  //list of WifiModes that are supported.
625  NS_LOG_UNCOND ("Could not find match for WifiMode named \""
626  << name << "\". Valid options are:");
627  for (i = m_itemList.begin (); i != m_itemList.end (); i++)
628  {
629  NS_LOG_UNCOND (" " << i->uniqueUid);
630  }
631  //Empty fatal error to die. We've already unconditionally logged
632  //the helpful information.
633  NS_FATAL_ERROR ("");
634 
635  //This next line is unreachable because of the fatal error
636  //immediately above, and that is fortunate, because we have no idea
637  //what is in WifiMode (0), but we do know it is not what our caller
638  //has requested by name. It's here only because it's the safest
639  //thing that'll give valid code.
640  return WifiMode (0);
641 }
642 
643 uint32_t
644 WifiModeFactory::AllocateUid (std::string uniqueUid)
645 {
646  uint32_t j = 0;
647  for (WifiModeItemList::const_iterator i = m_itemList.begin ();
648  i != m_itemList.end (); i++)
649  {
650  if (i->uniqueUid == uniqueUid)
651  {
652  return j;
653  }
654  j++;
655  }
656  uint32_t uid = m_itemList.size ();
657  m_itemList.push_back (WifiModeItem ());
658  return uid;
659 }
660 
662 WifiModeFactory::Get (uint32_t uid)
663 {
664  NS_ASSERT (uid < m_itemList.size ());
665  return &m_itemList[uid];
666 }
667 
670 {
671  static bool isFirstTime = true;
672  static WifiModeFactory factory;
673  if (isFirstTime)
674  {
675  uint32_t uid = factory.AllocateUid ("Invalid-WifiMode");
676  WifiModeItem *item = factory.Get (uid);
677  item->uniqueUid = "Invalid-WifiMode";
679  item->constellationSize = 0;
681  item->isMandatory = false;
682  item->mcsValue = 0;
683  isFirstTime = false;
684  }
685  return &factory;
686 }
687 
688 } //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:526
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
enum WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:384
#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:162
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:355
static WifiMode CreateWifiMcs(std::string uniqueName, uint8_t mcsValue, enum WifiModulationClass modClass)
Definition: wifi-mode.cc:586
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:662
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:294
bool IsHigherDataRate(WifiMode mode) const
Definition: wifi-mode.cc:470
uint32_t m_uid
Definition: wifi-mode.h:218
enum WifiCodeRate GetCodeRate(void) const
Definition: wifi-mode.cc:242
uint32_t GetChannelWidth(void) const
HT PHY (Clause 20)
Definition: wifi-mode.h:62
uint8_t GetMcsValue(void) const
Definition: wifi-mode.cc:362
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:347
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
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionaly.
bool operator==(const BleAccessAddress &a, const BleAccessAddress &b)
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:391
static WifiMode CreateWifiMode(std::string uniqueName, enum WifiModulationClass modClass, bool isMandatory, enum WifiCodeRate codingRate, uint16_t constellationSize)
Definition: wifi-mode.cc:548
#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:90
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:450
OFDM PHY (Clause 17)
Definition: wifi-mode.h:60
static WifiModeFactory * GetFactory()
Return a WifiModeFactory.
Definition: wifi-mode.cc:669
uint32_t AllocateUid(std::string uniqueUid)
Allocate a WifiModeItem from a given uniqueUid.
Definition: wifi-mode.cc:644
enum WifiModulationClass modClass
Definition: wifi-mode.h:305
uint32_t GetUid(void) const
Definition: wifi-mode.cc:378
WifiMode Search(std::string name)
Search and return WifiMode from a given name.
Definition: wifi-mode.cc:609
ATTRIBUTE_HELPER_CPP(BleAccessAddress)
This is the data associated to a unique WifiMode.
Definition: wifi-mode.h:302
DSSS PHY (Clause 15)
Definition: wifi-mode.h:50