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