A Discrete-Event Network Simulator
API
he-ru.cc
Go to the documentation of this file.
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2018
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 * Author: Stefano Avallone <stavallo@unina.it>
19 */
20
21#include "he-ru.h"
22#include "ns3/abort.h"
23#include "ns3/assert.h"
24
25namespace ns3 {
26
28{
29 // RUs in a 20 MHz HE PPDU (Table 28-6)
30 { {20, HeRu::RU_26_TONE}, { /* 1 */ {{-121, -96}},
31 /* 2 */ {{-95, -70}},
32 /* 3 */ {{-68, -43}},
33 /* 4 */ {{-42, -17}},
34 /* 5 */ {{-16, -4}, {4, 16}},
35 /* 6 */ {{17, 42}},
36 /* 7 */ {{43, 68}},
37 /* 8 */ {{70, 95}},
38 /* 9 */ {{96, 121}} } },
39 { {20, HeRu::RU_52_TONE}, { /* 1 */ {{-121, -70}},
40 /* 2 */ {{-68, -17}},
41 /* 3 */ {{17, 68}},
42 /* 4 */ {{70, 121}} } },
43 { {20, HeRu::RU_106_TONE}, { /* 1 */ {{-122, -17}},
44 /* 2 */ {{17, 122}} } },
45 { {20, HeRu::RU_242_TONE}, { /* 1 */ {{-122, -2}, {2, 122}} } },
46 // RUs in a 40 MHz HE PPDU (Table 28-7)
47 { {40, HeRu::RU_26_TONE}, { /* 1 */ {{-243, -218}},
48 /* 2 */ {{-217, -192}},
49 /* 3 */ {{-189, -164}},
50 /* 4 */ {{-163, -138}},
51 /* 5 */ {{-136, -111}},
52 /* 6 */ {{-109, -84}},
53 /* 7 */ {{-83, -58}},
54 /* 8 */ {{-55, -30}},
55 /* 9 */ {{-29, -4}},
56 /* 10 */ {{4, 29}},
57 /* 11 */ {{30, 55}},
58 /* 12 */ {{58, 83}},
59 /* 13 */ {{84, 109}},
60 /* 14 */ {{111, 136}},
61 /* 15 */ {{138, 163}},
62 /* 16 */ {{164, 189}},
63 /* 17 */ {{192, 217}},
64 /* 18 */ {{218, 243}} } },
65 { {40, HeRu::RU_52_TONE}, { /* 1 */ {{-243, -192}},
66 /* 2 */ {{-189, -138}},
67 /* 3 */ {{-109, -58}},
68 /* 4 */ {{-55, -4}},
69 /* 5 */ {{4, 55}},
70 /* 6 */ {{58, 109}},
71 /* 7 */ {{138, 189}},
72 /* 8 */ {{192, 243}} } },
73 { {40, HeRu::RU_106_TONE}, { /* 1 */ {{-243, -138}},
74 /* 2 */ {{-109, -4}},
75 /* 3 */ {{4, 109}},
76 /* 4 */ {{138, 243}} } },
77 { {40, HeRu::RU_242_TONE}, { /* 1 */ {{-244, -3}},
78 /* 2 */ {{3, 244}} } },
79 { {40, HeRu::RU_484_TONE}, { /* 1 */ {{-244, -3}, {3, 244}} } },
80 // RUs in an 80 MHz HE PPDU (Table 28-8)
81 { {80, HeRu::RU_26_TONE}, { /* 1 */ {{-499, -474}},
82 /* 2 */ {{-473, -448}},
83 /* 3 */ {{-445, -420}},
84 /* 4 */ {{-419, -394}},
85 /* 5 */ {{-392, -367}},
86 /* 6 */ {{-365, -340}},
87 /* 7 */ {{-339, -314}},
88 /* 8 */ {{-311, -286}},
89 /* 9 */ {{-285, -260}},
90 /* 10 */ {{-257, -232}},
91 /* 11 */ {{-231, -206}},
92 /* 12 */ {{-203, -178}},
93 /* 13 */ {{-177, -152}},
94 /* 14 */ {{-150, -125}},
95 /* 15 */ {{-123, -98}},
96 /* 16 */ {{-97, -72}},
97 /* 17 */ {{-69, -44}},
98 /* 18 */ {{-43, -18}},
99 /* 19 */ {{-16, -4}, {4, 16}},
100 /* 20 */ {{18, 43}},
101 /* 21 */ {{44, 69}},
102 /* 22 */ {{72, 97}},
103 /* 23 */ {{98, 123}},
104 /* 24 */ {{125, 150}},
105 /* 25 */ {{152, 177}},
106 /* 26 */ {{178, 203}},
107 /* 27 */ {{206, 231}},
108 /* 28 */ {{232, 257}},
109 /* 29 */ {{260, 285}},
110 /* 30 */ {{286, 311}},
111 /* 31 */ {{314, 339}},
112 /* 32 */ {{340, 365}},
113 /* 33 */ {{367, 392}},
114 /* 34 */ {{394, 419}},
115 /* 35 */ {{420, 445}},
116 /* 36 */ {{448, 473}},
117 /* 37 */ {{474, 499}} } },
118 { {80, HeRu::RU_52_TONE}, { /* 1 */ {{-499, -448}},
119 /* 2 */ {{-445, -394}},
120 /* 3 */ {{-365, -314}},
121 /* 4 */ {{-311, -260}},
122 /* 5 */ {{-257, -206}},
123 /* 6 */ {{-203, -152}},
124 /* 7 */ {{-123, -72}},
125 /* 8 */ {{-69, -18}},
126 /* 9 */ {{18, 69}},
127 /* 10 */ {{72, 123}},
128 /* 11 */ {{152, 203}},
129 /* 12 */ {{206, 257}},
130 /* 13 */ {{260, 311}},
131 /* 14 */ {{314, 365}},
132 /* 15 */ {{394, 445}},
133 /* 16 */ {{448, 499}} } },
134 { {80, HeRu::RU_106_TONE}, { /* 1 */ {{-499, -394}},
135 /* 2 */ {{-365, -260}},
136 /* 3 */ {{-257, -152}},
137 /* 4 */ {{-123, -18}},
138 /* 5 */ {{18, 123}},
139 /* 6 */ {{152, 257}},
140 /* 7 */ {{260, 365}},
141 /* 8 */ {{394, 499}} } },
142 { {80, HeRu::RU_242_TONE}, { /* 1 */ {{-500, -259}},
143 /* 2 */ {{-258, -17}},
144 /* 3 */ {{17, 258}},
145 /* 4 */ {{259, 500}} } },
146 { {80, HeRu::RU_484_TONE}, { /* 1 */ {{-500, -17}},
147 /* 2 */ {{17, 500}} } },
148 { {80, HeRu::RU_996_TONE}, { /* 1 */ {{-500, -3}, {3, 500}} } }
149};
150
151
153 : m_index (0) // indicates undefined RU
154{
155}
156
157HeRu::RuSpec::RuSpec (RuType ruType, std::size_t index, bool primary80MHz)
158 : m_ruType (ruType),
159 m_index (index),
160 m_primary80MHz (primary80MHz),
161 m_phyIndex (0)
162{
163 NS_ABORT_MSG_IF (index == 0, "Index cannot be zero");
164}
165
168{
169 NS_ABORT_MSG_IF (m_index == 0, "Undefined RU");
170 return m_ruType;
171}
172
173std::size_t
175{
176 NS_ABORT_MSG_IF (m_index == 0, "Undefined RU");
177 return m_index;
178}
179
180bool
182{
183 NS_ABORT_MSG_IF (m_index == 0, "Undefined RU");
184 return m_primary80MHz;
185}
186
187void
188HeRu::RuSpec::SetPhyIndex (uint16_t bw, uint8_t p20Index)
189{
190 bool primary80IsLower80 = (p20Index < bw / 40);
191
192 if (bw < 160
193 || m_ruType == HeRu::RU_2x996_TONE
194 || (primary80IsLower80 && m_primary80MHz)
195 || (!primary80IsLower80 && !m_primary80MHz))
196 {
197 m_phyIndex = m_index;
198 }
199 else
200 {
201 m_phyIndex = m_index + GetNRus (bw, m_ruType) / 2;
202 }
203}
204
205bool
207{
208 return (m_phyIndex != 0);
209}
210
211std::size_t
213{
214 NS_ABORT_MSG_IF (m_phyIndex == 0, "RU PHY index not set");
215 return m_phyIndex;
216}
217
218std::size_t
219HeRu::GetNRus (uint16_t bw, RuType ruType)
220{
221 if (bw == 160 && ruType == RU_2x996_TONE)
222 {
223 return 1;
224 }
225
226 // if the bandwidth is 160MHz, search for the number of RUs available
227 // in 80MHz and double the result.
228 auto it = m_heRuSubcarrierGroups.find ({(bw == 160 ? 80 : bw), ruType});
229
230 if (it == m_heRuSubcarrierGroups.end ())
231 {
232 return 0;
233 }
234
235 return (bw == 160 ? 2 : 1) * it->second.size ();
236}
237
238std::vector<HeRu::RuSpec>
239HeRu::GetRusOfType (uint16_t bw, HeRu::RuType ruType)
240{
241 if (ruType == HeRu::RU_2x996_TONE)
242 {
243 NS_ASSERT (bw >= 160);
244 return {{ruType, 1, true}};
245 }
246
247 std::vector<HeRu::RuSpec> ret;
248 std::vector<bool> primary80MHzSet {true};
249
250 if (bw == 160)
251 {
252 primary80MHzSet.push_back (false);
253 bw = 80;
254 }
255
256 for (auto primary80MHz : primary80MHzSet)
257 {
258 for (std::size_t ruIndex = 1; ruIndex <= HeRu::m_heRuSubcarrierGroups.at ({bw, ruType}).size (); ruIndex++)
259 {
260 ret.push_back ({ruType, ruIndex, primary80MHz});
261 }
262 }
263 return ret;
264}
265
266std::vector<HeRu::RuSpec>
268{
269 std::vector<std::size_t> indices;
270
271 if (ruType == HeRu::RU_52_TONE || ruType == HeRu::RU_106_TONE)
272 {
273 if (bw == 20)
274 {
275 indices.push_back (5);
276 }
277 else if (bw == 40)
278 {
279 indices.insert (indices.end (), {5, 14});
280 }
281 else if (bw >= 80)
282 {
283 indices.insert (indices.end (), {5, 14, 19, 24, 33});
284 }
285 }
286 else if (ruType == HeRu::RU_242_TONE || ruType == HeRu::RU_484_TONE)
287 {
288 if (bw >= 80)
289 {
290 indices.push_back (19);
291 }
292 }
293
294 std::vector<HeRu::RuSpec> ret;
295 std::vector<bool> primary80MHzSet {true};
296
297 if (bw == 160)
298 {
299 primary80MHzSet.push_back (false);
300 }
301
302 for (auto primary80MHz : primary80MHzSet)
303 {
304 for (const auto& index : indices)
305 {
306 ret.push_back ({HeRu::RU_26_TONE, index, primary80MHz});
307 }
308 }
309 return ret;
310}
311
313HeRu::GetSubcarrierGroup (uint16_t bw, RuType ruType, std::size_t phyIndex)
314{
315 if (ruType == HeRu::RU_2x996_TONE) //handle special case of RU covering 160 MHz channel
316 {
317 NS_ABORT_MSG_IF (bw != 160, "2x996 tone RU can only be used on 160 MHz band");
318 return {{-1012, -3}, {3, 1012}};
319 }
320
321 // Determine the shift to apply to tone indices for 160 MHz channel (i.e. -1012 to 1012), since
322 // m_heRuSubcarrierGroups contains indices for lower 80 MHz subchannel (i.e. from -500 to 500).
323 // The phyIndex is used to that aim.
324 std::size_t indexInLower80MHz = phyIndex;
325 std::size_t numRus = GetNRus (bw, ruType);
326 int16_t shift = (bw == 160) ? -512 : 0;
327 if (bw == 160 && phyIndex > (numRus / 2))
328 {
329 // The provided index is that of the upper 80 MHz subchannel
330 indexInLower80MHz = phyIndex - (numRus / 2);
331 shift = 512;
332 }
333
334 auto it = m_heRuSubcarrierGroups.find ({(bw == 160 ? 80 : bw), ruType});
335
336 NS_ABORT_MSG_IF (it == m_heRuSubcarrierGroups.end (), "RU not found");
337 NS_ABORT_MSG_IF (indexInLower80MHz > it->second.size (), "RU index not available");
338
339 SubcarrierGroup group = it->second.at (indexInLower80MHz - 1);
340 if (bw == 160)
341 {
342 for (auto & range : group)
343 {
344 range.first += shift;
345 range.second += shift;
346 }
347 }
348 return group;
349}
350
351bool
352HeRu::DoesOverlap (uint16_t bw, RuSpec ru, const std::vector<RuSpec> &v)
353{
354 // A 2x996-tone RU spans 160 MHz, hence it overlaps with any other RU
355 if (bw == 160 && ru.GetRuType () == RU_2x996_TONE && !v.empty ())
356 {
357 return true;
358 }
359
360 // This function may be called by the MAC layer, hence the PHY index may have
361 // not been set yet. Hence, we pass the "MAC" index to GetSubcarrierGroup instead
362 // of the PHY index. This is fine because we compare the primary 80 MHz bands of
363 // the two RUs below.
364 SubcarrierGroup rangesRu = GetSubcarrierGroup (bw, ru.GetRuType (), ru.GetIndex ());
365 for (auto& p : v)
366 {
367 if (ru.GetPrimary80MHz () != p.GetPrimary80MHz ())
368 {
369 // the two RUs are located in distinct 80MHz bands
370 continue;
371 }
372 for (const auto& rangeRu : rangesRu)
373 {
374 SubcarrierGroup rangesP = GetSubcarrierGroup (bw, p.GetRuType (), p.GetIndex ());
375 for (auto& rangeP : rangesP)
376 {
377 if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
378 {
379 return true;
380 }
381 }
382 }
383 }
384 return false;
385}
386
387bool
388HeRu::DoesOverlap (uint16_t bw, RuSpec ru, const SubcarrierGroup &toneRanges)
389{
390 for (const auto & range : toneRanges)
391 {
392 if (bw == 160 && ru.GetRuType () == RU_2x996_TONE)
393 {
394 return true;
395 }
396
397 SubcarrierGroup rangesRu = GetSubcarrierGroup (bw, ru.GetRuType (), ru.GetPhyIndex ());
398 for (auto& r : rangesRu)
399 {
400 if (range.second >= r.first && r.second >= range.first)
401 {
402 return true;
403 }
404 }
405 }
406 return false;
407}
408
410HeRu::FindOverlappingRu (uint16_t bw, RuSpec referenceRu, RuType searchedRuType)
411{
412 std::size_t numRus = HeRu::GetNRus (bw, searchedRuType);
413
414 std::size_t numRusPer80Mhz;
415 std::vector<bool> primary80MhzFlags;
416 if (bw == 160)
417 {
418 primary80MhzFlags.push_back (true);
419 primary80MhzFlags.push_back (false);
420 numRusPer80Mhz = (searchedRuType == HeRu::RU_2x996_TONE ? 1 : numRus / 2);
421 }
422 else
423 {
424 primary80MhzFlags.push_back (referenceRu.GetPrimary80MHz ());
425 numRusPer80Mhz = numRus;
426 }
427
428 for (const auto primary80MHz : primary80MhzFlags)
429 {
430 std::size_t index = 1;
431 for (std::size_t indexPer80Mhz = 1; indexPer80Mhz <= numRusPer80Mhz; ++indexPer80Mhz, ++index)
432 {
433 RuSpec searchedRu (searchedRuType, index, primary80MHz);
434 if (DoesOverlap (bw, referenceRu, {searchedRu}))
435 {
436 return searchedRu;
437 }
438 }
439 }
440 NS_ABORT_MSG ("The searched RU type " << searchedRuType << " was not found for bw=" << bw << " and referenceRu=" << referenceRu);
441 return HeRu::RuSpec ();
442}
443
444std::ostream& operator<< (std::ostream& os, const HeRu::RuType &ruType)
445{
446 switch (ruType)
447 {
448 case HeRu::RU_26_TONE:
449 os << "26-tones";
450 break;
451 case HeRu::RU_52_TONE:
452 os << "52-tones";
453 break;
455 os << "106-tones";
456 break;
458 os << "242-tones";
459 break;
461 os << "484-tones";
462 break;
464 os << "996-tones";
465 break;
467 os << "2x996-tones";
468 break;
469 default:
470 NS_FATAL_ERROR ("Unknown RU type");
471 }
472 return os;
473}
474
475std::ostream& operator<< (std::ostream& os, const HeRu::RuSpec &ru)
476{
477 os << "RU{" << ru.GetRuType () << "/" << ru.GetIndex () << "/" << (ru.GetPrimary80MHz () ? "primary80MHz" : "secondary80MHz");
478 if (ru.IsPhyIndexSet ())
479 {
480 os << "[" << ru.GetPhyIndex () << "]";
481 }
482 os << "}";
483 return os;
484}
485
486uint16_t
488{
489 switch (ruType)
490 {
491 case RU_26_TONE:
492 return 2;
493 case RU_52_TONE:
494 return 4;
495 case RU_106_TONE:
496 return 8;
497 case RU_242_TONE:
498 return 20;
499 case RU_484_TONE:
500 return 40;
501 case RU_996_TONE:
502 return 80;
503 case RU_2x996_TONE:
504 return 160;
505 default:
506 NS_ABORT_MSG ("RU type " << ruType << " not found");
507 return 0;
508 }
509}
510
512HeRu::GetRuType (uint16_t bandwidth)
513{
514 switch (bandwidth)
515 {
516 case 2:
517 return RU_26_TONE;
518 case 4:
519 return RU_52_TONE;
520 case 8:
521 return RU_106_TONE;
522 case 20:
523 return RU_242_TONE;
524 case 40:
525 return RU_484_TONE;
526 case 80:
527 return RU_996_TONE;
528 case 160:
529 return RU_2x996_TONE;
530 default:
531 NS_ABORT_MSG (bandwidth << " MHz bandwidth not found");
532 return RU_242_TONE;
533 }
534}
535
537HeRu::GetEqualSizedRusForStations (uint16_t bandwidth, std::size_t& nStations,
538 std::size_t& nCentral26TonesRus)
539{
540 RuType ruType;
541 uint8_t nRusAssigned = 0;
542
543 // iterate over all the available RU types
544 for (auto& ru : m_heRuSubcarrierGroups)
545 {
546 if (ru.first.first == bandwidth && ru.second.size () <= nStations)
547 {
548 ruType = ru.first.second;
549 nRusAssigned = ru.second.size ();
550 break;
551 }
552 else if (bandwidth == 160 && ru.first.first == 80 && (2 * ru.second.size () <= nStations))
553 {
554 ruType = ru.first.second;
555 nRusAssigned = 2 * ru.second.size ();
556 break;
557 }
558 }
559 if (nRusAssigned == 0)
560 {
561 NS_ABORT_IF (bandwidth != 160 || nStations != 1);
562 nRusAssigned = 1;
563 ruType = RU_2x996_TONE;
564 }
565
566 nStations = nRusAssigned;
567
568 switch (ruType)
569 {
570 case RU_52_TONE:
571 case RU_106_TONE:
572 if (bandwidth == 20)
573 {
574 nCentral26TonesRus = 1;
575 }
576 else if (bandwidth == 40)
577 {
578 nCentral26TonesRus = 2;
579 }
580 else
581 {
582 nCentral26TonesRus = 5;
583 }
584 break;
585 case RU_242_TONE:
586 case RU_484_TONE:
587 nCentral26TonesRus = (bandwidth >= 80 ? 1 : 0);
588 break;
589 default:
590 nCentral26TonesRus = 0;
591 }
592
593 if (bandwidth == 160)
594 {
595 nCentral26TonesRus *= 2;
596 }
597
598 return ruType;
599}
600
601bool
603{
604 // we do not compare the RU PHY indices because they may be uninitialized for
605 // one of the compared RUs. This event should not cause the comparison to evaluate
606 // to false
607 return m_ruType == other.m_ruType
608 && m_index == other.m_index
609 && m_primary80MHz == other.m_primary80MHz;
610}
611
612bool
614{
615 return !(*this == other);
616}
617
618} //namespace ns3
RU Specification.
Definition: he-ru.h:68
std::size_t m_index
RU index (starting at 1) as defined by Tables 27-7 to 27-9 of 802.11ax D8.0.
Definition: he-ru.h:138
RuType GetRuType(void) const
Get the RU type.
Definition: he-ru.cc:167
RuSpec()
Default constructor.
Definition: he-ru.cc:152
bool GetPrimary80MHz(void) const
Get the primary 80 MHz flag.
Definition: he-ru.cc:181
bool m_primary80MHz
true if the RU is allocated in the primary 80MHz channel
Definition: he-ru.h:140
bool IsPhyIndexSet(void) const
Return true if the RU PHY index has been set, false otherwise.
Definition: he-ru.cc:206
RuType m_ruType
RU type.
Definition: he-ru.h:137
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
Definition: he-ru.cc:602
std::size_t GetIndex(void) const
Get the RU index.
Definition: he-ru.cc:174
void SetPhyIndex(uint16_t bw, uint8_t p20Index)
Set the RU PHY index.
Definition: he-ru.cc:188
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
Definition: he-ru.cc:613
std::size_t GetPhyIndex(void) const
Get the RU PHY index.
Definition: he-ru.cc:212
static RuSpec FindOverlappingRu(uint16_t bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
Definition: he-ru.cc:410
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
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:487
static SubcarrierGroup GetSubcarrierGroup(uint16_t bw, RuType ruType, std::size_t phyIndex)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
Definition: he-ru.cc:313
static std::size_t GetNRus(uint16_t bw, RuType ruType)
Get the number of distinct RUs of the given type (number of tones) available in a HE PPDU of the give...
Definition: he-ru.cc:219
static std::vector< HeRu::RuSpec > GetRusOfType(uint16_t bw, HeRu::RuType ruType)
Get the set of distinct RUs of the given type (number of tones) available in a HE PPDU of the given b...
Definition: he-ru.cc:239
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition: he-ru.h:56
static std::vector< HeRu::RuSpec > GetCentral26TonesRus(uint16_t bw, HeRu::RuType ruType)
Get the set of 26-tone RUs that can be additionally allocated if the given bandwidth is split in RUs ...
Definition: he-ru.cc:267
static const SubcarrierGroups m_heRuSubcarrierGroups
Subcarrier groups for all RUs (with indices being applicable to primary 80 MHz channel)
Definition: he-ru.h:269
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
@ RU_26_TONE
Definition: he-ru.h:43
@ RU_484_TONE
Definition: he-ru.h:47
@ RU_996_TONE
Definition: he-ru.h:48
@ RU_106_TONE
Definition: he-ru.h:45
@ RU_52_TONE
Definition: he-ru.h:44
@ RU_242_TONE
Definition: he-ru.h:46
@ RU_2x996_TONE
Definition: he-ru.h:49
static RuType GetEqualSizedRusForStations(uint16_t bandwidth, std::size_t &nStations, std::size_t &nCentral26TonesRus)
Given the channel bandwidth and the number of stations candidate for being assigned an RU,...
Definition: he-ru.cc:537
static RuType GetRuType(uint16_t bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition: he-ru.cc:512
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
Definition: he-ru.h:266
#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
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:77
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:139