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