A Discrete-Event Network Simulator
API
he-ru.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018
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  * Author: Stefano Avallone <stavallo@unina.it>
18  */
19 
20 #include "he-ru.h"
21 
22 #include "ns3/abort.h"
23 #include "ns3/assert.h"
24 
25 #include <optional>
26 #include <tuple>
27 
28 namespace ns3
29 {
30 
32  // RUs in a 20 MHz HE PPDU (Table 28-6)
33  {{20, HeRu::RU_26_TONE},
34  {/* 1 */ {{-121, -96}},
35  /* 2 */ {{-95, -70}},
36  /* 3 */ {{-68, -43}},
37  /* 4 */ {{-42, -17}},
38  /* 5 */ {{-16, -4}, {4, 16}},
39  /* 6 */ {{17, 42}},
40  /* 7 */ {{43, 68}},
41  /* 8 */ {{70, 95}},
42  /* 9 */ {{96, 121}}}},
43  {{20, HeRu::RU_52_TONE},
44  {/* 1 */ {{-121, -70}},
45  /* 2 */ {{-68, -17}},
46  /* 3 */ {{17, 68}},
47  /* 4 */ {{70, 121}}}},
48  {{20, HeRu::RU_106_TONE},
49  {/* 1 */ {{-122, -17}},
50  /* 2 */ {{17, 122}}}},
51  {{20, HeRu::RU_242_TONE}, {/* 1 */ {{-122, -2}, {2, 122}}}},
52  // RUs in a 40 MHz HE PPDU (Table 28-7)
53  {{40, HeRu::RU_26_TONE},
54  {/* 1 */ {{-243, -218}},
55  /* 2 */ {{-217, -192}},
56  /* 3 */ {{-189, -164}},
57  /* 4 */ {{-163, -138}},
58  /* 5 */ {{-136, -111}},
59  /* 6 */ {{-109, -84}},
60  /* 7 */ {{-83, -58}},
61  /* 8 */ {{-55, -30}},
62  /* 9 */ {{-29, -4}},
63  /* 10 */ {{4, 29}},
64  /* 11 */ {{30, 55}},
65  /* 12 */ {{58, 83}},
66  /* 13 */ {{84, 109}},
67  /* 14 */ {{111, 136}},
68  /* 15 */ {{138, 163}},
69  /* 16 */ {{164, 189}},
70  /* 17 */ {{192, 217}},
71  /* 18 */ {{218, 243}}}},
72  {{40, HeRu::RU_52_TONE},
73  {/* 1 */ {{-243, -192}},
74  /* 2 */ {{-189, -138}},
75  /* 3 */ {{-109, -58}},
76  /* 4 */ {{-55, -4}},
77  /* 5 */ {{4, 55}},
78  /* 6 */ {{58, 109}},
79  /* 7 */ {{138, 189}},
80  /* 8 */ {{192, 243}}}},
81  {{40, HeRu::RU_106_TONE},
82  {/* 1 */ {{-243, -138}},
83  /* 2 */ {{-109, -4}},
84  /* 3 */ {{4, 109}},
85  /* 4 */ {{138, 243}}}},
86  {{40, HeRu::RU_242_TONE},
87  {/* 1 */ {{-244, -3}},
88  /* 2 */ {{3, 244}}}},
89  {{40, HeRu::RU_484_TONE}, {/* 1 */ {{-244, -3}, {3, 244}}}},
90  // RUs in an 80 MHz HE PPDU (Table 28-8)
91  {{80, HeRu::RU_26_TONE},
92  {/* 1 */ {{-499, -474}},
93  /* 2 */ {{-473, -448}},
94  /* 3 */ {{-445, -420}},
95  /* 4 */ {{-419, -394}},
96  /* 5 */ {{-392, -367}},
97  /* 6 */ {{-365, -340}},
98  /* 7 */ {{-339, -314}},
99  /* 8 */ {{-311, -286}},
100  /* 9 */ {{-285, -260}},
101  /* 10 */ {{-257, -232}},
102  /* 11 */ {{-231, -206}},
103  /* 12 */ {{-203, -178}},
104  /* 13 */ {{-177, -152}},
105  /* 14 */ {{-150, -125}},
106  /* 15 */ {{-123, -98}},
107  /* 16 */ {{-97, -72}},
108  /* 17 */ {{-69, -44}},
109  /* 18 */ {{-43, -18}},
110  /* 19 */ {{-16, -4}, {4, 16}},
111  /* 20 */ {{18, 43}},
112  /* 21 */ {{44, 69}},
113  /* 22 */ {{72, 97}},
114  /* 23 */ {{98, 123}},
115  /* 24 */ {{125, 150}},
116  /* 25 */ {{152, 177}},
117  /* 26 */ {{178, 203}},
118  /* 27 */ {{206, 231}},
119  /* 28 */ {{232, 257}},
120  /* 29 */ {{260, 285}},
121  /* 30 */ {{286, 311}},
122  /* 31 */ {{314, 339}},
123  /* 32 */ {{340, 365}},
124  /* 33 */ {{367, 392}},
125  /* 34 */ {{394, 419}},
126  /* 35 */ {{420, 445}},
127  /* 36 */ {{448, 473}},
128  /* 37 */ {{474, 499}}}},
129  {{80, HeRu::RU_52_TONE},
130  {/* 1 */ {{-499, -448}},
131  /* 2 */ {{-445, -394}},
132  /* 3 */ {{-365, -314}},
133  /* 4 */ {{-311, -260}},
134  /* 5 */ {{-257, -206}},
135  /* 6 */ {{-203, -152}},
136  /* 7 */ {{-123, -72}},
137  /* 8 */ {{-69, -18}},
138  /* 9 */ {{18, 69}},
139  /* 10 */ {{72, 123}},
140  /* 11 */ {{152, 203}},
141  /* 12 */ {{206, 257}},
142  /* 13 */ {{260, 311}},
143  /* 14 */ {{314, 365}},
144  /* 15 */ {{394, 445}},
145  /* 16 */ {{448, 499}}}},
146  {{80, HeRu::RU_106_TONE},
147  {/* 1 */ {{-499, -394}},
148  /* 2 */ {{-365, -260}},
149  /* 3 */ {{-257, -152}},
150  /* 4 */ {{-123, -18}},
151  /* 5 */ {{18, 123}},
152  /* 6 */ {{152, 257}},
153  /* 7 */ {{260, 365}},
154  /* 8 */ {{394, 499}}}},
155  {{80, HeRu::RU_242_TONE},
156  {/* 1 */ {{-500, -259}},
157  /* 2 */ {{-258, -17}},
158  /* 3 */ {{17, 258}},
159  /* 4 */ {{259, 500}}}},
160  {{80, HeRu::RU_484_TONE},
161  {/* 1 */ {{-500, -17}},
162  /* 2 */ {{17, 500}}}},
163  {{80, HeRu::RU_996_TONE}, {/* 1 */ {{-500, -3}, {3, 500}}}},
164 };
165 
166 // Table 27-26 IEEE802.11ax-2021
168  // clang-format off
169  {0,
170  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
171  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
172  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
173  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
174  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
175  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
176  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
177  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
178  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
179  {1,
180  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
181  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
182  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
183  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
184  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
185  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
186  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
187  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
188  {2,
189  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
190  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
191  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
192  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
193  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
194  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
195  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
196  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
197  {3,
198  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
199  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
200  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
201  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
202  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
203  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
204  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
205  {4,
206  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
207  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
208  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
209  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
210  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
211  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
212  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
213  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
214  {5,
215  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
216  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
217  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
218  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
219  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
220  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
221  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
222  {6,
223  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
224  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
225  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
226  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
227  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
228  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
229  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
230  {7,
231  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
232  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
233  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
234  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
235  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
236  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
237  {8,
238  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
239  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
240  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
241  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
242  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
243  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
244  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
245  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
246  {9,
247  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
248  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
249  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
250  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
251  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
252  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
253  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
254  {10,
255  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
256  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
257  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
258  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
259  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
260  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
261  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
262  {11,
263  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
264  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
265  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
266  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
267  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
268  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
269  {12,
270  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
271  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
272  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
273  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
274  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
275  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
276  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
277  {13,
278  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
279  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
280  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
281  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
282  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
283  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
284  {14,
285  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
286  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
287  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
288  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
289  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
290  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
291  {15,
292  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
293  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
294  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
295  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
296  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
297  {16,
298  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
299  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
300  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
301  {24,
302  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
303  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
304  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
305  {32,
306  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
307  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
308  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
309  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
310  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
311  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
312  {40,
313  {HeRu::RuSpec{HeRu::RU_26_TONE, 1, true},
314  HeRu::RuSpec{HeRu::RU_26_TONE, 2, true},
315  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
316  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
317  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
318  {48,
319  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
320  HeRu::RuSpec{HeRu::RU_26_TONE, 3, true},
321  HeRu::RuSpec{HeRu::RU_26_TONE, 4, true},
322  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
323  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
324  {56,
325  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
326  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
327  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
328  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
329  {64,
330  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
331  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
332  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
333  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
334  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
335  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
336  {72,
337  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
338  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
339  HeRu::RuSpec{HeRu::RU_26_TONE, 6, true},
340  HeRu::RuSpec{HeRu::RU_26_TONE, 7, true},
341  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
342  {80,
343  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
344  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
345  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
346  HeRu::RuSpec{HeRu::RU_26_TONE, 8, true},
347  HeRu::RuSpec{HeRu::RU_26_TONE, 9, true}}},
348  {88,
349  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
350  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
351  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
352  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
353  {96,
354  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
355  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
356  {112,
357  {HeRu::RuSpec{HeRu::RU_52_TONE, 1, true},
358  HeRu::RuSpec{HeRu::RU_52_TONE, 2, true},
359  HeRu::RuSpec{HeRu::RU_52_TONE, 3, true},
360  HeRu::RuSpec{HeRu::RU_52_TONE, 4, true}}},
361  {128,
362  {HeRu::RuSpec{HeRu::RU_106_TONE, 1, true},
363  HeRu::RuSpec{HeRu::RU_26_TONE, 5, true},
364  HeRu::RuSpec{HeRu::RU_106_TONE, 2, true}}},
365  {192,
366  {HeRu::RuSpec{HeRu::RU_242_TONE, 1, true}}},
367  {200,
368  {HeRu::RuSpec{HeRu::RU_484_TONE, 1, true}}},
369  {208,
370  {HeRu::RuSpec{HeRu::RU_996_TONE, 1, true}}},
371  // clang-format on
372 };
373 
374 HeRu::RuSpecCompare::RuSpecCompare(uint16_t channelWidth, uint8_t p20Index)
375  : m_channelWidth(channelWidth),
376  m_p20Index(p20Index)
377 {
378 }
379 
380 bool
382 {
383  const auto lhsIndex = lhs.GetPhyIndex(m_channelWidth, m_p20Index);
384  const auto rhsIndex = rhs.GetPhyIndex(m_channelWidth, m_p20Index);
385  const auto lhsStartTone =
386  HeRu::GetSubcarrierGroup(m_channelWidth, lhs.GetRuType(), lhsIndex).front().first;
387  const auto rhsStartTone =
388  HeRu::GetSubcarrierGroup(m_channelWidth, rhs.GetRuType(), rhsIndex).front().first;
389  return lhsStartTone < rhsStartTone;
390 }
391 
392 std::vector<HeRu::RuSpec>
393 HeRu::GetRuSpecs(uint8_t ruAllocation)
394 {
395  std::optional<std::size_t> idx;
396  switch (ruAllocation)
397  {
398  case 0 ... 15:
399  case 112:
400  idx = ruAllocation;
401  break;
402  case 16 ... 95:
403  case 192 ... 215:
404  idx = ruAllocation & 0xF8;
405  break;
406  case 96 ... 111:
407  idx = ruAllocation & 0xF0;
408  break;
409  case 113 ... 115:
410  break;
411  case 128 ... 191:
412  idx = ruAllocation & 0xC0;
413  break;
414  default:
415  NS_FATAL_ERROR("Reserved RU allocation " << +ruAllocation);
416  }
417  return idx.has_value() ? m_heRuAllocations.at(idx.value()) : std::vector<HeRu::RuSpec>{};
418 }
419 
420 uint8_t
422 {
423  switch (ruType)
424  {
425  case HeRu::RU_26_TONE:
426  return 0;
427  case HeRu::RU_52_TONE:
428  return isOdd ? 15 : 112;
429  case HeRu::RU_106_TONE:
430  return isOdd ? 128 : 96;
431  case HeRu::RU_242_TONE:
432  return 192;
433  case HeRu::RU_484_TONE:
434  return 200;
435  default:
436  return 208;
437  }
438 }
439 
441  : m_index(0) // indicates undefined RU
442 {
443 }
444 
445 HeRu::RuSpec::RuSpec(RuType ruType, std::size_t index, bool primary80MHz)
446  : m_ruType(ruType),
447  m_index(index),
448  m_primary80MHz(primary80MHz)
449 {
450  NS_ABORT_MSG_IF(index == 0, "Index cannot be zero");
451 }
452 
455 {
456  NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
457  return m_ruType;
458 }
459 
460 std::size_t
462 {
463  NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
464  return m_index;
465 }
466 
467 bool
469 {
470  NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
471  return m_primary80MHz;
472 }
473 
474 std::size_t
475 HeRu::RuSpec::GetPhyIndex(uint16_t bw, uint8_t p20Index) const
476 {
477  bool primary80IsLower80 = (p20Index < bw / 40);
478 
479  if (bw < 160 || m_ruType == HeRu::RU_2x996_TONE || (primary80IsLower80 && m_primary80MHz) ||
480  (!primary80IsLower80 && !m_primary80MHz))
481  {
482  return m_index;
483  }
484  else
485  {
486  return m_index + GetNRus(bw, m_ruType) / 2;
487  }
488 }
489 
490 std::size_t
491 HeRu::GetNRus(uint16_t bw, RuType ruType)
492 {
493  if (bw == 160 && ruType == RU_2x996_TONE)
494  {
495  return 1;
496  }
497 
498  // if the bandwidth is 160MHz, search for the number of RUs available
499  // in 80MHz and double the result.
500  auto it = m_heRuSubcarrierGroups.find({(bw == 160 ? 80 : bw), ruType});
501 
502  if (it == m_heRuSubcarrierGroups.end())
503  {
504  return 0;
505  }
506 
507  return (bw == 160 ? 2 : 1) * it->second.size();
508 }
509 
510 std::vector<HeRu::RuSpec>
511 HeRu::GetRusOfType(uint16_t bw, HeRu::RuType ruType)
512 {
513  if (ruType == HeRu::RU_2x996_TONE)
514  {
515  NS_ASSERT(bw >= 160);
516  return {{ruType, 1, true}};
517  }
518 
519  std::vector<HeRu::RuSpec> ret;
520  std::vector<bool> primary80MHzSet{true};
521 
522  if (bw == 160)
523  {
524  primary80MHzSet.push_back(false);
525  bw = 80;
526  }
527 
528  for (auto primary80MHz : primary80MHzSet)
529  {
530  for (std::size_t ruIndex = 1;
531  ruIndex <= HeRu::m_heRuSubcarrierGroups.at({bw, ruType}).size();
532  ruIndex++)
533  {
534  ret.emplace_back(ruType, ruIndex, primary80MHz);
535  }
536  }
537  return ret;
538 }
539 
540 std::vector<HeRu::RuSpec>
542 {
543  std::vector<std::size_t> indices;
544 
545  if (ruType == HeRu::RU_52_TONE || ruType == HeRu::RU_106_TONE)
546  {
547  if (bw == 20)
548  {
549  indices.push_back(5);
550  }
551  else if (bw == 40)
552  {
553  indices.insert(indices.end(), {5, 14});
554  }
555  else if (bw >= 80)
556  {
557  indices.insert(indices.end(), {5, 14, 19, 24, 33});
558  }
559  }
560  else if (ruType == HeRu::RU_242_TONE || ruType == HeRu::RU_484_TONE)
561  {
562  if (bw >= 80)
563  {
564  indices.push_back(19);
565  }
566  }
567 
568  std::vector<HeRu::RuSpec> ret;
569  std::vector<bool> primary80MHzSet{true};
570 
571  if (bw == 160)
572  {
573  primary80MHzSet.push_back(false);
574  }
575 
576  for (auto primary80MHz : primary80MHzSet)
577  {
578  for (const auto& index : indices)
579  {
580  ret.emplace_back(HeRu::RU_26_TONE, index, primary80MHz);
581  }
582  }
583  return ret;
584 }
585 
587 HeRu::GetSubcarrierGroup(uint16_t bw, RuType ruType, std::size_t phyIndex)
588 {
589  if (ruType == HeRu::RU_2x996_TONE) // handle special case of RU covering 160 MHz channel
590  {
591  NS_ABORT_MSG_IF(bw != 160, "2x996 tone RU can only be used on 160 MHz band");
592  return {{-1012, -3}, {3, 1012}};
593  }
594 
595  // Determine the shift to apply to tone indices for 160 MHz channel (i.e. -1012 to 1012), since
596  // m_heRuSubcarrierGroups contains indices for lower 80 MHz subchannel (i.e. from -500 to 500).
597  // The phyIndex is used to that aim.
598  std::size_t indexInLower80MHz = phyIndex;
599  std::size_t numRus = GetNRus(bw, ruType);
600  int16_t shift = (bw == 160) ? -512 : 0;
601  if (bw == 160 && phyIndex > (numRus / 2))
602  {
603  // The provided index is that of the upper 80 MHz subchannel
604  indexInLower80MHz = phyIndex - (numRus / 2);
605  shift = 512;
606  }
607 
608  auto it = m_heRuSubcarrierGroups.find({(bw == 160 ? 80 : bw), ruType});
609 
610  NS_ABORT_MSG_IF(it == m_heRuSubcarrierGroups.end(), "RU not found");
611  NS_ABORT_MSG_IF(indexInLower80MHz > it->second.size(), "RU index not available");
612 
613  SubcarrierGroup group = it->second.at(indexInLower80MHz - 1);
614  if (bw == 160)
615  {
616  for (auto& range : group)
617  {
618  range.first += shift;
619  range.second += shift;
620  }
621  }
622  return group;
623 }
624 
625 bool
626 HeRu::DoesOverlap(uint16_t bw, RuSpec ru, const std::vector<RuSpec>& v)
627 {
628  // A 2x996-tone RU spans 160 MHz, hence it overlaps with any other RU
629  if (bw == 160 && ru.GetRuType() == RU_2x996_TONE && !v.empty())
630  {
631  return true;
632  }
633 
634  // This function may be called by the MAC layer, hence the PHY index may have
635  // not been set yet. Hence, we pass the "MAC" index to GetSubcarrierGroup instead
636  // of the PHY index. This is fine because we compare the primary 80 MHz bands of
637  // the two RUs below.
638  SubcarrierGroup rangesRu = GetSubcarrierGroup(bw, ru.GetRuType(), ru.GetIndex());
639  for (auto& p : v)
640  {
641  if (ru.GetPrimary80MHz() != p.GetPrimary80MHz())
642  {
643  // the two RUs are located in distinct 80MHz bands
644  continue;
645  }
646  for (const auto& rangeRu : rangesRu)
647  {
648  SubcarrierGroup rangesP = GetSubcarrierGroup(bw, p.GetRuType(), p.GetIndex());
649  for (auto& rangeP : rangesP)
650  {
651  if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
652  {
653  return true;
654  }
655  }
656  }
657  }
658  return false;
659 }
660 
661 bool
662 HeRu::DoesOverlap(uint16_t bw, RuSpec ru, const SubcarrierGroup& toneRanges, uint8_t p20Index)
663 {
664  for (const auto& range : toneRanges)
665  {
666  if (bw == 160 && ru.GetRuType() == RU_2x996_TONE)
667  {
668  return true;
669  }
670 
671  SubcarrierGroup rangesRu =
672  GetSubcarrierGroup(bw, ru.GetRuType(), ru.GetPhyIndex(bw, p20Index));
673  for (auto& r : rangesRu)
674  {
675  if (range.second >= r.first && r.second >= range.first)
676  {
677  return true;
678  }
679  }
680  }
681  return false;
682 }
683 
685 HeRu::FindOverlappingRu(uint16_t bw, RuSpec referenceRu, RuType searchedRuType)
686 {
687  std::size_t numRus = HeRu::GetNRus(bw, searchedRuType);
688 
689  std::size_t numRusPer80Mhz;
690  std::vector<bool> primary80MhzFlags;
691  if (bw == 160)
692  {
693  primary80MhzFlags.push_back(true);
694  primary80MhzFlags.push_back(false);
695  numRusPer80Mhz = (searchedRuType == HeRu::RU_2x996_TONE ? 1 : numRus / 2);
696  }
697  else
698  {
699  primary80MhzFlags.push_back(referenceRu.GetPrimary80MHz());
700  numRusPer80Mhz = numRus;
701  }
702 
703  for (const auto primary80MHz : primary80MhzFlags)
704  {
705  std::size_t index = 1;
706  for (std::size_t indexPer80Mhz = 1; indexPer80Mhz <= numRusPer80Mhz;
707  ++indexPer80Mhz, ++index)
708  {
709  RuSpec searchedRu(searchedRuType, index, primary80MHz);
710  if (DoesOverlap(bw, referenceRu, {searchedRu}))
711  {
712  return searchedRu;
713  }
714  }
715  }
716  NS_ABORT_MSG("The searched RU type " << searchedRuType << " was not found for bw=" << bw
717  << " and referenceRu=" << referenceRu);
718  return HeRu::RuSpec();
719 }
720 
721 std::ostream&
722 operator<<(std::ostream& os, const HeRu::RuType& ruType)
723 {
724  switch (ruType)
725  {
726  case HeRu::RU_26_TONE:
727  os << "26-tones";
728  break;
729  case HeRu::RU_52_TONE:
730  os << "52-tones";
731  break;
732  case HeRu::RU_106_TONE:
733  os << "106-tones";
734  break;
735  case HeRu::RU_242_TONE:
736  os << "242-tones";
737  break;
738  case HeRu::RU_484_TONE:
739  os << "484-tones";
740  break;
741  case HeRu::RU_996_TONE:
742  os << "996-tones";
743  break;
744  case HeRu::RU_2x996_TONE:
745  os << "2x996-tones";
746  break;
747  default:
748  NS_FATAL_ERROR("Unknown RU type");
749  }
750  return os;
751 }
752 
753 std::ostream&
754 operator<<(std::ostream& os, const HeRu::RuSpec& ru)
755 {
756  os << "RU{" << ru.GetRuType() << "/" << ru.GetIndex() << "/"
757  << (ru.GetPrimary80MHz() ? "primary80MHz" : "secondary80MHz");
758  os << "}";
759  return os;
760 }
761 
762 uint16_t
764 {
765  switch (ruType)
766  {
767  case RU_26_TONE:
768  return 2;
769  case RU_52_TONE:
770  return 4;
771  case RU_106_TONE:
772  return 8;
773  case RU_242_TONE:
774  return 20;
775  case RU_484_TONE:
776  return 40;
777  case RU_996_TONE:
778  return 80;
779  case RU_2x996_TONE:
780  return 160;
781  default:
782  NS_ABORT_MSG("RU type " << ruType << " not found");
783  return 0;
784  }
785 }
786 
788 HeRu::GetRuType(uint16_t bandwidth)
789 {
790  switch (bandwidth)
791  {
792  case 2:
793  return RU_26_TONE;
794  case 4:
795  return RU_52_TONE;
796  case 8:
797  return RU_106_TONE;
798  case 20:
799  return RU_242_TONE;
800  case 40:
801  return RU_484_TONE;
802  case 80:
803  return RU_996_TONE;
804  case 160:
805  return RU_2x996_TONE;
806  default:
807  NS_ABORT_MSG(bandwidth << " MHz bandwidth not found");
808  return RU_242_TONE;
809  }
810 }
811 
814  std::size_t& nStations,
815  std::size_t& nCentral26TonesRus)
816 {
817  RuType ruType;
818  uint8_t nRusAssigned = 0;
819 
820  // iterate over all the available RU types
821  for (auto& ru : m_heRuSubcarrierGroups)
822  {
823  if (ru.first.first == bandwidth && ru.second.size() <= nStations)
824  {
825  ruType = ru.first.second;
826  nRusAssigned = ru.second.size();
827  break;
828  }
829  else if (bandwidth == 160 && ru.first.first == 80 && (2 * ru.second.size() <= nStations))
830  {
831  ruType = ru.first.second;
832  nRusAssigned = 2 * ru.second.size();
833  break;
834  }
835  }
836  if (nRusAssigned == 0)
837  {
838  NS_ABORT_IF(bandwidth != 160 || nStations != 1);
839  nRusAssigned = 1;
840  ruType = RU_2x996_TONE;
841  }
842 
843  nStations = nRusAssigned;
844 
845  switch (ruType)
846  {
847  case RU_52_TONE:
848  case RU_106_TONE:
849  if (bandwidth == 20)
850  {
851  nCentral26TonesRus = 1;
852  }
853  else if (bandwidth == 40)
854  {
855  nCentral26TonesRus = 2;
856  }
857  else
858  {
859  nCentral26TonesRus = 5;
860  }
861  break;
862  case RU_242_TONE:
863  case RU_484_TONE:
864  nCentral26TonesRus = (bandwidth >= 80 ? 1 : 0);
865  break;
866  default:
867  nCentral26TonesRus = 0;
868  }
869 
870  if (bandwidth == 160)
871  {
872  nCentral26TonesRus *= 2;
873  }
874 
875  return ruType;
876 }
877 
878 bool
879 HeRu::RuSpec::operator==(const RuSpec& other) const
880 {
881  // we do not compare the RU PHY indices because they may be uninitialized for
882  // one of the compared RUs. This event should not cause the comparison to evaluate
883  // to false
884  return m_ruType == other.m_ruType && m_index == other.m_index &&
885  m_primary80MHz == other.m_primary80MHz;
886 }
887 
888 bool
889 HeRu::RuSpec::operator!=(const RuSpec& other) const
890 {
891  return !(*this == other);
892 }
893 
894 bool
895 HeRu::RuSpec::operator<(const RuSpec& other) const
896 {
897  // we do not compare the RU PHY indices because they may be uninitialized for
898  // one of the compared RUs. This event should not cause the comparison to evaluate
899  // to false
900  return std::tie(m_ruType, m_index, m_primary80MHz) <
901  std::tie(other.m_ruType, other.m_index, other.m_primary80MHz);
902 }
903 
904 } // namespace ns3
RU Specification.
Definition: he-ru.h:66
std::size_t GetIndex() const
Get the RU index.
Definition: he-ru.cc:461
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:132
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:454
bool operator<(const RuSpec &other) const
Compare this RU to the given RU.
Definition: he-ru.cc:895
RuSpec()
Default constructor.
Definition: he-ru.cc:440
bool m_primary80MHz
true if the RU is allocated in the primary 80MHz channel
Definition: he-ru.h:134
std::size_t GetPhyIndex(uint16_t bw, uint8_t p20Index) const
Get the RU PHY index.
Definition: he-ru.cc:475
RuType m_ruType
RU type.
Definition: he-ru.h:131
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
Definition: he-ru.cc:879
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition: he-ru.cc:468
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
Definition: he-ru.cc:889
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:685
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:626
static std::vector< RuSpec > GetRuSpecs(uint8_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
Definition: he-ru.cc:393
static uint16_t GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition: he-ru.cc:763
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:587
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:491
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:511
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition: he-ru.h:55
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
Definition: he-ru.h:294
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:541
static const SubcarrierGroups m_heRuSubcarrierGroups
Subcarrier groups for all RUs (with indices being applicable to primary 80 MHz channel)
Definition: he-ru.h:291
static uint8_t GetEqualizedRuAllocation(RuType ruType, bool isOdd)
Get the RU_ALLOCATION value for equal size RUs.
Definition: he-ru.cc:421
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
@ RU_26_TONE
Definition: he-ru.h:42
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_52_TONE
Definition: he-ru.h:43
@ RU_242_TONE
Definition: he-ru.h:45
@ RU_2x996_TONE
Definition: he-ru.h:48
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:813
static RuType GetRuType(uint16_t bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition: he-ru.cc:788
static const RuAllocationMap m_heRuAllocations
Table 27-26 of IEEE 802.11ax-2021.
Definition: he-ru.h:297
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
Definition: he-ru.h:288
#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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#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:76
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:159
RuSpecCompare(uint16_t channelWidth, uint8_t p20Index)
Constructor.
Definition: he-ru.cc:374
bool operator()(const RuSpec &lhs, const RuSpec &rhs) const
Function call operator.
Definition: he-ru.cc:381