A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
eht-ru.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "eht-ru.h"
10
11#include "ns3/abort.h"
12#include "ns3/assert.h"
13#include "ns3/wifi-ru.h"
14
15#include <algorithm>
16#include <optional>
17#include <set>
18#include <tuple>
19
20namespace ns3
21{
22
24 // TODO: cleanup code duplication with HeRu
25 // RUs in a 20 MHz HE PPDU (Table 27-7 IEEE802.11ax-2021)
27 {/* 1 */ {{-121, -96}},
28 /* 2 */ {{-95, -70}},
29 /* 3 */ {{-68, -43}},
30 /* 4 */ {{-42, -17}},
31 /* 5 */ {{-16, -4}, {4, 16}},
32 /* 6 */ {{17, 42}},
33 /* 7 */ {{43, 68}},
34 /* 8 */ {{70, 95}},
35 /* 9 */ {{96, 121}}}},
37 {/* 1 */ {{-121, -70}},
38 /* 2 */ {{-68, -17}},
39 /* 3 */ {{17, 68}},
40 /* 4 */ {{70, 121}}}},
42 {/* 1 */ {{-122, -17}},
43 /* 2 */ {{17, 122}}}},
44 {{MHz_u{20}, RuType::RU_242_TONE}, {/* 1 */ {{-122, -2}, {2, 122}}}},
45 // RUs in a 40 MHz HE PPDU (Table 27-8 IEEE802.11ax-2021)
47 {/* 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}}}},
66 {/* 1 */ {{-243, -192}},
67 /* 2 */ {{-189, -138}},
68 /* 3 */ {{-109, -58}},
69 /* 4 */ {{-55, -4}},
70 /* 5 */ {{4, 55}},
71 /* 6 */ {{58, 109}},
72 /* 7 */ {{138, 189}},
73 /* 8 */ {{192, 243}}}},
75 {/* 1 */ {{-243, -138}},
76 /* 2 */ {{-109, -4}},
77 /* 3 */ {{4, 109}},
78 /* 4 */ {{138, 243}}}},
80 {/* 1 */ {{-244, -3}},
81 /* 2 */ {{3, 244}}}},
82 {{MHz_u{40}, RuType::RU_484_TONE}, {/* 1 */ {{-244, -3}, {3, 244}}}},
83 // RUs in an 80 MHz EHT PPDU (Table 36-5 IEEE802.11be-D7.0)
85 {/* 1 */ {{-499, -474}},
86 /* 2 */ {{-473, -448}},
87 /* 3 */ {{-445, -420}},
88 /* 4 */ {{-419, -394}},
89 /* 5 */ {{-392, -367}},
90 /* 6 */ {{-365, -340}},
91 /* 7 */ {{-339, -314}},
92 /* 8 */ {{-311, -286}},
93 /* 9 */ {{-285, -260}},
94 /* 10 */ {{-252, -227}},
95 /* 11 */ {{-226, -201}},
96 /* 12 */ {{-198, -173}},
97 /* 13 */ {{-172, -147}},
98 /* 14 */ {{-145, -120}},
99 /* 15 */ {{-118, -93}},
100 /* 16 */ {{-92, -67}},
101 /* 17 */ {{-64, -39}},
102 /* 18 */ {{-38, -13}},
103 /* 19 not defined */ {},
104 /* 20 */ {{13, 38}},
105 /* 21 */ {{39, 64}},
106 /* 22 */ {{67, 92}},
107 /* 23 */ {{93, 118}},
108 /* 24 */ {{120, 145}},
109 /* 25 */ {{147, 172}},
110 /* 26 */ {{173, 198}},
111 /* 27 */ {{201, 226}},
112 /* 28 */ {{227, 252}},
113 /* 29 */ {{260, 285}},
114 /* 30 */ {{286, 311}},
115 /* 31 */ {{314, 339}},
116 /* 32 */ {{340, 365}},
117 /* 33 */ {{367, 392}},
118 /* 34 */ {{394, 419}},
119 /* 35 */ {{420, 445}},
120 /* 36 */ {{448, 473}},
121 /* 37 */ {{474, 499}}}},
123 {/* 1 */ {{-499, -448}},
124 /* 2 */ {{-445, -394}},
125 /* 3 */ {{-365, -314}},
126 /* 4 */ {{-311, -260}},
127 /* 5 */ {{-252, -201}},
128 /* 6 */ {{-198, -147}},
129 /* 7 */ {{-118, -67}},
130 /* 8 */ {{-64, -13}},
131 /* 9 */ {{13, 64}},
132 /* 10 */ {{67, 118}},
133 /* 11 */ {{147, 198}},
134 /* 12 */ {{201, 252}},
135 /* 13 */ {{260, 311}},
136 /* 14 */ {{314, 365}},
137 /* 15 */ {{394, 445}},
138 /* 16 */ {{448, 499}}}},
140 {/* 1 */ {{-499, -394}},
141 /* 2 */ {{-365, -260}},
142 /* 3 */ {{-252, -147}},
143 /* 4 */ {{-118, -13}},
144 /* 5 */ {{13, 118}},
145 /* 6 */ {{147, 252}},
146 /* 7 */ {{260, 365}},
147 /* 8 */ {{394, 499}}}},
149 {/* 1 */ {{-500, -259}},
150 /* 2 */ {{-253, -12}},
151 /* 3 */ {{12, 253}},
152 /* 4 */ {{259, 500}}}},
154 {/* 1 */ {{-500, -259}, {-253, -12}},
155 /* 2 */ {{12, 253}, {259, 500}}}},
156 {{MHz_u{80}, RuType::RU_996_TONE}, {/* 1 */ {{-500, -3}, {3, 500}}}},
157 // RUs in an 160 MHz EHT PPDU (Table 36-6 IEEE802.11be-D7.0)
158 {{MHz_u{160}, RuType::RU_26_TONE},
159 {/* 1 */ {{-1011, -986}},
160 /* 2 */ {{-985, -960}},
161 /* 3 */ {{-957, -932}},
162 /* 4 */ {{-931, -906}},
163 /* 5 */ {{-904, -879}},
164 /* 6 */ {{-877, -852}},
165 /* 7 */ {{-851, -826}},
166 /* 8 */ {{-823, -798}},
167 /* 9 */ {{-797, -772}},
168 /* 10 */ {{-764, -739}},
169 /* 11 */ {{-738, -713}},
170 /* 12 */ {{-710, -685}},
171 /* 13 */ {{-684, -659}},
172 /* 14 */ {{-657, -632}},
173 /* 15 */ {{-630, -605}},
174 /* 16 */ {{-604, -579}},
175 /* 17 */ {{-576, -551}},
176 /* 18 */ {{-550, -525}},
177 /* 19 not defined */ {},
178 /* 20 */ {{-499, -474}},
179 /* 21 */ {{-473, -448}},
180 /* 22 */ {{-445, -420}},
181 /* 23 */ {{-419, -394}},
182 /* 24 */ {{-392, -367}},
183 /* 25 */ {{-365, -340}},
184 /* 26 */ {{-339, -314}},
185 /* 27 */ {{-311, -286}},
186 /* 28 */ {{-285, -260}},
187 /* 29 */ {{-252, -227}},
188 /* 30 */ {{-226, -201}},
189 /* 31 */ {{-198, -173}},
190 /* 32 */ {{-172, -147}},
191 /* 33 */ {{-145, -120}},
192 /* 34 */ {{-118, -93}},
193 /* 35 */ {{-92, -67}},
194 /* 36 */ {{-64, -39}},
195 /* 37 */ {{-38, -13}},
196 /* 38 */ {{13, 38}},
197 /* 39 */ {{39, 64}},
198 /* 40 */ {{67, 92}},
199 /* 41 */ {{93, 118}},
200 /* 42 */ {{120, 145}},
201 /* 43 */ {{147, 172}},
202 /* 44 */ {{173, 198}},
203 /* 45 */ {{201, 226}},
204 /* 46 */ {{227, 252}},
205 /* 47 */ {{260, 285}},
206 /* 48 */ {{286, 311}},
207 /* 49 */ {{314, 339}},
208 /* 50 */ {{340, 365}},
209 /* 51 */ {{367, 392}},
210 /* 52 */ {{394, 419}},
211 /* 53 */ {{420, 445}},
212 /* 54 */ {{448, 473}},
213 /* 55 */ {{474, 499}},
214 /* 56 not defined */ {},
215 /* 57 */ {{525, 550}},
216 /* 58 */ {{551, 576}},
217 /* 59 */ {{579, 604}},
218 /* 60 */ {{605, 630}},
219 /* 61 */ {{632, 657}},
220 /* 62 */ {{659, 684}},
221 /* 63 */ {{685, 710}},
222 /* 64 */ {{713, 738}},
223 /* 65 */ {{739, 764}},
224 /* 66 */ {{772, 797}},
225 /* 67 */ {{798, 823}},
226 /* 68 */ {{826, 851}},
227 /* 69 */ {{852, 877}},
228 /* 70 */ {{879, 904}},
229 /* 71 */ {{906, 931}},
230 /* 72 */ {{932, 957}},
231 /* 73 */ {{960, 985}},
232 /* 74 */ {{986, 1011}}}},
233 {{MHz_u{160}, RuType::RU_52_TONE},
234 {/* 1 */ {{-1011, -960}},
235 /* 2 */ {{-957, -906}},
236 /* 3 */ {{-877, -826}},
237 /* 4 */ {{-823, -772}},
238 /* 5 */ {{-764, -713}},
239 /* 6 */ {{-710, -659}},
240 /* 7 */ {{-630, -579}},
241 /* 8 */ {{-576, -525}},
242 /* 9 */ {{-499, -448}},
243 /* 10 */ {{-445, -394}},
244 /* 11 */ {{-365, -314}},
245 /* 12 */ {{-311, -260}},
246 /* 13 */ {{-252, -201}},
247 /* 14 */ {{-198, -147}},
248 /* 15 */ {{-118, -67}},
249 /* 16 */ {{-64, -13}},
250 /* 17 */ {{13, 64}},
251 /* 18 */ {{67, 118}},
252 /* 19 */ {{147, 198}},
253 /* 20 */ {{201, 252}},
254 /* 21 */ {{260, 311}},
255 /* 22 */ {{314, 365}},
256 /* 23 */ {{394, 445}},
257 /* 24 */ {{448, 499}},
258 /* 25 */ {{525, 576}},
259 /* 26 */ {{579, 630}},
260 /* 27 */ {{659, 710}},
261 /* 28 */ {{713, 764}},
262 /* 29 */ {{772, 823}},
263 /* 30 */ {{826, 877}},
264 /* 31 */ {{906, 957}},
265 /* 32 */ {{960, 1011}}}},
266 {{MHz_u{160}, RuType::RU_106_TONE},
267 {/* 1 */ {{-1011, -906}},
268 /* 2 */ {{-877, -772}},
269 /* 3 */ {{-764, -659}},
270 /* 4 */ {{-630, -525}},
271 /* 5 */ {{-499, -394}},
272 /* 6 */ {{-365, -260}},
273 /* 7 */ {{-252, -147}},
274 /* 8 */ {{-118, -13}},
275 /* 9 */ {{13, 118}},
276 /* 10 */ {{147, 252}},
277 /* 11 */ {{260, 365}},
278 /* 12 */ {{394, 499}},
279 /* 13 */ {{525, 630}},
280 /* 14 */ {{659, 764}},
281 /* 15 */ {{772, 877}},
282 /* 16 */ {{906, 1011}}}},
283 {{MHz_u{160}, RuType::RU_242_TONE},
284 {/* 1 */ {{-1012, -771}},
285 /* 2 */ {{-765, -524}},
286 /* 3 */ {{-500, -259}},
287 /* 4 */ {{-253, -12}},
288 /* 5 */ {{12, 253}},
289 /* 6 */ {{259, 500}},
290 /* 7 */ {{524, 765}},
291 /* 8 */ {{771, 1012}}}},
292 {{MHz_u{160}, RuType::RU_484_TONE},
293 {/* 1 */ {{-1012, -771}, {-765, -524}},
294 /* 2 */ {{-500, -259}, {-253, -12}},
295 /* 3 */ {{12, 253}, {259, 500}},
296 /* 4 */ {{524, 765}, {771, 1012}}}},
297 {{MHz_u{160}, RuType::RU_996_TONE},
298 {/* 1 */ {{-1012, -515}, {-509, -12}},
299 /* 2 */ {{12, 509}, {515, 1012}}}},
301 {/* 1 */ {{-1012, -515}, {-509, -12}, {12, 509}, {515, 1012}}}},
302 // RUs in an 320 MHz EHT PPDU (Table 36-7 IEEE802.11be-D7.0)
303 {{MHz_u{320}, RuType::RU_26_TONE},
304 {/* 1 */ {{-2035, -2010}},
305 /* 2 */ {{-2009, -1984}},
306 /* 3 */ {{-1981, -1956}},
307 /* 4 */ {{-1955, -1930}},
308 /* 5 */ {{-1928, -1903}},
309 /* 6 */ {{-1901, -1876}},
310 /* 7 */ {{-1875, -1850}},
311 /* 8 */ {{-1847, -1822}},
312 /* 9 */ {{-1821, -1796}},
313 /* 10 */ {{-1788, -1763}},
314 /* 11 */ {{-1762, -1737}},
315 /* 12 */ {{-1734, -1709}},
316 /* 13 */ {{-1708, -1683}},
317 /* 14 */ {{-1681, -1656}},
318 /* 15 */ {{-1654, -1629}},
319 /* 16 */ {{-1628, -1603}},
320 /* 17 */ {{-1600, -1575}},
321 /* 18 */ {{-1574, -1549}},
322 /* 19 not defined */ {},
323 /* 20 */ {{-1523, -1498}},
324 /* 21 */ {{-1497, -1472}},
325 /* 22 */ {{-1469, -1444}},
326 /* 23 */ {{-1443, -1418}},
327 /* 24 */ {{-1416, -1391}},
328 /* 25 */ {{-1389, -1364}},
329 /* 26 */ {{-1363, -1338}},
330 /* 27 */ {{-1335, -1310}},
331 /* 28 */ {{-1309, -1284}},
332 /* 29 */ {{-1276, -1251}},
333 /* 30 */ {{-1250, -1225}},
334 /* 31 */ {{-1222, -1197}},
335 /* 32 */ {{-1196, -1171}},
336 /* 33 */ {{-1169, -1144}},
337 /* 34 */ {{-1142, -1117}},
338 /* 35 */ {{-1116, -1091}},
339 /* 36 */ {{-1088, -1063}},
340 /* 37 */ {{-1062, -1037}},
341 /* 38 */ {{-1011, -986}},
342 /* 39 */ {{-985, -960}},
343 /* 40 */ {{-957, -932}},
344 /* 41 */ {{-931, -906}},
345 /* 42 */ {{-904, -879}},
346 /* 43 */ {{-877, -852}},
347 /* 44 */ {{-851, -826}},
348 /* 45 */ {{-823, -798}},
349 /* 46 */ {{-797, -772}},
350 /* 47 */ {{-764, -739}},
351 /* 48 */ {{-738, -713}},
352 /* 49 */ {{-710, -685}},
353 /* 50 */ {{-684, -659}},
354 /* 51 */ {{-657, -632}},
355 /* 52 */ {{-630, -605}},
356 /* 53 */ {{-604, -579}},
357 /* 54 */ {{-576, -551}},
358 /* 55 */ {{-550, -525}},
359 /* 56 not defined */ {},
360 /* 57 */ {{-499, -474}},
361 /* 58 */ {{-473, -448}},
362 /* 59 */ {{-445, -420}},
363 /* 60 */ {{-419, -394}},
364 /* 61 */ {{-392, -367}},
365 /* 62 */ {{-365, -340}},
366 /* 63 */ {{-339, -314}},
367 /* 64 */ {{-311, -286}},
368 /* 65 */ {{-285, -260}},
369 /* 66 */ {{-252, -227}},
370 /* 67 */ {{-226, -201}},
371 /* 68 */ {{-198, -173}},
372 /* 69 */ {{-172, -147}},
373 /* 70 */ {{-145, -120}},
374 /* 71 */ {{-118, -93}},
375 /* 72 */ {{-92, -67}},
376 /* 73 */ {{-64, -39}},
377 /* 74 */ {{-38, -13}},
378 /* 75 */ {{13, 38}},
379 /* 76 */ {{39, 64}},
380 /* 77 */ {{67, 92}},
381 /* 78 */ {{93, 118}},
382 /* 79 */ {{120, 145}},
383 /* 80 */ {{147, 172}},
384 /* 81 */ {{173, 198}},
385 /* 82 */ {{201, 226}},
386 /* 83 */ {{227, 252}},
387 /* 84 */ {{260, 285}},
388 /* 85 */ {{286, 311}},
389 /* 86 */ {{314, 339}},
390 /* 87 */ {{340, 365}},
391 /* 88 */ {{367, 392}},
392 /* 89 */ {{394, 419}},
393 /* 90 */ {{420, 445}},
394 /* 91 */ {{448, 473}},
395 /* 92 */ {{474, 499}},
396 /* 93 not defined */ {},
397 /* 94 */ {{525, 550}},
398 /* 95 */ {{551, 576}},
399 /* 96 */ {{579, 604}},
400 /* 97 */ {{605, 630}},
401 /* 98 */ {{632, 657}},
402 /* 99 */ {{659, 684}},
403 /* 100 */ {{685, 710}},
404 /* 101 */ {{713, 738}},
405 /* 102 */ {{739, 764}},
406 /* 103 */ {{772, 797}},
407 /* 104 */ {{798, 823}},
408 /* 105 */ {{826, 851}},
409 /* 106 */ {{852, 877}},
410 /* 107 */ {{879, 904}},
411 /* 108 */ {{906, 931}},
412 /* 109 */ {{932, 957}},
413 /* 110 */ {{960, 985}},
414 /* 111 */ {{986, 1011}},
415 /* 112 */ {{1037, 1062}},
416 /* 113 */ {{1063, 1088}},
417 /* 114 */ {{1091, 1116}},
418 /* 115 */ {{1117, 1142}},
419 /* 116 */ {{1144, 1169}},
420 /* 117 */ {{1171, 1196}},
421 /* 118 */ {{1197, 1222}},
422 /* 119 */ {{1225, 1250}},
423 /* 120 */ {{1251, 1276}},
424 /* 121 */ {{1284, 1309}},
425 /* 122 */ {{1310, 1335}},
426 /* 123 */ {{1338, 1363}},
427 /* 124 */ {{1364, 1389}},
428 /* 125 */ {{1391, 1416}},
429 /* 126 */ {{1418, 1443}},
430 /* 127 */ {{1444, 1469}},
431 /* 128 */ {{1472, 1497}},
432 /* 129 */ {{1498, 1523}},
433 /* 130 not defined */ {},
434 /* 131 */ {{1549, 1574}},
435 /* 132 */ {{1575, 1600}},
436 /* 133 */ {{1603, 1628}},
437 /* 134 */ {{1629, 1654}},
438 /* 135 */ {{1656, 1681}},
439 /* 136 */ {{1683, 1708}},
440 /* 137 */ {{1709, 1734}},
441 /* 138 */ {{1737, 1762}},
442 /* 139 */ {{1763, 1788}},
443 /* 140 */ {{1796, 1821}},
444 /* 141 */ {{1822, 1847}},
445 /* 142 */ {{1850, 1875}},
446 /* 143 */ {{1876, 1901}},
447 /* 144 */ {{1903, 1928}},
448 /* 145 */ {{1930, 1955}},
449 /* 146 */ {{1956, 1981}},
450 /* 147 */ {{1984, 2009}},
451 /* 148 */ {{2010, 2035}}}},
452 {{MHz_u{320}, RuType::RU_52_TONE},
453 {/* 1 */ {{-2035, -1984}},
454 /* 2 */ {{-1981, -1930}},
455 /* 3 */ {{-1901, -1850}},
456 /* 4 */ {{-1847, -1796}},
457 /* 5 */ {{-1788, -1737}},
458 /* 6 */ {{-1734, -1683}},
459 /* 7 */ {{-1654, -1603}},
460 /* 8 */ {{-1600, -1549}},
461 /* 9 */ {{-1523, -1472}},
462 /* 10 */ {{-1469, -1418}},
463 /* 11 */ {{-1389, -1338}},
464 /* 12 */ {{-1335, -1284}},
465 /* 13 */ {{-1276, -1225}},
466 /* 14 */ {{-1222, -1171}},
467 /* 15 */ {{-1142, -1091}},
468 /* 16 */ {{-1088, -1037}},
469 /* 17 */ {{-1011, -960}},
470 /* 18 */ {{-957, -906}},
471 /* 19 */ {{-877, -826}},
472 /* 20 */ {{-823, -772}},
473 /* 21 */ {{-764, -713}},
474 /* 22 */ {{-710, -659}},
475 /* 23 */ {{-630, -579}},
476 /* 24 */ {{-576, -525}},
477 /* 25 */ {{-499, -448}},
478 /* 26 */ {{-445, -394}},
479 /* 27 */ {{-365, -314}},
480 /* 28 */ {{-311, -260}},
481 /* 29 */ {{-252, -201}},
482 /* 30 */ {{-198, -147}},
483 /* 31 */ {{-118, -67}},
484 /* 32 */ {{-64, -13}},
485 /* 33 */ {{13, 64}},
486 /* 34 */ {{67, 118}},
487 /* 35 */ {{147, 198}},
488 /* 36 */ {{201, 252}},
489 /* 37 */ {{260, 311}},
490 /* 38 */ {{314, 365}},
491 /* 39 */ {{394, 445}},
492 /* 40 */ {{448, 499}},
493 /* 41 */ {{525, 576}},
494 /* 42 */ {{579, 630}},
495 /* 43 */ {{659, 710}},
496 /* 44 */ {{713, 764}},
497 /* 45 */ {{772, 823}},
498 /* 46 */ {{826, 877}},
499 /* 47 */ {{906, 957}},
500 /* 48 */ {{960, 1011}},
501 /* 49 */ {{1037, 1088}},
502 /* 50 */ {{1091, 1142}},
503 /* 51 */ {{1171, 1222}},
504 /* 52 */ {{1225, 1276}},
505 /* 53 */ {{1284, 1335}},
506 /* 54 */ {{1338, 1389}},
507 /* 55 */ {{1418, 1469}},
508 /* 56 */ {{1472, 1523}},
509 /* 57 */ {{1549, 1600}},
510 /* 58 */ {{1603, 1654}},
511 /* 59 */ {{1683, 1734}},
512 /* 60 */ {{1737, 1788}},
513 /* 61 */ {{1796, 1847}},
514 /* 62 */ {{1850, 1901}},
515 /* 63 */ {{1930, 1981}},
516 /* 64 */ {{1984, 2035}}}},
517 {{MHz_u{320}, RuType::RU_106_TONE},
518 {/* 1 */ {{-2035, -1930}},
519 /* 2 */ {{-1901, -1796}},
520 /* 3 */ {{-1788, -1683}},
521 /* 4 */ {{-1654, -1549}},
522 /* 5 */ {{-1523, -1418}},
523 /* 6 */ {{-1389, -1284}},
524 /* 7 */ {{-1276, -1171}},
525 /* 8 */ {{-1142, -1037}},
526 /* 9 */ {{-1011, -906}},
527 /* 10 */ {{-877, -772}},
528 /* 11 */ {{-764, -659}},
529 /* 12 */ {{-630, -525}},
530 /* 13 */ {{-499, -394}},
531 /* 14 */ {{-365, -260}},
532 /* 15 */ {{-252, -147}},
533 /* 16 */ {{-118, -13}},
534 /* 17 */ {{13, 118}},
535 /* 18 */ {{147, 252}},
536 /* 19 */ {{260, 365}},
537 /* 20 */ {{394, 499}},
538 /* 21 */ {{525, 630}},
539 /* 22 */ {{659, 764}},
540 /* 23 */ {{772, 877}},
541 /* 24 */ {{906, 1011}},
542 /* 25 */ {{1037, 1142}},
543 /* 26 */ {{1171, 1276}},
544 /* 27 */ {{1284, 1389}},
545 /* 28 */ {{1418, 1523}},
546 /* 29 */ {{1549, 1654}},
547 /* 30 */ {{1683, 1788}},
548 /* 31 */ {{1796, 1901}},
549 /* 32 */ {{1930, 2035}}}},
550 {{MHz_u{320}, RuType::RU_242_TONE},
551 {/* 1 */ {{-2036, -1795}},
552 /* 2 */ {{-1789, -1548}},
553 /* 3 */ {{-1524, -1283}},
554 /* 4 */ {{-1277, -1036}},
555 /* 5 */ {{-1012, -771}},
556 /* 6 */ {{-765, -524}},
557 /* 7 */ {{-500, -259}},
558 /* 8 */ {{-253, -12}},
559 /* 9 */ {{12, 253}},
560 /* 10 */ {{259, 500}},
561 /* 11 */ {{524, 765}},
562 /* 12 */ {{771, 1012}},
563 /* 13 */ {{1036, 1277}},
564 /* 14 */ {{1283, 1524}},
565 /* 15 */ {{1548, 1789}},
566 /* 16 */ {{1795, 2036}}}},
567 {{MHz_u{320}, RuType::RU_484_TONE},
568 {/* 1 */ {{-2036, -1795}, {-1789, -1548}},
569 /* 2 */ {{-1524, -1283}, {-1277, -1036}},
570 /* 3 */ {{-1012, -771}, {-765, -524}},
571 /* 4 */ {{-500, -259}, {-253, -12}},
572 /* 5 */ {{12, 253}, {259, 500}},
573 /* 6 */ {{524, 765}, {771, 1012}},
574 /* 7 */ {{1036, 1277}, {1283, 1524}},
575 /* 8 */ {{1548, 1789}, {1795, 2036}}}},
576 {{MHz_u{320}, RuType::RU_996_TONE},
577 {/* 1 */ {{-2036, -1539}, {-1533, -1036}},
578 /* 2 */ {{-1012, -515}, {-509, -12}},
579 /* 3 */ {{12, 509}, {515, 1012}},
580 /* 4 */ {{1036, 1533}, {1539, 2036}}}},
582 {/* 1 */ {{-2036, -1539}, {-1533, -1036}, {-1012, -515}, {-509, -12}},
583 /* 2 */ {{12, 509}, {515, 1012}, {1036, 1533}, {1539, 2036}}}},
585 {/* 1 */ {{-2036, -1539},
586 {-1533, -1036},
587 {-1012, -515},
588 {-509, -12},
589 {12, 509},
590 {515, 1012},
591 {1036, 1533},
592 {1539, 2036}}}},
593};
594
595// Table 36-34 IEEE802.11be-D7.0
597 // clang-format off
598 {0,
599 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
600 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
601 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
602 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
603 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
604 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
605 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
606 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
607 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
608 {1,
609 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
610 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
611 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
612 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
613 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
614 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
615 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
616 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
617 {2,
618 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
619 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
620 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
621 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
622 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
623 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
624 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
625 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
626 {3,
627 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
628 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
629 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
630 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
631 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
632 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
633 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
634 {4,
635 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
636 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
637 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
638 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
639 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
640 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
641 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
642 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
643 {5,
644 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
645 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
646 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
647 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
648 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
649 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
650 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
651 {6,
652 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
653 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
654 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
655 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
656 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
657 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
658 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
659 {7,
660 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
661 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
662 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
663 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
664 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
665 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
666 {8,
667 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
668 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
669 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
670 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
671 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
672 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
673 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
674 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
675 {9,
676 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
677 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
678 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
679 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
680 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
681 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
682 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
683 {10,
684 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
685 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
686 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
687 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
688 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
689 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
690 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
691 {11,
692 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
693 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
694 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
695 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
696 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
697 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
698 {12,
699 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
700 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
701 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
702 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
703 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
704 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
705 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
706 {13,
707 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
708 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
709 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
710 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
711 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
712 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
713 {14,
714 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
715 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
716 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
717 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
718 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
719 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
720 {15,
721 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
722 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
723 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
724 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
725 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
726 {16,
727 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
728 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
729 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
730 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
731 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
732 EhtRu::RuSpec{RuType::RU_106_TONE, 2, true, true}}},
733 {17,
734 {EhtRu::RuSpec{RuType::RU_26_TONE, 1, true, true},
735 EhtRu::RuSpec{RuType::RU_26_TONE, 2, true, true},
736 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
737 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
738 EhtRu::RuSpec{RuType::RU_106_TONE, 2, true, true}}},
739 {18,
740 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
741 EhtRu::RuSpec{RuType::RU_26_TONE, 3, true, true},
742 EhtRu::RuSpec{RuType::RU_26_TONE, 4, true, true},
743 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
744 EhtRu::RuSpec{RuType::RU_106_TONE, 2, true, true}}},
745 {19,
746 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
747 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
748 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
749 EhtRu::RuSpec{RuType::RU_106_TONE, 2, true, true}}},
750 {20,
751 {EhtRu::RuSpec{RuType::RU_106_TONE, 1, true, true},
752 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
753 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
754 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
755 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
756 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
757 {21,
758 {EhtRu::RuSpec{RuType::RU_106_TONE, 1, true, true},
759 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
760 EhtRu::RuSpec{RuType::RU_26_TONE, 6, true, true},
761 EhtRu::RuSpec{RuType::RU_26_TONE, 7, true, true},
762 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
763 {22,
764 {EhtRu::RuSpec{RuType::RU_106_TONE, 1, true, true},
765 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
766 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
767 EhtRu::RuSpec{RuType::RU_26_TONE, 8, true, true},
768 EhtRu::RuSpec{RuType::RU_26_TONE, 9, true, true}}},
769 {23,
770 {EhtRu::RuSpec{RuType::RU_106_TONE, 1, true, true},
771 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
772 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
773 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
774 {24,
775 {EhtRu::RuSpec{RuType::RU_52_TONE, 1, true, true},
776 EhtRu::RuSpec{RuType::RU_52_TONE, 2, true, true},
777 EhtRu::RuSpec{RuType::RU_52_TONE, 3, true, true},
778 EhtRu::RuSpec{RuType::RU_52_TONE, 4, true, true}}},
779 {25,
780 {EhtRu::RuSpec{RuType::RU_106_TONE, 1, true, true},
781 EhtRu::RuSpec{RuType::RU_26_TONE, 5, true, true},
782 EhtRu::RuSpec{RuType::RU_106_TONE, 2, true, true}}},
783 {48, // FIXME: map 106/106 to 106+26/106 as long as MRU is not supported
784 {EhtRu::RuSpec{RuType::RU_106_TONE, 1, true, true},
785 EhtRu::RuSpec{RuType::RU_106_TONE, 2, true, true}}},
786 {64,
787 {EhtRu::RuSpec{RuType::RU_242_TONE, 1, true, true}}},
788 {72,
789 {EhtRu::RuSpec{RuType::RU_484_TONE, 1, true, true}}},
790 {80,
791 {EhtRu::RuSpec{RuType::RU_996_TONE, 1, true, true}}},
792 {88,
793 {EhtRu::RuSpec{RuType::RU_2x996_TONE, 1, true, true}}},
794 // clang-format on
795};
796
797std::vector<EhtRu::RuSpec>
798EhtRu::GetRuSpecs(uint16_t ruAllocation)
799{
800 std::optional<std::size_t> idx;
801 if ((ruAllocation <= 25) || (ruAllocation == 48))
802 {
803 idx = ruAllocation;
804 }
805 else if ((ruAllocation >= 26) && (ruAllocation <= 31))
806 {
807 // unassigned RU, punctured RU or contributes to zero User fields
808 }
809 else if (((ruAllocation >= 64) && (ruAllocation <= 95)))
810 {
811 idx = ruAllocation & 0x1F8;
812 }
813 else
814 {
815 NS_FATAL_ERROR("Unsupported RU allocation " << ruAllocation);
816 }
817 return idx.has_value() ? m_ruAllocations.at(idx.value()) : std::vector<EhtRu::RuSpec>{};
818}
819
820uint16_t
821EhtRu::GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers)
822{
823 switch (ruType)
824 {
826 return 0;
828 return isOdd ? 15 : 24;
830 // FIXME: map 106/106 to 106+26/106 as long as MRU is not supported
831 return isOdd ? 25 : 48;
833 return hasUsers ? 64 : 28;
835 return hasUsers ? 72 : 29;
836 default:
837 const auto ruAlloc = (ruType == RuType::RU_2x996_TONE) ? 88 : 80;
838 return hasUsers ? ruAlloc : 30;
839 }
840}
841
843 std::size_t index,
844 bool primary160MHz,
845 bool primary80MHzOrLower80MHz)
846 : m_ruType{ruType},
847 m_index{index},
848 m_primary160MHz{primary160MHz},
849 m_primary80MHzOrLower80MHz{primary80MHzOrLower80MHz}
850{
851 NS_ABORT_MSG_IF(index == 0, "Index cannot be zero");
852}
853
854RuType
856{
857 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
858 return m_ruType;
859}
860
861std::size_t
863{
864 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
865 return m_index;
866}
867
868bool
870{
871 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
872 return m_primary160MHz;
873}
874
875bool
877{
878 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
879 return m_primary80MHzOrLower80MHz;
880}
881
882std::size_t
883EhtRu::RuSpec::GetPhyIndex(MHz_u bw, uint8_t p20Index) const
884{
885 auto phyIndex{m_index};
886 const auto primary160IsLower160 = (p20Index < (MHz_u{320} / MHz_u{20}) / 2);
887 if ((bw > MHz_u{160}) && (m_ruType == RuType::RU_2x996_TONE) &&
888 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
889 {
890 phyIndex += 1;
891 }
892 const auto indicesPer80MHz = GetNRus(MHz_u{80}, m_ruType, true);
893 if ((bw > MHz_u{160}) && (m_ruType < RuType::RU_2x996_TONE) &&
894 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
895 {
896 phyIndex += 2 * indicesPer80MHz;
897 }
898 const uint8_t num20MHzSubchannelsIn160 = MHz_u{160} / MHz_u{20};
899 const auto primary80IsLower80 =
900 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
901 if ((bw > MHz_u{80}) && (m_ruType < RuType::RU_4x996_TONE) &&
902 ((m_primary160MHz && ((primary80IsLower80 && !m_primary80MHzOrLower80MHz) ||
903 (!primary80IsLower80 && m_primary80MHzOrLower80MHz))) ||
904 (!m_primary160MHz && !m_primary80MHzOrLower80MHz)))
905 {
906 phyIndex += indicesPer80MHz;
907 }
908 return phyIndex;
909}
910
911std::pair<bool, bool>
912EhtRu::GetPrimaryFlags(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
913{
914 const auto nRus = GetNRus(bw, ruType);
915 const auto ruWidth = WifiRu::GetBandwidth(ruType);
916 const auto indicesPer80MHz = (ruWidth <= MHz_u{80}) ? GetNRus(MHz_u{80}, ruType, true) : 1;
917 const auto undefinedRusPer80MHz =
918 (ruWidth <= MHz_u{80}) ? (indicesPer80MHz - GetNRus(MHz_u{80}, ruType)) : 0;
919 const auto primary160IsLower160 = (p20Index < (MHz_u{320} / MHz_u{20}) / 2);
920 const auto primary160 =
921 (bw < MHz_u{320} || ruType == RuType::RU_4x996_TONE ||
922 (primary160IsLower160 && phyIndex <= (nRus / 2) + (2 * undefinedRusPer80MHz)) ||
923 (!primary160IsLower160 && phyIndex > (nRus / 2) + (2 * undefinedRusPer80MHz)));
924 bool primary80OrLow80;
925 if (primary160)
926 {
927 const uint8_t num20MHzSubchannelsIn160 = MHz_u{160} / MHz_u{20};
928 const auto primary80IsLower80 =
929 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
930 const auto threshold =
931 ((bw < MHz_u{320}) || primary160IsLower160) ? indicesPer80MHz : 3 * indicesPer80MHz;
932 primary80OrLow80 = (bw < MHz_u{160}) || (ruType >= RuType::RU_2x996_TONE) ||
933 (primary80IsLower80 && phyIndex <= threshold) ||
934 (!primary80IsLower80 && phyIndex > threshold);
935 }
936 else
937 {
938 primary80OrLow80 = (bw < MHz_u{160}) || (ruType >= RuType::RU_2x996_TONE) ||
939 ((((phyIndex - 1) / indicesPer80MHz) % 2) == 0);
940 }
941 return {primary160, primary80OrLow80};
942}
943
944std::size_t
945EhtRu::GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
946{
947 if (WifiRu::GetBandwidth(ruType) > MHz_u{80})
948 {
949 return 1;
950 }
951
952 if (const auto indicesPer80MHz = GetNRus(MHz_u{80}, ruType, true);
953 bw > MHz_u{80} && phyIndex > indicesPer80MHz)
954 {
955 return (((phyIndex - 1) % indicesPer80MHz) + 1);
956 }
957
958 return phyIndex;
959}
960
961std::size_t
962EhtRu::GetNRus(MHz_u bw, RuType ruType, bool includeUndefinedRus /* = false */)
963{
964 if (WifiRu::GetBandwidth(ruType) >= MHz_u{20})
965 {
966 return bw / WifiRu::GetBandwidth(ruType);
967 }
968
969 const auto it = m_ruSubcarrierGroups.find({bw, ruType});
970 if (it == m_ruSubcarrierGroups.end())
971 {
972 return 0;
973 }
974
975 auto nRus = it->second.size();
976 if (!includeUndefinedRus)
977 {
978 const auto num80MHz = std::max<uint16_t>(bw / MHz_u{80}, 1);
979 const auto undefinedRus =
980 ((ruType == RuType::RU_26_TONE) && (bw >= MHz_u{80})) ? num80MHz : 0;
981 nRus -= undefinedRus;
982 }
983 return nRus;
984}
985
986std::vector<EhtRu::RuSpec>
988{
989 if (GetNRus(bw, ruType) == 0)
990 {
991 return {};
992 }
993
994 if (WifiRu::GetBandwidth(ruType) == bw)
995 {
996 return {{ruType, 1, true, true}};
997 }
998
999 if (ruType == RuType::RU_2x996_TONE)
1000 {
1001 NS_ASSERT(bw >= MHz_u{160});
1002 return {{ruType, 1, true, true}, {ruType, 1, false, true}};
1003 }
1004
1005 std::vector<EhtRu::RuSpec> ret;
1006 const auto subcarrierGroup = EhtRu::m_ruSubcarrierGroups.at({bw, ruType});
1007 const auto indices = GetNRus(std::min(bw, MHz_u{80}), ruType, true);
1008 for (uint8_t idx80MHz = 0; idx80MHz < (bw / MHz_u{80}); ++idx80MHz)
1009 {
1010 const auto p160 = (idx80MHz < 2);
1011 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1012 for (std::size_t ruIndex = 1; ruIndex <= indices; ++ruIndex)
1013 {
1014 if (subcarrierGroup.at(ruIndex - 1).empty())
1015 {
1016 // undefined RU
1017 continue;
1018 }
1019 ret.emplace_back(ruType, ruIndex, p160, p80orLow80);
1020 }
1021 }
1022 return ret;
1023}
1024
1025std::vector<EhtRu::RuSpec>
1027{
1028 if ((ruType == RuType::RU_26_TONE) || (ruType >= RuType::RU_242_TONE))
1029 {
1030 return {};
1031 }
1032
1033 std::vector<std::size_t> indices;
1034 if (bw >= MHz_u{20})
1035 {
1036 indices.push_back(5);
1037 }
1038 if (bw >= MHz_u{40})
1039 {
1040 indices.push_back(14);
1041 }
1042 if (bw >= MHz_u{80})
1043 {
1044 indices.insert(indices.end(), {24, 33});
1045 }
1046
1047 std::vector<EhtRu::RuSpec> ret;
1048 for (uint8_t idx80MHz = 0; idx80MHz < (bw / MHz_u{80}); ++idx80MHz)
1049 {
1050 const auto p160 = (idx80MHz < 2);
1051 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1052 std::transform(indices.cbegin(),
1053 indices.cend(),
1054 std::back_inserter(ret),
1055 [p160, p80orLow80](const auto indice) {
1056 return EhtRu::RuSpec{RuType::RU_26_TONE, indice, p160, p80orLow80};
1057 });
1058 }
1059 return ret;
1060}
1061
1063EhtRu::GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex)
1064{
1065 const auto it = m_ruSubcarrierGroups.find({bw, ruType});
1066 NS_ABORT_MSG_IF(it == m_ruSubcarrierGroups.cend(), "RU not found");
1067 return it->second.at(phyIndex - 1);
1068}
1069
1070bool
1071EhtRu::DoesOverlap(MHz_u bw, EhtRu::RuSpec ru, const std::vector<EhtRu::RuSpec>& v)
1072{
1073 // A 4x996-tone RU spans 320 MHz, hence it overlaps with any other RU
1074 if (bw == MHz_u{320} && ru.GetRuType() == RuType::RU_4x996_TONE && !v.empty())
1075 {
1076 return true;
1077 }
1078
1079 // This function may be called by the MAC layer, hence the PHY index may have
1080 // not been set yet. Hence, we pass the "MAC" index to GetSubcarrierGroup instead
1081 // of the PHY index. This is fine because we compare the primary 80 MHz bands of
1082 // the two RUs below.
1083 const auto rangesRu = GetSubcarrierGroup(bw, ru.GetRuType(), ru.GetIndex());
1084 const auto ruBw = WifiRu::GetBandwidth(ru.GetRuType());
1085 for (auto& p : v)
1086 {
1087 // A 4x996-tone RU spans 160 MHz, hence it overlaps
1088 if (bw == MHz_u{320} && p.GetRuType() == RuType::RU_4x996_TONE)
1089 {
1090 return true;
1091 }
1092 if ((ru.GetPrimary160MHz() != p.GetPrimary160MHz()))
1093 {
1094 // the two RUs are located in distinct 160MHz bands
1095 continue;
1096 }
1097 if (const auto otherRuBw = WifiRu::GetBandwidth(p.GetRuType());
1098 (ruBw <= MHz_u{80}) && (otherRuBw <= MHz_u{80}) &&
1099 (ru.GetPrimary80MHzOrLower80MHz() != p.GetPrimary80MHzOrLower80MHz()))
1100 {
1101 // the two RUs are located in distinct 80MHz bands
1102 continue;
1103 }
1104 for (const auto& rangeRu : rangesRu)
1105 {
1106 SubcarrierGroup rangesP = GetSubcarrierGroup(bw, p.GetRuType(), p.GetIndex());
1107 for (auto& rangeP : rangesP)
1108 {
1109 if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
1110 {
1111 return true;
1112 }
1113 }
1114 }
1115 }
1116 return false;
1117}
1118
1120EhtRu::FindOverlappingRu(MHz_u bw, EhtRu::RuSpec referenceRu, RuType searchedRuType)
1121{
1122 const auto numRus = EhtRu::GetNRus(bw, searchedRuType);
1123 for (uint8_t idx80MHz = 0; idx80MHz < (bw / MHz_u{80}); ++idx80MHz)
1124 {
1125 const auto p160 = (idx80MHz < 2);
1126 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1127 for (std::size_t index = 1; index <= numRus; ++index)
1128 {
1129 EhtRu::RuSpec searchedRu(searchedRuType, index, p160, p80orLow80);
1130 if (DoesOverlap(bw, referenceRu, {searchedRu}))
1131 {
1132 return searchedRu;
1133 }
1134 }
1135 }
1136 NS_ABORT_MSG("The searched RU type " << searchedRuType << " was not found for bw=" << bw
1137 << " and referenceRu=" << referenceRu);
1138 return EhtRu::RuSpec();
1139}
1140
1141RuType
1143 std::size_t& nStations,
1144 std::size_t& nCentral26TonesRus)
1145{
1147 for (int i = static_cast<int>(RuType::RU_4x996_TONE); i >= static_cast<int>(RuType::RU_26_TONE);
1148 i--)
1149 {
1150 if (WifiRu::GetBandwidth(static_cast<RuType>(i)) > bandwidth)
1151 {
1152 continue;
1153 }
1154 if (GetNRus(bandwidth, static_cast<RuType>(i)) > nStations)
1155 {
1156 /* the number of RUs that can be allocated using that RU type
1157 * is larger than the number of stations to allocate, the RU type
1158 * to return is hence the previous one and we can stop here */
1159 break;
1160 }
1161 ruType = static_cast<RuType>(i);
1162 }
1163 NS_ASSERT_MSG(ruType != RuType::RU_TYPE_MAX, "Cannot find equal size RUs");
1164 nStations = GetNRus(bandwidth, ruType);
1165 nCentral26TonesRus = GetNumCentral26TonesRus(bandwidth, ruType);
1166 return ruType;
1167}
1168
1169uint8_t
1171{
1172 return ((ruType == RuType::RU_52_TONE) || (ruType == RuType::RU_106_TONE))
1173 ? (bandwidth / MHz_u{20})
1174 : 0;
1175}
1176
1177bool
1179{
1180 // we do not compare the RU PHY indices because they may be uninitialized for
1181 // one of the compared RUs. This event should not cause the comparison to evaluate
1182 // to false
1185}
1186
1187bool
1189{
1190 return !(*this == other);
1191}
1192
1193bool
1194EhtRu::RuSpec::operator<(const EhtRu::RuSpec& other) const
1195{
1196 // we do not compare the RU PHY indices because they may be uninitialized for
1197 // one of the compared RUs. This event should not cause the comparison to evaluate
1198 // to false
1199 return std::tie(m_ruType, m_index, m_primary160MHz, m_primary80MHzOrLower80MHz) <
1200 std::tie(other.m_ruType, other.m_index, m_primary160MHz, m_primary80MHzOrLower80MHz);
1201}
1202
1203std::ostream&
1204operator<<(std::ostream& os, const EhtRu::RuSpec& ru)
1205{
1206 os << "RU{" << ru.GetRuType() << "/" << ru.GetIndex() << "/"
1207 << (ru.GetPrimary160MHz() ? "primary160MHz" : "secondary160MHz") << "/";
1208 if (ru.GetPrimary160MHz())
1209 {
1210 os << (ru.GetPrimary80MHzOrLower80MHz() ? "primary80MHz" : "secondary80MHz");
1211 }
1212 else
1213 {
1214 os << (ru.GetPrimary80MHzOrLower80MHz() ? "Lower80MHz" : "high80MHz");
1215 }
1216 os << "}";
1217 return os;
1218}
1219
1220} // namespace ns3
RU Specification.
Definition eht-ru.h:34
bool m_primary160MHz
true if the RU is allocated in the primary 160MHz channel
Definition eht-ru.h:116
std::size_t m_index
RU index (starting at 1) within the 80 MHz segment.
Definition eht-ru.h:115
bool operator!=(const RuSpec &other) const
Compare this RU to the given RU.
Definition eht-ru.cc:1188
bool GetPrimary80MHzOrLower80MHz() const
Definition eht-ru.cc:876
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
Definition eht-ru.cc:1178
bool m_primary80MHzOrLower80MHz
if the RU is allocated in the primary 160MHz channel, true if the RU is allocated in the primary 80MH...
Definition eht-ru.h:117
bool operator<(const RuSpec &other) const
Compare this RU to the given RU.
Definition eht-ru.cc:1194
RuSpec()=default
Default constructor.
RuType GetRuType() const
Get the RU type.
Definition eht-ru.cc:855
std::size_t GetPhyIndex(MHz_u bw, uint8_t p20Index) const
Get the RU PHY index.
Definition eht-ru.cc:883
std::size_t GetIndex() const
Get the RU index within the 80 MHz segment.
Definition eht-ru.cc:862
RuType m_ruType
RU type.
Definition eht-ru.h:114
bool GetPrimary160MHz() const
Get whether the RU is allocated in the primary 160MHz channel.
Definition eht-ru.cc:869
static const RuAllocationMap m_ruAllocations
Table 36-34 of IEEE802.11be-D7.0.
Definition eht-ru.h:268
static bool DoesOverlap(MHz_u bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
Definition eht-ru.cc:1071
static std::pair< bool, bool > GetPrimaryFlags(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary flags of a given RU transmitted in a PPDU.
Definition eht-ru.cc:912
static uint16_t GetEqualizedRuAllocation(RuType ruType, bool isOdd, bool hasUsers)
Get the RU_ALLOCATION value for equal size RUs.
Definition eht-ru.cc:821
std::map< uint8_t, std::vector< RuSpec > > RuAllocationMap
RU allocation map.
Definition eht-ru.h:265
static std::vector< RuSpec > GetRusOfType(MHz_u bw, RuType ruType)
Get the set of distinct RUs of the given type (number of tones) available in an PPDU of the given ban...
Definition eht-ru.cc:987
static std::vector< RuSpec > GetRuSpecs(uint16_t ruAllocation)
Get the RU specs based on RU_ALLOCATION.
Definition eht-ru.cc:798
static std::size_t GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the index of a given RU transmitted in a PPDU within its 80 MHz segment.
Definition eht-ru.cc:945
static SubcarrierGroup GetSubcarrierGroup(MHz_u 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 eht-ru.cc:1063
static std::vector< RuSpec > GetCentral26TonesRus(MHz_u bw, RuType ruType)
Get the set of 26-tone RUs that can be additionally allocated if the given bandwidth is split in RUs ...
Definition eht-ru.cc:1026
static RuSpec FindOverlappingRu(MHz_u bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
Definition eht-ru.cc:1120
static const SubcarrierGroups m_ruSubcarrierGroups
Subcarrier groups for all EHT RUs.
Definition eht-ru.h:262
static uint8_t GetNumCentral26TonesRus(MHz_u bw, RuType ruType)
Get the number of 26-tone RUs that can be allocated if returned RU size is greater than 26 tones.
Definition eht-ru.cc:1170
static RuType GetEqualSizedRusForStations(MHz_u 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 eht-ru.cc:1142
static std::size_t GetNRus(MHz_u bw, RuType ruType, bool includeUndefinedRus=false)
Get the number of distinct RUs of the given type (number of tones) available in a PPDU of the given b...
Definition eht-ru.cc:962
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
Definition wifi-ru.cc:78
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
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:148
RuType
The different Resource Unit (RU) types.
Definition wifi-types.h:99
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition wifi-types.h:157
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
Definition wifi-types.h:163
double MHz_u
MHz weak type.
Definition wifi-units.h:31