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 "ns3/simulator.h"
24 #include "ns3/assert.h"
25 #include "ns3/log.h"
26 #include <cmath>
27 
28 namespace ns3 {
29 
39 bool operator == (const WifiMode &a, const WifiMode &b)
40 {
41  return a.GetUid () == b.GetUid ();
42 }
51 std::ostream & operator << (std::ostream & os, const WifiMode &mode)
52 {
53  os << mode.GetUniqueName ();
54  return os;
55 }
64 std::istream & operator >> (std::istream &is, WifiMode &mode)
65 {
66  std::string str;
67  is >> str;
68  mode = WifiModeFactory::GetFactory ()->Search (str);
69  return is;
70 }
71 
72 uint64_t
73 WifiMode::GetPhyRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
74 {
75  uint32_t dataRate, phyRate;
76  dataRate = GetDataRate (channelWidth, isShortGuardInterval, nss);
77  switch (GetCodeRate (nss))
78  {
79  case WIFI_CODE_RATE_5_6:
80  phyRate = dataRate * 6 / 5;
81  break;
82  case WIFI_CODE_RATE_3_4:
83  phyRate = dataRate * 4 / 3;
84  break;
85  case WIFI_CODE_RATE_2_3:
86  phyRate = dataRate * 3 / 2;
87  break;
88  case WIFI_CODE_RATE_1_2:
89  phyRate = dataRate * 2 / 1;
90  break;
92  default:
93  phyRate = dataRate;
94  break;
95  }
96  return phyRate;
97 }
98 
99 uint64_t
100 WifiMode::GetDataRate (uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
101 {
103  uint64_t dataRate = 0;
104  if (nss > 1)
105  {
106  NS_FATAL_ERROR ("MIMO is not supported");
107  return 0;
108  }
109  if (item->modClass == WIFI_MOD_CLASS_DSSS)
110  {
111  dataRate = (11000000 / 11) * log2 (GetConstellationSize (1));
112  }
113  else if (item->modClass == WIFI_MOD_CLASS_HR_DSSS)
114  {
115  dataRate = (11000000 / 8) * log2 (GetConstellationSize (1));
116  }
117  else if (item->modClass == WIFI_MOD_CLASS_OFDM || item->modClass == WIFI_MOD_CLASS_ERP_OFDM)
118  {
119  double symbolRate = (1 / 4.0) * 1e6;
120 
121  uint32_t usableSubCarriers;
122  switch (channelWidth)
123  {
124  case 20:
125  default:
126  usableSubCarriers = 48;
127  break;
128  case 10:
129  usableSubCarriers = 24;
130  break;
131  case 5:
132  usableSubCarriers = 12;
133  break;
134  }
135 
136  double codingRate;
137  switch (GetCodeRate (1))
138  {
139  case WIFI_CODE_RATE_3_4:
140  codingRate = (3.0 / 4.0);
141  break;
142  case WIFI_CODE_RATE_2_3:
143  codingRate = (2.0 / 3.0);
144  break;
145  case WIFI_CODE_RATE_1_2:
146  codingRate = (1.0 / 2.0);
147  break;
149  default:
150  NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined");
151  break;
152  }
153 
154  uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize (1));
155 
156  dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
157  }
158  else if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
159  {
160  if (item->mcsValue == 9)
161  {
162  //VHT MCS 9 forbidden at 20 MHz
163  NS_ASSERT (channelWidth != 20);
164  }
165 
166  double symbolRate;
167  if (!isShortGuardInterval)
168  {
169  symbolRate = (1 / 4.0) * 1e6;
170  }
171  else
172  {
173  symbolRate = (1 / 3.6) * 1e6;
174  }
175 
176  uint32_t usableSubCarriers;
177  switch (channelWidth)
178  {
179  case 20:
180  default:
181  usableSubCarriers = 52;
182  break;
183  case 40:
184  usableSubCarriers = 108;
185  break;
186  case 80:
187  usableSubCarriers = 234;
188  break;
189  case 160:
190  usableSubCarriers = 468;
191  break;
192  }
193 
194  double codingRate;
195  switch (GetCodeRate (nss))
196  {
197  case WIFI_CODE_RATE_5_6:
198  codingRate = (5.0 / 6.0);
199  break;
200  case WIFI_CODE_RATE_3_4:
201  codingRate = (3.0 / 4.0);
202  break;
203  case WIFI_CODE_RATE_2_3:
204  codingRate = (2.0 / 3.0);
205  break;
206  case WIFI_CODE_RATE_1_2:
207  codingRate = (1.0 / 2.0);
208  break;
210  default:
211  NS_FATAL_ERROR ("trying to get datarate for a mcs without any coding rate defined");
212  break;
213  }
214 
215  uint32_t numberOfBitsPerSubcarrier = log2 (GetConstellationSize (nss));
216 
217  dataRate = lrint (ceil (symbolRate * usableSubCarriers * numberOfBitsPerSubcarrier * codingRate));
218  }
219  else
220  {
221  NS_ASSERT ("undefined datarate for the modulation class!");
222  }
223  return dataRate;
224 }
225 
226 enum WifiCodeRate
227 WifiMode::GetCodeRate (uint8_t nss) const
228 {
230  if (item->modClass == WIFI_MOD_CLASS_HT)
231  {
232  NS_ASSERT (nss <= 4);
233  NS_ASSERT ((item->mcsValue - (8 * (nss - 1))) >= 0 || (item->mcsValue - (8 * (nss - 1))) <= 7);
234  switch (item->mcsValue - (8 * (nss - 1)))
235  {
236  case 0:
237  case 1:
238  case 3:
239  return WIFI_CODE_RATE_1_2;
240  case 2:
241  case 4:
242  case 6:
243  return WIFI_CODE_RATE_3_4;
244  case 5:
245  return WIFI_CODE_RATE_2_3;
246  case 7:
247  return WIFI_CODE_RATE_5_6;
248  default:
250  }
251  }
252  else if (item->modClass == WIFI_MOD_CLASS_VHT)
253  {
254  NS_ASSERT (nss <= 8);
255  switch (item->mcsValue)
256  {
257  case 0:
258  case 1:
259  case 3:
260  return WIFI_CODE_RATE_1_2;
261  case 2:
262  case 4:
263  case 6:
264  case 8:
265  return WIFI_CODE_RATE_3_4;
266  case 5:
267  return WIFI_CODE_RATE_2_3;
268  case 7:
269  case 9:
270  return WIFI_CODE_RATE_5_6;
271  default:
273  }
274  }
275  else
276  {
277  return item->codingRate;
278  }
279 }
280 
281 uint16_t
283 {
285  if (item->modClass == WIFI_MOD_CLASS_HT)
286  {
287  NS_ASSERT (nss <= 4);
288  NS_ASSERT ((item->mcsValue - (8 * (nss - 1))) >= 0 || (item->mcsValue - (8 * (nss - 1))) <= 7);
289  switch (item->mcsValue - (8 * (nss - 1)))
290  {
291  case 0:
292  return 2;
293  case 1:
294  case 2:
295  return 4;
296  case 3:
297  case 4:
298  return 16;
299  case 5:
300  case 6:
301  case 7:
302  return 64;
303  default:
304  return 0;
305  }
306  }
307  else if (item->modClass == WIFI_MOD_CLASS_VHT)
308  {
309  NS_ASSERT (nss <= 8);
310  switch (item->mcsValue)
311  {
312  case 0:
313  return 2;
314  case 1:
315  case 2:
316  return 4;
317  case 3:
318  case 4:
319  return 16;
320  case 5:
321  case 6:
322  case 7:
323  return 64;
324  case 8:
325  case 9:
326  return 256;
327  default:
328  return 0;
329  }
330  }
331  else
332  {
333  return item->constellationSize;
334  }
335 }
336 
337 std::string
339 {
340  //needed for ostream printing of the invalid mode
342  return item->uniqueUid;
343 }
344 
345 bool
347 {
349  return item->isMandatory;
350 }
351 
352 uint8_t
354 {
356  if (item->modClass == WIFI_MOD_CLASS_HT || item->modClass == WIFI_MOD_CLASS_VHT)
357  {
358  return item->mcsValue;
359  }
360  else
361  {
362  //We should not go here!
363  NS_ASSERT (false);
364  return 0;
365  }
366 }
367 
368 uint32_t
369 WifiMode::GetUid (void) const
370 {
371  return m_uid;
372 }
373 
376 {
378  return item->modClass;
379 }
380 
382  : m_uid (0)
383 {
384 }
385 
386 WifiMode::WifiMode (uint32_t uid)
387  : m_uid (uid)
388 {
389 }
390 
391 WifiMode::WifiMode (std::string name)
392 {
393  *this = WifiModeFactory::GetFactory ()->Search (name);
394 }
395 
397 
399 {
400 }
401 
402 WifiMode
403 WifiModeFactory::CreateWifiMode (std::string uniqueName,
404  enum WifiModulationClass modClass,
405  bool isMandatory,
406  enum WifiCodeRate codingRate,
407  uint16_t constellationSize)
408 {
409  WifiModeFactory *factory = GetFactory ();
410  uint32_t uid = factory->AllocateUid (uniqueName);
411  WifiModeItem *item = factory->Get (uid);
412  item->uniqueUid = uniqueName;
413  item->modClass = modClass;
414  //The modulation class for this WifiMode must be valid.
415  NS_ASSERT (modClass != WIFI_MOD_CLASS_UNKNOWN);
416  item->codingRate = codingRate;
417 
418  //Check for compatibility between modulation class and coding
419  //rate. If modulation class is DSSS then coding rate must be
420  //undefined, and vice versa. I could have done this with an
421  //assertion, but it seems better to always give the error (i.e.,
422  //not only in non-optimised builds) and the cycles that extra test
423  //here costs are only suffered at simulation setup.
424  if ((codingRate == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS && modClass != WIFI_MOD_CLASS_HR_DSSS)
425  {
426  NS_FATAL_ERROR ("Error in creation of WifiMode named " << uniqueName << std::endl
427  << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is WIFI_MOD_CLASS_DSSS or WIFI_MOD_CLASS_HR_DSSS");
428  }
429 
430  item->constellationSize = constellationSize;
431  item->isMandatory = isMandatory;
432 
433  NS_ASSERT (modClass != WIFI_MOD_CLASS_HT && modClass != WIFI_MOD_CLASS_VHT);
434  //fill unused mcs item with a dummy value
435  item->mcsValue = 0;
436 
437  return WifiMode (uid);
438 }
439 
440 WifiMode
441 WifiModeFactory::CreateWifiMcs (std::string uniqueName,
442  uint8_t mcsValue,
443  enum WifiModulationClass modClass)
444 {
445  WifiModeFactory *factory = GetFactory ();
446  uint32_t uid = factory->AllocateUid (uniqueName);
447  WifiModeItem *item = factory->Get (uid);
448  item->uniqueUid = uniqueName;
449  item->modClass = modClass;
450 
451  //The modulation class must be either HT or VHT
452  NS_ASSERT (modClass == WIFI_MOD_CLASS_HT || modClass == WIFI_MOD_CLASS_VHT);
453 
454  item->mcsValue = mcsValue;
455  //fill unused items with dummy values
456  item->constellationSize = 0;
458  item->isMandatory = false;
459 
460  return WifiMode (uid);
461 }
462 
463 WifiMode
464 WifiModeFactory::Search (std::string name)
465 {
466  WifiModeItemList::const_iterator i;
467  uint32_t j = 0;
468  for (i = m_itemList.begin (); i != m_itemList.end (); i++)
469  {
470  if (i->uniqueUid == name)
471  {
472  return WifiMode (j);
473  }
474  j++;
475  }
476 
477  //If we get here then a matching WifiMode was not found above. This
478  //is a fatal problem, but we try to be helpful by displaying the
479  //list of WifiModes that are supported.
480  NS_LOG_UNCOND ("Could not find match for WifiMode named \""
481  << name << "\". Valid options are:");
482  for (i = m_itemList.begin (); i != m_itemList.end (); i++)
483  {
484  NS_LOG_UNCOND (" " << i->uniqueUid);
485  }
486  //Empty fatal error to die. We've already unconditionally logged
487  //the helpful information.
488  NS_FATAL_ERROR ("");
489 
490  //This next line is unreachable because of the fatal error
491  //immediately above, and that is fortunate, because we have no idea
492  //what is in WifiMode (0), but we do know it is not what our caller
493  //has requested by name. It's here only because it's the safest
494  //thing that'll give valid code.
495  return WifiMode (0);
496 }
497 
498 uint32_t
499 WifiModeFactory::AllocateUid (std::string uniqueUid)
500 {
501  uint32_t j = 0;
502  for (WifiModeItemList::const_iterator i = m_itemList.begin ();
503  i != m_itemList.end (); i++)
504  {
505  if (i->uniqueUid == uniqueUid)
506  {
507  return j;
508  }
509  j++;
510  }
511  uint32_t uid = m_itemList.size ();
512  m_itemList.push_back (WifiModeItem ());
513  return uid;
514 }
515 
517 WifiModeFactory::Get (uint32_t uid)
518 {
519  NS_ASSERT (uid < m_itemList.size ());
520  return &m_itemList[uid];
521 }
522 
525 {
526  static bool isFirstTime = true;
527  static WifiModeFactory factory;
528  if (isFirstTime)
529  {
530  uint32_t uid = factory.AllocateUid ("Invalid-WifiMode");
531  WifiModeItem *item = factory.Get (uid);
532  item->uniqueUid = "Invalid-WifiMode";
534  item->constellationSize = 0;
536  item->isMandatory = false;
537  item->mcsValue = 0;
538  isFirstTime = false;
539  }
540  return &factory;
541 }
542 
543 } //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:381
ERP-OFDM PHY (19.5)
Definition: wifi-mode.h:56
enum WifiCodeRate GetCodeRate(uint8_t nss) const
Definition: wifi-mode.cc:227
WifiCodeRate
This enumeration defines the various convolutional coding rates used for the OFDM transmission modes ...
Definition: wifi-mode.h:72
uint16_t GetConstellationSize(uint8_t nss) const
Definition: wifi-mode.cc:282
#define ATTRIBUTE_HELPER_CPP(type)
Define the attribute value, accessor and checkers for class type.
enum WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:375
#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
#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:62
HR/DSSS PHY (Clause 18)
Definition: wifi-mode.h:50
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:97
bool IsMandatory(void) const
Definition: wifi-mode.cc:346
static WifiMode CreateWifiMcs(std::string uniqueName, uint8_t mcsValue, enum WifiModulationClass modClass)
Definition: wifi-mode.cc:441
Modulation class unknown or unspecified.
Definition: wifi-mode.h:42
WifiModeItem * Get(uint32_t uid)
Return a WifiModeItem at the given uid index.
Definition: wifi-mode.cc:517
uint64_t GetPhyRate(uint32_t channelWidth, bool isShortGuardInterval, uint8_t nss) const
Definition: wifi-mode.cc:73
uint32_t m_uid
Definition: wifi-mode.h:188
HT PHY (Clause 20)
Definition: wifi-mode.h:60
uint8_t GetMcsValue(void) const
Definition: wifi-mode.cc:353
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:338
WifiModeItemList m_itemList
Definition: wifi-mode.h:311
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:100
friend class WifiMode
Definition: wifi-mode.h:256
static WifiMode CreateWifiMode(std::string uniqueName, enum WifiModulationClass modClass, bool isMandatory, enum WifiCodeRate codingRate, uint16_t constellationSize)
Definition: wifi-mode.cc:403
No explicit coding (e.g., DSSS rates)
Definition: wifi-mode.h:75
create WifiMode class instances and keep track of them.
Definition: wifi-mode.h:215
WifiModulationClass
This enumeration defines the modulation classes per (Table 9-4 "Modulation classes"; IEEE 802...
Definition: wifi-mode.h:38
OFDM PHY (Clause 17)
Definition: wifi-mode.h:58
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.cc:95
static WifiModeFactory * GetFactory()
Return a WifiModeFactory.
Definition: wifi-mode.cc:524
uint32_t AllocateUid(std::string uniqueUid)
Allocate a WifiModeItem from a given uniqueUid.
Definition: wifi-mode.cc:499
enum WifiModulationClass modClass
Definition: wifi-mode.h:275
uint32_t GetUid(void) const
Definition: wifi-mode.cc:369
WifiMode Search(std::string name)
Search and return WifiMode from a given name.
Definition: wifi-mode.cc:464
This is the data associated to a unique WifiMode.
Definition: wifi-mode.h:272
DSSS PHY (Clause 15)
Definition: wifi-mode.h:48