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