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