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