A Discrete-Event Network Simulator
API
wifi-mode.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005,2006,2007 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  * Sébastien Deronne <sebastien.deronne@gmail.com>
19  */
20 
21 #include "wifi-mode.h"
22 
23 #include "wifi-tx-vector.h"
24 
25 #include "ns3/he-ru.h"
26 #include "ns3/log.h"
27 
28 #include <cmath>
29 
30 namespace ns3
31 {
32 
33 bool
34 operator==(const WifiMode& a, const WifiMode& b)
35 {
36  return a.GetUid() == b.GetUid();
37 }
38 
39 bool
40 operator!=(const WifiMode& a, const WifiMode& b)
41 {
42  return a.GetUid() != b.GetUid();
43 }
44 
45 bool
46 operator<(const WifiMode& a, const WifiMode& b)
47 {
48  return a.GetUid() < b.GetUid();
49 }
50 
51 std::ostream&
52 operator<<(std::ostream& os, const WifiMode& mode)
53 {
54  os << mode.GetUniqueName();
55  return os;
56 }
57 
58 std::istream&
59 operator>>(std::istream& is, WifiMode& mode)
60 {
61  std::string str;
62  is >> str;
63  mode = WifiModeFactory::GetFactory()->Search(str);
64  return is;
65 }
66 
67 bool
68 WifiMode::IsAllowed(uint16_t channelWidth, uint8_t nss) const
69 {
70  WifiTxVector txVector;
71  txVector.SetMode(WifiMode(m_uid));
72  txVector.SetChannelWidth(channelWidth);
73  txVector.SetNss(nss);
74  return IsAllowed(txVector);
75 }
76 
77 bool
78 WifiMode::IsAllowed(const WifiTxVector& txVector) const
79 {
81  return item->IsAllowedCallback(txVector);
82 }
83 
84 uint64_t
85 WifiMode::GetPhyRate(uint16_t channelWidth) const
86 {
87  return GetPhyRate(channelWidth, 800, 1);
88 }
89 
90 uint64_t
91 WifiMode::GetPhyRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
92 {
93  WifiTxVector txVector;
94  txVector.SetMode(WifiMode(m_uid));
95  txVector.SetChannelWidth(channelWidth);
96  txVector.SetGuardInterval(guardInterval);
97  txVector.SetNss(nss);
98  return GetPhyRate(txVector);
99 }
100 
101 uint64_t
102 WifiMode::GetPhyRate(const WifiTxVector& txVector, uint16_t staId) const
103 {
105  return item->GetPhyRateCallback(txVector, staId);
106 }
107 
108 uint64_t
109 WifiMode::GetDataRate(uint16_t channelWidth) const
110 {
111  return GetDataRate(channelWidth, 800, 1);
112 }
113 
114 uint64_t
115 WifiMode::GetDataRate(const WifiTxVector& txVector, uint16_t staId) const
116 {
118  return item->GetDataRateCallback(txVector, staId);
119 }
120 
121 uint64_t
122 WifiMode::GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
123 {
124  NS_ASSERT(nss <= 8);
125  WifiTxVector txVector;
126  txVector.SetMode(WifiMode(m_uid));
127  txVector.SetChannelWidth(channelWidth);
128  txVector.SetGuardInterval(guardInterval);
129  txVector.SetNss(nss);
130  return GetDataRate(txVector);
131 }
132 
135 {
137  return item->GetCodeRateCallback();
138 }
139 
140 uint16_t
142 {
144  return item->GetConstellationSizeCallback();
145 }
146 
147 std::string
149 {
150  // needed for ostream printing of the invalid mode
152  return item->uniqueUid;
153 }
154 
155 bool
157 {
159  return item->isMandatory;
160 }
161 
162 uint8_t
164 {
166  if (item->modClass >= WIFI_MOD_CLASS_HT)
167  {
168  return item->mcsValue;
169  }
170  else
171  {
172  // We should not go here!
173  NS_ASSERT(false);
174  return 0;
175  }
176 }
177 
178 uint32_t
180 {
181  return m_uid;
182 }
183 
186 {
188  return item->modClass;
189 }
190 
191 uint64_t
193 {
196  "Trying to get HT reference rate for a non-HT rate");
197  return item->GetNonHtReferenceRateCallback();
198 }
199 
200 bool
202 {
203  NS_ASSERT_MSG(GetCodeRate() != WIFI_CODE_RATE_UNDEFINED, "Wifi Code Rate not defined");
204  return (GetCodeRate() > mode.GetCodeRate());
205 }
206 
207 bool
209 {
210  // If current modulation class is DSSS and other is not, the other is always higher
213  {
214  return false;
215  }
216  // If other modulation class is DSSS and current is not, the current is always higher
217  else if (GetModulationClass() != WIFI_MOD_CLASS_DSSS &&
219  {
220  return true;
221  }
222  // If current is not HR/DSSS while other is not, check constellation size of other against
223  // current
226  {
227  return (mode.GetConstellationSize() > GetConstellationSize());
228  }
229  // This block is for current and other mode > HR/DSSS, if constellation size
230  // is the same, check the code rate (DSSS and HR/DSSS does not define code rate)
231  else if (GetConstellationSize() == mode.GetConstellationSize() &&
234  {
235  return IsHigherCodeRate(mode);
236  }
237  // Otherwise, check constellation size of current against other,
238  // the code go here if:
239  // - both current and other mode is DSSS
240  // - current mode is HR/DSSS and other mode is not HR/DSSS
241  // - current and other mode > HR/DSSS and both constellation size is not equal
242  else
243  {
244  return (GetConstellationSize() > mode.GetConstellationSize());
245  }
246 }
247 
249  : m_uid(0)
250 {
251 }
252 
253 WifiMode::WifiMode(uint32_t uid)
254  : m_uid(uid)
255 {
256 }
257 
258 WifiMode::WifiMode(std::string name)
259 {
260  *this = WifiModeFactory::GetFactory()->Search(name);
261 }
262 
264 
266 {
267 }
268 
269 WifiMode
270 WifiModeFactory::CreateWifiMode(std::string uniqueName,
271  WifiModulationClass modClass,
272  bool isMandatory,
273  CodeRateCallback codeRateCallback,
274  ConstellationSizeCallback constellationSizeCallback,
275  PhyRateCallback phyRateCallback,
276  DataRateCallback dataRateCallback,
277  AllowedCallback isAllowedCallback)
278 {
279  WifiModeFactory* factory = GetFactory();
280  uint32_t uid = factory->AllocateUid(uniqueName);
281  WifiModeItem* item = factory->Get(uid);
282  item->uniqueUid = uniqueName;
283  item->modClass = modClass;
284  // The modulation class for this WifiMode must be valid.
285  NS_ASSERT(modClass != WIFI_MOD_CLASS_UNKNOWN);
286 
287  // Check for compatibility between modulation class and coding
288  // rate. If modulation class is DSSS then coding rate must be
289  // undefined, and vice versa. I could have done this with an
290  // assertion, but it seems better to always give the error (i.e.,
291  // not only in non-optimised builds) and the cycles that extra test
292  // here costs are only suffered at simulation setup.
293  if ((codeRateCallback() == WIFI_CODE_RATE_UNDEFINED) && modClass != WIFI_MOD_CLASS_DSSS &&
294  modClass != WIFI_MOD_CLASS_HR_DSSS)
295  {
296  NS_FATAL_ERROR("Error in creation of WifiMode named "
297  << uniqueName << std::endl
298  << "Code rate must be WIFI_CODE_RATE_UNDEFINED iff Modulation Class is "
299  "WIFI_MOD_CLASS_DSSS or WIFI_MOD_CLASS_HR_DSSS");
300  }
301 
302  item->isMandatory = isMandatory;
303  item->GetCodeRateCallback = codeRateCallback;
304  item->GetConstellationSizeCallback = constellationSizeCallback;
305  item->GetPhyRateCallback = phyRateCallback;
306  item->GetDataRateCallback = dataRateCallback;
307  item->GetNonHtReferenceRateCallback = MakeNullCallback<uint64_t>();
308  item->IsAllowedCallback = isAllowedCallback;
309 
310  NS_ASSERT(modClass < WIFI_MOD_CLASS_HT);
311  // fill unused MCS item with a dummy value
312  item->mcsValue = 0;
313 
314  return WifiMode(uid);
315 }
316 
317 WifiMode
318 WifiModeFactory::CreateWifiMcs(std::string uniqueName,
319  uint8_t mcsValue,
320  WifiModulationClass modClass,
321  bool isMandatory,
322  CodeRateCallback codeRateCallback,
323  ConstellationSizeCallback constellationSizeCallback,
324  PhyRateCallback phyRateCallback,
325  DataRateCallback dataRateCallback,
326  NonHtReferenceRateCallback nonHtReferenceRateCallback,
327  AllowedCallback isAllowedCallback)
328 {
329  WifiModeFactory* factory = GetFactory();
330  uint32_t uid = factory->AllocateUid(uniqueName);
331  WifiModeItem* item = factory->Get(uid);
332  item->uniqueUid = uniqueName;
333  item->modClass = modClass;
334 
335  NS_ASSERT(modClass >= WIFI_MOD_CLASS_HT);
336 
337  item->mcsValue = mcsValue;
338  item->isMandatory = isMandatory;
339  item->GetCodeRateCallback = codeRateCallback;
340  item->GetConstellationSizeCallback = constellationSizeCallback;
341  item->GetPhyRateCallback = phyRateCallback;
342  item->GetDataRateCallback = dataRateCallback;
343  item->GetNonHtReferenceRateCallback = nonHtReferenceRateCallback;
344  item->IsAllowedCallback = isAllowedCallback;
345 
346  return WifiMode(uid);
347 }
348 
349 WifiMode
350 WifiModeFactory::Search(std::string name) const
351 {
352  uint32_t j = 0;
353  for (auto i = m_itemList.begin(); i != m_itemList.end(); i++)
354  {
355  if (i->uniqueUid == name)
356  {
357  return WifiMode(j);
358  }
359  j++;
360  }
361 
362  // If we get here then a matching WifiMode was not found above. This
363  // is a fatal problem, but we try to be helpful by displaying the
364  // list of WifiModes that are supported.
365  NS_LOG_UNCOND("Could not find match for WifiMode named \"" << name << "\". Valid options are:");
366  for (auto i = m_itemList.begin(); i != m_itemList.end(); i++)
367  {
368  NS_LOG_UNCOND(" " << i->uniqueUid);
369  }
370  // Empty fatal error to die. We've already unconditionally logged
371  // the helpful information.
372  NS_FATAL_ERROR("");
373 
374  // This next line is unreachable because of the fatal error
375  // immediately above, and that is fortunate, because we have no idea
376  // what is in WifiMode (0), but we do know it is not what our caller
377  // has requested by name. It's here only because it's the safest
378  // thing that'll give valid code.
379  return WifiMode(0);
380 }
381 
382 uint32_t
383 WifiModeFactory::AllocateUid(std::string uniqueUid)
384 {
385  uint32_t j = 0;
386  for (auto i = m_itemList.begin(); i != m_itemList.end(); i++)
387  {
388  if (i->uniqueUid == uniqueUid)
389  {
390  return j;
391  }
392  j++;
393  }
394  auto uid = static_cast<uint32_t>(m_itemList.size());
395  m_itemList.emplace_back();
396  return uid;
397 }
398 
400 WifiModeFactory::Get(uint32_t uid)
401 {
402  NS_ASSERT(uid < m_itemList.size());
403  return &m_itemList[uid];
404 }
405 
408 {
409  static bool isFirstTime = true;
410  static WifiModeFactory factory;
411  if (isFirstTime)
412  {
413  uint32_t uid = factory.AllocateUid("Invalid-WifiMode");
414  WifiModeItem* item = factory.Get(uid);
415  item->uniqueUid = "Invalid-WifiMode";
417  item->isMandatory = false;
418  item->mcsValue = 0;
419  item->GetCodeRateCallback = MakeNullCallback<WifiCodeRate>();
420  item->GetConstellationSizeCallback = MakeNullCallback<uint16_t>();
421  item->GetPhyRateCallback = MakeNullCallback<uint64_t, const WifiTxVector&, uint16_t>();
422  item->GetDataRateCallback = MakeNullCallback<uint64_t, const WifiTxVector&, uint16_t>();
423  item->GetNonHtReferenceRateCallback = MakeNullCallback<uint64_t>();
424  item->IsAllowedCallback = MakeNullCallback<bool, const WifiTxVector&>();
425  isFirstTime = false;
426  }
427  return &factory;
428 }
429 
430 } // namespace ns3
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
create WifiMode class instances and keep track of them.
Definition: wifi-mode.h:275
WifiModeItem * Get(uint32_t uid)
Return a WifiModeItem at the given UID index.
Definition: wifi-mode.cc:400
static WifiMode CreateWifiMcs(std::string uniqueName, uint8_t mcsValue, WifiModulationClass modClass, bool isMandatory, CodeRateCallback codeRateCallback, ConstellationSizeCallback constellationSizeCallback, PhyRateCallback phyRateCallback, DataRateCallback dataRateCallback, NonHtReferenceRateCallback nonHtReferenceRateCallback, AllowedCallback isAllowedCallback)
Definition: wifi-mode.cc:318
uint32_t AllocateUid(std::string uniqueUid)
Allocate a WifiModeItem from a given uniqueUid.
Definition: wifi-mode.cc:383
static WifiModeFactory * GetFactory()
Return a WifiModeFactory.
Definition: wifi-mode.cc:407
WifiModeItemList m_itemList
item list
Definition: wifi-mode.h:459
WifiMode Search(std::string name) const
Search and return WifiMode from a given name.
Definition: wifi-mode.cc:350
static WifiMode CreateWifiMode(std::string uniqueName, WifiModulationClass modClass, bool isMandatory, CodeRateCallback codeRateCallback, ConstellationSizeCallback constellationSizeCallback, PhyRateCallback phyRateCallback, DataRateCallback dataRateCallback, AllowedCallback isAllowedCallback)
Definition: wifi-mode.cc:270
friend class WifiMode
allow WifiMode class access
Definition: wifi-mode.h:392
represent a single transmission mode
Definition: wifi-mode.h:51
WifiMode()
Create an invalid WifiMode.
Definition: wifi-mode.cc:248
uint32_t GetUid() const
Definition: wifi-mode.cc:179
std::string GetUniqueName() const
Definition: wifi-mode.cc:148
bool IsHigherDataRate(WifiMode mode) const
Definition: wifi-mode.cc:208
uint16_t GetConstellationSize() const
Definition: wifi-mode.cc:141
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:185
uint64_t GetPhyRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:91
bool IsMandatory() const
Definition: wifi-mode.cc:156
uint64_t GetNonHtReferenceRate() const
Definition: wifi-mode.cc:192
WifiCodeRate GetCodeRate() const
Definition: wifi-mode.cc:134
uint32_t m_uid
UID.
Definition: wifi-mode.h:199
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
bool IsHigherCodeRate(WifiMode mode) const
Definition: wifi-mode.cc:201
bool IsAllowed(uint16_t channelWidth, uint8_t nss) const
Definition: wifi-mode.cc:68
uint8_t GetMcsValue() const
Definition: wifi-mode.cc:163
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionally.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
@ WIFI_MOD_CLASS_HR_DSSS
HR/DSSS (Clause 16)
@ WIFI_MOD_CLASS_UNKNOWN
Modulation class unknown or unspecified.
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_DSSS
DSSS (Clause 15)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
Definition: callback.h:678
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:157
ATTRIBUTE_HELPER_CPP(ValueClassTest)
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:170
std::istream & operator>>(std::istream &is, Angles &a)
Definition: angles.cc:183
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
WifiCodeRate
These constants define the various convolutional coding rates used for the OFDM transmission modes in...
@ WIFI_CODE_RATE_UNDEFINED
undefined coding rate
This is the data associated to a unique WifiMode.
Definition: wifi-mode.h:409
WifiModulationClass modClass
modulation class
Definition: wifi-mode.h:411
AllowedCallback IsAllowedCallback
Callback to check whether a given combination of is allowed.
Definition: wifi-mode.h:427
std::string uniqueUid
unique UID
Definition: wifi-mode.h:410
bool isMandatory
flag to indicate whether this mode is mandatory
Definition: wifi-mode.h:412
PhyRateCallback GetPhyRateCallback
Callback to calculate PHY rate in bps of this WifiModeItem.
Definition: wifi-mode.h:420
DataRateCallback GetDataRateCallback
Callback to calculate data rate in bps of this WifiModeItem.
Definition: wifi-mode.h:422
NonHtReferenceRateCallback GetNonHtReferenceRateCallback
Callback to calculate non-HT reference rate of this WifiModeItem.
Definition: wifi-mode.h:424
ConstellationSizeCallback GetConstellationSizeCallback
Callback to retrieve constellation size of this WifiModeItem.
Definition: wifi-mode.h:417
CodeRateCallback GetCodeRateCallback
Callback to retrieve code rate of this WifiModeItem.
Definition: wifi-mode.h:415