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;
837 return hasUsers ? 80 : 30;
838 default:
839 return hasUsers ? 88 : 30;
840 }
841}
842
844 std::size_t index,
845 bool primary160MHz,
846 bool primary80MHzOrLower80MHz)
847 : m_ruType{ruType},
848 m_index{index},
849 m_primary160MHz{primary160MHz},
850 m_primary80MHzOrLower80MHz{primary80MHzOrLower80MHz}
851{
852 NS_ABORT_MSG_IF(index == 0, "Index cannot be zero");
853}
854
855RuType
857{
858 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
859 return m_ruType;
860}
861
862std::size_t
864{
865 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
866 return m_index;
867}
868
869bool
871{
872 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
873 return m_primary160MHz;
874}
875
876bool
878{
879 NS_ABORT_MSG_IF(m_index == 0, "Undefined RU");
880 return m_primary80MHzOrLower80MHz;
881}
882
883std::size_t
884EhtRu::RuSpec::GetPhyIndex(MHz_u bw, uint8_t p20Index) const
885{
886 auto phyIndex{m_index};
887 const auto primary160IsLower160 = (p20Index < (MHz_u{320} / MHz_u{20}) / 2);
888 if ((bw > MHz_u{160}) && (m_ruType == RuType::RU_2x996_TONE) &&
889 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
890 {
891 phyIndex += 1;
892 }
893 const auto indicesPer80MHz = GetNRus(MHz_u{80}, m_ruType, true);
894 if ((bw > MHz_u{160}) && (m_ruType < RuType::RU_2x996_TONE) &&
895 ((primary160IsLower160 && !m_primary160MHz) || (!primary160IsLower160 && m_primary160MHz)))
896 {
897 phyIndex += 2 * indicesPer80MHz;
898 }
899 const uint8_t num20MHzSubchannelsIn160 = MHz_u{160} / MHz_u{20};
900 const auto primary80IsLower80 =
901 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
902 if ((bw > MHz_u{80}) && (m_ruType < RuType::RU_4x996_TONE) &&
903 ((m_primary160MHz && ((primary80IsLower80 && !m_primary80MHzOrLower80MHz) ||
904 (!primary80IsLower80 && m_primary80MHzOrLower80MHz))) ||
905 (!m_primary160MHz && !m_primary80MHzOrLower80MHz)))
906 {
907 phyIndex += indicesPer80MHz;
908 }
909 return phyIndex;
910}
911
912std::pair<bool, bool>
913EhtRu::GetPrimaryFlags(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
914{
915 const auto nRus = GetNRus(bw, ruType);
916 const auto ruWidth = WifiRu::GetBandwidth(ruType);
917 const auto indicesPer80MHz = (ruWidth <= MHz_u{80}) ? GetNRus(MHz_u{80}, ruType, true) : 1;
918 const auto undefinedRusPer80MHz =
919 (ruWidth <= MHz_u{80}) ? (indicesPer80MHz - GetNRus(MHz_u{80}, ruType)) : 0;
920 const auto primary160IsLower160 = (p20Index < (MHz_u{320} / MHz_u{20}) / 2);
921 const auto primary160 =
922 (bw < MHz_u{320} || ruType == RuType::RU_4x996_TONE ||
923 (primary160IsLower160 && phyIndex <= (nRus / 2) + (2 * undefinedRusPer80MHz)) ||
924 (!primary160IsLower160 && phyIndex > (nRus / 2) + (2 * undefinedRusPer80MHz)));
925 bool primary80OrLow80;
926 if (primary160)
927 {
928 const uint8_t num20MHzSubchannelsIn160 = MHz_u{160} / MHz_u{20};
929 const auto primary80IsLower80 =
930 ((p20Index % num20MHzSubchannelsIn160) < (num20MHzSubchannelsIn160 / 2));
931 const auto threshold =
932 ((bw < MHz_u{320}) || primary160IsLower160) ? indicesPer80MHz : 3 * indicesPer80MHz;
933 primary80OrLow80 = (bw < MHz_u{160}) || (ruType >= RuType::RU_2x996_TONE) ||
934 (primary80IsLower80 && phyIndex <= threshold) ||
935 (!primary80IsLower80 && phyIndex > threshold);
936 }
937 else
938 {
939 primary80OrLow80 = (bw < MHz_u{160}) || (ruType >= RuType::RU_2x996_TONE) ||
940 ((((phyIndex - 1) / indicesPer80MHz) % 2) == 0);
941 }
942 return {primary160, primary80OrLow80};
943}
944
945std::size_t
946EhtRu::GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
947{
948 if (WifiRu::GetBandwidth(ruType) > MHz_u{80})
949 {
950 return 1;
951 }
952
953 if (const auto indicesPer80MHz = GetNRus(MHz_u{80}, ruType, true);
954 bw > MHz_u{80} && phyIndex > indicesPer80MHz)
955 {
956 return (((phyIndex - 1) % indicesPer80MHz) + 1);
957 }
958
959 return phyIndex;
960}
961
962std::size_t
963EhtRu::GetNRus(MHz_u bw, RuType ruType, bool includeUndefinedRus /* = false */)
964{
965 if (WifiRu::GetBandwidth(ruType) >= MHz_u{20})
966 {
967 return bw / WifiRu::GetBandwidth(ruType);
968 }
969
970 const auto it = m_ruSubcarrierGroups.find({bw, ruType});
971 if (it == m_ruSubcarrierGroups.end())
972 {
973 return 0;
974 }
975
976 auto nRus = it->second.size();
977 if (!includeUndefinedRus)
978 {
979 const auto num80MHz = std::max<uint16_t>(bw / MHz_u{80}, 1);
980 const auto undefinedRus =
981 ((ruType == RuType::RU_26_TONE) && (bw >= MHz_u{80})) ? num80MHz : 0;
982 nRus -= undefinedRus;
983 }
984 return nRus;
985}
986
987std::vector<EhtRu::RuSpec>
989{
990 if (GetNRus(bw, ruType) == 0)
991 {
992 return {};
993 }
994
995 if (WifiRu::GetBandwidth(ruType) == bw)
996 {
997 return {{ruType, 1, true, true}};
998 }
999
1000 if (ruType == RuType::RU_2x996_TONE)
1001 {
1002 NS_ASSERT(bw >= MHz_u{160});
1003 return {{ruType, 1, true, true}, {ruType, 1, false, true}};
1004 }
1005
1006 std::vector<EhtRu::RuSpec> ret;
1007 const auto subcarrierGroup = EhtRu::m_ruSubcarrierGroups.at({bw, ruType});
1008 const auto indices = GetNRus(std::min(bw, MHz_u{80}), ruType, true);
1009 for (uint8_t idx80MHz = 0; idx80MHz < (bw / MHz_u{80}); ++idx80MHz)
1010 {
1011 const auto p160 = (idx80MHz < 2);
1012 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1013 for (std::size_t ruIndex = 1; ruIndex <= indices; ++ruIndex)
1014 {
1015 if (subcarrierGroup.at(ruIndex - 1).empty())
1016 {
1017 // undefined RU
1018 continue;
1019 }
1020 ret.emplace_back(ruType, ruIndex, p160, p80orLow80);
1021 }
1022 }
1023 return ret;
1024}
1025
1026std::vector<EhtRu::RuSpec>
1028{
1029 if ((ruType == RuType::RU_26_TONE) || (ruType >= RuType::RU_242_TONE))
1030 {
1031 return {};
1032 }
1033
1034 std::vector<std::size_t> indices;
1035 if (bw >= MHz_u{20})
1036 {
1037 indices.push_back(5);
1038 }
1039 if (bw >= MHz_u{40})
1040 {
1041 indices.push_back(14);
1042 }
1043 if (bw >= MHz_u{80})
1044 {
1045 indices.insert(indices.end(), {24, 33});
1046 }
1047
1048 std::vector<EhtRu::RuSpec> ret;
1049 for (uint8_t idx80MHz = 0; idx80MHz < (bw / MHz_u{80}); ++idx80MHz)
1050 {
1051 const auto p160 = (idx80MHz < 2);
1052 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1053 std::transform(indices.cbegin(),
1054 indices.cend(),
1055 std::back_inserter(ret),
1056 [p160, p80orLow80](const auto indice) {
1057 return EhtRu::RuSpec{RuType::RU_26_TONE, indice, p160, p80orLow80};
1058 });
1059 }
1060 return ret;
1061}
1062
1064EhtRu::GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex)
1065{
1066 const auto it = m_ruSubcarrierGroups.find({bw, ruType});
1067 NS_ABORT_MSG_IF(it == m_ruSubcarrierGroups.cend(), "RU not found");
1068 return it->second.at(phyIndex - 1);
1069}
1070
1071bool
1072EhtRu::DoesOverlap(MHz_u bw, EhtRu::RuSpec ru, const std::vector<EhtRu::RuSpec>& v)
1073{
1074 // A 4x996-tone RU spans 320 MHz, hence it overlaps with any other RU
1075 if (bw == MHz_u{320} && ru.GetRuType() == RuType::RU_4x996_TONE && !v.empty())
1076 {
1077 return true;
1078 }
1079
1080 // This function may be called by the MAC layer, hence the PHY index may have
1081 // not been set yet. Hence, we pass the "MAC" index to GetSubcarrierGroup instead
1082 // of the PHY index. This is fine because we compare the primary 80 MHz bands of
1083 // the two RUs below.
1084 const auto rangesRu = GetSubcarrierGroup(bw, ru.GetRuType(), ru.GetIndex());
1085 const auto ruBw = WifiRu::GetBandwidth(ru.GetRuType());
1086 for (auto& p : v)
1087 {
1088 // A 4x996-tone RU spans 160 MHz, hence it overlaps
1089 if (bw == MHz_u{320} && p.GetRuType() == RuType::RU_4x996_TONE)
1090 {
1091 return true;
1092 }
1093 if ((ru.GetPrimary160MHz() != p.GetPrimary160MHz()))
1094 {
1095 // the two RUs are located in distinct 160MHz bands
1096 continue;
1097 }
1098 if (const auto otherRuBw = WifiRu::GetBandwidth(p.GetRuType());
1099 (ruBw <= MHz_u{80}) && (otherRuBw <= MHz_u{80}) &&
1100 (ru.GetPrimary80MHzOrLower80MHz() != p.GetPrimary80MHzOrLower80MHz()))
1101 {
1102 // the two RUs are located in distinct 80MHz bands
1103 continue;
1104 }
1105 for (const auto& rangeRu : rangesRu)
1106 {
1107 SubcarrierGroup rangesP = GetSubcarrierGroup(bw, p.GetRuType(), p.GetIndex());
1108 for (auto& rangeP : rangesP)
1109 {
1110 if (rangeP.second >= rangeRu.first && rangeRu.second >= rangeP.first)
1111 {
1112 return true;
1113 }
1114 }
1115 }
1116 }
1117 return false;
1118}
1119
1121EhtRu::FindOverlappingRu(MHz_u bw, EhtRu::RuSpec referenceRu, RuType searchedRuType)
1122{
1123 const auto numRus = EhtRu::GetNRus(bw, searchedRuType);
1124 for (uint8_t idx80MHz = 0; idx80MHz < (bw / MHz_u{80}); ++idx80MHz)
1125 {
1126 const auto p160 = (idx80MHz < 2);
1127 const auto p80orLow80 = ((idx80MHz % 2) == 0);
1128 for (std::size_t index = 1; index <= numRus; ++index)
1129 {
1130 EhtRu::RuSpec searchedRu(searchedRuType, index, p160, p80orLow80);
1131 if (DoesOverlap(bw, referenceRu, {searchedRu}))
1132 {
1133 return searchedRu;
1134 }
1135 }
1136 }
1137 NS_ABORT_MSG("The searched RU type " << searchedRuType << " was not found for bw=" << bw
1138 << " and referenceRu=" << referenceRu);
1139 return EhtRu::RuSpec();
1140}
1141
1142RuType
1144 std::size_t& nStations,
1145 std::size_t& nCentral26TonesRus)
1146{
1148 for (int i = static_cast<int>(RuType::RU_4x996_TONE); i >= static_cast<int>(RuType::RU_26_TONE);
1149 i--)
1150 {
1151 if (WifiRu::GetBandwidth(static_cast<RuType>(i)) > bandwidth)
1152 {
1153 continue;
1154 }
1155 if (GetNRus(bandwidth, static_cast<RuType>(i)) > nStations)
1156 {
1157 /* the number of RUs that can be allocated using that RU type
1158 * is larger than the number of stations to allocate, the RU type
1159 * to return is hence the previous one and we can stop here */
1160 break;
1161 }
1162 ruType = static_cast<RuType>(i);
1163 }
1164 NS_ASSERT_MSG(ruType != RuType::RU_TYPE_MAX, "Cannot find equal size RUs");
1165 nStations = GetNRus(bandwidth, ruType);
1166 nCentral26TonesRus = GetNumCentral26TonesRus(bandwidth, ruType);
1167 return ruType;
1168}
1169
1170uint8_t
1172{
1173 return ((ruType == RuType::RU_52_TONE) || (ruType == RuType::RU_106_TONE))
1174 ? (bandwidth / MHz_u{20})
1175 : 0;
1176}
1177
1178bool
1180{
1181 // we do not compare the RU PHY indices because they may be uninitialized for
1182 // one of the compared RUs. This event should not cause the comparison to evaluate
1183 // to false
1186}
1187
1188bool
1190{
1191 return !(*this == other);
1192}
1193
1194bool
1195EhtRu::RuSpec::operator<(const EhtRu::RuSpec& other) const
1196{
1197 // we do not compare the RU PHY indices because they may be uninitialized for
1198 // one of the compared RUs. This event should not cause the comparison to evaluate
1199 // to false
1200 return std::tie(m_ruType, m_index, m_primary160MHz, m_primary80MHzOrLower80MHz) <
1201 std::tie(other.m_ruType, other.m_index, m_primary160MHz, m_primary80MHzOrLower80MHz);
1202}
1203
1204std::ostream&
1205operator<<(std::ostream& os, const EhtRu::RuSpec& ru)
1206{
1207 os << "RU{" << ru.GetRuType() << "/" << ru.GetIndex() << "/"
1208 << (ru.GetPrimary160MHz() ? "primary160MHz" : "secondary160MHz") << "/";
1209 if (ru.GetPrimary160MHz())
1210 {
1211 os << (ru.GetPrimary80MHzOrLower80MHz() ? "primary80MHz" : "secondary80MHz");
1212 }
1213 else
1214 {
1215 os << (ru.GetPrimary80MHzOrLower80MHz() ? "Lower80MHz" : "high80MHz");
1216 }
1217 os << "}";
1218 return os;
1219}
1220
1221} // 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:1189
bool GetPrimary80MHzOrLower80MHz() const
Definition eht-ru.cc:877
bool operator==(const RuSpec &other) const
Compare this RU to the given RU.
Definition eht-ru.cc:1179
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:1195
RuSpec()=default
Default constructor.
RuType GetRuType() const
Get the RU type.
Definition eht-ru.cc:856
std::size_t GetPhyIndex(MHz_u bw, uint8_t p20Index) const
Get the RU PHY index.
Definition eht-ru.cc:884
std::size_t GetIndex() const
Get the RU index within the 80 MHz segment.
Definition eht-ru.cc:863
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:870
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:1072
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:913
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:988
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:946
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:1064
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:1027
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:1121
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:1171
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:1143
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:963
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:98
std::vector< SubcarrierRange > SubcarrierGroup
a vector of subcarrier ranges defining a subcarrier group
Definition wifi-types.h:156
std::map< BwTonesPair, std::vector< SubcarrierGroup > > SubcarrierGroups
map (bandwidth, number of tones) pairs to the group of subcarrier ranges
Definition wifi-types.h:162
double MHz_u
MHz weak type.
Definition wifi-units.h:31