A Discrete-Event Network Simulator
API
wifi-tx-vector.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2010 CTTC
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: Nicola Baldo <nbaldo@cttc.es>
19  * Ghada Badawy <gbadawy@gmail.com>
20  */
21 
22 #include "wifi-tx-vector.h"
23 #include "wifi-phy-common.h"
24 #include "ns3/abort.h"
25 
26 namespace ns3 {
27 
29  : m_preamble (WIFI_PREAMBLE_LONG),
30  m_channelWidth (20),
31  m_guardInterval (800),
32  m_nTx (1),
33  m_nss (1),
34  m_ness (0),
35  m_aggregation (false),
36  m_stbc (false),
37  m_ldpc (false),
38  m_bssColor (0),
39  m_length (0),
40  m_modeInitialized (false)
41 {
42 }
43 
45  uint8_t powerLevel,
46  WifiPreamble preamble,
47  uint16_t guardInterval,
48  uint8_t nTx,
49  uint8_t nss,
50  uint8_t ness,
51  uint16_t channelWidth,
52  bool aggregation,
53  bool stbc,
54  bool ldpc,
55  uint8_t bssColor,
56  uint16_t length)
57  : m_mode (mode),
58  m_txPowerLevel (powerLevel),
59  m_preamble (preamble),
60  m_channelWidth (channelWidth),
61  m_guardInterval (guardInterval),
62  m_nTx (nTx),
63  m_nss (nss),
64  m_ness (ness),
65  m_aggregation (aggregation),
66  m_stbc (stbc),
67  m_ldpc (ldpc),
68  m_bssColor (bssColor),
69  m_length (length),
70  m_modeInitialized (true)
71 {
72 }
73 
75  : m_mode (txVector.m_mode),
76  m_txPowerLevel (txVector.m_txPowerLevel),
77  m_preamble (txVector.m_preamble),
78  m_channelWidth (txVector.m_channelWidth),
79  m_guardInterval (txVector.m_guardInterval),
80  m_nTx (txVector.m_nTx),
81  m_nss (txVector.m_nss),
82  m_ness (txVector.m_ness),
83  m_aggregation (txVector.m_aggregation),
84  m_stbc (txVector.m_stbc),
85  m_ldpc (txVector.m_ldpc),
86  m_bssColor (txVector.m_bssColor),
87  m_length (txVector.m_length),
88  m_modeInitialized (txVector.m_modeInitialized)
89 {
90  m_muUserInfos.clear ();
91  if (!txVector.m_muUserInfos.empty ()) //avoids crashing for loop
92  {
93  for (auto & info : txVector.m_muUserInfos)
94  {
95  m_muUserInfos.insert (std::make_pair (info.first, info.second));
96  }
97  }
98 }
99 
101 {
102  m_muUserInfos.clear ();
103 }
104 
105 bool
107 {
108  return m_modeInitialized;
109 }
110 
111 WifiMode
112 WifiTxVector::GetMode (uint16_t staId) const
113 {
114  if (!m_modeInitialized)
115  {
116  NS_FATAL_ERROR ("WifiTxVector mode must be set before using");
117  }
118  if (IsMu ())
119  {
120  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
121  NS_ASSERT (m_muUserInfos.find (staId) != m_muUserInfos.end ());
122  return m_muUserInfos.at (staId).mcs;
123  }
124  return m_mode;
125 }
126 
129 {
130  NS_ABORT_MSG_IF (!m_modeInitialized, "WifiTxVector mode must be set before using");
131 
132  if (IsMu ())
133  {
134  NS_ASSERT (!m_muUserInfos.empty ());
135  // all the modes belong to the same modulation class
136  return m_muUserInfos.begin ()->second.mcs.GetModulationClass ();
137  }
138  return m_mode.GetModulationClass ();
139 }
140 
141 uint8_t
143 {
144  return m_txPowerLevel;
145 }
146 
149 {
150  return m_preamble;
151 }
152 
153 uint16_t
155 {
156  return m_channelWidth;
157 }
158 
159 uint16_t
161 {
162  return m_guardInterval;
163 }
164 
165 uint8_t
167 {
168  return m_nTx;
169 }
170 
171 uint8_t
172 WifiTxVector::GetNss (uint16_t staId) const
173 {
174  if (IsMu ())
175  {
176  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU (" << staId << ")");
177  NS_ASSERT (m_muUserInfos.find (staId) != m_muUserInfos.end ());
178  return m_muUserInfos.at (staId).nss;
179  }
180  return m_nss;
181 }
182 
183 uint8_t
185 {
186  uint8_t nss = 0;
187  if (IsMu ())
188  {
189  for (const auto & info : m_muUserInfos)
190  {
191  nss = (nss < info.second.nss) ? info.second.nss : nss;
192  }
193  }
194  else
195  {
196  nss = m_nss;
197  }
198  return nss;
199 }
200 
201 uint8_t
203 {
204  return m_ness;
205 }
206 
207 bool
209 {
210  return m_aggregation;
211 }
212 
213 bool
215 {
216  return m_stbc;
217 }
218 
219 bool
221 {
222  return m_ldpc;
223 }
224 
225 void
227 {
228  m_mode = mode;
229  m_modeInitialized = true;
230 }
231 
232 void
233 WifiTxVector::SetMode (WifiMode mode, uint16_t staId)
234 {
235  NS_ABORT_MSG_IF (!IsMu (), "Not a MU transmission");
236  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU");
237  m_muUserInfos[staId].mcs = mode;
238  m_modeInitialized = true;
239 }
240 
241 void
242 WifiTxVector::SetTxPowerLevel (uint8_t powerlevel)
243 {
244  m_txPowerLevel = powerlevel;
245 }
246 
247 void
249 {
250  m_preamble = preamble;
251 }
252 
253 void
254 WifiTxVector::SetChannelWidth (uint16_t channelWidth)
255 {
256  m_channelWidth = channelWidth;
257 }
258 
259 void
260 WifiTxVector::SetGuardInterval (uint16_t guardInterval)
261 {
262  m_guardInterval = guardInterval;
263 }
264 
265 void
266 WifiTxVector::SetNTx (uint8_t nTx)
267 {
268  m_nTx = nTx;
269 }
270 
271 void
272 WifiTxVector::SetNss (uint8_t nss)
273 {
274  m_nss = nss;
275 }
276 
277 void
278 WifiTxVector::SetNss (uint8_t nss, uint16_t staId)
279 {
280  NS_ABORT_MSG_IF (!IsMu (), "Not a MU transmission");
281  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU");
282  m_muUserInfos[staId].nss = nss;
283 }
284 
285 void
286 WifiTxVector::SetNess (uint8_t ness)
287 {
288  m_ness = ness;
289 }
290 
291 void
293 {
294  m_aggregation = aggregation;
295 }
296 
297 void
299 {
300  m_stbc = stbc;
301 }
302 
303 void
305 {
306  m_ldpc = ldpc;
307 }
308 
309 void
311 {
312  m_bssColor = color;
313 }
314 
315 uint8_t
317 {
318  return m_bssColor;
319 }
320 
321 void
322 WifiTxVector::SetLength (uint16_t length)
323 {
324  m_length = length;
325 }
326 
327 uint16_t
329 {
330  return m_length;
331 }
332 
333 bool
335 {
336  if (!GetModeInitialized ())
337  {
338  return false;
339  }
340  std::string modeName = m_mode.GetUniqueName ();
341  if (m_channelWidth == 20)
342  {
343  if (m_nss != 3 && m_nss != 6)
344  {
345  return (modeName != "VhtMcs9");
346  }
347  }
348  else if (m_channelWidth == 80)
349  {
350  if (m_nss == 3 || m_nss == 7)
351  {
352  return (modeName != "VhtMcs6");
353  }
354  else if (m_nss == 6)
355  {
356  return (modeName != "VhtMcs9");
357  }
358  }
359  else if (m_channelWidth == 160)
360  {
361  if (m_nss == 3)
362  {
363  return (modeName != "VhtMcs9");
364  }
365  }
366  return true;
367 }
368 
369 bool
370 WifiTxVector::IsMu (void) const
371 {
372  return ns3::IsMu (m_preamble);
373 }
374 
375 bool
377 {
378  return ns3::IsDlMu (m_preamble);
379 }
380 
381 bool
383 {
384  return ns3::IsUlMu (m_preamble);
385 }
386 
388 WifiTxVector::GetRu (uint16_t staId) const
389 {
390  NS_ABORT_MSG_IF (!IsMu (), "RU only available for MU");
391  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU");
392  return m_muUserInfos.at (staId).ru;
393 }
394 
395 void
396 WifiTxVector::SetRu (HeRu::RuSpec ru, uint16_t staId)
397 {
398  NS_ABORT_MSG_IF (!IsMu (), "RU only available for MU");
399  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU");
400  m_muUserInfos[staId].ru = ru;
401 }
402 
404 WifiTxVector::GetHeMuUserInfo (uint16_t staId) const
405 {
406  NS_ABORT_MSG_IF (!IsMu (), "HE MU user info only available for MU");
407  return m_muUserInfos.at (staId);
408 }
409 
410 void
411 WifiTxVector::SetHeMuUserInfo (uint16_t staId, HeMuUserInfo userInfo)
412 {
413  NS_ABORT_MSG_IF (!IsMu (), "HE MU user info only available for MU");
414  NS_ABORT_MSG_IF (staId > 2048, "STA-ID should be correctly set for MU");
415  NS_ABORT_MSG_IF (userInfo.mcs.GetModulationClass () < WIFI_MOD_CLASS_HE, "Only HE (or newer) modes authorized for MU");
416  m_muUserInfos[staId] = userInfo;
417  m_modeInitialized = true;
418 }
419 
422 {
423  NS_ABORT_MSG_IF (!IsMu (), "HE MU user info map only available for MU");
424  return m_muUserInfos;
425 }
426 
429 {
430  NS_ABORT_MSG_IF (!IsMu (), "HE MU user info map only available for MU");
431  return m_muUserInfos;
432 }
433 
434 std::pair<std::size_t, std::size_t>
436 {
437  //MU-MIMO is not handled for now, i.e. one station per RU
438 
439  if (m_channelWidth == 20)
440  {
441  return std::make_pair (m_muUserInfos.size (), 0); //all RUs are in HE-SIG-B content channel 1
442  }
443 
444  HeRu::SubcarrierGroup toneRangesContentChannel1, toneRangesContentChannel2;
445  // See section 27.3.10.8.3 of IEEE 802.11ax draft 4.0 for tone ranges per HE-SIG-B content channel
446  switch (m_channelWidth)
447  {
448  case 40:
449  toneRangesContentChannel1.push_back (std::make_pair (-244, -3));
450  toneRangesContentChannel2.push_back (std::make_pair (3, 244));
451  break;
452  case 80:
453  toneRangesContentChannel1.push_back (std::make_pair (-500, -259));
454  toneRangesContentChannel2.push_back (std::make_pair (-258, -17));
455  toneRangesContentChannel1.push_back (std::make_pair (-16, -4)); //first part of center carrier (in HE-SIG-B content channel 1)
456  toneRangesContentChannel1.push_back (std::make_pair (4, 16)); //second part of center carrier (in HE-SIG-B content channel 1)
457  toneRangesContentChannel1.push_back (std::make_pair (17, 258));
458  toneRangesContentChannel2.push_back (std::make_pair (259, 500));
459  break;
460  case 160:
461  toneRangesContentChannel1.push_back (std::make_pair (-1012, -771));
462  toneRangesContentChannel2.push_back (std::make_pair (-770, -529));
463  toneRangesContentChannel1.push_back (std::make_pair (-528, -516)); //first part of center carrier of lower 80 MHz band (in HE-SIG-B content channel 1)
464  toneRangesContentChannel1.push_back (std::make_pair (-508, -496)); //second part of center carrier of lower 80 MHz band (in HE-SIG-B content channel 1)
465  toneRangesContentChannel1.push_back (std::make_pair (-495, -254));
466  toneRangesContentChannel2.push_back (std::make_pair (-253, -12));
467  toneRangesContentChannel1.push_back (std::make_pair (12, 253));
468  toneRangesContentChannel2.push_back (std::make_pair (254, 495));
469  toneRangesContentChannel2.push_back (std::make_pair (496, 508)); //first part of center carrier of upper 80 MHz band (in HE-SIG-B content channel 2)
470  toneRangesContentChannel2.push_back (std::make_pair (516, 528)); //second part of center carrier of upper 80 MHz band (in HE-SIG-B content channel 2)
471  toneRangesContentChannel1.push_back (std::make_pair (529, 770));
472  toneRangesContentChannel2.push_back (std::make_pair (771, 1012));
473  break;
474  default:
475  NS_ABORT_MSG ("Unknown channel width: " << m_channelWidth);
476  }
477 
478  std::size_t numRusContentChannel1 = 0;
479  std::size_t numRusContentChannel2 = 0;
480  for (auto & userInfo : m_muUserInfos)
481  {
482  HeRu::RuSpec ru = userInfo.second.ru;
483  if (!ru.IsPhyIndexSet ())
484  {
485  // this method can be called when calculating the TX duration of a frame
486  // and at that time the RU PHY index may have not been set yet
487  ru.SetPhyIndex (m_channelWidth, 0);
488  }
489  if (HeRu::DoesOverlap (m_channelWidth, ru, toneRangesContentChannel1))
490  {
491  numRusContentChannel1++;
492  }
493  if (HeRu::DoesOverlap (m_channelWidth, ru, toneRangesContentChannel2))
494  {
495  numRusContentChannel2++;
496  }
497  }
498  return std::make_pair (numRusContentChannel1, numRusContentChannel2);
499 }
500 
501 std::ostream & operator << ( std::ostream &os, const WifiTxVector &v)
502 {
503  if (!v.IsValid ())
504  {
505  os << "TXVECTOR not valid";
506  return os;
507  }
508  os << "txpwrlvl: " << +v.GetTxPowerLevel ()
509  << " preamble: " << v.GetPreambleType ()
510  << " channel width: " << v.GetChannelWidth ()
511  << " GI: " << v.GetGuardInterval ()
512  << " NTx: " << +v.GetNTx ()
513  << " Ness: " << +v.GetNess ()
514  << " MPDU aggregation: " << v.IsAggregation ()
515  << " STBC: " << v.IsStbc ()
516  << " FEC coding: " << (v.IsLdpc () ? "LDPC" : "BCC");
518  {
519  os << " BSS color: " << +v.GetBssColor ();
520  }
521  if (v.IsUlMu ())
522  {
523  os << " Length: " << v.GetLength ();
524  }
525  if (v.IsMu ())
526  {
528  os << " num User Infos: " << userInfoMap.size ();
529  for (auto & ui : userInfoMap)
530  {
531  os << ", {STA-ID: " << ui.first
532  << ", " << ui.second.ru
533  << ", MCS: " << ui.second.mcs
534  << ", Nss: " << +ui.second.nss << "}";
535  }
536  }
537  else
538  {
539  os << " mode: " << v.GetMode ()
540  << " Nss: " << +v.GetNss ();
541  }
542  return os;
543 }
544 
545 bool
547 {
548  return ru == other.ru
549  && mcs.GetMcsValue () == other.mcs.GetMcsValue ()
550  && nss == other.nss;
551 }
552 
553 bool
555 {
556  return !(*this == other);
557 }
558 
559 } //namespace ns3
RU Specification.
Definition: he-ru.h:68
bool IsPhyIndexSet(void) const
Return true if the RU PHY index has been set, false otherwise.
Definition: he-ru.cc:206
void SetPhyIndex(uint16_t bw, uint8_t p20Index)
Set the RU PHY index.
Definition: he-ru.cc:188
static bool DoesOverlap(uint16_t bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
Definition: he-ru.cc:352
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition: he-ru.h:56
represent a single transmission mode
Definition: wifi-mode.h:48
uint8_t GetMcsValue(void) const
Definition: wifi-mode.cc:155
WifiModulationClass GetModulationClass() const
Definition: wifi-mode.cc:177
std::string GetUniqueName(void) const
Definition: wifi-mode.cc:140
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint8_t GetBssColor(void) const
Get the BSS color.
uint16_t m_channelWidth
channel width in MHz
void SetStbc(bool stbc)
Sets if STBC is being used.
void SetNess(uint8_t ness)
Sets the Ness number.
bool IsDlMu(void) const
Return true if this TX vector is used for a downlink multi-user transmission.
bool m_aggregation
Flag whether the PSDU contains A-MPDU.
uint8_t GetNTx(void) const
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetLdpc(bool ldpc)
Sets if LDPC FEC coding is being used.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
WifiMode m_mode
The DATARATE parameter in Table 15-4.
std::map< uint16_t, HeMuUserInfo > HeMuUserInfoMap
map of HE MU specific user info paramters indexed by STA-ID
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.
uint8_t GetTxPowerLevel(void) const
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
uint8_t GetNess(void) const
uint16_t GetLength(void) const
Get the LENGTH field of the L-SIG.
HeMuUserInfo GetHeMuUserInfo(uint16_t staId) const
Get the HE MU user-specific transmission information for the given STA-ID.
uint8_t m_nTx
number of TX antennas
void SetAggregation(bool aggregation)
Sets if PSDU contains A-MPDU.
WifiPreamble GetPreambleType(void) const
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
HeMuUserInfoMap m_muUserInfos
HE MU specific per-user information indexed by station ID (STA-ID) corresponding to the 11 LSBs of th...
bool GetModeInitialized(void) const
uint8_t m_txPowerLevel
The TXPWR_LEVEL parameter in Table 15-4.
bool m_ldpc
LDPC FEC coding if true, BCC otherwise.
uint16_t m_guardInterval
guard interval duration in nanoseconds
bool m_stbc
STBC used or not.
uint8_t m_nss
number of spatial streams
void SetRu(HeRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
bool IsValid(void) const
The standard disallows certain combinations of WifiMode, number of spatial streams,...
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 SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
bool IsAggregation(void) const
Checks whether the PSDU contains A-MPDU.
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel(void) const
Get the number of RUs per HE-SIG-B content channel.
uint16_t m_length
LENGTH field of the L-SIG.
uint8_t m_bssColor
BSS color.
bool IsMu(void) const
Return true if this TX vector is used for a multi-user transmission.
void SetBssColor(uint8_t color)
Set the BSS color.
void SetNTx(uint8_t nTx)
Sets the number of TX antennas.
uint16_t GetChannelWidth(void) const
bool IsLdpc(void) const
Check if LDPC FEC coding is used or not.
WifiPreamble m_preamble
preamble
bool IsStbc(void) const
Check if STBC is used or not.
bool m_modeInitialized
Internal initialization flag.
uint8_t m_ness
number of spatial streams in beamforming
uint16_t GetGuardInterval(void) const
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
uint8_t GetNssMax(void) const
void SetNss(uint8_t nss)
Sets the number of Nss.
bool IsUlMu(void) const
Return true if this TX vector is used for an uplink multi-user transmission.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
WifiModulationClass GetModulationClass(void) const
Get the modulation class specified by this TXVECTOR.
#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:165
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_HE_SU
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool IsMu(WifiPreamble preamble)
Return true if a preamble corresponds to a multi-user transmission.
bool IsDlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a downlink multi-user transmission.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139
bool IsUlMu(WifiPreamble preamble)
Return true if a preamble corresponds to a uplink multi-user transmission.
HE MU specific user transmission parameters.
HeRu::RuSpec ru
RU specification.
uint8_t nss
number of spatial streams
bool operator!=(const HeMuUserInfo &other) const
Compare this user info to the given user info.
bool operator==(const HeMuUserInfo &other) const
Compare this user info to the given user info.
WifiMode mcs
MCS.
Declaration of the following enums: