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
25 namespace ns3 {
26
27 const HeRu::SubcarrierGroups HeRu::m_heRuSubcarrierGroups =
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
RuSpec()152 HeRu::RuSpec::RuSpec ()
153 : m_index (0) // indicates undefined RU
154 {
155 }
156
RuSpec(RuType ruType,std::size_t index,bool primary80MHz)157 HeRu::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
166 HeRu::RuType
GetRuType(void) const167 HeRu::RuSpec::GetRuType (void) const
168 {
169 NS_ABORT_MSG_IF (m_index == 0, "Undefined RU");
170 return m_ruType;
171 }
172
173 std::size_t
GetIndex(void) const174 HeRu::RuSpec::GetIndex (void) const
175 {
176 NS_ABORT_MSG_IF (m_index == 0, "Undefined RU");
177 return m_index;
178 }
179
180 bool
GetPrimary80MHz(void) const181 HeRu::RuSpec::GetPrimary80MHz (void) const
182 {
183 NS_ABORT_MSG_IF (m_index == 0, "Undefined RU");
184 return m_primary80MHz;
185 }
186
187 void
SetPhyIndex(uint16_t bw,uint8_t p20Index)188 HeRu::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
205 bool
IsPhyIndexSet(void) const206 HeRu::RuSpec::IsPhyIndexSet (void) const
207 {
208 return (m_phyIndex != 0);
209 }
210
211 std::size_t
GetPhyIndex(void) const212 HeRu::RuSpec::GetPhyIndex (void) const
213 {
214 NS_ABORT_MSG_IF (m_phyIndex == 0, "RU PHY index not set");
215 return m_phyIndex;
216 }
217
218 std::size_t
GetNRus(uint16_t bw,RuType ruType)219 HeRu::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
238 std::vector<HeRu::RuSpec>
GetRusOfType(uint16_t bw,HeRu::RuType ruType)239 HeRu::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
266 std::vector<HeRu::RuSpec>
GetCentral26TonesRus(uint16_t bw,HeRu::RuType ruType)267 HeRu::GetCentral26TonesRus (uint16_t bw, HeRu::RuType ruType)
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
312 HeRu::SubcarrierGroup
GetSubcarrierGroup(uint16_t bw,RuType ruType,std::size_t phyIndex)313 HeRu::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
351 bool
DoesOverlap(uint16_t bw,RuSpec ru,const std::vector<RuSpec> & v)352 HeRu::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
387 bool
DoesOverlap(uint16_t bw,RuSpec ru,const SubcarrierGroup & toneRanges)388 HeRu::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
409 HeRu::RuSpec
FindOverlappingRu(uint16_t bw,RuSpec referenceRu,RuType searchedRuType)410 HeRu::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
operator <<(std::ostream & os,const HeRu::RuType & ruType)444 std::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;
454 case HeRu::RU_106_TONE:
455 os << "106-tones";
456 break;
457 case HeRu::RU_242_TONE:
458 os << "242-tones";
459 break;
460 case HeRu::RU_484_TONE:
461 os << "484-tones";
462 break;
463 case HeRu::RU_996_TONE:
464 os << "996-tones";
465 break;
466 case HeRu::RU_2x996_TONE:
467 os << "2x996-tones";
468 break;
469 default:
470 NS_FATAL_ERROR ("Unknown RU type");
471 }
472 return os;
473 }
474
operator <<(std::ostream & os,const HeRu::RuSpec & ru)475 std::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
486 uint16_t
GetBandwidth(RuType ruType)487 HeRu::GetBandwidth (RuType ruType)
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
511 HeRu::RuType
GetRuType(uint16_t bandwidth)512 HeRu::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
536 HeRu::RuType
GetEqualSizedRusForStations(uint16_t bandwidth,std::size_t & nStations,std::size_t & nCentral26TonesRus)537 HeRu::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
601
602 } //namespace ns3
603