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