A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-ru-allocation-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
9#include "ns3/test.h"
10#include "ns3/wifi-phy-operating-channel.h"
11#include "ns3/wifi-ru.h"
12#include "ns3/wifi-utils.h"
13
14using namespace ns3;
15
16NS_LOG_COMPONENT_DEFINE("WifiRuAllocationTest");
17
18namespace
19{
20/**
21 * Create an HE or an EHT RU Specification.
22 * If a primary80 is provided, an HE RU Specification is created, other it is an EHT RU
23 * Specification.
24 *
25 * @param ruType the RU type
26 * @param index the RU index (starting at 1)
27 * @param primaryOrLow80MHz whether the RU is allocated in the primary 80MHz channel or in the low
28 * 80 MHz if the RU is allocated in the secondary 160 MHz
29 * @param primary160MHz whether the RU is allocated in the primary 160MHz channel (only for EHT)
30 * @return the created RU Specification.
31 */
34 std::size_t index,
35 bool primaryOrLow80MHz,
36 std::optional<bool> primary160MHz = std::nullopt)
37{
38 if (!primary160MHz)
39 {
40 return HeRu::RuSpec{ruType, index, primaryOrLow80MHz};
41 }
42 return EhtRu::RuSpec{ruType, index, *primary160MHz, primaryOrLow80MHz};
43}
44
45} // namespace
46
47/**
48 * @ingroup wifi-test
49 * @ingroup tests
50 *
51 * @brief Test the WifiPhyOperatingChannel::Get20MHzIndicesCoveringRu() method.
52 */
54{
55 public:
56 /**
57 * Constructor
58 * @param standard the standard to use for the test
59 */
61 ~Wifi20MHzIndicesCoveringRuTest() override = default;
62
63 /**
64 * Check that the indices of the 20 MHz channels covering the given RU as computed
65 * by WifiPhyOperatingChannel::Get20MHzIndicesCoveringRu() are correct.
66 *
67 * @param primary20 the index of the primary20 channel to configure
68 * @param ru the given RU
69 * @param width the width of the channel to which the given RU refers to; normally, it is the
70 * width of the PPDU for which the RU is allocated
71 * @param indices the expected indices
72 */
73 void RunOne(uint8_t primary20,
75 MHz_u width,
76 const std::set<uint8_t>& indices);
77
78 private:
79 void DoRun() override;
80
81 WifiStandard m_standard; ///< The standard to use for the test
82 WifiPhyOperatingChannel m_channel; //!< operating channel
83};
84
86 : TestCase("Check computation of the indices of the 20 MHz channels covering an RU for " +
87 std::string((standard == WIFI_STANDARD_80211ax) ? "11ax" : "11be")),
88 m_standard(standard)
89{
90}
91
92void
95 MHz_u width,
96 const std::set<uint8_t>& indices)
97{
98 auto printToStr = [](const std::set<uint8_t>& s) {
99 std::stringstream ss;
100 ss << "{";
101 for (const auto& index : s)
102 {
103 ss << +index << " ";
104 }
105 ss << "}";
106 return ss.str();
107 };
108
109 m_channel.SetPrimary20Index(primary20);
110 auto actualIndices = m_channel.Get20MHzIndicesCoveringRu(ru, width);
111 NS_TEST_EXPECT_MSG_EQ((actualIndices == indices),
112 true,
113 "Channel width=" << m_channel.GetWidth() << ", PPDU width=" << width
114 << ", p20Index=" << +primary20 << " , RU=" << ru
115 << ". Expected indices " << printToStr(indices)
116 << " differs from actual " << printToStr(actualIndices));
117}
118
119void
121{
122 const auto p80{true};
123 const auto p160{(m_standard == WIFI_STANDARD_80211be) ? std::optional(true) : std::nullopt};
124
125 /******************
126 * 20 MHz channel *
127 ******************/
129
130 /* 20 MHz PPDU */
131 {
132 const MHz_u width{20};
133 const uint8_t p20Index = 0;
134
135 // All the 9 26-tone RUs are covered by the unique 20 MHz channel
136 for (std::size_t idx = 1; idx <= 9; idx++)
137 {
138 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {p20Index});
139 }
140 // All the 4 52-tone RUs are covered by the unique 20 MHz channel
141 for (std::size_t idx = 1; idx <= 4; idx++)
142 {
143 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {p20Index});
144 }
145 // Both 106-tone RUs are covered by the unique 20 MHz channel
146 for (std::size_t idx = 1; idx <= 2; idx++)
147 {
148 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {p20Index});
149 }
150 // The 242-tone RU is covered by the unique 20 MHz channel
151 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {p20Index});
152 }
153
154 /******************
155 * 40 MHz channel *
156 ******************/
158
159 /* 20 MHz PPDU */
160 for (uint8_t p20Index = 0; p20Index < 2; p20Index++)
161 {
162 const MHz_u width{20};
163
164 // All the 9 26-tone RUs are covered by the primary 20 MHz channel
165 for (std::size_t idx = 1; idx <= 9; idx++)
166 {
167 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {p20Index});
168 }
169 // All the 4 52-tone RUs are covered by the primary 20 MHz channel
170 for (std::size_t idx = 1; idx <= 4; idx++)
171 {
172 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {p20Index});
173 }
174 // Both 106-tone RUs are covered by the primary 20 MHz channel
175 for (std::size_t idx = 1; idx <= 2; idx++)
176 {
177 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {p20Index});
178 }
179 // The 242-tone RU is covered by the primary 20 MHz channel
180 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {p20Index});
181 }
182
183 /* 40 MHz PPDU */
184 for (uint8_t p20Index = 0; p20Index < 2; p20Index++)
185 {
186 const MHz_u width{40};
187
188 // The first 9 26-tone RUs are covered by the first 20 MHz channel
189 for (std::size_t idx = 1; idx <= 9; idx++)
190 {
191 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {0});
192 }
193 // The second 9 26-tone RUs are covered by the second 20 MHz channel
194 for (std::size_t idx = 10; idx <= 18; idx++)
195 {
196 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {1});
197 }
198 // The first 4 52-tone RUs are covered by the first 20 MHz channel
199 for (std::size_t idx = 1; idx <= 4; idx++)
200 {
201 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {0});
202 }
203 // The second 4 52-tone RUs are covered by the second 20 MHz channel
204 for (std::size_t idx = 5; idx <= 8; idx++)
205 {
206 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {1});
207 }
208 // The first 2 106-tone RUs are covered by the first 20 MHz channel
209 for (std::size_t idx = 1; idx <= 2; idx++)
210 {
211 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {0});
212 }
213 // The second 2 106-tone RUs are covered by the second 20 MHz channel
214 for (std::size_t idx = 3; idx <= 4; idx++)
215 {
216 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {1});
217 }
218 // The first 242-tone RU is covered by the first 20 MHz channel
219 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {0});
220 // The second 242-tone RU is covered by the second 20 MHz channel
221 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160), width, {1});
222 // The 484-tone RU is covered by both 20 MHz channels
223 RunOne(p20Index, MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160), width, {0, 1});
224 }
225
226 /******************
227 * 80 MHz channel *
228 ******************/
230
231 /* 20 MHz PPDU */
232 for (uint8_t p20Index = 0; p20Index < 4; p20Index++)
233 {
234 const MHz_u width{20};
235
236 // All the 9 26-tone RUs are covered by the primary 20 MHz channel
237 for (std::size_t idx = 1; idx <= 9; idx++)
238 {
239 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {p20Index});
240 }
241 // All the 4 52-tone RUs are covered by the primary 20 MHz channel
242 for (std::size_t idx = 1; idx <= 4; idx++)
243 {
244 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {p20Index});
245 }
246 // Both 106-tone RUs are covered by the primary 20 MHz channel
247 for (std::size_t idx = 1; idx <= 2; idx++)
248 {
249 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {p20Index});
250 }
251 // The 242-tone RU is covered by the primary 20 MHz channel
252 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {p20Index});
253 }
254
255 /* 40 MHz PPDU */
256 for (uint8_t p20Index = 0; p20Index < 4; p20Index++)
257 {
258 const MHz_u width{40};
259 // PPDU is transmitted on P40, which may be in the lower or higher 40 MHz
260 const uint8_t p40Index = p20Index / 2;
261 // RUs can be allocated in one (or both) of the two 20 MHz channels in P40
262 const uint8_t ch20Index0 = p40Index * 2;
263 const uint8_t ch20Index1 = p40Index * 2 + 1;
264
265 // The first 9 26-tone RUs are in the lower 20 MHz of the PPDU bandwidth
266 for (std::size_t idx = 1; idx <= 9; idx++)
267 {
268 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index0});
269 }
270 // The second 9 26-tone RUs are in the higher 20 MHz of the PPDU bandwidth
271 for (std::size_t idx = 10; idx <= 18; idx++)
272 {
273 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index1});
274 }
275 // The first 4 52-tone RUs are in the lower 20 MHz of the PPDU bandwidth
276 for (std::size_t idx = 1; idx <= 4; idx++)
277 {
278 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index0});
279 }
280 // The second 4 52-tone RUs are in the higher 20 MHz of the PPDU bandwidth
281 for (std::size_t idx = 5; idx <= 8; idx++)
282 {
283 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index1});
284 }
285 // The first 2 106-tone RUs are in the lower 20 MHz of the PPDU bandwidth
286 for (std::size_t idx = 1; idx <= 2; idx++)
287 {
288 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index0});
289 }
290 // The second 2 106-tone RUs are in the higher 20 MHz of the PPDU bandwidth
291 for (std::size_t idx = 3; idx <= 4; idx++)
292 {
293 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index1});
294 }
295 // The first 242-tone RU is in the lower 20 MHz of the PPDU bandwidth
296 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {ch20Index0});
297 // The second 242-tone RU is in the higher 20 MHz of the PPDU bandwidth
298 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160), width, {ch20Index1});
299 // The 484-tone RU is covered by both 20 MHz channels
300 RunOne(p20Index,
301 MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160),
302 width,
303 {ch20Index0, ch20Index1});
304 }
305
306 /* 80 MHz PPDU */
307 for (uint8_t p20Index = 0; p20Index < 4; p20Index++)
308 {
309 const MHz_u width{80};
310
311 // The first 9 26-tone RUs are in the first 20 MHz channel
312 for (std::size_t idx = 1; idx <= 9; idx++)
313 {
314 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {0});
315 }
316 // The second 9 26-tone RUs are in the second 20 MHz channel
317 for (std::size_t idx = 10; idx <= 18; idx++)
318 {
319 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {1});
320 }
322 {
323 // The center 26-tone RU is covered by the central 20 MHz channels
324 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, 19, p80, p160), width, {1, 2});
325 }
326 // The following 9 26-tone RUs are in the third 20 MHz channel
327 for (std::size_t idx = 20; idx <= 28; idx++)
328 {
329 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {2});
330 }
331 // The last 9 26-tone RUs are in the fourth 20 MHz channel
332 for (std::size_t idx = 29; idx <= 37; idx++)
333 {
334 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {3});
335 }
336 // The first 4 52-tone RUs are in the first 20 MHz channel
337 for (std::size_t idx = 1; idx <= 4; idx++)
338 {
339 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {0});
340 }
341 // The second 4 52-tone RUs are in the second 20 MHz channel
342 for (std::size_t idx = 5; idx <= 8; idx++)
343 {
344 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {1});
345 }
346 // The third 4 52-tone RUs are in the third 20 MHz channel
347 for (std::size_t idx = 9; idx <= 12; idx++)
348 {
349 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {2});
350 }
351 // The fourth 4 52-tone RUs are in the fourth 20 MHz channel
352 for (std::size_t idx = 13; idx <= 16; idx++)
353 {
354 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {3});
355 }
356 // The first 2 106-tone RUs are in the first 20 MHz channel
357 for (std::size_t idx = 1; idx <= 2; idx++)
358 {
359 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {0});
360 }
361 // The second 2 106-tone RUs are in the second 20 MHz channel
362 for (std::size_t idx = 3; idx <= 4; idx++)
363 {
364 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {1});
365 }
366 // The third 2 106-tone RUs are in the third 20 MHz channel
367 for (std::size_t idx = 5; idx <= 6; idx++)
368 {
369 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {2});
370 }
371 // The fourth 2 106-tone RUs are in the fourth 20 MHz channel
372 for (std::size_t idx = 7; idx <= 8; idx++)
373 {
374 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {3});
375 }
376 // The first 242-tone RU is in the first 20 MHz channel
377 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {0});
378 // The second 242-tone RU is in the second 20 MHz channel
379 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160), width, {1});
380 // The third 242-tone RU is in the third 20 MHz channel
381 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 3, p80, p160), width, {2});
382 // The fourth 242-tone RU is in the fourth 20 MHz channel
383 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 4, p80, p160), width, {3});
384 // The first 484-tone RU is covered by the first two 20 MHz channels
385 RunOne(p20Index, MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160), width, {0, 1});
386 // The second 484-tone RU is covered by the last two 20 MHz channels
387 RunOne(p20Index, MakeRuSpec(RuType::RU_484_TONE, 2, p80, p160), width, {2, 3});
388 // The 996-tone RU is covered by all the 20 MHz channels
389 RunOne(p20Index, MakeRuSpec(RuType::RU_996_TONE, 1, p80, p160), width, {0, 1, 2, 3});
390 }
391
392 /******************
393 * 160 MHz channel *
394 ******************/
396
397 /* 20 MHz PPDU */
398 for (uint8_t p20Index = 0; p20Index < 8; p20Index++)
399 {
400 const MHz_u width{20};
401
402 // All the 9 26-tone RUs are covered by the primary 20 MHz channel
403 for (std::size_t idx = 1; idx <= 9; idx++)
404 {
405 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {p20Index});
406 }
407 // All the 4 52-tone RUs are covered by the primary 20 MHz channel
408 for (std::size_t idx = 1; idx <= 4; idx++)
409 {
410 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {p20Index});
411 }
412 // Both 106-tone RUs are covered by the primary 20 MHz channel
413 for (std::size_t idx = 1; idx <= 2; idx++)
414 {
415 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {p20Index});
416 }
417 // The 242-tone RU is covered by the primary 20 MHz channel
418 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {p20Index});
419 }
420
421 /* 40 MHz PPDU */
422 for (uint8_t p20Index = 0; p20Index < 8; p20Index++)
423 {
424 const MHz_u width{40};
425 // PPDU is transmitted on P40, which is one of the four 40 MHz channels
426 const uint8_t p40Index = p20Index / 2;
427 // RUs can be allocated in one (or both) of the two 20 MHz channels in P40
428 const uint8_t ch20Index0 = p40Index * 2;
429 const uint8_t ch20Index1 = p40Index * 2 + 1;
430
431 // The first 9 26-tone RUs are in the lower 20 MHz of the PPDU bandwidth
432 for (std::size_t idx = 1; idx <= 9; idx++)
433 {
434 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index0});
435 }
436 // The second 9 26-tone RUs are in the higher 20 MHz of the PPDU bandwidth
437 for (std::size_t idx = 10; idx <= 18; idx++)
438 {
439 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index1});
440 }
441 // The first 4 52-tone RUs are in the lower 20 MHz of the PPDU bandwidth
442 for (std::size_t idx = 1; idx <= 4; idx++)
443 {
444 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index0});
445 }
446 // The second 4 52-tone RUs are in the higher 20 MHz of the PPDU bandwidth
447 for (std::size_t idx = 5; idx <= 8; idx++)
448 {
449 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index1});
450 }
451 // The first 2 106-tone RUs are in the lower 20 MHz of the PPDU bandwidth
452 for (std::size_t idx = 1; idx <= 2; idx++)
453 {
454 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index0});
455 }
456 // The second 2 106-tone RUs are in the higher 20 MHz of the PPDU bandwidth
457 for (std::size_t idx = 3; idx <= 4; idx++)
458 {
459 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index1});
460 }
461 // The first 242-tone RU is in the lower 20 MHz of the PPDU bandwidth
462 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {ch20Index0});
463 // The second 242-tone RU is in the higher 20 MHz of the PPDU bandwidth
464 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160), width, {ch20Index1});
465 // The 484-tone RU is covered by both 20 MHz channels
466 RunOne(p20Index,
467 MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160),
468 width,
469 {ch20Index0, ch20Index1});
470 }
471
472 /* 80 MHz PPDU */
473 for (uint8_t p20Index = 0; p20Index < 8; p20Index++)
474 {
475 const MHz_u width{80};
476 // PPDU is transmitted on P80, which is one of the two 80 MHz channels
477 const uint8_t p80Index = p20Index / 4;
478 // RUs can be allocated in one (or more) of the four 20 MHz channels in P80
479 const uint8_t ch20Index0 = p80Index * 4;
480 const uint8_t ch20Index1 = p80Index * 4 + 1;
481 const uint8_t ch20Index2 = p80Index * 4 + 2;
482 const uint8_t ch20Index3 = p80Index * 4 + 3;
483
484 // The first 9 26-tone RUs are in the first 20 MHz channel
485 for (std::size_t idx = 1; idx <= 9; idx++)
486 {
487 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index0});
488 }
489 // The second 9 26-tone RUs are in the second 20 MHz channel
490 for (std::size_t idx = 10; idx <= 18; idx++)
491 {
492 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index1});
493 }
495 {
496 // The center 26-tone RU is covered by the central 20 MHz channels
497 RunOne(p20Index,
498 MakeRuSpec(RuType::RU_26_TONE, 19, p80, p160),
499 width,
500 {ch20Index1, ch20Index2});
501 }
502 // The following 9 26-tone RUs are in the third 20 MHz channel
503 for (std::size_t idx = 20; idx <= 28; idx++)
504 {
505 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index2});
506 }
507 // The last 9 26-tone RUs are in the fourth 20 MHz channel
508 for (std::size_t idx = 29; idx <= 37; idx++)
509 {
510 RunOne(p20Index, MakeRuSpec(RuType::RU_26_TONE, idx, p80, p160), width, {ch20Index3});
511 }
512 // The first 4 52-tone RUs are in the first 20 MHz channel
513 for (std::size_t idx = 1; idx <= 4; idx++)
514 {
515 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index0});
516 }
517 // The second 4 52-tone RUs are in the second 20 MHz channel
518 for (std::size_t idx = 5; idx <= 8; idx++)
519 {
520 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index1});
521 }
522 // The third 4 52-tone RUs are in the third 20 MHz channel
523 for (std::size_t idx = 9; idx <= 12; idx++)
524 {
525 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index2});
526 }
527 // The fourth 4 52-tone RUs are in the fourth 20 MHz channel
528 for (std::size_t idx = 13; idx <= 16; idx++)
529 {
530 RunOne(p20Index, MakeRuSpec(RuType::RU_52_TONE, idx, p80, p160), width, {ch20Index3});
531 }
532 // The first 2 106-tone RUs are in the first 20 MHz channel
533 for (std::size_t idx = 1; idx <= 2; idx++)
534 {
535 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index0});
536 }
537 // The second 2 106-tone RUs are in the second 20 MHz channel
538 for (std::size_t idx = 3; idx <= 4; idx++)
539 {
540 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index1});
541 }
542 // The third 2 106-tone RUs are in the third 20 MHz channel
543 for (std::size_t idx = 5; idx <= 6; idx++)
544 {
545 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index2});
546 }
547 // The fourth 2 106-tone RUs are in the fourth 20 MHz channel
548 for (std::size_t idx = 7; idx <= 8; idx++)
549 {
550 RunOne(p20Index, MakeRuSpec(RuType::RU_106_TONE, idx, p80, p160), width, {ch20Index3});
551 }
552 // The first 242-tone RU is in the first 20 MHz channel
553 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160), width, {ch20Index0});
554 // The second 242-tone RU is in the second 20 MHz channel
555 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160), width, {ch20Index1});
556 // The third 242-tone RU is in the third 20 MHz channel
557 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 3, p80, p160), width, {ch20Index2});
558 // The fourth 242-tone RU is in the fourth 20 MHz channel
559 RunOne(p20Index, MakeRuSpec(RuType::RU_242_TONE, 4, p80, p160), width, {ch20Index3});
560 // The first 484-tone RU is covered by the first two 20 MHz channels
561 RunOne(p20Index,
562 MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160),
563 width,
564 {ch20Index0, ch20Index1});
565 // The second 484-tone RU is covered by the last two 20 MHz channels
566 RunOne(p20Index,
567 MakeRuSpec(RuType::RU_484_TONE, 2, p80, p160),
568 width,
569 {ch20Index2, ch20Index3});
570 // The 996-tone RU is covered by all the 20 MHz channels
571 RunOne(p20Index,
572 MakeRuSpec(RuType::RU_996_TONE, 1, p80, p160),
573 width,
574 {ch20Index0, ch20Index1, ch20Index2, ch20Index3});
575 }
576
577 /* 160 MHz PPDU */
578 for (uint8_t p20Index = 0; p20Index < 8; p20Index++)
579 {
580 const MHz_u width{160};
581
582 for (auto primary80 : {true, false})
583 {
584 // RUs can be allocated in one (or more) of the four 20 MHz channels in P80/S80
585 // (depending on the primary80 flag)
586 const uint8_t p80Index = (primary80 == (p20Index < 4)) ? 0 : 1;
587 const uint8_t ch20Index0 = p80Index * 4;
588 const uint8_t ch20Index1 = p80Index * 4 + 1;
589 const uint8_t ch20Index2 = p80Index * 4 + 2;
590 const uint8_t ch20Index3 = p80Index * 4 + 3;
591
592 // The first 9 26-tone RUs are in the first 20 MHz channel
593 std::size_t startIdx = 1;
594 std::size_t stopIdx = startIdx + 8;
595 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
596 {
597 RunOne(p20Index,
598 MakeRuSpec(RuType::RU_26_TONE, idx, primary80, p160),
599 width,
600 {ch20Index0});
601 }
602 // The second 9 26-tone RUs are in the second 20 MHz channel
603 startIdx = stopIdx + 1;
604 stopIdx = startIdx + 8;
605 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
606 {
607 RunOne(p20Index,
608 MakeRuSpec(RuType::RU_26_TONE, idx, primary80, p160),
609 width,
610 {ch20Index1});
611 }
613 {
614 // The center 26-tone RU is covered by the central 20 MHz channels
615 RunOne(p20Index,
616 MakeRuSpec(RuType::RU_26_TONE, 19, primary80, p160),
617 width,
618 {ch20Index1, ch20Index2});
619 }
620 // The following 9 26-tone RUs are in the third 20 MHz channel
621 startIdx = stopIdx + 2;
622 stopIdx = startIdx + 8;
623 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
624 {
625 RunOne(p20Index,
626 MakeRuSpec(RuType::RU_26_TONE, idx, primary80, p160),
627 width,
628 {ch20Index2});
629 }
630 // The last 9 26-tone RUs are in the fourth 20 MHz channel
631 startIdx = stopIdx + 1;
632 stopIdx = startIdx + 8;
633 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
634 {
635 RunOne(p20Index,
636 MakeRuSpec(RuType::RU_26_TONE, idx, primary80, p160),
637 width,
638 {ch20Index3});
639 }
640 // The first 4 52-tone RUs are in the first 20 MHz channel
641 startIdx = 1;
642 stopIdx = startIdx + 3;
643 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
644 {
645 RunOne(p20Index,
646 MakeRuSpec(RuType::RU_52_TONE, idx, primary80, p160),
647 width,
648 {ch20Index0});
649 }
650 // The second 4 52-tone RUs are in the second 20 MHz channel
651 startIdx = stopIdx + 1;
652 stopIdx = startIdx + 3;
653 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
654 {
655 RunOne(p20Index,
656 MakeRuSpec(RuType::RU_52_TONE, idx, primary80, p160),
657 width,
658 {ch20Index1});
659 }
660 // The third 4 52-tone RUs are in the third 20 MHz channel
661 startIdx = stopIdx + 1;
662 stopIdx = startIdx + 3;
663 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
664 {
665 RunOne(p20Index,
666 MakeRuSpec(RuType::RU_52_TONE, idx, primary80, p160),
667 width,
668 {ch20Index2});
669 }
670 // The fourth 4 52-tone RUs are in the fourth 20 MHz channel
671 startIdx = stopIdx + 1;
672 stopIdx = startIdx + 3;
673 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
674 {
675 RunOne(p20Index,
676 MakeRuSpec(RuType::RU_52_TONE, idx, primary80, p160),
677 width,
678 {ch20Index3});
679 }
680 // The first 2 106-tone RUs are in the first 20 MHz channel
681 startIdx = 1;
682 stopIdx = startIdx + 1;
683 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
684 {
685 RunOne(p20Index,
686 MakeRuSpec(RuType::RU_106_TONE, idx, primary80, p160),
687 width,
688 {ch20Index0});
689 }
690 // The second 2 106-tone RUs are in the second 20 MHz channel
691 startIdx = stopIdx + 1;
692 stopIdx = startIdx + 1;
693 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
694 {
695 RunOne(p20Index,
696 MakeRuSpec(RuType::RU_106_TONE, idx, primary80, p160),
697 width,
698 {ch20Index1});
699 }
700 // The third 2 106-tone RUs are in the third 20 MHz channel
701 startIdx = stopIdx + 1;
702 stopIdx = startIdx + 1;
703 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
704 {
705 RunOne(p20Index,
706 MakeRuSpec(RuType::RU_106_TONE, idx, primary80, p160),
707 width,
708 {ch20Index2});
709 }
710 // The fourth 2 106-tone RUs are in the fourth 20 MHz channel
711 startIdx = stopIdx + 1;
712 stopIdx = startIdx + 1;
713 for (std::size_t idx = startIdx; idx <= stopIdx; idx++)
714 {
715 RunOne(p20Index,
716 MakeRuSpec(RuType::RU_106_TONE, idx, primary80, p160),
717 width,
718 {ch20Index3});
719 }
720 // The first 242-tone RU is in the first 20 MHz channel
721 auto idx = 1;
722 RunOne(p20Index,
723 MakeRuSpec(RuType::RU_242_TONE, idx++, primary80, p160),
724 width,
725 {ch20Index0});
726 // The second 242-tone RU is in the second 20 MHz channel
727 RunOne(p20Index,
728 MakeRuSpec(RuType::RU_242_TONE, idx++, primary80, p160),
729 width,
730 {ch20Index1});
731 // The third 242-tone RU is in the third 20 MHz channel
732 RunOne(p20Index,
733 MakeRuSpec(RuType::RU_242_TONE, idx++, primary80, p160),
734 width,
735 {ch20Index2});
736 // The fourth 242-tone RU is in the fourth 20 MHz channel
737 RunOne(p20Index,
738 MakeRuSpec(RuType::RU_242_TONE, idx, primary80, p160),
739 width,
740 {ch20Index3});
741 // The first 484-tone RU is covered by the first two 20 MHz channels
742 idx = 1;
743 RunOne(p20Index,
744 MakeRuSpec(RuType::RU_484_TONE, idx++, primary80, p160),
745 width,
746 {ch20Index0, ch20Index1});
747 // The second 484-tone RU is covered by the last two 20 MHz channels
748 RunOne(p20Index,
749 MakeRuSpec(RuType::RU_484_TONE, idx, primary80, p160),
750 width,
751 {ch20Index2, ch20Index3});
752 // The 996-tone RU is covered by all the 20 MHz channels
753 idx = 1;
754 RunOne(p20Index,
755 MakeRuSpec(RuType::RU_996_TONE, idx, primary80, p160),
756 width,
757 {ch20Index0, ch20Index1, ch20Index2, ch20Index3});
758 }
759 // The 2x996-tone RU is covered by all the eight 20 MHz channels
760 RunOne(p20Index,
761 MakeRuSpec(RuType::RU_2x996_TONE, 1, p80),
762 width,
763 {0, 1, 2, 3, 4, 5, 6, 7});
764 }
765}
766
767/**
768 * @ingroup wifi-test
769 * @ingroup tests
770 *
771 * @brief Test the WifiRu::GetNRus() method.
772 */
774{
775 public:
776 /**
777 * Constructor
778 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
779 */
781
782 private:
783 void DoRun() override;
784
785 /**
786 * Check the number of RUs for a given channel width as computed
787 * by GetNRus() is correct.
788 *
789 * @param rutype the given RU type
790 * @param width the width of the channel to check
791 * @param size the expected size
792 */
793 void RunOne(RuType rutype, MHz_u width, std::size_t size);
794
795 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
796};
797
799 : TestCase{"Check returned set of RUs of a given type for a given channel width for " +
800 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
801 m_modClass{modClass}
802{
803}
804
805void
806WifiNumRusInChannelTest::RunOne(RuType rutype, MHz_u width, std::size_t size)
807{
808 const auto numRus = WifiRu::GetNRus(width, rutype, m_modClass);
810 size,
811 "Channel width=" << width << ", RU type=" << rutype << ". Expected size "
812 << size << " differs from computed size " << numRus);
813}
814
815void
817{
818 /******************
819 * 20 MHz channel *
820 ******************/
821 {
822 const MHz_u width{20};
823
824 // 9x 26-tone RUs are in 20 MHz channels
825 RunOne(RuType::RU_26_TONE, width, 9);
826
827 // 4x 52-tone RUs are in 20 MHz channels
828 RunOne(RuType::RU_52_TONE, width, 4);
829
830 // 2x 106-tone RUs are in 20 MHz channels
831 RunOne(RuType::RU_106_TONE, width, 2);
832
833 // 1x 242-tone RUs are in 20 MHz channels
834 RunOne(RuType::RU_242_TONE, width, 1);
835
836 // no 484-tone RUs are in 20 MHz channels
837 RunOne(RuType::RU_484_TONE, width, 0);
838
839 // no 996-tone RUs are in 20 MHz channels
840 RunOne(RuType::RU_996_TONE, width, 0);
841
842 // no 2x996-tone RUs are in 20 MHz channels
843 RunOne(RuType::RU_2x996_TONE, width, 0);
844
845 // no 4x996-tone RUs are in 20 MHz channels
846 RunOne(RuType::RU_4x996_TONE, width, 0);
847 }
848
849 /******************
850 * 40 MHz channel *
851 ******************/
852 {
853 const MHz_u width{40};
854
855 // 18x 26-tone RUs are in 40 MHz channels
856 RunOne(RuType::RU_26_TONE, width, 18);
857
858 // 8x 52-tone RUs are in 40 MHz channels
859 RunOne(RuType::RU_52_TONE, width, 8);
860
861 // 4x 106-tone RUs are in 40 MHz channels
862 RunOne(RuType::RU_106_TONE, width, 4);
863
864 // 2x 242-tone RUs are in 40 MHz channels
865 RunOne(RuType::RU_242_TONE, width, 2);
866
867 // 1x 484-tone RUs are in 40 MHz channels
868 RunOne(RuType::RU_484_TONE, width, 1);
869
870 // no 996-tone RUs are in 40 MHz channels
871 RunOne(RuType::RU_996_TONE, width, 0);
872
873 // no 2x996-tone RUs are in 40 MHz channels
874 RunOne(RuType::RU_2x996_TONE, width, 0);
875
876 // no 4x996-tone RUs are in 40 MHz channels
877 RunOne(RuType::RU_4x996_TONE, width, 0);
878 }
879
880 /******************
881 * 80 MHz channel *
882 ******************/
883 {
884 const MHz_u width{80};
885
886 // 37x (defined) 26-tone RUs are in 80 MHz channels (1 less for EHT)
887 RunOne(RuType::RU_26_TONE, width, (m_modClass == WIFI_MOD_CLASS_HE) ? 37 : 36);
888
889 // 16x 52-tone RUs are in 80 MHz channels
890 RunOne(RuType::RU_52_TONE, width, 16);
891
892 // 8x 106-tone RUs are in 80 MHz channels
893 RunOne(RuType::RU_106_TONE, width, 8);
894
895 // 4x 242-tone RUs are in 80 MHz channels
896 RunOne(RuType::RU_242_TONE, width, 4);
897
898 // 2x 484-tone RUs are in 80 MHz channels
899 RunOne(RuType::RU_484_TONE, width, 2);
900
901 // 1x 996-tone RUs are in 80 MHz channels
902 RunOne(RuType::RU_996_TONE, width, 1);
903
904 // no 2x996-tone RUs are in 80 MHz channels
905 RunOne(RuType::RU_2x996_TONE, width, 0);
906
907 // no 4x996-tone RUs are in 80 MHz channels
908 RunOne(RuType::RU_4x996_TONE, width, 0);
909 }
910
911 /******************
912 * 160 MHz channel *
913 ******************/
914 {
915 const MHz_u width{160};
916
917 // 74x (defined) 26-tone RUs are in 160 MHz channels (2 less for EHT)
918 RunOne(RuType::RU_26_TONE, width, (m_modClass == WIFI_MOD_CLASS_HE) ? 74 : 72);
919
920 // 32x 52-tone RUs are in 160 MHz channels
921 RunOne(RuType::RU_52_TONE, width, 32);
922
923 // 16x 106-tone RUs are in 160 MHz channels
924 RunOne(RuType::RU_106_TONE, width, 16);
925
926 // 8x 242-tone RUs are in 160 MHz channels
927 RunOne(RuType::RU_242_TONE, width, 8);
928
929 // 4x 484-tone RUs are in 160 MHz channels
930 RunOne(RuType::RU_484_TONE, width, 4);
931
932 // 2x 996-tone RUs are in 160 MHz channels
933 RunOne(RuType::RU_996_TONE, width, 2);
934
935 // 1x 2x996-tone RUs are in 160 MHz channels
936 RunOne(RuType::RU_2x996_TONE, width, 1);
937
938 // no 4x996-tone RUs are in 160 MHz channels
939 RunOne(RuType::RU_4x996_TONE, width, 0);
940 }
941}
942
943/**
944 * @ingroup wifi-test
945 * @ingroup tests
946 *
947 * @brief Test the WifiRu::GetRusOfType() method.
948 */
950{
951 public:
952 /**
953 * Constructor
954 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
955 */
957
958 private:
959 void DoRun() override;
960
961 /**
962 * Check the set of RUs returned by GetRusOfType() is correct.
963 *
964 * @param rutype the given RU type
965 * @param width the width of the channel to check
966 * @param expectedRus the expected set of RUs
967 */
968 void RunOne(RuType rutype, MHz_u width, const std::vector<WifiRu::RuSpec>& expectedRus);
969
970 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
971};
972
974 : TestCase{"Check returned RUs of a given type for a given channel width for " +
975 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
976 m_modClass{modClass}
977{
978}
979
980void
982 MHz_u width,
983 const std::vector<WifiRu::RuSpec>& expectedRus)
984{
985 auto printToStr = [](const std::vector<WifiRu::RuSpec>& v) {
986 std::stringstream ss;
987 ss << "{";
988 for (const auto& ru : v)
989 {
990 ss << ru << " ";
991 }
992 ss << "}";
993 return ss.str();
994 };
995
996 const auto actualRus = WifiRu::GetRusOfType(width, rutype, m_modClass);
997 NS_TEST_EXPECT_MSG_EQ((actualRus == expectedRus),
998 true,
999 "Channel width=" << width << ", RU type=" << rutype << ". Expected RUs "
1000 << printToStr(expectedRus) << " differs from actual RUs "
1001 << printToStr(actualRus));
1002}
1003
1004void
1006{
1007 const auto p80{true};
1008 const auto s80{false};
1009 const auto p160{(m_modClass == WIFI_MOD_CLASS_HE) ? std::nullopt : std::optional(true)};
1010
1011 /******************
1012 * 20 MHz channel *
1013 ******************/
1014 {
1015 const MHz_u width{20};
1016
1017 // 9x 26-tone RUs are in 20 MHz channels
1018 RunOne(RuType::RU_26_TONE,
1019 width,
1020 {MakeRuSpec(RuType::RU_26_TONE, 1, p80, p160),
1021 MakeRuSpec(RuType::RU_26_TONE, 2, p80, p160),
1022 MakeRuSpec(RuType::RU_26_TONE, 3, p80, p160),
1023 MakeRuSpec(RuType::RU_26_TONE, 4, p80, p160),
1024 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1025 MakeRuSpec(RuType::RU_26_TONE, 6, p80, p160),
1026 MakeRuSpec(RuType::RU_26_TONE, 7, p80, p160),
1027 MakeRuSpec(RuType::RU_26_TONE, 8, p80, p160),
1028 MakeRuSpec(RuType::RU_26_TONE, 9, p80, p160)});
1029
1030 // 4x 52-tone RUs are in 20 MHz channels
1031 RunOne(RuType::RU_52_TONE,
1032 width,
1033 {MakeRuSpec(RuType::RU_52_TONE, 1, p80, p160),
1034 MakeRuSpec(RuType::RU_52_TONE, 2, p80, p160),
1035 MakeRuSpec(RuType::RU_52_TONE, 3, p80, p160),
1036 MakeRuSpec(RuType::RU_52_TONE, 4, p80, p160)});
1037
1038 // 2x 106-tone RUs are in 20 MHz channels
1039 RunOne(RuType::RU_106_TONE,
1040 width,
1041 {MakeRuSpec(RuType::RU_106_TONE, 1, p80, p160),
1042 MakeRuSpec(RuType::RU_106_TONE, 2, p80, p160)});
1043
1044 // 1x 242-tone RUs are in 20 MHz channels
1045 RunOne(RuType::RU_242_TONE, width, {MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160)});
1046
1047 // no 484-tone RUs are in 20 MHz channels
1048 RunOne(RuType::RU_484_TONE, width, {});
1049
1050 // no 996-tone RUs are in 20 MHz channels
1051 RunOne(RuType::RU_996_TONE, width, {});
1052
1053 // no 2x996-tone RUs are in 20 MHz channels
1054 RunOne(RuType::RU_2x996_TONE, width, {});
1055
1056 // no 4x996-tone RUs are in 20 MHz channels
1057 RunOne(RuType::RU_4x996_TONE, width, {});
1058 }
1059
1060 /******************
1061 * 40 MHz channel *
1062 ******************/
1063 {
1064 const MHz_u width{40};
1065
1066 // 18x 26-tone RUs are in 40 MHz channels
1067 RunOne(RuType::RU_26_TONE,
1068 width,
1069 {MakeRuSpec(RuType::RU_26_TONE, 1, p80, p160),
1070 MakeRuSpec(RuType::RU_26_TONE, 2, p80, p160),
1071 MakeRuSpec(RuType::RU_26_TONE, 3, p80, p160),
1072 MakeRuSpec(RuType::RU_26_TONE, 4, p80, p160),
1073 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1074 MakeRuSpec(RuType::RU_26_TONE, 6, p80, p160),
1075 MakeRuSpec(RuType::RU_26_TONE, 7, p80, p160),
1076 MakeRuSpec(RuType::RU_26_TONE, 8, p80, p160),
1077 MakeRuSpec(RuType::RU_26_TONE, 9, p80, p160),
1078 MakeRuSpec(RuType::RU_26_TONE, 10, p80, p160),
1079 MakeRuSpec(RuType::RU_26_TONE, 11, p80, p160),
1080 MakeRuSpec(RuType::RU_26_TONE, 12, p80, p160),
1081 MakeRuSpec(RuType::RU_26_TONE, 13, p80, p160),
1082 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160),
1083 MakeRuSpec(RuType::RU_26_TONE, 15, p80, p160),
1084 MakeRuSpec(RuType::RU_26_TONE, 16, p80, p160),
1085 MakeRuSpec(RuType::RU_26_TONE, 17, p80, p160),
1086 MakeRuSpec(RuType::RU_26_TONE, 18, p80, p160)});
1087
1088 // 8x 52-tone RUs are in 40 MHz channels
1089 RunOne(RuType::RU_52_TONE,
1090 width,
1091 {MakeRuSpec(RuType::RU_52_TONE, 1, p80, p160),
1092 MakeRuSpec(RuType::RU_52_TONE, 2, p80, p160),
1093 MakeRuSpec(RuType::RU_52_TONE, 3, p80, p160),
1094 MakeRuSpec(RuType::RU_52_TONE, 4, p80, p160),
1095 MakeRuSpec(RuType::RU_52_TONE, 5, p80, p160),
1096 MakeRuSpec(RuType::RU_52_TONE, 6, p80, p160),
1097 MakeRuSpec(RuType::RU_52_TONE, 7, p80, p160),
1098 MakeRuSpec(RuType::RU_52_TONE, 8, p80, p160)});
1099
1100 // 4x 106-tone RUs are in 40 MHz channels
1101 RunOne(RuType::RU_106_TONE,
1102 width,
1103 {MakeRuSpec(RuType::RU_106_TONE, 1, p80, p160),
1104 MakeRuSpec(RuType::RU_106_TONE, 2, p80, p160),
1105 MakeRuSpec(RuType::RU_106_TONE, 3, p80, p160),
1106 MakeRuSpec(RuType::RU_106_TONE, 4, p80, p160)});
1107
1108 // 2x 242-tone RUs are in 40 MHz channels
1109 RunOne(RuType::RU_242_TONE,
1110 width,
1111 {MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160),
1112 MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160)});
1113
1114 // 1x 484-tone RUs are in 40 MHz channels
1115 RunOne(RuType::RU_484_TONE, width, {MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160)});
1116
1117 // no 996-tone RUs are in 40 MHz channels
1118 RunOne(RuType::RU_996_TONE, width, {});
1119
1120 // no 2x996-tone RUs are in 40 MHz channels
1121 RunOne(RuType::RU_2x996_TONE, width, {});
1122
1123 // no 4x996-tone RUs are in 40 MHz channels
1124 RunOne(RuType::RU_4x996_TONE, width, {});
1125 }
1126
1127 /******************
1128 * 80 MHz channel *
1129 ******************/
1130 {
1131 const MHz_u width{80};
1132
1133 // 37x 26-tone RUs are in 80 MHz channels (1 less for EHT)
1134 std::vector<WifiRu::RuSpec> expectedRus{MakeRuSpec(RuType::RU_26_TONE, 1, p80, p160),
1135 MakeRuSpec(RuType::RU_26_TONE, 2, p80, p160),
1136 MakeRuSpec(RuType::RU_26_TONE, 3, p80, p160),
1137 MakeRuSpec(RuType::RU_26_TONE, 4, p80, p160),
1138 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1139 MakeRuSpec(RuType::RU_26_TONE, 6, p80, p160),
1140 MakeRuSpec(RuType::RU_26_TONE, 7, p80, p160),
1141 MakeRuSpec(RuType::RU_26_TONE, 8, p80, p160),
1142 MakeRuSpec(RuType::RU_26_TONE, 9, p80, p160),
1143 MakeRuSpec(RuType::RU_26_TONE, 10, p80, p160),
1144 MakeRuSpec(RuType::RU_26_TONE, 11, p80, p160),
1145 MakeRuSpec(RuType::RU_26_TONE, 12, p80, p160),
1146 MakeRuSpec(RuType::RU_26_TONE, 13, p80, p160),
1147 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160),
1148 MakeRuSpec(RuType::RU_26_TONE, 15, p80, p160),
1149 MakeRuSpec(RuType::RU_26_TONE, 16, p80, p160),
1150 MakeRuSpec(RuType::RU_26_TONE, 17, p80, p160),
1151 MakeRuSpec(RuType::RU_26_TONE, 18, p80, p160),
1152 MakeRuSpec(RuType::RU_26_TONE, 20, p80, p160),
1153 MakeRuSpec(RuType::RU_26_TONE, 21, p80, p160),
1154 MakeRuSpec(RuType::RU_26_TONE, 22, p80, p160),
1155 MakeRuSpec(RuType::RU_26_TONE, 23, p80, p160),
1156 MakeRuSpec(RuType::RU_26_TONE, 24, p80, p160),
1157 MakeRuSpec(RuType::RU_26_TONE, 25, p80, p160),
1158 MakeRuSpec(RuType::RU_26_TONE, 26, p80, p160),
1159 MakeRuSpec(RuType::RU_26_TONE, 27, p80, p160),
1160 MakeRuSpec(RuType::RU_26_TONE, 28, p80, p160),
1161 MakeRuSpec(RuType::RU_26_TONE, 29, p80, p160),
1162 MakeRuSpec(RuType::RU_26_TONE, 30, p80, p160),
1163 MakeRuSpec(RuType::RU_26_TONE, 31, p80, p160),
1164 MakeRuSpec(RuType::RU_26_TONE, 32, p80, p160),
1165 MakeRuSpec(RuType::RU_26_TONE, 33, p80, p160),
1166 MakeRuSpec(RuType::RU_26_TONE, 34, p80, p160),
1167 MakeRuSpec(RuType::RU_26_TONE, 35, p80, p160),
1168 MakeRuSpec(RuType::RU_26_TONE, 36, p80, p160),
1169 MakeRuSpec(RuType::RU_26_TONE, 37, p80, p160)};
1171 {
1172 // RU 19 is undefined for EHT
1173 const auto it = std::next(expectedRus.cbegin(), 18);
1174 expectedRus.insert(it, MakeRuSpec(RuType::RU_26_TONE, 19, p80, p160));
1175 }
1176 RunOne(RuType::RU_26_TONE, width, expectedRus);
1177
1178 // 16x 52-tone RUs are in 80 MHz channels
1179 RunOne(RuType::RU_52_TONE,
1180 width,
1181 {MakeRuSpec(RuType::RU_52_TONE, 1, p80, p160),
1182 MakeRuSpec(RuType::RU_52_TONE, 2, p80, p160),
1183 MakeRuSpec(RuType::RU_52_TONE, 3, p80, p160),
1184 MakeRuSpec(RuType::RU_52_TONE, 4, p80, p160),
1185 MakeRuSpec(RuType::RU_52_TONE, 5, p80, p160),
1186 MakeRuSpec(RuType::RU_52_TONE, 6, p80, p160),
1187 MakeRuSpec(RuType::RU_52_TONE, 7, p80, p160),
1188 MakeRuSpec(RuType::RU_52_TONE, 8, p80, p160),
1189 MakeRuSpec(RuType::RU_52_TONE, 9, p80, p160),
1190 MakeRuSpec(RuType::RU_52_TONE, 10, p80, p160),
1191 MakeRuSpec(RuType::RU_52_TONE, 11, p80, p160),
1192 MakeRuSpec(RuType::RU_52_TONE, 12, p80, p160),
1193 MakeRuSpec(RuType::RU_52_TONE, 13, p80, p160),
1194 MakeRuSpec(RuType::RU_52_TONE, 14, p80, p160),
1195 MakeRuSpec(RuType::RU_52_TONE, 15, p80, p160),
1196 MakeRuSpec(RuType::RU_52_TONE, 16, p80, p160)});
1197
1198 // 8x 106-tone RUs are in 80 MHz channels
1199 RunOne(RuType::RU_106_TONE,
1200 width,
1201 {MakeRuSpec(RuType::RU_106_TONE, 1, p80, p160),
1202 MakeRuSpec(RuType::RU_106_TONE, 2, p80, p160),
1203 MakeRuSpec(RuType::RU_106_TONE, 3, p80, p160),
1204 MakeRuSpec(RuType::RU_106_TONE, 4, p80, p160),
1205 MakeRuSpec(RuType::RU_106_TONE, 5, p80, p160),
1206 MakeRuSpec(RuType::RU_106_TONE, 6, p80, p160),
1207 MakeRuSpec(RuType::RU_106_TONE, 7, p80, p160),
1208 MakeRuSpec(RuType::RU_106_TONE, 8, p80, p160)});
1209
1210 // 4x 242-tone RUs are in 80 MHz channels
1211 RunOne(RuType::RU_242_TONE,
1212 width,
1213 {MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160),
1214 MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160),
1215 MakeRuSpec(RuType::RU_242_TONE, 3, p80, p160),
1216 MakeRuSpec(RuType::RU_242_TONE, 4, p80, p160)});
1217
1218 // 2x 484-tone RUs are in 80 MHz channels
1219 RunOne(RuType::RU_484_TONE,
1220 width,
1221 {MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160),
1222 MakeRuSpec(RuType::RU_484_TONE, 2, p80, p160)});
1223
1224 // 1x 996-tone RUs are in 80 MHz channels
1225 RunOne(RuType::RU_996_TONE, width, {MakeRuSpec(RuType::RU_996_TONE, 1, p80, p160)});
1226
1227 // no 2x996-tone RUs are in 80 MHz channels
1228 RunOne(RuType::RU_2x996_TONE, width, {});
1229
1230 // no 4x996-tone RUs are in 80 MHz channels
1231 RunOne(RuType::RU_4x996_TONE, width, {});
1232 }
1233
1234 /******************
1235 * 160 MHz channel *
1236 ******************/
1237 {
1238 const MHz_u width{160};
1239
1240 // 74x 26-tone RUs are in 160 MHz channels (2 less for EHT)
1241 std::vector<WifiRu::RuSpec> expectedRus{MakeRuSpec(RuType::RU_26_TONE, 1, p80, p160),
1242 MakeRuSpec(RuType::RU_26_TONE, 2, p80, p160),
1243 MakeRuSpec(RuType::RU_26_TONE, 3, p80, p160),
1244 MakeRuSpec(RuType::RU_26_TONE, 4, p80, p160),
1245 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1246 MakeRuSpec(RuType::RU_26_TONE, 6, p80, p160),
1247 MakeRuSpec(RuType::RU_26_TONE, 7, p80, p160),
1248 MakeRuSpec(RuType::RU_26_TONE, 8, p80, p160),
1249 MakeRuSpec(RuType::RU_26_TONE, 9, p80, p160),
1250 MakeRuSpec(RuType::RU_26_TONE, 10, p80, p160),
1251 MakeRuSpec(RuType::RU_26_TONE, 11, p80, p160),
1252 MakeRuSpec(RuType::RU_26_TONE, 12, p80, p160),
1253 MakeRuSpec(RuType::RU_26_TONE, 13, p80, p160),
1254 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160),
1255 MakeRuSpec(RuType::RU_26_TONE, 15, p80, p160),
1256 MakeRuSpec(RuType::RU_26_TONE, 16, p80, p160),
1257 MakeRuSpec(RuType::RU_26_TONE, 17, p80, p160),
1258 MakeRuSpec(RuType::RU_26_TONE, 18, p80, p160),
1259 MakeRuSpec(RuType::RU_26_TONE, 20, p80, p160),
1260 MakeRuSpec(RuType::RU_26_TONE, 21, p80, p160),
1261 MakeRuSpec(RuType::RU_26_TONE, 22, p80, p160),
1262 MakeRuSpec(RuType::RU_26_TONE, 23, p80, p160),
1263 MakeRuSpec(RuType::RU_26_TONE, 24, p80, p160),
1264 MakeRuSpec(RuType::RU_26_TONE, 25, p80, p160),
1265 MakeRuSpec(RuType::RU_26_TONE, 26, p80, p160),
1266 MakeRuSpec(RuType::RU_26_TONE, 27, p80, p160),
1267 MakeRuSpec(RuType::RU_26_TONE, 28, p80, p160),
1268 MakeRuSpec(RuType::RU_26_TONE, 29, p80, p160),
1269 MakeRuSpec(RuType::RU_26_TONE, 30, p80, p160),
1270 MakeRuSpec(RuType::RU_26_TONE, 31, p80, p160),
1271 MakeRuSpec(RuType::RU_26_TONE, 32, p80, p160),
1272 MakeRuSpec(RuType::RU_26_TONE, 33, p80, p160),
1273 MakeRuSpec(RuType::RU_26_TONE, 34, p80, p160),
1274 MakeRuSpec(RuType::RU_26_TONE, 35, p80, p160),
1275 MakeRuSpec(RuType::RU_26_TONE, 36, p80, p160),
1276 MakeRuSpec(RuType::RU_26_TONE, 37, p80, p160),
1277 MakeRuSpec(RuType::RU_26_TONE, 1, s80, p160),
1278 MakeRuSpec(RuType::RU_26_TONE, 2, s80, p160),
1279 MakeRuSpec(RuType::RU_26_TONE, 3, s80, p160),
1280 MakeRuSpec(RuType::RU_26_TONE, 4, s80, p160),
1281 MakeRuSpec(RuType::RU_26_TONE, 5, s80, p160),
1282 MakeRuSpec(RuType::RU_26_TONE, 6, s80, p160),
1283 MakeRuSpec(RuType::RU_26_TONE, 7, s80, p160),
1284 MakeRuSpec(RuType::RU_26_TONE, 8, s80, p160),
1285 MakeRuSpec(RuType::RU_26_TONE, 9, s80, p160),
1286 MakeRuSpec(RuType::RU_26_TONE, 10, s80, p160),
1287 MakeRuSpec(RuType::RU_26_TONE, 11, s80, p160),
1288 MakeRuSpec(RuType::RU_26_TONE, 12, s80, p160),
1289 MakeRuSpec(RuType::RU_26_TONE, 13, s80, p160),
1290 MakeRuSpec(RuType::RU_26_TONE, 14, s80, p160),
1291 MakeRuSpec(RuType::RU_26_TONE, 15, s80, p160),
1292 MakeRuSpec(RuType::RU_26_TONE, 16, s80, p160),
1293 MakeRuSpec(RuType::RU_26_TONE, 17, s80, p160),
1294 MakeRuSpec(RuType::RU_26_TONE, 18, s80, p160),
1295 MakeRuSpec(RuType::RU_26_TONE, 20, s80, p160),
1296 MakeRuSpec(RuType::RU_26_TONE, 21, s80, p160),
1297 MakeRuSpec(RuType::RU_26_TONE, 22, s80, p160),
1298 MakeRuSpec(RuType::RU_26_TONE, 23, s80, p160),
1299 MakeRuSpec(RuType::RU_26_TONE, 24, s80, p160),
1300 MakeRuSpec(RuType::RU_26_TONE, 25, s80, p160),
1301 MakeRuSpec(RuType::RU_26_TONE, 26, s80, p160),
1302 MakeRuSpec(RuType::RU_26_TONE, 27, s80, p160),
1303 MakeRuSpec(RuType::RU_26_TONE, 28, s80, p160),
1304 MakeRuSpec(RuType::RU_26_TONE, 29, s80, p160),
1305 MakeRuSpec(RuType::RU_26_TONE, 30, s80, p160),
1306 MakeRuSpec(RuType::RU_26_TONE, 31, s80, p160),
1307 MakeRuSpec(RuType::RU_26_TONE, 32, s80, p160),
1308 MakeRuSpec(RuType::RU_26_TONE, 33, s80, p160),
1309 MakeRuSpec(RuType::RU_26_TONE, 34, s80, p160),
1310 MakeRuSpec(RuType::RU_26_TONE, 35, s80, p160),
1311 MakeRuSpec(RuType::RU_26_TONE, 36, s80, p160),
1312 MakeRuSpec(RuType::RU_26_TONE, 37, s80, p160)};
1314 {
1315 // RU 19 and RU 56 are undefined for EHT
1316 auto it = std::next(expectedRus.cbegin(), 18);
1317 expectedRus.insert(it, MakeRuSpec(RuType::RU_26_TONE, 19, p80));
1318 it = std::next(expectedRus.cbegin(), 55);
1319 expectedRus.insert(it, MakeRuSpec(RuType::RU_26_TONE, 19, s80));
1320 }
1321 RunOne(RuType::RU_26_TONE, width, expectedRus);
1322
1323 // 32x 52-tone RUs are in 160 MHz channels
1324 RunOne(RuType::RU_52_TONE, width, {MakeRuSpec(RuType::RU_52_TONE, 1, p80, p160),
1325 MakeRuSpec(RuType::RU_52_TONE, 2, p80, p160),
1326 MakeRuSpec(RuType::RU_52_TONE, 3, p80, p160),
1327 MakeRuSpec(RuType::RU_52_TONE, 4, p80, p160),
1328 MakeRuSpec(RuType::RU_52_TONE, 5, p80, p160),
1329 MakeRuSpec(RuType::RU_52_TONE, 6, p80, p160),
1330 MakeRuSpec(RuType::RU_52_TONE, 7, p80, p160),
1331 MakeRuSpec(RuType::RU_52_TONE, 8, p80, p160),
1332 MakeRuSpec(RuType::RU_52_TONE, 9, p80, p160),
1333 MakeRuSpec(RuType::RU_52_TONE, 10, p80, p160),
1334 MakeRuSpec(RuType::RU_52_TONE, 11, p80, p160),
1335 MakeRuSpec(RuType::RU_52_TONE, 12, p80, p160),
1336 MakeRuSpec(RuType::RU_52_TONE, 13, p80, p160),
1337 MakeRuSpec(RuType::RU_52_TONE, 14, p80, p160),
1338 MakeRuSpec(RuType::RU_52_TONE, 15, p80, p160),
1339 MakeRuSpec(RuType::RU_52_TONE, 16, p80, p160),
1340 MakeRuSpec(RuType::RU_52_TONE, 1, s80, p160),
1341 MakeRuSpec(RuType::RU_52_TONE, 2, s80, p160),
1342 MakeRuSpec(RuType::RU_52_TONE, 3, s80, p160),
1343 MakeRuSpec(RuType::RU_52_TONE, 4, s80, p160),
1344 MakeRuSpec(RuType::RU_52_TONE, 5, s80, p160),
1345 MakeRuSpec(RuType::RU_52_TONE, 6, s80, p160),
1346 MakeRuSpec(RuType::RU_52_TONE, 7, s80, p160),
1347 MakeRuSpec(RuType::RU_52_TONE, 8, s80, p160),
1348 MakeRuSpec(RuType::RU_52_TONE, 9, s80, p160),
1349 MakeRuSpec(RuType::RU_52_TONE, 10, s80, p160),
1350 MakeRuSpec(RuType::RU_52_TONE, 11, s80, p160),
1351 MakeRuSpec(RuType::RU_52_TONE, 12, s80, p160),
1352 MakeRuSpec(RuType::RU_52_TONE, 13, s80, p160),
1353 MakeRuSpec(RuType::RU_52_TONE, 14, s80, p160),
1354 MakeRuSpec(RuType::RU_52_TONE, 15, s80, p160),
1355 MakeRuSpec(RuType::RU_52_TONE, 16, s80, p160)});
1356
1357 // 16x 106-tone RUs are in 160 MHz channels
1358 RunOne(RuType::RU_106_TONE,
1359 width,
1360 {MakeRuSpec(RuType::RU_106_TONE, 1, p80, p160),
1361 MakeRuSpec(RuType::RU_106_TONE, 2, p80, p160),
1362 MakeRuSpec(RuType::RU_106_TONE, 3, p80, p160),
1363 MakeRuSpec(RuType::RU_106_TONE, 4, p80, p160),
1364 MakeRuSpec(RuType::RU_106_TONE, 5, p80, p160),
1365 MakeRuSpec(RuType::RU_106_TONE, 6, p80, p160),
1366 MakeRuSpec(RuType::RU_106_TONE, 7, p80, p160),
1367 MakeRuSpec(RuType::RU_106_TONE, 8, p80, p160),
1368 MakeRuSpec(RuType::RU_106_TONE, 1, s80, p160),
1369 MakeRuSpec(RuType::RU_106_TONE, 2, s80, p160),
1370 MakeRuSpec(RuType::RU_106_TONE, 3, s80, p160),
1371 MakeRuSpec(RuType::RU_106_TONE, 4, s80, p160),
1372 MakeRuSpec(RuType::RU_106_TONE, 5, s80, p160),
1373 MakeRuSpec(RuType::RU_106_TONE, 6, s80, p160),
1374 MakeRuSpec(RuType::RU_106_TONE, 7, s80, p160),
1375 MakeRuSpec(RuType::RU_106_TONE, 8, s80, p160)});
1376
1377 // 8x 242-tone RUs are in 160 MHz channels
1378 RunOne(RuType::RU_242_TONE,
1379 width,
1380 {MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160),
1381 MakeRuSpec(RuType::RU_242_TONE, 2, p80, p160),
1382 MakeRuSpec(RuType::RU_242_TONE, 3, p80, p160),
1383 MakeRuSpec(RuType::RU_242_TONE, 4, p80, p160),
1384 MakeRuSpec(RuType::RU_242_TONE, 1, s80, p160),
1385 MakeRuSpec(RuType::RU_242_TONE, 2, s80, p160),
1386 MakeRuSpec(RuType::RU_242_TONE, 3, s80, p160),
1387 MakeRuSpec(RuType::RU_242_TONE, 4, s80, p160)});
1388
1389 // 4x 484-tone RUs are in 160 MHz channels
1390 RunOne(RuType::RU_484_TONE,
1391 width,
1392 {MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160),
1393 MakeRuSpec(RuType::RU_484_TONE, 2, p80, p160),
1394 MakeRuSpec(RuType::RU_484_TONE, 1, s80, p160),
1395 MakeRuSpec(RuType::RU_484_TONE, 2, s80, p160)});
1396
1397 // 2x 996-tone RUs are in 160 MHz channels
1398 RunOne(RuType::RU_996_TONE,
1399 width,
1400 {MakeRuSpec(RuType::RU_996_TONE, 1, p80, p160),
1401 MakeRuSpec(RuType::RU_996_TONE, 1, s80, p160)});
1402
1403 // 1x 2x996-tone RUs are in 160 MHz channels
1404 RunOne(RuType::RU_2x996_TONE, width, {MakeRuSpec(RuType::RU_2x996_TONE, 1, p80, p160)});
1405
1406 // no 4x996-tone RUs are in 160 MHz channels
1407 RunOne(RuType::RU_4x996_TONE, width, {});
1408 }
1409}
1410
1411/**
1412 * @ingroup wifi-test
1413 * @ingroup tests
1414 *
1415 * @brief Test the WifiRu::GetCentral26TonesRus() method.
1416 */
1418{
1419 public:
1420 /**
1421 * Constructor
1422 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
1423 */
1425
1426 private:
1427 void DoRun() override;
1428
1429 /**
1430 * Check the set of 26-tone RUs returned by GetCentral26TonesRus() is correct.
1431 *
1432 * @param rutype the given RU type
1433 * @param width the width of the channel to check
1434 * @param expectedCentral26TonesRus the expected set of 26-tone RUs
1435 */
1436 void RunOne(RuType rutype,
1437 MHz_u width,
1438 const std::vector<WifiRu::RuSpec>& expectedCentral26TonesRus);
1439
1440 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
1441};
1442
1444 : TestCase{"Check returned set of 26-tone RUs in a given RU type and a given channel width "
1445 "for " +
1446 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
1447 m_modClass{modClass}
1448{
1449}
1450
1451void
1453 MHz_u width,
1454 const std::vector<WifiRu::RuSpec>& expectedRus)
1455{
1456 auto printToStr = [](const std::vector<WifiRu::RuSpec>& v) {
1457 std::stringstream ss;
1458 ss << "{";
1459 for (const auto& ru : v)
1460 {
1461 ss << ru << " ";
1462 }
1463 ss << "}";
1464 return ss.str();
1465 };
1466
1467 const auto actualRus = WifiRu::GetCentral26TonesRus(width, rutype, m_modClass);
1468 NS_TEST_EXPECT_MSG_EQ((actualRus == expectedRus),
1469 true,
1470 "Channel width=" << width << ", RU type=" << rutype
1471 << ". Expected 26-tone RUs " << printToStr(expectedRus)
1472 << " differs from actual 26-tone RUs "
1473 << printToStr(actualRus));
1474}
1475
1476void
1478{
1479 const auto p80{true};
1480 const auto s80{false};
1481 const auto p160{(m_modClass == WIFI_MOD_CLASS_HE) ? std::nullopt : std::optional(true)};
1482
1483 /******************
1484 * 20 MHz channel *
1485 ******************/
1486 {
1487 const MHz_u width{20};
1488
1489 // returned set should be empty for 26-tones RUs
1490 RunOne(RuType::RU_26_TONE, width, {});
1491
1492 // there is room for 1 center 26-tone RU when 52-tone RUs are used over 20 MHz
1493 RunOne(RuType::RU_52_TONE, width, {MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160)});
1494
1495 // there is room for 1 center 26-tone RU when 106-tone RUs are used over 20 MHz
1496 RunOne(RuType::RU_106_TONE, width, {MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160)});
1497
1498 // there is no room for center 26-tone RUs when 242-tone RUs are used over 20 MHz
1499 RunOne(RuType::RU_242_TONE, width, {});
1500 }
1501
1502 /******************
1503 * 40 MHz channel *
1504 ******************/
1505 {
1506 const MHz_u width{40};
1507
1508 // returned set should be empty for 26-tones RUs
1509 RunOne(RuType::RU_26_TONE, width, {});
1510
1511 // there is room for 2 center 26-tone RUs when 52-tone RUs are used over 40 MHz
1512 RunOne(RuType::RU_52_TONE,
1513 width,
1514 {MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1515 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160)});
1516
1517 // there is room for 2 center 26-tone RUs when 106-tone RUs are used over 40 MHz
1518 RunOne(RuType::RU_106_TONE,
1519 width,
1520 {MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1521 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160)});
1522
1523 // there is no room for center 26-tone RUs when 242-tone RUs are used over 40 MHz
1524 RunOne(RuType::RU_242_TONE, width, {});
1525
1526 // there is no room for center 26-tone RUs when 484-tone RUs are used over 40 MHz
1527 RunOne(RuType::RU_484_TONE, width, {});
1528 }
1529
1530 /******************
1531 * 80 MHz channel *
1532 ******************/
1533 {
1534 const MHz_u width{80};
1535
1536 // returned set should be empty for 26-tones RUs
1537 RunOne(RuType::RU_26_TONE, width, {});
1538
1539 // there is room for 5 (1 less for EHT) center 26-tone RUs when
1540 // 52-tone/106-tone/242-tone/484-tone RUs are used over 80 MHz
1541 std::vector<WifiRu::RuSpec> expectedCentral26TonesRus{
1542 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1543 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160),
1544 MakeRuSpec(RuType::RU_26_TONE, 24, p80, p160),
1545 MakeRuSpec(RuType::RU_26_TONE, 33, p80, p160)};
1546 std::vector<WifiRu::RuSpec> extraCentral26TonesRus{};
1547 if (m_modClass == WIFI_MOD_CLASS_HE) // RU 19 is undefined for EHT
1548 {
1549 HeRu::RuSpec central26TonesRu{RuType::RU_26_TONE, 19, p80};
1550 extraCentral26TonesRus.emplace_back(central26TonesRu);
1551 const auto it = std::next(expectedCentral26TonesRus.cbegin(), 2);
1552 expectedCentral26TonesRus.insert(it, central26TonesRu);
1553 }
1554
1555 RunOne(RuType::RU_52_TONE, width, expectedCentral26TonesRus);
1556 RunOne(RuType::RU_106_TONE, width, expectedCentral26TonesRus);
1557
1558 RunOne(RuType::RU_242_TONE, width, extraCentral26TonesRus);
1559 RunOne(RuType::RU_484_TONE, width, extraCentral26TonesRus);
1560
1561 // there is no room for center 26-tone RUs when 996-tone RUs are used over 80 MHz
1562 RunOne(RuType::RU_996_TONE, width, {});
1563 }
1564
1565 /******************
1566 * 160 MHz channel *
1567 ******************/
1568 {
1569 const MHz_u width{160};
1570
1571 // returned set should be empty for 26-tones RUs
1572 RunOne(RuType::RU_26_TONE, width, {});
1573
1574 // there is room for 10 (2 less for EHT) center 26-tone RUs when
1575 // 52-tone/106-tone/242-tone/484-tone RUs are used over 80 MHz
1576 std::vector<WifiRu::RuSpec> expectedCentral26TonesRus{
1577 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
1578 MakeRuSpec(RuType::RU_26_TONE, 14, p80, p160),
1579 MakeRuSpec(RuType::RU_26_TONE, 24, p80, p160),
1580 MakeRuSpec(RuType::RU_26_TONE, 33, p80, p160),
1581 MakeRuSpec(RuType::RU_26_TONE, 5, s80, p160),
1582 MakeRuSpec(RuType::RU_26_TONE, 14, s80, p160),
1583 MakeRuSpec(RuType::RU_26_TONE, 24, s80, p160),
1584 MakeRuSpec(RuType::RU_26_TONE, 33, s80, p160)};
1585 std::vector<WifiRu::RuSpec> extraCentral26TonesRus{};
1586 if (m_modClass == WIFI_MOD_CLASS_HE) // RU 19 and RU 56 are undefined for EHT
1587 {
1588 {
1589 HeRu::RuSpec central26TonesRu{RuType::RU_26_TONE, 19, p80};
1590 extraCentral26TonesRus.emplace_back(central26TonesRu);
1591 const auto it = std::next(expectedCentral26TonesRus.cbegin(), 2);
1592 expectedCentral26TonesRus.insert(it, central26TonesRu);
1593 }
1594 {
1595 HeRu::RuSpec central26TonesRu{RuType::RU_26_TONE, 19, s80};
1596 extraCentral26TonesRus.emplace_back(central26TonesRu);
1597 const auto it = std::next(expectedCentral26TonesRus.cbegin(), 7);
1598 expectedCentral26TonesRus.insert(it, central26TonesRu);
1599 }
1600 }
1601
1602 RunOne(RuType::RU_52_TONE, width, expectedCentral26TonesRus);
1603 RunOne(RuType::RU_106_TONE, width, expectedCentral26TonesRus);
1604
1605 RunOne(RuType::RU_242_TONE, width, extraCentral26TonesRus);
1606 RunOne(RuType::RU_484_TONE, width, extraCentral26TonesRus);
1607
1608 // there is no room for center 26-tone RUs when 996-tone/2x996-tone RUs are used over 160
1609 // MHz
1610 RunOne(RuType::RU_996_TONE, width, {});
1611 RunOne(RuType::RU_2x996_TONE, width, {});
1612 }
1613}
1614
1615/**
1616 * @ingroup wifi-test
1617 * @ingroup tests
1618 *
1619 * @brief Test the WifiRu::GetEqualSizedRusForStations() method.
1620 */
1622{
1623 public:
1624 /**
1625 * Constructor
1626 *
1627 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
1628 */
1630
1631 /**
1632 * Check the maximization of the number of candidate stations that can be assigned
1633 * a RU subject to the constraint that all the stations must be assigned a RU
1634 * of the same size as computed by GetEqualSizedRusForStations() is correct.
1635 *
1636 * @param width the width of the channel to check
1637 * @param numStas the number of candidate stations we want to assign a RU
1638 * @param expectedNumStas the expected number of candidate stations that can be assigned a RU
1639 * @param expectedNumCentral26TonesRus the expected number of additional 26-tone RUs that can be
1640 * allocated @param expectedRuType the expected RU type
1641 */
1642 void RunOne(MHz_u width,
1643 std::size_t numStas,
1644 std::size_t expectedNumStas,
1645 std::size_t expectedNumCentral26TonesRus,
1646 RuType expectedRuType);
1647
1648 private:
1649 void DoRun() override;
1650
1651 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
1652};
1653
1655 : TestCase{"Check computation of the number of equal sized RUs for a given channel width for " +
1656 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
1657 m_modClass{modClass}
1658{
1659}
1660
1661void
1663 std::size_t numStas,
1664 std::size_t expectedNumStas,
1665 std::size_t expectedNumCentral26TonesRus,
1666 RuType expectedRuType)
1667{
1668 std::size_t actualNumStas{numStas};
1669 std::size_t actualNumCentral26TonesRus{0};
1670 const auto actualRuType = WifiRu::GetEqualSizedRusForStations(width,
1671 actualNumStas,
1672 actualNumCentral26TonesRus,
1673 m_modClass);
1675 actualNumStas,
1676 expectedNumStas,
1677 "Channel width=" << width << " MHz. Expected number of candidate stations "
1678 << expectedNumStas << " differs from actual number of candidate stations "
1679 << actualNumStas);
1680 NS_TEST_EXPECT_MSG_EQ(actualNumCentral26TonesRus,
1681 expectedNumCentral26TonesRus,
1682 "Channel width="
1683 << width << " MHz. Expected number of additional 26-tone RUs "
1684 << expectedNumStas
1685 << " differs from actual number of additional 26-tone RUs "
1686 << actualNumStas);
1687 NS_TEST_EXPECT_MSG_EQ(actualRuType,
1688 expectedRuType,
1689 "Channel width=" << width << " MHz. Expected RU type " << expectedRuType
1690 << " differs from actual RU type " << actualRuType);
1691}
1692
1693void
1695{
1696 /******************
1697 * 20 MHz channel *
1698 ******************/
1699 {
1700 const MHz_u width{20};
1701
1702 // 1 STA using 242-tone RU and no center 26-tone RU available over a 20 MHz channel can be
1703 // allocated for 1 candidate station
1704 RunOne(width, 1, 1, 0, RuType::RU_242_TONE);
1705
1706 // 2 STAs using 106-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1707 // allocated for 2 candidate stations
1708 RunOne(width, 2, 2, 1, RuType::RU_106_TONE);
1709
1710 // 2 STAs using 106-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1711 // allocated for 3 candidate stations
1712 RunOne(width, 3, 2, 1, RuType::RU_106_TONE);
1713
1714 // 4 STAs using 52-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1715 // allocated for 4 candidate stations
1716 RunOne(width, 4, 4, 1, RuType::RU_52_TONE);
1717
1718 // 4 STAs using 52-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1719 // allocated for 5 candidate stations
1720 RunOne(width, 5, 4, 1, RuType::RU_52_TONE);
1721
1722 // 4 STAs using 52-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1723 // allocated for 6 candidate stations
1724 RunOne(width, 6, 4, 1, RuType::RU_52_TONE);
1725
1726 // 4 STAs using 52-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1727 // allocated for 7 candidate stations
1728 RunOne(width, 7, 4, 1, RuType::RU_52_TONE);
1729
1730 // 4 STAs using 52-tone RUs and 1 center 26-tone RU available over a 20 MHz channel can be
1731 // allocated for 8 candidate stations
1732 RunOne(width, 8, 4, 1, RuType::RU_52_TONE);
1733
1734 // 9 STAs using 26-tone RUs and no center 26-tone RU available over a 20 MHz channel can be
1735 // allocated for 9 candidate stations
1736 RunOne(width, 9, 9, 0, RuType::RU_26_TONE);
1737
1738 // 9 STAs using 26-tone RUs over a 20 MHz channel can be allocated for 10 candidate stations
1739 RunOne(width, 10, 9, 0, RuType::RU_26_TONE);
1740 }
1741
1742 /******************
1743 * 40 MHz channel *
1744 ******************/
1745 {
1746 const MHz_u width{40};
1747
1748 // 1 STA using 484-tone RU and no center 26-tone RU available over a 40 MHz channel can be
1749 // allocated for 1 candidate station
1750 RunOne(width, 1, 1, 0, RuType::RU_484_TONE);
1751
1752 // 2 STAs using 242-tone RUs and no center 26-tone RU available over a 40 MHz channel can be
1753 // allocated for 2 candidate stations
1754 RunOne(width, 2, 2, 0, RuType::RU_242_TONE);
1755
1756 // 2 STAs using 242-tone RUs and no center 26-tone RU available over a 40 MHz channel can be
1757 // allocated for 3 candidate stations
1758 RunOne(width, 3, 2, 0, RuType::RU_242_TONE);
1759
1760 // 4 STAs using 106-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1761 // allocated for 4 candidate stations
1762 RunOne(width, 4, 4, 2, RuType::RU_106_TONE);
1763
1764 // 4 STAs using 106-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1765 // allocated for 5 candidate stations
1766 RunOne(width, 5, 4, 2, RuType::RU_106_TONE);
1767
1768 // 4 STAs using 106-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1769 // allocated for 6 candidate stations
1770 RunOne(width, 6, 4, 2, RuType::RU_106_TONE);
1771
1772 // 4 STAs using 106-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1773 // allocated for 7 candidate stations
1774 RunOne(width, 7, 4, 2, RuType::RU_106_TONE);
1775
1776 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1777 // allocated for 8 candidate stations
1778 RunOne(width, 8, 8, 2, RuType::RU_52_TONE);
1779
1780 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1781 // allocated for 9 candidate stations
1782 RunOne(width, 9, 8, 2, RuType::RU_52_TONE);
1783
1784 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1785 // allocated for 10 candidate stations
1786 RunOne(width, 10, 8, 2, RuType::RU_52_TONE);
1787
1788 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1789 // allocated for 11 candidate stations
1790 RunOne(width, 11, 8, 2, RuType::RU_52_TONE);
1791
1792 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1793 // allocated for 12 candidate stations
1794 RunOne(width, 12, 8, 2, RuType::RU_52_TONE);
1795
1796 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1797 // allocated for 13 candidate stations
1798 RunOne(width, 13, 8, 2, RuType::RU_52_TONE);
1799
1800 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1801 // allocated for 14 candidate stations
1802 RunOne(width, 14, 8, 2, RuType::RU_52_TONE);
1803
1804 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1805 // allocated for 15 candidate stations
1806 RunOne(width, 15, 8, 2, RuType::RU_52_TONE);
1807
1808 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1809 // allocated for 16 candidate stations
1810 RunOne(width, 16, 8, 2, RuType::RU_52_TONE);
1811
1812 // 8 STAs using 52-tone RUs and 2 center 26-tone RUs available over a 40 MHz channel can be
1813 // allocated for 17 candidate stations
1814 RunOne(width, 17, 8, 2, RuType::RU_52_TONE);
1815
1816 // 18 STAs using 26-tone RUs over a 40 MHz channel can be allocated for 18 candidate
1817 // stations
1818 RunOne(width, 18, 18, 0, RuType::RU_26_TONE);
1819
1820 // 18 STAs using 26-tone RUs over a 40 MHz channel can be allocated for 19 candidate
1821 // stations
1822 RunOne(width, 19, 18, 0, RuType::RU_26_TONE);
1823 }
1824
1825 /******************
1826 * 80 MHz channel *
1827 ******************/
1828 {
1829 const MHz_u width{80};
1830
1831 // 1 STA using 996-tone RU and no center 26-tone RU available over a 80 MHz channel can be
1832 // allocated for 11 candidate stations for 1 candidate station
1833 RunOne(width, 1, 1, 0, RuType::RU_996_TONE);
1834
1835 // 2 STAs using 484-tone RUs and 1 center 26-tone RU (HE only) available over a 80 MHz
1836 // channel can be allocated for 2 candidate stations
1837 RunOne(width, 2, 2, (m_modClass == WIFI_MOD_CLASS_HE) ? 1 : 0, RuType::RU_484_TONE);
1838
1839 // 2 STAs using 484-tone RUs and 1 center 26-tone RU (HE only) available over a 80 MHz
1840 // channel can be allocated for 3 candidate stations
1841 RunOne(width, 3, 2, (m_modClass == WIFI_MOD_CLASS_HE) ? 1 : 0, RuType::RU_484_TONE);
1842
1843 // 4 STAs using 242-tone RUs and 1 center 26-tone RU (HE only) available over a 80 MHz
1844 // channel can be allocated for 4 candidate stations
1845 RunOne(width, 4, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 1 : 0, RuType::RU_242_TONE);
1846
1847 // 4 STAs using 242-tone RUs and 1 center 26-tone RU (HE only) available over a 80 MHz
1848 // channel can be allocated for 5 candidate stations
1849 RunOne(width, 5, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 1 : 0, RuType::RU_242_TONE);
1850
1851 // 4 STAs using 242-tone RUs and 1 center 26-tone RU (HE only) available over a 80 MHz
1852 // channel can be allocated for 6 candidate stations
1853 RunOne(width, 6, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 1 : 0, RuType::RU_242_TONE);
1854
1855 // 4 STAs using 242-tone RUs and 1 center 26-tone RU (HE only) available over a 80 MHz
1856 // channel can be allocated for 7 candidate stations
1857 RunOne(width, 7, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 1 : 0, RuType::RU_242_TONE);
1858
1859 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1860 // MHz channel can be allocated for 8 candidate stations
1861 RunOne(width, 8, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1862
1863 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1864 // MHz channel can be allocated for 9 candidate stations
1865 RunOne(width, 9, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1866
1867 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1868 // MHz channel can be allocated for 10 candidate stations
1869 RunOne(width, 10, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1870
1871 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1872 // MHz channel can be allocated for 11 candidate stations
1873 RunOne(width, 11, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1874
1875 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1876 // MHz channel can be allocated for 11 candidate stations for 12 candidate stations
1877 RunOne(width, 12, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1878
1879 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1880 // MHz channel can be allocated for 11 candidate stations for 13 candidate stations
1881 RunOne(width, 13, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1882
1883 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1884 // MHz channel can be allocated for 11 candidate stations for 14 candidate stations
1885 RunOne(width, 14, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1886
1887 // 8 STAs using 106-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1888 // MHz channel can be allocated for 11 candidate stations for 15 candidate stations
1889 RunOne(width, 15, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_106_TONE);
1890
1891 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1892 // MHz channel can be allocated for 11 candidate stations for 16 candidate stations
1893 RunOne(width, 16, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1894
1895 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1896 // MHz channel can be allocated for 11 candidate stations for 17 candidate stations
1897 RunOne(width, 17, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1898
1899 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1900 // MHz channel can be allocated for 11 candidate stations for 18 candidate stations
1901 RunOne(width, 18, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1902
1903 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1904 // MHz channel can be allocated for 11 candidate stations for 19 candidate stations
1905 RunOne(width, 19, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1906
1907 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1908 // MHz channel can be allocated for 11 candidate stations for 20 candidate stations
1909 RunOne(width, 20, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1910
1911 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1912 // MHz channel can be allocated for 11 candidate stations for 21 candidate stations
1913 RunOne(width, 21, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1914
1915 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1916 // MHz channel can be allocated for 11 candidate stations for 22 candidate stations
1917 RunOne(width, 22, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1918
1919 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1920 // MHz channel can be allocated for 11 candidate stations for 23 candidate stations
1921 RunOne(width, 23, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1922
1923 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1924 // MHz channel can be allocated for 11 candidate stations for 24 candidate stations
1925 RunOne(width, 24, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1926
1927 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1928 // MHz channel can be allocated for 11 candidate stations for 25 candidate stations
1929 RunOne(width, 25, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1930
1931 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1932 // MHz channel can be allocated for 11 candidate stations for 26 candidate stations
1933 RunOne(width, 26, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1934
1935 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1936 // MHz channel can be allocated for 11 candidate stations for 27 candidate stations
1937 RunOne(width, 27, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1938
1939 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1940 // MHz channel can be allocated for 11 candidate stations for 28 candidate stations
1941 RunOne(width, 28, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1942
1943 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1944 // MHz channel can be allocated for 11 candidate stations for 29 candidate stations
1945 RunOne(width, 29, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1946
1947 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1948 // MHz channel can be allocated for 11 candidate stations for 30 candidate stations
1949 RunOne(width, 30, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1950
1951 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1952 // MHz channel can be allocated for 11 candidate stations for 31 candidate stations
1953 RunOne(width, 31, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1954
1955 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1956 // MHz channel can be allocated for 11 candidate stations for 31 candidate stations
1957 RunOne(width, 31, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1958
1959 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1960 // MHz channel can be allocated for 11 candidate stations for 32 candidate stations
1961 RunOne(width, 32, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1962
1963 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1964 // MHz channel can be allocated for 11 candidate stations for 33 candidate stations
1965 RunOne(width, 33, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1966
1967 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1968 // MHz channel can be allocated for 11 candidate stations for 34 candidate stations
1969 RunOne(width, 34, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1970
1971 // 16 STAs using 52-tone RUs and 5 center 26-tone RUs (1 less for EHT) available over a 80
1972 // MHz channel can be allocated for 11 candidate stations for 35 candidate stations
1973 RunOne(width, 35, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 4, RuType::RU_52_TONE);
1974
1975 // 16 STAs (36 for EHT) using 52-tone RUs (26-tone RUs for EHT) and 5 center 26-tone RUs
1976 // (HE only) available over a 80 MHz channel can be allocated for 11 candidate stations for
1977 // 36 candidate stations
1978 RunOne(width,
1979 36,
1980 (m_modClass == WIFI_MOD_CLASS_HE) ? 16 : 36,
1981 (m_modClass == WIFI_MOD_CLASS_HE) ? 5 : 0,
1982 (m_modClass == WIFI_MOD_CLASS_HE) ? RuType::RU_52_TONE : RuType::RU_26_TONE);
1983
1984 // 37 STAs (36 for EHT) using 26-tone RUs over a 80 MHz channel can be allocated for 37
1985 // candidate stations
1986 RunOne(width, 37, (m_modClass == WIFI_MOD_CLASS_HE) ? 37 : 36, 0, RuType::RU_26_TONE);
1987
1988 // 37 STAs (36 for EHT) using 26-tone RUs over a 80 MHz channel can be allocated for 38
1989 // candidate stations
1990 RunOne(width, 38, (m_modClass == WIFI_MOD_CLASS_HE) ? 37 : 36, 0, RuType::RU_26_TONE);
1991 }
1992
1993 /******************
1994 * 160 MHz channel *
1995 ******************/
1996 {
1997 const MHz_u width{160};
1998
1999 // 1 STA using 2x996-tone RU and no center 26-tone RU available over a 160 MHz channel can
2000 // be allocated for 1 candidate station
2001 RunOne(width, 1, 1, 0, RuType::RU_2x996_TONE);
2002
2003 // 2 STAs using 996-tone RUs and no center 26-tone RU available over a 160 MHz channel can
2004 // be allocated for 2 candidate stations
2005 RunOne(width, 2, 2, 0, RuType::RU_996_TONE);
2006
2007 // 2 STAs using 996-tone RUs and no center 26-tone RU available over a 160 MHz channel can
2008 // be allocated for 3 candidate stations
2009 RunOne(width, 3, 2, 0, RuType::RU_996_TONE);
2010
2011 // 4 STAs using 484-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2012 // channel can be allocated for 4 candidate stations
2013 RunOne(width, 4, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_484_TONE);
2014
2015 // 4 STAs using 484-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2016 // channel can be allocated for 5 candidate stations
2017 RunOne(width, 5, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_484_TONE);
2018
2019 // 4 STAs using 484-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2020 // channel can be allocated for 6 candidate stations
2021 RunOne(width, 6, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_484_TONE);
2022
2023 // 4 STAs using 484-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2024 // channel can be allocated for 7 candidate stations
2025 RunOne(width, 7, 4, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_484_TONE);
2026
2027 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2028 // channel can be allocated for 8 candidate stations
2029 RunOne(width, 8, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2030
2031 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2032 // channel can be allocated for 9 candidate stations
2033 RunOne(width, 9, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2034
2035 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2036 // channel can be allocated for 10 candidate stations
2037 RunOne(width, 10, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2038
2039 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2040 // channel can be allocated for 11 candidate stations
2041 RunOne(width, 11, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2042
2043 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2044 // channel can be allocated for 12 candidate stations
2045 RunOne(width, 12, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2046
2047 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2048 // channel can be allocated for 13 candidate stations
2049 RunOne(width, 13, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2050
2051 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2052 // channel can be allocated for 14 candidate stations
2053 RunOne(width, 14, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2054
2055 // 8 STAs using 242-tone RUs and 2 center 26-tone RUs (HE only) available over a 160 MHz
2056 // channel can be allocated for 15 candidate stations
2057 RunOne(width, 15, 8, (m_modClass == WIFI_MOD_CLASS_HE) ? 2 : 0, RuType::RU_242_TONE);
2058
2059 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2060 // 160 MHz channel can be allocated for 16 candidate stations
2061 RunOne(width, 16, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2062
2063 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2064 // 160 MHz channel can be allocated for 17 candidate stations
2065 RunOne(width, 17, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2066
2067 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2068 // 160 MHz channel can be allocated for 18 candidate stations
2069 RunOne(width, 18, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2070
2071 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2072 // 160 MHz channel can be allocated for 19 candidate stations
2073 RunOne(width, 19, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2074
2075 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2076 // 160 MHz channel can be allocated for 20 candidate stations
2077 RunOne(width, 20, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2078
2079 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2080 // 160 MHz channel can be allocated for 21 candidate stations
2081 RunOne(width, 21, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2082
2083 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2084 // 160 MHz channel can be allocated for 22 candidate stations
2085 RunOne(width, 22, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2086
2087 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2088 // 160 MHz channel can be allocated for 23 candidate stations
2089 RunOne(width, 23, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2090
2091 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2092 // 160 MHz channel can be allocated for 24 candidate stations
2093 RunOne(width, 24, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2094
2095 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2096 // 160 MHz channel can be allocated for 25 candidate stations
2097 RunOne(width, 25, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2098
2099 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2100 // 160 MHz channel can be allocated for 26 candidate stations
2101 RunOne(width, 26, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2102
2103 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2104 // 160 MHz channel can be allocated for 27 candidate stations
2105 RunOne(width, 27, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2106
2107 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2108 // 160 MHz channel can be allocated for 28 candidate stations
2109 RunOne(width, 28, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2110
2111 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2112 // 160 MHz channel can be allocated for 29 candidate stations
2113 RunOne(width, 29, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2114
2115 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2116 // 160 MHz channel can be allocated for 30 candidate stations
2117 RunOne(width, 30, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2118
2119 // 16 STAs using 106-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a
2120 // 160 MHz channel can be allocated for 31 candidate stations
2121 RunOne(width, 31, 16, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_106_TONE);
2122
2123 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2124 // MHz channel can be allocated for 32 candidate stations
2125 RunOne(width, 32, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2126
2127 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2128 // MHz channel can be allocated for 33 candidate stations
2129 RunOne(width, 33, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2130
2131 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2132 // MHz channel can be allocated for 34 candidate stations
2133 RunOne(width, 34, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2134
2135 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2136 // MHz channel can be allocated for 35 candidate stations
2137 RunOne(width, 35, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2138
2139 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2140 // MHz channel can be allocated for 36 candidate stations
2141 RunOne(width, 36, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2142
2143 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2144 // MHz channel can be allocated for 37 candidate stations
2145 RunOne(width, 37, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2146
2147 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2148 // MHz channel can be allocated for 38 candidate stations
2149 RunOne(width, 38, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2150
2151 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2152 // MHz channel can be allocated for 39 candidate stations
2153 RunOne(width, 39, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2154
2155 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2156 // MHz channel can be allocated for 40 candidate stations
2157 RunOne(width, 40, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2158
2159 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2160 // MHz channel can be allocated for 41 candidate stations
2161 RunOne(width, 41, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2162
2163 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2164 // MHz channel can be allocated for 42 candidate stations
2165 RunOne(width, 42, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2166
2167 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2168 // MHz channel can be allocated for 43 candidate stations
2169 RunOne(width, 43, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2170
2171 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2172 // MHz channel can be allocated for 44 candidate stations
2173 RunOne(width, 44, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2174
2175 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2176 // MHz channel can be allocated for 45 candidate stations
2177 RunOne(width, 45, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2178
2179 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2180 // MHz channel can be allocated for 46 candidate stations
2181 RunOne(width, 46, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2182
2183 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2184 // MHz channel can be allocated for 47 candidate stations
2185 RunOne(width, 47, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2186
2187 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2188 // MHz channel can be allocated for 48 candidate stations
2189 RunOne(width, 48, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2190
2191 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2192 // MHz channel can be allocated for 49 candidate stations
2193 RunOne(width, 49, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2194
2195 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2196 // MHz channel can be allocated for 50 candidate stations
2197 RunOne(width, 50, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2198
2199 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2200 // MHz channel can be allocated for 51 candidate stations
2201 RunOne(width, 51, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2202
2203 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2204 // MHz channel can be allocated for 52 candidate stations
2205 RunOne(width, 52, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2206
2207 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2208 // MHz channel can be allocated for 53 candidate stations
2209 RunOne(width, 53, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2210
2211 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2212 // MHz channel can be allocated for 54 candidate stations
2213 RunOne(width, 54, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2214
2215 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2216 // MHz channel can be allocated for 55 candidate stations
2217 RunOne(width, 55, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2218
2219 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2220 // MHz channel can be allocated for 56 candidate stations
2221 RunOne(width, 56, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2222
2223 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2224 // MHz channel can be allocated for 57 candidate stations
2225 RunOne(width, 57, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2226
2227 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2228 // MHz channel can be allocated for 58 candidate stations
2229 RunOne(width, 58, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2230
2231 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2232 // MHz channel can be allocated for 59 candidate stations
2233 RunOne(width, 59, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2234
2235 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2236 // MHz channel can be allocated for 60 candidate stations
2237 RunOne(width, 60, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2238
2239 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2240 // MHz channel can be allocated for 61 candidate stations
2241 RunOne(width, 61, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2242
2243 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2244 // MHz channel can be allocated for 62 candidate stations
2245 RunOne(width, 62, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2246
2247 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2248 // MHz channel can be allocated for 63 candidate stations
2249 RunOne(width, 63, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2250
2251 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2252 // MHz channel can be allocated for 64 candidate stations
2253 RunOne(width, 64, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2254
2255 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2256 // MHz channel can be allocated for 65 candidate stations
2257 RunOne(width, 65, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2258
2259 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2260 // MHz channel can be allocated for 66 candidate stations
2261 RunOne(width, 66, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2262
2263 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2264 // MHz channel can be allocated for 67 candidate stations
2265 RunOne(width, 67, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2266
2267 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2268 // MHz channel can be allocated for 68 candidate stations
2269 RunOne(width, 68, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2270
2271 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2272 // MHz channel can be allocated for 69 candidate stations
2273 RunOne(width, 69, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2274
2275 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2276 // MHz channel can be allocated for 70 candidate stations
2277 RunOne(width, 70, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2278
2279 // 32 STAs using 52-tone RUs and 10 center 26-tone RUs (2 less for EHT) available over a 160
2280 // MHz channel can be allocated for 71 candidate stations
2281 RunOne(width, 71, 32, (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 8, RuType::RU_52_TONE);
2282
2283 // 32 STAs (72 for EHT) using 52-tone RUs (26-tone RUs for EHT) and 10 center 26-tone RUs
2284 // (HE only) available over a 160 MHz channel can be allocated for 72 candidate stations
2285 RunOne(width,
2286 72,
2287 (m_modClass == WIFI_MOD_CLASS_HE) ? 32 : 72,
2288 (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 0,
2289 (m_modClass == WIFI_MOD_CLASS_HE) ? RuType::RU_52_TONE : RuType::RU_26_TONE);
2290
2291 // 32 STAs (72 for EHT) using 52-tone RUs (26-tone RUs for EHT) and 10 center 26-tone RUs
2292 // (HE only) available over a 160 MHz channel can be allocated for 73 candidate stations
2293 RunOne(width,
2294 73,
2295 (m_modClass == WIFI_MOD_CLASS_HE) ? 32 : 72,
2296 (m_modClass == WIFI_MOD_CLASS_HE) ? 10 : 0,
2297 (m_modClass == WIFI_MOD_CLASS_HE) ? RuType::RU_52_TONE : RuType::RU_26_TONE);
2298
2299 // 74 STAs (72 for EHT) using 26-tone RUs over a 160 MHz channel can be allocated for 74
2300 // candidate stations
2301 RunOne(width, 74, (m_modClass == WIFI_MOD_CLASS_HE) ? 74 : 72, 0, RuType::RU_26_TONE);
2302
2303 // 74 STAs (72 for EHT) using 26-tone RUs over a 160 MHz channel can be allocated for 75
2304 // candidate stations
2305 RunOne(width, 75, (m_modClass == WIFI_MOD_CLASS_HE) ? 74 : 72, 0, RuType::RU_26_TONE);
2306 }
2307}
2308
2309/**
2310 * @ingroup wifi-test
2311 * @ingroup tests
2312 *
2313 * @brief Test the WifiRu::GetSubcarrierGroup() method.
2314 */
2316{
2317 public:
2318 /**
2319 * Constructor
2320 *
2321 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
2322 */
2324
2325 /**
2326 * Check the subcarrier group as returned
2327 * by GetSubcarrierGroup() is correct.
2328 *
2329 * @param width the width of the channel to check
2330 * @param ruType the RU type to check
2331 * @param phyIndex the PHY index to check
2332 * @param expectedSubcarrierGroup the expected subcarrier range
2333 */
2334 void RunOne(MHz_u width,
2335 RuType ruType,
2336 std::size_t phyIndex,
2337 const SubcarrierGroup& expectedSubcarrierGroup);
2338
2339 private:
2340 void DoRun() override;
2341
2342 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
2343};
2344
2346 : TestCase{"Check computation of the subcarrier groups for " +
2347 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
2348 m_modClass{modClass}
2349{
2350}
2351
2352void
2354 RuType ruType,
2355 std::size_t phyIndex,
2356 const SubcarrierGroup& expectedSubcarrierGroup)
2357{
2358 auto printToStr = [](const SubcarrierGroup& groups) {
2359 std::stringstream ss;
2360 ss << "{ ";
2361 for (const auto& group : groups)
2362 {
2363 ss << "(" << group.first << ", " << group.second << ") ";
2364 }
2365 ss << "}";
2366 return ss.str();
2367 };
2368
2369 const auto actualSubcarrierGroup =
2370 WifiRu::GetSubcarrierGroup(width, ruType, phyIndex, m_modClass);
2371 NS_TEST_EXPECT_MSG_EQ((actualSubcarrierGroup == expectedSubcarrierGroup),
2372 true,
2373 "Channel width=" << width << ", RU type=" << ruType << ", PHY index="
2374 << phyIndex << ". Expected subcarrier groups "
2375 << printToStr(expectedSubcarrierGroup)
2376 << " differs from actual subcarrier groups "
2377 << printToStr(actualSubcarrierGroup));
2378}
2379
2380void
2382{
2383 const std::map<BwTonesPair, std::vector<SubcarrierGroup>> expectedHeRuSubcarrierGroups = {
2384 {{MHz_u{20}, RuType::RU_26_TONE},
2385 {/* 1 */ {{-121, -96}},
2386 /* 2 */ {{-95, -70}},
2387 /* 3 */ {{-68, -43}},
2388 /* 4 */ {{-42, -17}},
2389 /* 5 */ {{-16, -4}, {4, 16}},
2390 /* 6 */ {{17, 42}},
2391 /* 7 */ {{43, 68}},
2392 /* 8 */ {{70, 95}},
2393 /* 9 */ {{96, 121}}}},
2394 {{MHz_u{20}, RuType::RU_52_TONE},
2395 {/* 1 */ {{-121, -70}},
2396 /* 2 */ {{-68, -17}},
2397 /* 3 */ {{17, 68}},
2398 /* 4 */ {{70, 121}}}},
2399 {{MHz_u{20}, RuType::RU_106_TONE},
2400 {/* 1 */ {{-122, -17}},
2401 /* 2 */ {{17, 122}}}},
2402 {{MHz_u{20}, RuType::RU_242_TONE}, {/* 1 */ {{-122, -2}, {2, 122}}}},
2403 {{MHz_u{40}, RuType::RU_26_TONE},
2404 {/* 1 */ {{-243, -218}},
2405 /* 2 */ {{-217, -192}},
2406 /* 3 */ {{-189, -164}},
2407 /* 4 */ {{-163, -138}},
2408 /* 5 */ {{-136, -111}},
2409 /* 6 */ {{-109, -84}},
2410 /* 7 */ {{-83, -58}},
2411 /* 8 */ {{-55, -30}},
2412 /* 9 */ {{-29, -4}},
2413 /* 10 */ {{4, 29}},
2414 /* 11 */ {{30, 55}},
2415 /* 12 */ {{58, 83}},
2416 /* 13 */ {{84, 109}},
2417 /* 14 */ {{111, 136}},
2418 /* 15 */ {{138, 163}},
2419 /* 16 */ {{164, 189}},
2420 /* 17 */ {{192, 217}},
2421 /* 18 */ {{218, 243}}}},
2422 {{MHz_u{40}, RuType::RU_52_TONE},
2423 {/* 1 */ {{-243, -192}},
2424 /* 2 */ {{-189, -138}},
2425 /* 3 */ {{-109, -58}},
2426 /* 4 */ {{-55, -4}},
2427 /* 5 */ {{4, 55}},
2428 /* 6 */ {{58, 109}},
2429 /* 7 */ {{138, 189}},
2430 /* 8 */ {{192, 243}}}},
2431 {{MHz_u{40}, RuType::RU_106_TONE},
2432 {/* 1 */ {{-243, -138}},
2433 /* 2 */ {{-109, -4}},
2434 /* 3 */ {{4, 109}},
2435 /* 4 */ {{138, 243}}}},
2436 {{MHz_u{40}, RuType::RU_242_TONE},
2437 {/* 1 */ {{-244, -3}},
2438 /* 2 */ {{3, 244}}}},
2439 {{MHz_u{40}, RuType::RU_484_TONE}, {/* 1 */ {{-244, -3}, {3, 244}}}},
2440 {{MHz_u{80}, RuType::RU_26_TONE},
2441 {/* 1 */ {{-499, -474}},
2442 /* 2 */ {{-473, -448}},
2443 /* 3 */ {{-445, -420}},
2444 /* 4 */ {{-419, -394}},
2445 /* 5 */ {{-392, -367}},
2446 /* 6 */ {{-365, -340}},
2447 /* 7 */ {{-339, -314}},
2448 /* 8 */ {{-311, -286}},
2449 /* 9 */ {{-285, -260}},
2450 /* 10 */ {{-257, -232}},
2451 /* 11 */ {{-231, -206}},
2452 /* 12 */ {{-203, -178}},
2453 /* 13 */ {{-177, -152}},
2454 /* 14 */ {{-150, -125}},
2455 /* 15 */ {{-123, -98}},
2456 /* 16 */ {{-97, -72}},
2457 /* 17 */ {{-69, -44}},
2458 /* 18 */ {{-43, -18}},
2459 /* 19 */ {{-16, -4}, {4, 16}},
2460 /* 20 */ {{18, 43}},
2461 /* 21 */ {{44, 69}},
2462 /* 22 */ {{72, 97}},
2463 /* 23 */ {{98, 123}},
2464 /* 24 */ {{125, 150}},
2465 /* 25 */ {{152, 177}},
2466 /* 26 */ {{178, 203}},
2467 /* 27 */ {{206, 231}},
2468 /* 28 */ {{232, 257}},
2469 /* 29 */ {{260, 285}},
2470 /* 30 */ {{286, 311}},
2471 /* 31 */ {{314, 339}},
2472 /* 32 */ {{340, 365}},
2473 /* 33 */ {{367, 392}},
2474 /* 34 */ {{394, 419}},
2475 /* 35 */ {{420, 445}},
2476 /* 36 */ {{448, 473}},
2477 /* 37 */ {{474, 499}}}},
2478 {{MHz_u{80}, RuType::RU_52_TONE},
2479 {/* 1 */ {{-499, -448}},
2480 /* 2 */ {{-445, -394}},
2481 /* 3 */ {{-365, -314}},
2482 /* 4 */ {{-311, -260}},
2483 /* 5 */ {{-257, -206}},
2484 /* 6 */ {{-203, -152}},
2485 /* 7 */ {{-123, -72}},
2486 /* 8 */ {{-69, -18}},
2487 /* 9 */ {{18, 69}},
2488 /* 10 */ {{72, 123}},
2489 /* 11 */ {{152, 203}},
2490 /* 12 */ {{206, 257}},
2491 /* 13 */ {{260, 311}},
2492 /* 14 */ {{314, 365}},
2493 /* 15 */ {{394, 445}},
2494 /* 16 */ {{448, 499}}}},
2495 {{MHz_u{80}, RuType::RU_106_TONE},
2496 {/* 1 */ {{-499, -394}},
2497 /* 2 */ {{-365, -260}},
2498 /* 3 */ {{-257, -152}},
2499 /* 4 */ {{-123, -18}},
2500 /* 5 */ {{18, 123}},
2501 /* 6 */ {{152, 257}},
2502 /* 7 */ {{260, 365}},
2503 /* 8 */ {{394, 499}}}},
2504 {{MHz_u{80}, RuType::RU_242_TONE},
2505 {/* 1 */ {{-500, -259}},
2506 /* 2 */ {{-258, -17}},
2507 /* 3 */ {{17, 258}},
2508 /* 4 */ {{259, 500}}}},
2509 {{MHz_u{80}, RuType::RU_484_TONE},
2510 {/* 1 */ {{-500, -17}},
2511 /* 2 */ {{17, 500}}}},
2512 {{MHz_u{80}, RuType::RU_996_TONE}, {/* 1 */ {{-500, -3}, {3, 500}}}},
2513 {{MHz_u{160}, RuType::RU_26_TONE},
2514 {/* 1 */ {{-1011, -986}},
2515 /* 2 */ {{-985, -960}},
2516 /* 3 */ {{-957, -932}},
2517 /* 4 */ {{-931, -906}},
2518 /* 5 */ {{-904, -879}},
2519 /* 6 */ {{-877, -852}},
2520 /* 7 */ {{-851, -826}},
2521 /* 8 */ {{-823, -798}},
2522 /* 9 */ {{-797, -772}},
2523 /* 10 */ {{-769, -744}},
2524 /* 11 */ {{-743, -718}},
2525 /* 12 */ {{-715, -690}},
2526 /* 13 */ {{-689, -664}},
2527 /* 14 */ {{-662, -637}},
2528 /* 15 */ {{-635, -610}},
2529 /* 16 */ {{-609, -584}},
2530 /* 17 */ {{-581, -556}},
2531 /* 18 */ {{-555, -530}},
2532 /* 19 */ {{{-528, -516}, {-508, -496}}},
2533 /* 20 */ {{-494, -469}},
2534 /* 21 */ {{-468, -443}},
2535 /* 22 */ {{-440, -415}},
2536 /* 23 */ {{-414, -389}},
2537 /* 24 */ {{-387, -362}},
2538 /* 25 */ {{-360, -335}},
2539 /* 26 */ {{-334, -309}},
2540 /* 27 */ {{-306, -281}},
2541 /* 28 */ {{-280, -255}},
2542 /* 29 */ {{-252, -227}},
2543 /* 30 */ {{-226, -201}},
2544 /* 31 */ {{-198, -173}},
2545 /* 32 */ {{-172, -147}},
2546 /* 33 */ {{-145, -120}},
2547 /* 34 */ {{-118, -93}},
2548 /* 35 */ {{-92, -67}},
2549 /* 36 */ {{-64, -39}},
2550 /* 37 */ {{-38, -13}},
2551 /* 38 */ {{13, 38}},
2552 /* 39 */ {{39, 64}},
2553 /* 40 */ {{67, 92}},
2554 /* 41 */ {{93, 118}},
2555 /* 42 */ {{120, 145}},
2556 /* 43 */ {{147, 172}},
2557 /* 44 */ {{173, 198}},
2558 /* 45 */ {{201, 226}},
2559 /* 46 */ {{227, 252}},
2560 /* 47 */ {{255, 280}},
2561 /* 48 */ {{281, 306}},
2562 /* 49 */ {{309, 334}},
2563 /* 50 */ {{335, 360}},
2564 /* 51 */ {{362, 387}},
2565 /* 52 */ {{389, 414}},
2566 /* 53 */ {{415, 440}},
2567 /* 54 */ {{443, 468}},
2568 /* 55 */ {{469, 494}},
2569 /* 56 */ {{496, 508}, {516, 528}},
2570 /* 57 */ {{530, 555}},
2571 /* 58 */ {{556, 581}},
2572 /* 59 */ {{584, 609}},
2573 /* 60 */ {{610, 635}},
2574 /* 61 */ {{637, 662}},
2575 /* 62 */ {{664, 689}},
2576 /* 63 */ {{690, 715}},
2577 /* 64 */ {{718, 743}},
2578 /* 65 */ {{744, 769}},
2579 /* 66 */ {{772, 797}},
2580 /* 67 */ {{798, 823}},
2581 /* 68 */ {{826, 851}},
2582 /* 69 */ {{852, 877}},
2583 /* 70 */ {{879, 904}},
2584 /* 71 */ {{906, 931}},
2585 /* 72 */ {{932, 957}},
2586 /* 73 */ {{960, 985}},
2587 /* 74 */ {{986, 1011}}}},
2588 {{MHz_u{160}, RuType::RU_52_TONE},
2589 {/* 1 */ {{-1011, -960}},
2590 /* 2 */ {{-957, -906}},
2591 /* 3 */ {{-877, -826}},
2592 /* 4 */ {{-823, -772}},
2593 /* 5 */ {{-769, -718}},
2594 /* 6 */ {{-715, -664}},
2595 /* 7 */ {{-635, -584}},
2596 /* 8 */ {{-581, -530}},
2597 /* 9 */ {{-494, -443}},
2598 /* 10 */ {{-440, -389}},
2599 /* 11 */ {{-360, -309}},
2600 /* 12 */ {{-306, -255}},
2601 /* 13 */ {{-252, -201}},
2602 /* 14 */ {{-198, -147}},
2603 /* 15 */ {{-118, -67}},
2604 /* 16 */ {{-64, -13}},
2605 /* 17 */ {{13, 64}},
2606 /* 18 */ {{67, 118}},
2607 /* 19 */ {{147, 198}},
2608 /* 20 */ {{201, 252}},
2609 /* 21 */ {{255, 306}},
2610 /* 22 */ {{309, 360}},
2611 /* 23 */ {{389, 440}},
2612 /* 24 */ {{443, 494}},
2613 /* 25 */ {{530, 581}},
2614 /* 26 */ {{584, 635}},
2615 /* 27 */ {{664, 715}},
2616 /* 28 */ {{718, 769}},
2617 /* 29 */ {{772, 823}},
2618 /* 30 */ {{826, 877}},
2619 /* 31 */ {{906, 957}},
2620 /* 32 */ {{960, 1011}}}},
2621 {{MHz_u{160}, RuType::RU_106_TONE},
2622 {/* 1 */ {{-1011, -906}},
2623 /* 2 */ {{-877, -772}},
2624 /* 3 */ {{-769, -664}},
2625 /* 4 */ {{-635, -530}},
2626 /* 5 */ {{-494, -389}},
2627 /* 6 */ {{-360, -255}},
2628 /* 7 */ {{-252, -147}},
2629 /* 8 */ {{-118, -13}},
2630 /* 9 */ {{13, 118}},
2631 /* 10 */ {{147, 252}},
2632 /* 11 */ {{255, 360}},
2633 /* 12 */ {{389, 494}},
2634 /* 13 */ {{530, 635}},
2635 /* 14 */ {{664, 769}},
2636 /* 15 */ {{772, 877}},
2637 /* 16 */ {{906, 1011}}}},
2638 {{MHz_u{160}, RuType::RU_242_TONE},
2639 {/* 1 */ {{-1012, -771}},
2640 /* 2 */ {{-770, -529}},
2641 /* 3 */ {{-495, -254}},
2642 /* 4 */ {{-253, -12}},
2643 /* 5 */ {{12, 253}},
2644 /* 6 */ {{254, 495}},
2645 /* 7 */ {{529, 770}},
2646 /* 8 */ {{771, 1012}}}},
2647 {{MHz_u{160}, RuType::RU_484_TONE},
2648 {/* 1 */ {{-1012, -529}},
2649 /* 2 */ {{-495, -12}},
2650 /* 3 */ {{12, 495}},
2651 /* 4 */ {{529, 1012}}}},
2652 {{MHz_u{160}, RuType::RU_996_TONE},
2653 {/* 1 */ {{-1012, -515}, {-509, -12}},
2654 /* 2 */ {{12, 509}, {515, 1012}}}},
2655 {{MHz_u{160}, RuType::RU_2x996_TONE},
2656 {/* 1 */ {{-1012, -515}, {-509, -12}, {12, 509}, {515, 1012}}}},
2657 };
2658
2659 const std::map<BwTonesPair, std::vector<SubcarrierGroup>> expectedEhtRuSubcarrierGroups = {
2660 {{MHz_u{20}, RuType::RU_26_TONE},
2661 {/* 1 */ {{-121, -96}},
2662 /* 2 */ {{-95, -70}},
2663 /* 3 */ {{-68, -43}},
2664 /* 4 */ {{-42, -17}},
2665 /* 5 */ {{-16, -4}, {4, 16}},
2666 /* 6 */ {{17, 42}},
2667 /* 7 */ {{43, 68}},
2668 /* 8 */ {{70, 95}},
2669 /* 9 */ {{96, 121}}}},
2670 {{MHz_u{20}, RuType::RU_52_TONE},
2671 {/* 1 */ {{-121, -70}},
2672 /* 2 */ {{-68, -17}},
2673 /* 3 */ {{17, 68}},
2674 /* 4 */ {{70, 121}}}},
2675 {{MHz_u{20}, RuType::RU_106_TONE},
2676 {/* 1 */ {{-122, -17}},
2677 /* 2 */ {{17, 122}}}},
2678 {{MHz_u{20}, RuType::RU_242_TONE}, {/* 1 */ {{-122, -2}, {2, 122}}}},
2679 {{MHz_u{40}, RuType::RU_26_TONE},
2680 {/* 1 */ {{-243, -218}},
2681 /* 2 */ {{-217, -192}},
2682 /* 3 */ {{-189, -164}},
2683 /* 4 */ {{-163, -138}},
2684 /* 5 */ {{-136, -111}},
2685 /* 6 */ {{-109, -84}},
2686 /* 7 */ {{-83, -58}},
2687 /* 8 */ {{-55, -30}},
2688 /* 9 */ {{-29, -4}},
2689 /* 10 */ {{4, 29}},
2690 /* 11 */ {{30, 55}},
2691 /* 12 */ {{58, 83}},
2692 /* 13 */ {{84, 109}},
2693 /* 14 */ {{111, 136}},
2694 /* 15 */ {{138, 163}},
2695 /* 16 */ {{164, 189}},
2696 /* 17 */ {{192, 217}},
2697 /* 18 */ {{218, 243}}}},
2698 {{MHz_u{40}, RuType::RU_52_TONE},
2699 {/* 1 */ {{-243, -192}},
2700 /* 2 */ {{-189, -138}},
2701 /* 3 */ {{-109, -58}},
2702 /* 4 */ {{-55, -4}},
2703 /* 5 */ {{4, 55}},
2704 /* 6 */ {{58, 109}},
2705 /* 7 */ {{138, 189}},
2706 /* 8 */ {{192, 243}}}},
2707 {{MHz_u{40}, RuType::RU_106_TONE},
2708 {/* 1 */ {{-243, -138}},
2709 /* 2 */ {{-109, -4}},
2710 /* 3 */ {{4, 109}},
2711 /* 4 */ {{138, 243}}}},
2712 {{MHz_u{40}, RuType::RU_242_TONE},
2713 {/* 1 */ {{-244, -3}},
2714 /* 2 */ {{3, 244}}}},
2715 {{MHz_u{40}, RuType::RU_484_TONE}, {/* 1 */ {{-244, -3}, {3, 244}}}},
2716 {{MHz_u{80}, RuType::RU_26_TONE},
2717 {/* 1 */ {{-499, -474}},
2718 /* 2 */ {{-473, -448}},
2719 /* 3 */ {{-445, -420}},
2720 /* 4 */ {{-419, -394}},
2721 /* 5 */ {{-392, -367}},
2722 /* 6 */ {{-365, -340}},
2723 /* 7 */ {{-339, -314}},
2724 /* 8 */ {{-311, -286}},
2725 /* 9 */ {{-285, -260}},
2726 /* 10 */ {{-252, -227}},
2727 /* 11 */ {{-226, -201}},
2728 /* 12 */ {{-198, -173}},
2729 /* 13 */ {{-172, -147}},
2730 /* 14 */ {{-145, -120}},
2731 /* 15 */ {{-118, -93}},
2732 /* 16 */ {{-92, -67}},
2733 /* 17 */ {{-64, -39}},
2734 /* 18 */ {{-38, -13}},
2735 /* 19 not defined */ {},
2736 /* 20 */ {{13, 38}},
2737 /* 21 */ {{39, 64}},
2738 /* 22 */ {{67, 92}},
2739 /* 23 */ {{93, 118}},
2740 /* 24 */ {{120, 145}},
2741 /* 25 */ {{147, 172}},
2742 /* 26 */ {{173, 198}},
2743 /* 27 */ {{201, 226}},
2744 /* 28 */ {{227, 252}},
2745 /* 29 */ {{260, 285}},
2746 /* 30 */ {{286, 311}},
2747 /* 31 */ {{314, 339}},
2748 /* 32 */ {{340, 365}},
2749 /* 33 */ {{367, 392}},
2750 /* 34 */ {{394, 419}},
2751 /* 35 */ {{420, 445}},
2752 /* 36 */ {{448, 473}},
2753 /* 37 */ {{474, 499}}}},
2754 {{MHz_u{80}, RuType::RU_52_TONE},
2755 {/* 1 */ {{-499, -448}},
2756 /* 2 */ {{-445, -394}},
2757 /* 3 */ {{-365, -314}},
2758 /* 4 */ {{-311, -260}},
2759 /* 5 */ {{-252, -201}},
2760 /* 6 */ {{-198, -147}},
2761 /* 7 */ {{-118, -67}},
2762 /* 8 */ {{-64, -13}},
2763 /* 9 */ {{13, 64}},
2764 /* 10 */ {{67, 118}},
2765 /* 11 */ {{147, 198}},
2766 /* 12 */ {{201, 252}},
2767 /* 13 */ {{260, 311}},
2768 /* 14 */ {{314, 365}},
2769 /* 15 */ {{394, 445}},
2770 /* 16 */ {{448, 499}}}},
2771 {{MHz_u{80}, RuType::RU_106_TONE},
2772 {/* 1 */ {{-499, -394}},
2773 /* 2 */ {{-365, -260}},
2774 /* 3 */ {{-252, -147}},
2775 /* 4 */ {{-118, -13}},
2776 /* 5 */ {{13, 118}},
2777 /* 6 */ {{147, 252}},
2778 /* 7 */ {{260, 365}},
2779 /* 8 */ {{394, 499}}}},
2780 {{MHz_u{80}, RuType::RU_242_TONE},
2781 {/* 1 */ {{-500, -259}},
2782 /* 2 */ {{-253, -12}},
2783 /* 3 */ {{12, 253}},
2784 /* 4 */ {{259, 500}}}},
2785 {{MHz_u{80}, RuType::RU_484_TONE},
2786 {/* 1 */ {{-500, -259}, {-253, -12}},
2787 /* 2 */ {{12, 253}, {259, 500}}}},
2788 {{MHz_u{80}, RuType::RU_996_TONE}, {/* 1 */ {{-500, -3}, {3, 500}}}},
2789 {{MHz_u{160}, RuType::RU_26_TONE},
2790 {/* 1 */ {{-1011, -986}},
2791 /* 2 */ {{-985, -960}},
2792 /* 3 */ {{-957, -932}},
2793 /* 4 */ {{-931, -906}},
2794 /* 5 */ {{-904, -879}},
2795 /* 6 */ {{-877, -852}},
2796 /* 7 */ {{-851, -826}},
2797 /* 8 */ {{-823, -798}},
2798 /* 9 */ {{-797, -772}},
2799 /* 10 */ {{-764, -739}},
2800 /* 11 */ {{-738, -713}},
2801 /* 12 */ {{-710, -685}},
2802 /* 13 */ {{-684, -659}},
2803 /* 14 */ {{-657, -632}},
2804 /* 15 */ {{-630, -605}},
2805 /* 16 */ {{-604, -579}},
2806 /* 17 */ {{-576, -551}},
2807 /* 18 */ {{-550, -525}},
2808 /* 19 not defined */ {},
2809 /* 20 */ {{-499, -474}},
2810 /* 21 */ {{-473, -448}},
2811 /* 22 */ {{-445, -420}},
2812 /* 23 */ {{-419, -394}},
2813 /* 24 */ {{-392, -367}},
2814 /* 25 */ {{-365, -340}},
2815 /* 26 */ {{-339, -314}},
2816 /* 27 */ {{-311, -286}},
2817 /* 28 */ {{-285, -260}},
2818 /* 29 */ {{-252, -227}},
2819 /* 30 */ {{-226, -201}},
2820 /* 31 */ {{-198, -173}},
2821 /* 32 */ {{-172, -147}},
2822 /* 33 */ {{-145, -120}},
2823 /* 34 */ {{-118, -93}},
2824 /* 35 */ {{-92, -67}},
2825 /* 36 */ {{-64, -39}},
2826 /* 37 */ {{-38, -13}},
2827 /* 38 */ {{13, 38}},
2828 /* 39 */ {{39, 64}},
2829 /* 40 */ {{67, 92}},
2830 /* 41 */ {{93, 118}},
2831 /* 42 */ {{120, 145}},
2832 /* 43 */ {{147, 172}},
2833 /* 44 */ {{173, 198}},
2834 /* 45 */ {{201, 226}},
2835 /* 46 */ {{227, 252}},
2836 /* 47 */ {{260, 285}},
2837 /* 48 */ {{286, 311}},
2838 /* 49 */ {{314, 339}},
2839 /* 50 */ {{340, 365}},
2840 /* 51 */ {{367, 392}},
2841 /* 52 */ {{394, 419}},
2842 /* 53 */ {{420, 445}},
2843 /* 54 */ {{448, 473}},
2844 /* 55 */ {{474, 499}},
2845 /* 56 not defined */ {},
2846 /* 57 */ {{525, 550}},
2847 /* 58 */ {{551, 576}},
2848 /* 59 */ {{579, 604}},
2849 /* 60 */ {{605, 630}},
2850 /* 61 */ {{632, 657}},
2851 /* 62 */ {{659, 684}},
2852 /* 63 */ {{685, 710}},
2853 /* 64 */ {{713, 738}},
2854 /* 65 */ {{739, 764}},
2855 /* 66 */ {{772, 797}},
2856 /* 67 */ {{798, 823}},
2857 /* 68 */ {{826, 851}},
2858 /* 69 */ {{852, 877}},
2859 /* 70 */ {{879, 904}},
2860 /* 71 */ {{906, 931}},
2861 /* 72 */ {{932, 957}},
2862 /* 73 */ {{960, 985}},
2863 /* 74 */ {{986, 1011}}}},
2864 {{MHz_u{160}, RuType::RU_52_TONE},
2865 {/* 1 */ {{-1011, -960}},
2866 /* 2 */ {{-957, -906}},
2867 /* 3 */ {{-877, -826}},
2868 /* 4 */ {{-823, -772}},
2869 /* 5 */ {{-764, -713}},
2870 /* 6 */ {{-710, -659}},
2871 /* 7 */ {{-630, -579}},
2872 /* 8 */ {{-576, -525}},
2873 /* 9 */ {{-499, -448}},
2874 /* 10 */ {{-445, -394}},
2875 /* 11 */ {{-365, -314}},
2876 /* 12 */ {{-311, -260}},
2877 /* 13 */ {{-252, -201}},
2878 /* 14 */ {{-198, -147}},
2879 /* 15 */ {{-118, -67}},
2880 /* 16 */ {{-64, -13}},
2881 /* 17 */ {{13, 64}},
2882 /* 18 */ {{67, 118}},
2883 /* 19 */ {{147, 198}},
2884 /* 20 */ {{201, 252}},
2885 /* 21 */ {{260, 311}},
2886 /* 22 */ {{314, 365}},
2887 /* 23 */ {{394, 445}},
2888 /* 24 */ {{448, 499}},
2889 /* 25 */ {{525, 576}},
2890 /* 26 */ {{579, 630}},
2891 /* 27 */ {{659, 710}},
2892 /* 28 */ {{713, 764}},
2893 /* 29 */ {{772, 823}},
2894 /* 30 */ {{826, 877}},
2895 /* 31 */ {{906, 957}},
2896 /* 32 */ {{960, 1011}}}},
2897 {{MHz_u{160}, RuType::RU_106_TONE},
2898 {/* 1 */ {{-1011, -906}},
2899 /* 2 */ {{-877, -772}},
2900 /* 3 */ {{-764, -659}},
2901 /* 4 */ {{-630, -525}},
2902 /* 5 */ {{-499, -394}},
2903 /* 6 */ {{-365, -260}},
2904 /* 7 */ {{-252, -147}},
2905 /* 8 */ {{-118, -13}},
2906 /* 9 */ {{13, 118}},
2907 /* 10 */ {{147, 252}},
2908 /* 11 */ {{260, 365}},
2909 /* 12 */ {{394, 499}},
2910 /* 13 */ {{525, 630}},
2911 /* 14 */ {{659, 764}},
2912 /* 15 */ {{772, 877}},
2913 /* 16 */ {{906, 1011}}}},
2914 {{MHz_u{160}, RuType::RU_242_TONE},
2915 {/* 1 */ {{-1012, -771}},
2916 /* 2 */ {{-765, -524}},
2917 /* 3 */ {{-500, -259}},
2918 /* 4 */ {{-253, -12}},
2919 /* 5 */ {{12, 253}},
2920 /* 6 */ {{259, 500}},
2921 /* 7 */ {{524, 765}},
2922 /* 8 */ {{771, 1012}}}},
2923 {{MHz_u{160}, RuType::RU_484_TONE},
2924 {/* 1 */ {{-1012, -771}, {-765, -524}},
2925 /* 2 */ {{-500, -259}, {-253, -12}},
2926 /* 3 */ {{12, 253}, {259, 500}},
2927 /* 4 */ {{524, 765}, {771, 1012}}}},
2928 {{MHz_u{160}, RuType::RU_996_TONE},
2929 {/* 1 */ {{-1012, -515}, {-509, -12}},
2930 /* 2 */ {{12, 509}, {515, 1012}}}},
2931 {{MHz_u{160}, RuType::RU_2x996_TONE},
2932 {/* 1 */ {{-1012, -515}, {-509, -12}, {12, 509}, {515, 1012}}}},
2933 {{MHz_u{320}, RuType::RU_26_TONE},
2934 {/* 1 */ {{-2035, -2010}},
2935 /* 2 */ {{-2009, -1984}},
2936 /* 3 */ {{-1981, -1956}},
2937 /* 4 */ {{-1955, -1930}},
2938 /* 5 */ {{-1928, -1903}},
2939 /* 6 */ {{-1901, -1876}},
2940 /* 7 */ {{-1875, -1850}},
2941 /* 8 */ {{-1847, -1822}},
2942 /* 9 */ {{-1821, -1796}},
2943 /* 10 */ {{-1788, -1763}},
2944 /* 11 */ {{-1762, -1737}},
2945 /* 12 */ {{-1734, -1709}},
2946 /* 13 */ {{-1708, -1683}},
2947 /* 14 */ {{-1681, -1656}},
2948 /* 15 */ {{-1654, -1629}},
2949 /* 16 */ {{-1628, -1603}},
2950 /* 17 */ {{-1600, -1575}},
2951 /* 18 */ {{-1574, -1549}},
2952 /* 19 not defined */ {},
2953 /* 20 */ {{-1523, -1498}},
2954 /* 21 */ {{-1497, -1472}},
2955 /* 22 */ {{-1469, -1444}},
2956 /* 23 */ {{-1443, -1418}},
2957 /* 24 */ {{-1416, -1391}},
2958 /* 25 */ {{-1389, -1364}},
2959 /* 26 */ {{-1363, -1338}},
2960 /* 27 */ {{-1335, -1310}},
2961 /* 28 */ {{-1309, -1284}},
2962 /* 29 */ {{-1276, -1251}},
2963 /* 30 */ {{-1250, -1225}},
2964 /* 31 */ {{-1222, -1197}},
2965 /* 32 */ {{-1196, -1171}},
2966 /* 33 */ {{-1169, -1144}},
2967 /* 34 */ {{-1142, -1117}},
2968 /* 35 */ {{-1116, -1091}},
2969 /* 36 */ {{-1088, -1063}},
2970 /* 37 */ {{-1062, -1037}},
2971 /* 38 */ {{-1011, -986}},
2972 /* 39 */ {{-985, -960}},
2973 /* 40 */ {{-957, -932}},
2974 /* 41 */ {{-931, -906}},
2975 /* 42 */ {{-904, -879}},
2976 /* 43 */ {{-877, -852}},
2977 /* 44 */ {{-851, -826}},
2978 /* 45 */ {{-823, -798}},
2979 /* 46 */ {{-797, -772}},
2980 /* 47 */ {{-764, -739}},
2981 /* 48 */ {{-738, -713}},
2982 /* 49 */ {{-710, -685}},
2983 /* 50 */ {{-684, -659}},
2984 /* 51 */ {{-657, -632}},
2985 /* 52 */ {{-630, -605}},
2986 /* 53 */ {{-604, -579}},
2987 /* 54 */ {{-576, -551}},
2988 /* 55 */ {{-550, -525}},
2989 /* 56 not defined */ {},
2990 /* 57 */ {{-499, -474}},
2991 /* 58 */ {{-473, -448}},
2992 /* 59 */ {{-445, -420}},
2993 /* 60 */ {{-419, -394}},
2994 /* 61 */ {{-392, -367}},
2995 /* 62 */ {{-365, -340}},
2996 /* 63 */ {{-339, -314}},
2997 /* 64 */ {{-311, -286}},
2998 /* 65 */ {{-285, -260}},
2999 /* 66 */ {{-252, -227}},
3000 /* 67 */ {{-226, -201}},
3001 /* 68 */ {{-198, -173}},
3002 /* 69 */ {{-172, -147}},
3003 /* 70 */ {{-145, -120}},
3004 /* 71 */ {{-118, -93}},
3005 /* 72 */ {{-92, -67}},
3006 /* 73 */ {{-64, -39}},
3007 /* 74 */ {{-38, -13}},
3008 /* 75 */ {{13, 38}},
3009 /* 76 */ {{39, 64}},
3010 /* 77 */ {{67, 92}},
3011 /* 78 */ {{93, 118}},
3012 /* 79 */ {{120, 145}},
3013 /* 80 */ {{147, 172}},
3014 /* 81 */ {{173, 198}},
3015 /* 82 */ {{201, 226}},
3016 /* 83 */ {{227, 252}},
3017 /* 84 */ {{260, 285}},
3018 /* 85 */ {{286, 311}},
3019 /* 86 */ {{314, 339}},
3020 /* 87 */ {{340, 365}},
3021 /* 88 */ {{367, 392}},
3022 /* 89 */ {{394, 419}},
3023 /* 90 */ {{420, 445}},
3024 /* 91 */ {{448, 473}},
3025 /* 92 */ {{474, 499}},
3026 /* 93 not defined */ {},
3027 /* 94 */ {{525, 550}},
3028 /* 95 */ {{551, 576}},
3029 /* 96 */ {{579, 604}},
3030 /* 97 */ {{605, 630}},
3031 /* 98 */ {{632, 657}},
3032 /* 99 */ {{659, 684}},
3033 /* 100 */ {{685, 710}},
3034 /* 101 */ {{713, 738}},
3035 /* 102 */ {{739, 764}},
3036 /* 103 */ {{772, 797}},
3037 /* 104 */ {{798, 823}},
3038 /* 105 */ {{826, 851}},
3039 /* 106 */ {{852, 877}},
3040 /* 107 */ {{879, 904}},
3041 /* 108 */ {{906, 931}},
3042 /* 109 */ {{932, 957}},
3043 /* 110 */ {{960, 985}},
3044 /* 111 */ {{986, 1011}},
3045 /* 112 */ {{1037, 1062}},
3046 /* 113 */ {{1063, 1088}},
3047 /* 114 */ {{1091, 1116}},
3048 /* 115 */ {{1117, 1142}},
3049 /* 116 */ {{1144, 1169}},
3050 /* 117 */ {{1171, 1196}},
3051 /* 118 */ {{1197, 1222}},
3052 /* 119 */ {{1225, 1250}},
3053 /* 120 */ {{1251, 1276}},
3054 /* 121 */ {{1284, 1309}},
3055 /* 122 */ {{1310, 1335}},
3056 /* 123 */ {{1338, 1363}},
3057 /* 124 */ {{1364, 1389}},
3058 /* 125 */ {{1391, 1416}},
3059 /* 126 */ {{1418, 1443}},
3060 /* 127 */ {{1444, 1469}},
3061 /* 128 */ {{1472, 1497}},
3062 /* 129 */ {{1498, 1523}},
3063 /* 130 not defined */ {},
3064 /* 131 */ {{1549, 1574}},
3065 /* 132 */ {{1575, 1600}},
3066 /* 133 */ {{1603, 1628}},
3067 /* 134 */ {{1629, 1654}},
3068 /* 135 */ {{1656, 1681}},
3069 /* 136 */ {{1683, 1708}},
3070 /* 137 */ {{1709, 1734}},
3071 /* 138 */ {{1737, 1762}},
3072 /* 139 */ {{1763, 1788}},
3073 /* 140 */ {{1796, 1821}},
3074 /* 141 */ {{1822, 1847}},
3075 /* 142 */ {{1850, 1875}},
3076 /* 143 */ {{1876, 1901}},
3077 /* 144 */ {{1903, 1928}},
3078 /* 145 */ {{1930, 1955}},
3079 /* 146 */ {{1956, 1981}},
3080 /* 147 */ {{1984, 2009}},
3081 /* 148 */ {{2010, 2035}}}},
3082 {{MHz_u{320}, RuType::RU_52_TONE},
3083 {/* 1 */ {{-2035, -1984}},
3084 /* 2 */ {{-1981, -1930}},
3085 /* 3 */ {{-1901, -1850}},
3086 /* 4 */ {{-1847, -1796}},
3087 /* 5 */ {{-1788, -1737}},
3088 /* 6 */ {{-1734, -1683}},
3089 /* 7 */ {{-1654, -1603}},
3090 /* 8 */ {{-1600, -1549}},
3091 /* 9 */ {{-1523, -1472}},
3092 /* 10 */ {{-1469, -1418}},
3093 /* 11 */ {{-1389, -1338}},
3094 /* 12 */ {{-1335, -1284}},
3095 /* 13 */ {{-1276, -1225}},
3096 /* 14 */ {{-1222, -1171}},
3097 /* 15 */ {{-1142, -1091}},
3098 /* 16 */ {{-1088, -1037}},
3099 /* 17 */ {{-1011, -960}},
3100 /* 18 */ {{-957, -906}},
3101 /* 19 */ {{-877, -826}},
3102 /* 20 */ {{-823, -772}},
3103 /* 21 */ {{-764, -713}},
3104 /* 22 */ {{-710, -659}},
3105 /* 23 */ {{-630, -579}},
3106 /* 24 */ {{-576, -525}},
3107 /* 25 */ {{-499, -448}},
3108 /* 26 */ {{-445, -394}},
3109 /* 27 */ {{-365, -314}},
3110 /* 28 */ {{-311, -260}},
3111 /* 29 */ {{-252, -201}},
3112 /* 30 */ {{-198, -147}},
3113 /* 31 */ {{-118, -67}},
3114 /* 32 */ {{-64, -13}},
3115 /* 33 */ {{13, 64}},
3116 /* 34 */ {{67, 118}},
3117 /* 35 */ {{147, 198}},
3118 /* 36 */ {{201, 252}},
3119 /* 37 */ {{260, 311}},
3120 /* 38 */ {{314, 365}},
3121 /* 39 */ {{394, 445}},
3122 /* 40 */ {{448, 499}},
3123 /* 41 */ {{525, 576}},
3124 /* 42 */ {{579, 630}},
3125 /* 43 */ {{659, 710}},
3126 /* 44 */ {{713, 764}},
3127 /* 45 */ {{772, 823}},
3128 /* 46 */ {{826, 877}},
3129 /* 47 */ {{906, 957}},
3130 /* 48 */ {{960, 1011}},
3131 /* 49 */ {{1037, 1088}},
3132 /* 50 */ {{1091, 1142}},
3133 /* 51 */ {{1171, 1222}},
3134 /* 52 */ {{1225, 1276}},
3135 /* 53 */ {{1284, 1335}},
3136 /* 54 */ {{1338, 1389}},
3137 /* 55 */ {{1418, 1469}},
3138 /* 56 */ {{1472, 1523}},
3139 /* 57 */ {{1549, 1600}},
3140 /* 58 */ {{1603, 1654}},
3141 /* 59 */ {{1683, 1734}},
3142 /* 60 */ {{1737, 1788}},
3143 /* 61 */ {{1796, 1847}},
3144 /* 62 */ {{1850, 1901}},
3145 /* 63 */ {{1930, 1981}},
3146 /* 64 */ {{1984, 2035}}}},
3147 {{MHz_u{320}, RuType::RU_106_TONE},
3148 {/* 1 */ {{-2035, -1930}},
3149 /* 2 */ {{-1901, -1796}},
3150 /* 3 */ {{-1788, -1683}},
3151 /* 4 */ {{-1654, -1549}},
3152 /* 5 */ {{-1523, -1418}},
3153 /* 6 */ {{-1389, -1284}},
3154 /* 7 */ {{-1276, -1171}},
3155 /* 8 */ {{-1142, -1037}},
3156 /* 9 */ {{-1011, -906}},
3157 /* 10 */ {{-877, -772}},
3158 /* 11 */ {{-764, -659}},
3159 /* 12 */ {{-630, -525}},
3160 /* 13 */ {{-499, -394}},
3161 /* 14 */ {{-365, -260}},
3162 /* 15 */ {{-252, -147}},
3163 /* 16 */ {{-118, -13}},
3164 /* 17 */ {{13, 118}},
3165 /* 18 */ {{147, 252}},
3166 /* 19 */ {{260, 365}},
3167 /* 20 */ {{394, 499}},
3168 /* 21 */ {{525, 630}},
3169 /* 22 */ {{659, 764}},
3170 /* 23 */ {{772, 877}},
3171 /* 24 */ {{906, 1011}},
3172 /* 25 */ {{1037, 1142}},
3173 /* 26 */ {{1171, 1276}},
3174 /* 27 */ {{1284, 1389}},
3175 /* 28 */ {{1418, 1523}},
3176 /* 29 */ {{1549, 1654}},
3177 /* 30 */ {{1683, 1788}},
3178 /* 31 */ {{1796, 1901}},
3179 /* 32 */ {{1930, 2035}}}},
3180 {{MHz_u{320}, RuType::RU_242_TONE},
3181 {/* 1 */ {{-2036, -1795}},
3182 /* 2 */ {{-1789, -1548}},
3183 /* 3 */ {{-1524, -1283}},
3184 /* 4 */ {{-1277, -1036}},
3185 /* 5 */ {{-1012, -771}},
3186 /* 6 */ {{-765, -524}},
3187 /* 7 */ {{-500, -259}},
3188 /* 8 */ {{-253, -12}},
3189 /* 9 */ {{12, 253}},
3190 /* 10 */ {{259, 500}},
3191 /* 11 */ {{524, 765}},
3192 /* 12 */ {{771, 1012}},
3193 /* 13 */ {{1036, 1277}},
3194 /* 14 */ {{1283, 1524}},
3195 /* 15 */ {{1548, 1789}},
3196 /* 16 */ {{1795, 2036}}}},
3197 {{MHz_u{320}, RuType::RU_484_TONE},
3198 {/* 1 */ {{-2036, -1795}, {-1789, -1548}},
3199 /* 2 */ {{-1524, -1283}, {-1277, -1036}},
3200 /* 3 */ {{-1012, -771}, {-765, -524}},
3201 /* 4 */ {{-500, -259}, {-253, -12}},
3202 /* 5 */ {{12, 253}, {259, 500}},
3203 /* 6 */ {{524, 765}, {771, 1012}},
3204 /* 7 */ {{1036, 1277}, {1283, 1524}},
3205 /* 8 */ {{1548, 1789}, {1795, 2036}}}},
3206 {{MHz_u{320}, RuType::RU_996_TONE},
3207 {/* 1 */ {{-2036, -1539}, {-1533, -1036}},
3208 /* 2 */ {{-1012, -515}, {-509, -12}},
3209 /* 3 */ {{12, 509}, {515, 1012}},
3210 /* 4 */ {{1036, 1533}, {1539, 2036}}}},
3211 {{MHz_u{320}, RuType::RU_2x996_TONE},
3212 {/* 1 */ {{-2036, -1539}, {-1533, -1036}, {-1012, -515}, {-509, -12}},
3213 /* 2 */ {{12, 509}, {515, 1012}, {1036, 1533}, {1539, 2036}}}},
3214 {{MHz_u{320}, RuType::RU_4x996_TONE},
3215 {/* 1 */ {{-2036, -1539},
3216 {-1533, -1036},
3217 {-1012, -515},
3218 {-509, -12},
3219 {12, 509},
3220 {515, 1012},
3221 {1036, 1533},
3222 {1539, 2036}}}},
3223 };
3224
3225 const auto& expectedRuSubcarrierGroups = (m_modClass == WIFI_MOD_CLASS_HE)
3226 ? expectedHeRuSubcarrierGroups
3227 : expectedEhtRuSubcarrierGroups;
3228 for (const auto& [bwTonesPair, ruSubcarrierGroups] : expectedRuSubcarrierGroups)
3229 {
3230 std::size_t phyIndex = 1;
3231 for (const auto& subcarrierGroups : ruSubcarrierGroups)
3232 {
3233 RunOne(bwTonesPair.first, bwTonesPair.second, phyIndex++, subcarrierGroups);
3234 }
3235 }
3236}
3237
3238/**
3239 * @ingroup wifi-test
3240 * @ingroup tests
3241 *
3242 * @brief Test the methods to convert PHY indices to 80MHz indices with primary flags.
3243 */
3245{
3246 public:
3247 /**
3248 * Constructor
3249 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
3250 */
3252
3253 /**
3254 * Check converted PHY indices to 80MHz indices with primary flag are correct.
3255 *
3256 * @param primary20 the index of the primary20 channel to configure
3257 * @param bw the bandwidth
3258 * @param ruType the RU type
3259 * @param phyIndex the PHY index of the RU
3260 * @param expectedP160 the expected P160 flag
3261 * @param expectedP80OrLower80 the expected P80OrLower80 flag
3262 * @param expected80MHzIdx the expected index within the 80 MHz segment
3263 */
3264 void RunOne(uint8_t primary20,
3265 MHz_u bw,
3266 RuType ruType,
3267 std::size_t phyIndex,
3268 bool expectedP160,
3269 bool expectedP80OrLower80,
3270 std::size_t expected80MHzIdx);
3271
3272 private:
3273 void DoRun() override;
3274
3275 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
3276};
3277
3279 : TestCase{"Check conversion from PHY indices to 80MHz indices with primary flag for " +
3280 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
3281 m_modClass{modClass}
3282{
3283}
3284
3285void
3287 MHz_u bw,
3288 RuType ruType,
3289 std::size_t phyIndex,
3290 bool expectedP160,
3291 bool expectedP80OrLower80,
3292 std::size_t expected80MHzIdx)
3293{
3294 auto primary80OrLower80{true};
3295 auto primary160{true};
3296 std::size_t idx80MHz{1};
3298 {
3299 idx80MHz = HeRu::GetIndexIn80MHzSegment(bw, ruType, phyIndex);
3300 primary80OrLower80 = HeRu::GetPrimary80MHzFlag(bw, ruType, phyIndex, primary20);
3301 }
3302 else
3303 {
3304 idx80MHz = EhtRu::GetIndexIn80MHzSegment(bw, ruType, phyIndex);
3305 const auto& [p160, p80OrLower80] = EhtRu::GetPrimaryFlags(bw, ruType, phyIndex, primary20);
3306 primary160 = p160;
3307 primary80OrLower80 = p80OrLower80;
3308 }
3309 NS_TEST_EXPECT_MSG_EQ(idx80MHz,
3310 expected80MHzIdx,
3311 "BW=" << bw << ", p20Index=" << +primary20 << " , ruType=" << ruType
3312 << " , phyIndex=" << phyIndex << ". Expected 80MHz index "
3313 << expected80MHzIdx << " differs from actual " << idx80MHz);
3314 NS_TEST_EXPECT_MSG_EQ(primary160,
3315 expectedP160,
3316 "BW=" << bw << ", p20Index=" << +primary20 << " , ruType=" << ruType
3317 << " , phyIndex=" << phyIndex << ". Expected P160 flag "
3318 << expectedP160 << " differs from actual " << primary160);
3319 NS_TEST_EXPECT_MSG_EQ(primary80OrLower80,
3320 expectedP80OrLower80,
3321 "BW=" << bw << ", p20Index=" << +primary20 << " , ruType=" << ruType
3322 << " , phyIndex=" << phyIndex << ". Expected P80OrLower80 flag "
3323 << expectedP80OrLower80 << " differs from actual "
3324 << primary80OrLower80);
3325}
3326
3327void
3329{
3330 const auto p160{true};
3331 const auto s160{false};
3332 const auto p80OrLower80{true};
3333 const auto s80OrHigher80{false};
3334
3335 // consider maximum bandwidth for the test: 160 MHz for HE and 320 MHz otherwise (EHT)
3336 uint8_t p20IdxMax = (m_modClass == WIFI_MOD_CLASS_HE) ? 8 : 16;
3337
3338 /* 20 MHz */
3339 {
3340 const MHz_u bw{20};
3341
3342 for (uint8_t p20Index = 0; p20Index < p20IdxMax; p20Index++)
3343 {
3344 std::size_t numRusPer20MHz = 9;
3345 std::size_t startPhyIdx = p20Index * numRusPer20MHz;
3346 // All the 26-tone RUs in 20 MHz PPDUs are always in P80 (hence index within 80 MHz
3347 // segment equals PHY index)
3348 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer20MHz; phyIdx++)
3349 {
3350 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3351 }
3352
3353 numRusPer20MHz = 4;
3354 startPhyIdx = p20Index * numRusPer20MHz;
3355 // All the 52-tone RUs in 20 MHz PPDUs are always in P80 (hence index within 80 MHz
3356 // segment equals PHY index)
3357 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer20MHz; phyIdx++)
3358 {
3359 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3360 }
3361
3362 numRusPer20MHz = 2;
3363 startPhyIdx = p20Index * numRusPer20MHz;
3364 // Both the 106-tone RUs in 20 MHz PPDUs are always in P80 (hence index within 80 MHz
3365 // segment equals PHY index)
3366 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer20MHz; phyIdx++)
3367 {
3368 RunOne(p20Index, bw, RuType::RU_106_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3369 }
3370
3371 numRusPer20MHz = 1;
3372 startPhyIdx = p20Index * numRusPer20MHz;
3373 // The 242-tone RUs in 20 MHz PPDUs is always in P80 (hence index within 80 MHz segment
3374 // equals PHY index)
3375 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer20MHz; phyIdx++)
3376 {
3377 RunOne(p20Index, bw, RuType::RU_242_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3378 }
3379 }
3380 }
3381
3382 /* 40 MHz */
3383 {
3384 const MHz_u bw{40};
3385
3386 for (uint8_t p20Index = 0; p20Index < p20IdxMax; p20Index++)
3387 {
3388 std::size_t numRusPer40MHz = 18;
3389 std::size_t startPhyIdx = (p20Index / 2) * numRusPer40MHz;
3390 // All the 26-tone RUs in 40 MHz PPDUs are always in P80 (hence index within 80 MHz
3391 // segment equals PHY index)
3392 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer40MHz; phyIdx++)
3393 {
3394 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3395 }
3396
3397 numRusPer40MHz = 8;
3398 startPhyIdx = (p20Index / 2) * numRusPer40MHz;
3399 // All the 52-tone RUs in 40 MHz PPDUs are always in P80 (hence index within 80 MHz
3400 // segment equals PHY index)
3401 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer40MHz; phyIdx++)
3402 {
3403 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3404 }
3405
3406 numRusPer40MHz = 4;
3407 startPhyIdx = (p20Index / 2) * numRusPer40MHz;
3408 // All the 106-tone RUs in 40 MHz PPDUs are always in P80 (hence index within 80 MHz
3409 // segment equals PHY index)
3410 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer40MHz; phyIdx++)
3411 {
3412 RunOne(p20Index, bw, RuType::RU_106_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3413 }
3414
3415 numRusPer40MHz = 2;
3416 startPhyIdx = (p20Index / 2) * numRusPer40MHz;
3417 // Both the 242-tone RUs in 40 MHz PPDUs are always in P80 (hence index within 80 MHz
3418 // segment equals PHY index)
3419 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer40MHz; phyIdx++)
3420 {
3421 RunOne(p20Index, bw, RuType::RU_242_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3422 }
3423
3424 numRusPer40MHz = 1;
3425 startPhyIdx = (p20Index / 2) * numRusPer40MHz;
3426 // The 484-tone RUs in 40 MHz PPDUs is always in P80 (hence index within 80 MHz segment
3427 // equals PHY index)
3428 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer40MHz; phyIdx++)
3429 {
3430 RunOne(p20Index, bw, RuType::RU_484_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3431 }
3432 }
3433 }
3434
3435 /* 80 MHz */
3436 {
3437 const MHz_u bw{80};
3438
3439 for (uint8_t p20Index = 0; p20Index < p20IdxMax; p20Index++)
3440 {
3441 std::size_t numRusPer80MHz = 37;
3442 std::size_t startPhyIdx = (p20Index / 4) * numRusPer80MHz;
3443 // All the 26-tone RUs in 80 MHz PPDUs are always in P80 (hence index within 80 MHz
3444 // segment equals PHY index)
3445 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer80MHz; phyIdx++)
3446 {
3447 if (phyIdx == 19)
3448 {
3449 // Undefined RU
3450 continue;
3451 }
3452 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3453 }
3454
3455 numRusPer80MHz = 16;
3456 startPhyIdx = (p20Index / 4) * numRusPer80MHz;
3457 // All the 52-tone RUs in 80 MHz PPDUs are always in P80 (hence index within 80 MHz
3458 // segment equals PHY index)
3459 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer80MHz; phyIdx++)
3460 {
3461 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3462 }
3463
3464 numRusPer80MHz = 8;
3465 startPhyIdx = (p20Index / 4) * numRusPer80MHz;
3466 // All the 106-tone RUs in 80 MHz PPDUs are always in P80 (hence index within 80 MHz
3467 // segment equals PHY index)
3468 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer80MHz; phyIdx++)
3469 {
3470 RunOne(p20Index, bw, RuType::RU_106_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3471 }
3472
3473 numRusPer80MHz = 4;
3474 startPhyIdx = (p20Index / 4) * numRusPer80MHz;
3475 // All the 242-tone RUs in 80 MHz PPDUs are always in P80 (hence index within 80 MHz
3476 // segment equals PHY index)
3477 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer80MHz; phyIdx++)
3478 {
3479 RunOne(p20Index, bw, RuType::RU_242_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3480 }
3481
3482 numRusPer80MHz = 2;
3483 startPhyIdx = (p20Index / 4) * numRusPer80MHz;
3484 // Both The 484-tone RUs in 80 MHz PPDUs are always in P80 (hence index within 80 MHz
3485 // segment equals PHY index)
3486 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer80MHz; phyIdx++)
3487 {
3488 RunOne(p20Index, bw, RuType::RU_484_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3489 }
3490
3491 numRusPer80MHz = 1;
3492 startPhyIdx = (p20Index / 4) * numRusPer80MHz;
3493 // The 996-tone RUs in 80 MHz PPDUs is always in P80 (hence index within 80 MHz segment
3494 // equals PHY index)
3495 for (std::size_t phyIdx = startPhyIdx; phyIdx <= startPhyIdx + numRusPer80MHz; phyIdx++)
3496 {
3497 RunOne(p20Index, bw, RuType::RU_996_TONE, phyIdx, p160, p80OrLower80, phyIdx);
3498 }
3499 }
3500 }
3501
3502 /* 160 MHz */
3503 {
3504 const MHz_u bw{160};
3505
3506 for (uint8_t p20Index = 0; p20Index < p20IdxMax; p20Index++)
3507 {
3508 const uint8_t p80Index = p20Index / 4;
3509 const uint8_t s80Index = (p80Index % 2 == 0) ? (p80Index + 1) : (p80Index - 1);
3510
3511 // 26-tone RUs in P80
3512 std::size_t numRusPer80MHz = 37;
3513 std::size_t numRusPer160MHz = 2 * numRusPer80MHz;
3514 std::size_t startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3515 std::size_t idxIn80MHz = 1;
3516 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3517 {
3518 if ((m_modClass != WIFI_MOD_CLASS_HE) && (idxIn80MHz == 19))
3519 {
3520 // Undefined RU
3521 continue;
3522 }
3523 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3524 }
3525
3526 // 26-tone RUs in S80
3527 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3528 idxIn80MHz = 1;
3529 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3530 {
3531 if ((m_modClass != WIFI_MOD_CLASS_HE) && (idxIn80MHz == 19))
3532 {
3533 // Undefined RU
3534 continue;
3535 }
3536 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, s80OrHigher80, idxIn80MHz++);
3537 }
3538
3539 // 52-tone RUs in P80
3540 numRusPer80MHz = 16;
3541 numRusPer160MHz = 2 * numRusPer80MHz;
3542 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3543 idxIn80MHz = 1;
3544 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3545 {
3546 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3547 }
3548
3549 // 52-tone RUs in S80
3550 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3551 idxIn80MHz = 1;
3552 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3553 {
3554 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, s80OrHigher80, idxIn80MHz++);
3555 }
3556
3557 // 106-tone RUs in P80
3558 numRusPer80MHz = 8;
3559 numRusPer160MHz = 2 * numRusPer80MHz;
3560 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3561 idxIn80MHz = 1;
3562 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3563 {
3564 RunOne(p20Index, bw, RuType::RU_106_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3565 }
3566
3567 // 106-tone RUs in S80
3568 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3569 idxIn80MHz = 1;
3570 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3571 {
3572 RunOne(p20Index,
3573 bw,
3574 RuType::RU_106_TONE,
3575 phyIdx,
3576 p160,
3577 s80OrHigher80,
3578 idxIn80MHz++);
3579 }
3580
3581 // 242-tone RUs in P80
3582 numRusPer80MHz = 4;
3583 numRusPer160MHz = 2 * numRusPer80MHz;
3584 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3585 idxIn80MHz = 1;
3586 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3587 {
3588 RunOne(p20Index, bw, RuType::RU_242_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3589 }
3590
3591 // 242-tone RUs in S80
3592 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3593 idxIn80MHz = 1;
3594 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3595 {
3596 RunOne(p20Index,
3597 bw,
3598 RuType::RU_242_TONE,
3599 phyIdx,
3600 p160,
3601 s80OrHigher80,
3602 idxIn80MHz++);
3603 }
3604
3605 // 484-tone RUs in P80
3606 numRusPer80MHz = 2;
3607 numRusPer160MHz = 2 * numRusPer80MHz;
3608 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3609 idxIn80MHz = 1;
3610 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3611 {
3612 RunOne(p20Index, bw, RuType::RU_484_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3613 }
3614
3615 // 484-tone RUs in S80
3616 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3617 idxIn80MHz = 1;
3618 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3619 {
3620 RunOne(p20Index,
3621 bw,
3622 RuType::RU_484_TONE,
3623 phyIdx,
3624 p160,
3625 s80OrHigher80,
3626 idxIn80MHz++);
3627 }
3628
3629 // 996-tone RU in P80
3630 numRusPer80MHz = 1;
3631 numRusPer160MHz = 2 * numRusPer80MHz;
3632 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3633 idxIn80MHz = 1;
3634 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3635 {
3636 RunOne(p20Index, bw, RuType::RU_996_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3637 }
3638
3639 // 996-tone RU in S80
3640 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer160MHz) + 1;
3641 idxIn80MHz = 1;
3642 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3643 {
3644 RunOne(p20Index,
3645 bw,
3646 RuType::RU_996_TONE,
3647 phyIdx,
3648 p160,
3649 s80OrHigher80,
3650 idxIn80MHz++);
3651 }
3652
3653 // 2x996-tone RU
3654 RunOne(p20Index, bw, RuType::RU_2x996_TONE, 1, p160, p80OrLower80, 1);
3655 }
3656 }
3657
3658 /* 320 MHz */
3660 {
3661 const MHz_u bw{320};
3662
3663 for (uint8_t p20Index = 0; p20Index < p20IdxMax; p20Index++)
3664 {
3665 const uint8_t p160Index = p20Index / 8;
3666 const uint8_t s160Index = (p160Index % 2 == 0) ? (p160Index + 1) : (p160Index - 1);
3667 const uint8_t p80Index = p20Index / 4;
3668 const uint8_t s80Index = (p80Index % 2 == 0) ? (p80Index + 1) : (p80Index - 1);
3669
3670 // 26-tone RUs in P80
3671 std::size_t numRusPer80MHz = 37;
3672 std::size_t numRusPer320MHz = 4 * numRusPer80MHz;
3673 std::size_t startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3674 std::size_t idxIn80MHz = 1;
3675 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3676 {
3677 if ((m_modClass != WIFI_MOD_CLASS_HE) && (idxIn80MHz == 19))
3678 {
3679 // Undefined RU
3680 continue;
3681 }
3682 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3683 }
3684
3685 // 26-tone RUs in S80
3686 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3687 idxIn80MHz = 1;
3688 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3689 {
3690 if ((m_modClass != WIFI_MOD_CLASS_HE) && (idxIn80MHz == 19))
3691 {
3692 // Undefined RU
3693 continue;
3694 }
3695 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, p160, s80OrHigher80, idxIn80MHz++);
3696 }
3697
3698 // 26-tone RUs in S160
3699 std::size_t numRusPer160MHz = 2 * numRusPer80MHz;
3700 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3701 idxIn80MHz = 1;
3702 // lower 80 MHz
3703 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3704 {
3705 if ((m_modClass != WIFI_MOD_CLASS_HE) && (idxIn80MHz == 19))
3706 {
3707 // Undefined RU
3708 continue;
3709 }
3710 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, s160, p80OrLower80, idxIn80MHz++);
3711 }
3712 // higher 80 MHz
3713 startPhyIdx += numRusPer80MHz;
3714 idxIn80MHz = 1;
3715 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3716 {
3717 if ((m_modClass != WIFI_MOD_CLASS_HE) && (idxIn80MHz == 19))
3718 {
3719 // Undefined RU
3720 continue;
3721 }
3722 RunOne(p20Index, bw, RuType::RU_26_TONE, phyIdx, s160, s80OrHigher80, idxIn80MHz++);
3723 }
3724
3725 // 52-tone RUs in P80
3726 numRusPer80MHz = 16;
3727 numRusPer320MHz = 4 * numRusPer80MHz;
3728 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3729 idxIn80MHz = 1;
3730 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3731 {
3732 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3733 }
3734
3735 // 52-tone RUs in S80
3736 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3737 idxIn80MHz = 1;
3738 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3739 {
3740 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, p160, s80OrHigher80, idxIn80MHz++);
3741 }
3742
3743 // 52-tone RUs in S160
3744 numRusPer160MHz = 2 * numRusPer80MHz;
3745 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3746 idxIn80MHz = 1;
3747 // lower 80 MHz
3748 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3749 {
3750 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, s160, p80OrLower80, idxIn80MHz++);
3751 }
3752 // higher 80 MHz
3753 startPhyIdx += numRusPer80MHz;
3754 idxIn80MHz = 1;
3755 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3756 {
3757 RunOne(p20Index, bw, RuType::RU_52_TONE, phyIdx, s160, s80OrHigher80, idxIn80MHz++);
3758 }
3759
3760 // 106-tone RUs in P80
3761 numRusPer80MHz = 8;
3762 numRusPer320MHz = 4 * numRusPer80MHz;
3763 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3764 idxIn80MHz = 1;
3765 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3766 {
3767 RunOne(p20Index, bw, RuType::RU_106_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3768 }
3769
3770 // 106-tone RUs in S80
3771 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3772 idxIn80MHz = 1;
3773 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3774 {
3775 RunOne(p20Index,
3776 bw,
3777 RuType::RU_106_TONE,
3778 phyIdx,
3779 p160,
3780 s80OrHigher80,
3781 idxIn80MHz++);
3782 }
3783
3784 // 106-tone RUs in S160
3785 numRusPer160MHz = 2 * numRusPer80MHz;
3786 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3787 idxIn80MHz = 1;
3788 // lower 80 MHz
3789 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3790 {
3791 RunOne(p20Index, bw, RuType::RU_106_TONE, phyIdx, s160, p80OrLower80, idxIn80MHz++);
3792 }
3793 // higher 80 MHz
3794 startPhyIdx += numRusPer80MHz;
3795 idxIn80MHz = 1;
3796 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3797 {
3798 RunOne(p20Index,
3799 bw,
3800 RuType::RU_106_TONE,
3801 phyIdx,
3802 s160,
3803 s80OrHigher80,
3804 idxIn80MHz++);
3805 }
3806
3807 // 242-tone RUs in P80
3808 numRusPer80MHz = 4;
3809 numRusPer320MHz = 4 * numRusPer80MHz;
3810 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3811 idxIn80MHz = 1;
3812 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3813 {
3814 RunOne(p20Index, bw, RuType::RU_242_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3815 }
3816
3817 // 242-tone RUs in S80
3818 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3819 idxIn80MHz = 1;
3820 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3821 {
3822 RunOne(p20Index,
3823 bw,
3824 RuType::RU_242_TONE,
3825 phyIdx,
3826 p160,
3827 s80OrHigher80,
3828 idxIn80MHz++);
3829 }
3830
3831 // 242-tone RUs in S160
3832 numRusPer160MHz = 2 * numRusPer80MHz;
3833 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3834 idxIn80MHz = 1;
3835 // lower 80 MHz
3836 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3837 {
3838 RunOne(p20Index, bw, RuType::RU_242_TONE, phyIdx, s160, p80OrLower80, idxIn80MHz++);
3839 }
3840 // higher 80 MHz
3841 startPhyIdx += numRusPer80MHz;
3842 idxIn80MHz = 1;
3843 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3844 {
3845 RunOne(p20Index,
3846 bw,
3847 RuType::RU_242_TONE,
3848 phyIdx,
3849 s160,
3850 s80OrHigher80,
3851 idxIn80MHz++);
3852 }
3853
3854 // 484-tone RUs in P80
3855 numRusPer80MHz = 2;
3856 numRusPer320MHz = 4 * numRusPer80MHz;
3857 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3858 idxIn80MHz = 1;
3859 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3860 {
3861 RunOne(p20Index, bw, RuType::RU_484_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3862 }
3863
3864 // 484-tone RUs in S80
3865 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3866 idxIn80MHz = 1;
3867 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3868 {
3869 RunOne(p20Index,
3870 bw,
3871 RuType::RU_484_TONE,
3872 phyIdx,
3873 p160,
3874 s80OrHigher80,
3875 idxIn80MHz++);
3876 }
3877
3878 // 484-tone RUs in S160
3879 numRusPer160MHz = 2 * numRusPer80MHz;
3880 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3881 idxIn80MHz = 1;
3882 // lower 80 MHz
3883 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3884 {
3885 RunOne(p20Index, bw, RuType::RU_484_TONE, phyIdx, s160, p80OrLower80, idxIn80MHz++);
3886 }
3887 // higher 80 MHz
3888 startPhyIdx += numRusPer80MHz;
3889 idxIn80MHz = 1;
3890 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3891 {
3892 RunOne(p20Index,
3893 bw,
3894 RuType::RU_484_TONE,
3895 phyIdx,
3896 s160,
3897 s80OrHigher80,
3898 idxIn80MHz++);
3899 }
3900
3901 // 996-tone RU in P80
3902 numRusPer80MHz = 1;
3903 numRusPer320MHz = 4 * numRusPer80MHz;
3904 startPhyIdx = ((p80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3905 idxIn80MHz = 1;
3906 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3907 {
3908 RunOne(p20Index, bw, RuType::RU_996_TONE, phyIdx, p160, p80OrLower80, idxIn80MHz++);
3909 }
3910
3911 // 996-tone RU in S80
3912 startPhyIdx = ((s80Index * numRusPer80MHz) % numRusPer320MHz) + 1;
3913 idxIn80MHz = 1;
3914 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3915 {
3916 RunOne(p20Index,
3917 bw,
3918 RuType::RU_996_TONE,
3919 phyIdx,
3920 p160,
3921 s80OrHigher80,
3922 idxIn80MHz++);
3923 }
3924
3925 // 996-tone RUs in S160
3926 numRusPer160MHz = 2 * numRusPer80MHz;
3927 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3928 idxIn80MHz = 1;
3929 // lower 80 MHz
3930 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3931 {
3932 RunOne(p20Index, bw, RuType::RU_996_TONE, phyIdx, s160, p80OrLower80, idxIn80MHz++);
3933 }
3934 // higher 80 MHz
3935 startPhyIdx += numRusPer80MHz;
3936 idxIn80MHz = 1;
3937 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer80MHz; phyIdx++)
3938 {
3939 RunOne(p20Index,
3940 bw,
3941 RuType::RU_996_TONE,
3942 phyIdx,
3943 s160,
3944 s80OrHigher80,
3945 idxIn80MHz++);
3946 }
3947
3948 // 2x996-tone RU in P160
3949 numRusPer160MHz = 1;
3950 numRusPer320MHz = 2 * numRusPer160MHz;
3951 startPhyIdx = ((p160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3952 idxIn80MHz = 1;
3953 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer160MHz; phyIdx++)
3954 {
3955 RunOne(p20Index,
3956 bw,
3957 RuType::RU_2x996_TONE,
3958 phyIdx,
3959 p160,
3960 p80OrLower80,
3961 idxIn80MHz++);
3962 }
3963
3964 // 996-tone RU in S80
3965 startPhyIdx = ((s160Index * numRusPer160MHz) % numRusPer320MHz) + 1;
3966 idxIn80MHz = 1;
3967 for (std::size_t phyIdx = startPhyIdx; phyIdx < startPhyIdx + numRusPer160MHz; phyIdx++)
3968 {
3969 RunOne(p20Index,
3970 bw,
3971 RuType::RU_2x996_TONE,
3972 phyIdx,
3973 s160,
3974 p80OrLower80,
3975 idxIn80MHz++);
3976 }
3977
3978 // 4x996-tone RU
3979 RunOne(p20Index, bw, RuType::RU_4x996_TONE, 1, p160, p80OrLower80, 1);
3980 }
3981 }
3982}
3983
3984/**
3985 * @ingroup wifi-test
3986 * @ingroup tests
3987 *
3988 * @brief Test the WifiRu::DoesOverlap() method.
3989 */
3991{
3992 public:
3993 /**
3994 * Constructor
3995 * @param modClass the modulation class to distinguish 802.11ax and 802.11be
3996 */
3998
3999 /**
4000 * Check the result of DoesOverlap() is correct.
4001 *
4002 * @param bw the bandwidth of the PPDU
4003 * @param ru the given RU allocation
4004 * @param rus the given set of RUs
4005 * @param overlapExpected whether it is expected the given RU overlaps with the given set of RUs
4006 */
4007 void RunOne(MHz_u bw,
4008 WifiRu::RuSpec ru,
4009 const std::vector<WifiRu::RuSpec>& rus,
4010 bool overlapExpected);
4011
4012 private:
4013 void DoRun() override;
4014
4015 WifiModulationClass m_modClass; ///< the modulation class to consider for the test
4016};
4017
4019 : TestCase{"Check RUs overlapping for " +
4020 std::string((modClass == WIFI_MOD_CLASS_HE) ? "HE" : "EHT")},
4021 m_modClass{modClass}
4022{
4023}
4024
4025void
4027 WifiRu::RuSpec ru,
4028 const std::vector<WifiRu::RuSpec>& rus,
4029 bool overlapExpected)
4030{
4031 auto printToStr = [](const std::vector<WifiRu::RuSpec>& v) {
4032 std::stringstream ss;
4033 ss << "{";
4034 for (const auto& ru : v)
4035 {
4036 ss << ru << " ";
4037 }
4038 ss << "}";
4039 return ss.str();
4040 };
4041
4042 const auto overlap = WifiRu::DoesOverlap(bw, ru, rus);
4043 NS_TEST_EXPECT_MSG_EQ(overlap,
4044 overlapExpected,
4045 "BW=" << bw << ", ru=" << ru << " , rus=" << printToStr(rus)
4046 << ". Expected overlap " << overlapExpected
4047 << " differs from actual " << overlap);
4048}
4049
4050void
4052{
4053 const auto p80{true};
4054 const auto s80{false};
4055 const auto p160{(m_modClass == WIFI_MOD_CLASS_HE) ? std::nullopt : std::optional(true)};
4056 const auto s160{(m_modClass == WIFI_MOD_CLASS_HE) ? std::nullopt : std::optional(false)};
4057
4058 /* 20 MHz PPDU */
4059 {
4060 const MHz_u bw{20};
4061
4062 auto ru = MakeRuSpec(RuType::RU_242_TONE, 1, p80, p160);
4063
4064 // 242-tones RU should overlap with 26-tones RUs in same 80 MHz segment
4065 RunOne(bw,
4066 ru,
4067 {MakeRuSpec(RuType::RU_26_TONE, 1, p80, p160),
4068 MakeRuSpec(RuType::RU_26_TONE, 2, p80, p160),
4069 MakeRuSpec(RuType::RU_26_TONE, 3, p80, p160),
4070 MakeRuSpec(RuType::RU_26_TONE, 4, p80, p160),
4071 MakeRuSpec(RuType::RU_26_TONE, 5, p80, p160),
4072 MakeRuSpec(RuType::RU_26_TONE, 6, p80, p160),
4073 MakeRuSpec(RuType::RU_26_TONE, 7, p80, p160),
4074 MakeRuSpec(RuType::RU_26_TONE, 8, p80, p160),
4075 MakeRuSpec(RuType::RU_26_TONE, 9, p80, p160)},
4076 true);
4077
4078 // 242-tones RU should not overlap with 26-tones RUs in same 160 MHz segment but different
4079 // 80 MHz segment
4080 RunOne(bw,
4081 ru,
4082 {MakeRuSpec(RuType::RU_26_TONE, 1, s80, p160),
4083 MakeRuSpec(RuType::RU_26_TONE, 2, s80, p160),
4084 MakeRuSpec(RuType::RU_26_TONE, 3, s80, p160),
4085 MakeRuSpec(RuType::RU_26_TONE, 4, s80, p160),
4086 MakeRuSpec(RuType::RU_26_TONE, 5, s80, p160),
4087 MakeRuSpec(RuType::RU_26_TONE, 6, s80, p160),
4088 MakeRuSpec(RuType::RU_26_TONE, 7, s80, p160),
4089 MakeRuSpec(RuType::RU_26_TONE, 8, s80, p160),
4090 MakeRuSpec(RuType::RU_26_TONE, 9, s80, p160)},
4091 false);
4092
4093 // 242-tones RU should not overlap with 26-tones RUs in different 160 MHz segment
4095 {
4096 RunOne(bw,
4097 ru,
4098 {MakeRuSpec(RuType::RU_26_TONE, 1, p80, s160),
4099 MakeRuSpec(RuType::RU_26_TONE, 2, p80, s160),
4100 MakeRuSpec(RuType::RU_26_TONE, 3, p80, s160),
4101 MakeRuSpec(RuType::RU_26_TONE, 4, p80, s160),
4102 MakeRuSpec(RuType::RU_26_TONE, 5, p80, s160),
4103 MakeRuSpec(RuType::RU_26_TONE, 6, p80, s160),
4104 MakeRuSpec(RuType::RU_26_TONE, 7, p80, s160),
4105 MakeRuSpec(RuType::RU_26_TONE, 8, p80, s160),
4106 MakeRuSpec(RuType::RU_26_TONE, 9, p80, s160)},
4107 false);
4108 }
4109 }
4110
4111 /* 80 MHz PPDU */
4112 {
4113 const MHz_u bw{80};
4114
4115 auto ru = MakeRuSpec(RuType::RU_106_TONE, 1, p80, p160);
4116
4117 // 106-tones RU should overlap with 484-tones RUs in same 80 MHz segment
4118 RunOne(bw,
4119 ru,
4120 {MakeRuSpec(RuType::RU_484_TONE, 1, p80, p160),
4121 MakeRuSpec(RuType::RU_484_TONE, 2, p80, p160)},
4122 true);
4123
4124 // 106-tones RU should not overlap with 484-tones RUs in same 160 MHz segment but different
4125 // 80 MHz segment
4126 RunOne(bw,
4127 ru,
4128 {MakeRuSpec(RuType::RU_484_TONE, 1, s80, p160),
4129 MakeRuSpec(RuType::RU_484_TONE, 2, s80, p160)},
4130 false);
4131
4132 // 106-tones RU should not overlap with 484-tones RUs in different 160 MHz segment
4134 {
4135 RunOne(bw,
4136 ru,
4137 {MakeRuSpec(RuType::RU_484_TONE, 1, s80, s160),
4138 MakeRuSpec(RuType::RU_484_TONE, 2, s80, s160)},
4139 false);
4140 }
4141 }
4142
4143 /* 160 MHz PPDU */
4144 {
4145 const MHz_u bw{160};
4146
4147 auto ru = MakeRuSpec(RuType::RU_996_TONE, 1, s80, p160);
4148
4149 // 996-tones RU should overlap with 2x996 RU in same 160 MHz segment
4150 RunOne(bw, ru, {MakeRuSpec(RuType::RU_2x996_TONE, 1, p80, p160)}, true);
4151
4152 // 996-tones RU should not overlap with 2x996 RU in different 160 MHz segment
4154 {
4155 RunOne(bw, ru, {MakeRuSpec(RuType::RU_2x996_TONE, 1, p80, s160)}, false);
4156 }
4157 }
4158
4159 // TODO: these tests can be further extended with more combinations
4160}
4161
4162/**
4163 * @ingroup wifi-test
4164 * @ingroup tests
4165 *
4166 * @brief wifi primary channels test suite
4167 */
4169{
4170 public:
4172};
4173
4175 : TestSuite("wifi-ru-allocation", Type::UNIT)
4176{
4178 TestCase::Duration::QUICK);
4180 TestCase::Duration::QUICK);
4181 AddTestCase(new WifiNumRusInChannelTest(WIFI_MOD_CLASS_HE), TestCase::Duration::QUICK);
4182 AddTestCase(new WifiNumRusInChannelTest(WIFI_MOD_CLASS_EHT), TestCase::Duration::QUICK);
4183 AddTestCase(new WifiRusOfTypeInChannelTest(WIFI_MOD_CLASS_HE), TestCase::Duration::QUICK);
4184 AddTestCase(new WifiRusOfTypeInChannelTest(WIFI_MOD_CLASS_EHT), TestCase::Duration::QUICK);
4186 TestCase::Duration::QUICK);
4188 TestCase::Duration::QUICK);
4189 AddTestCase(new WifiEqualSizedRusTest(WIFI_MOD_CLASS_HE), TestCase::Duration::QUICK);
4190 AddTestCase(new WifiEqualSizedRusTest(WIFI_MOD_CLASS_EHT), TestCase::Duration::QUICK);
4191 AddTestCase(new WifiSubcarrierGroupsTest(WIFI_MOD_CLASS_HE), TestCase::Duration::QUICK);
4192 AddTestCase(new WifiSubcarrierGroupsTest(WIFI_MOD_CLASS_EHT), TestCase::Duration::QUICK);
4194 TestCase::Duration::QUICK);
4196 TestCase::Duration::QUICK);
4197 AddTestCase(new WifiRuOverlappingTest(WIFI_MOD_CLASS_HE), TestCase::Duration::QUICK);
4198 AddTestCase(new WifiRuOverlappingTest(WIFI_MOD_CLASS_EHT), TestCase::Duration::QUICK);
4199}
4200
Test the WifiPhyOperatingChannel::Get20MHzIndicesCoveringRu() method.
Wifi20MHzIndicesCoveringRuTest(WifiStandard standard)
Constructor.
WifiStandard m_standard
The standard to use for the test.
WifiPhyOperatingChannel m_channel
operating channel
~Wifi20MHzIndicesCoveringRuTest() override=default
void DoRun() override
Implementation to actually run this TestCase.
void RunOne(uint8_t primary20, WifiRu::RuSpec ru, MHz_u width, const std::set< uint8_t > &indices)
Check that the indices of the 20 MHz channels covering the given RU as computed by WifiPhyOperatingCh...
Test the WifiRu::GetCentral26TonesRus() method.
void DoRun() override
Implementation to actually run this TestCase.
void RunOne(RuType rutype, MHz_u width, const std::vector< WifiRu::RuSpec > &expectedCentral26TonesRus)
Check the set of 26-tone RUs returned by GetCentral26TonesRus() is correct.
WifiCentral26TonesRusInChannelTest(WifiModulationClass modClass)
Constructor.
WifiModulationClass m_modClass
the modulation class to consider for the test
Test the WifiRu::GetEqualSizedRusForStations() method.
void RunOne(MHz_u width, std::size_t numStas, std::size_t expectedNumStas, std::size_t expectedNumCentral26TonesRus, RuType expectedRuType)
Check the maximization of the number of candidate stations that can be assigned a RU subject to the c...
WifiModulationClass m_modClass
the modulation class to consider for the test
void DoRun() override
Implementation to actually run this TestCase.
WifiEqualSizedRusTest(WifiModulationClass modClass)
Constructor.
Test the WifiRu::GetNRus() method.
void RunOne(RuType rutype, MHz_u width, std::size_t size)
Check the number of RUs for a given channel width as computed by GetNRus() is correct.
void DoRun() override
Implementation to actually run this TestCase.
WifiModulationClass m_modClass
the modulation class to consider for the test
WifiNumRusInChannelTest(WifiModulationClass modClass)
Constructor.
wifi primary channels test suite
Test the WifiRu::DoesOverlap() method.
WifiRuOverlappingTest(WifiModulationClass modClass)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
WifiModulationClass m_modClass
the modulation class to consider for the test
void RunOne(MHz_u bw, WifiRu::RuSpec ru, const std::vector< WifiRu::RuSpec > &rus, bool overlapExpected)
Check the result of DoesOverlap() is correct.
Test the methods to convert PHY indices to 80MHz indices with primary flags.
void DoRun() override
Implementation to actually run this TestCase.
void RunOne(uint8_t primary20, MHz_u bw, RuType ruType, std::size_t phyIndex, bool expectedP160, bool expectedP80OrLower80, std::size_t expected80MHzIdx)
Check converted PHY indices to 80MHz indices with primary flag are correct.
WifiRuPhyIdxTo80MHzIdxAndFlagsTest(WifiModulationClass modClass)
Constructor.
WifiModulationClass m_modClass
the modulation class to consider for the test
Test the WifiRu::GetRusOfType() method.
void DoRun() override
Implementation to actually run this TestCase.
WifiRusOfTypeInChannelTest(WifiModulationClass modClass)
Constructor.
void RunOne(RuType rutype, MHz_u width, const std::vector< WifiRu::RuSpec > &expectedRus)
Check the set of RUs returned by GetRusOfType() is correct.
WifiModulationClass m_modClass
the modulation class to consider for the test
Test the WifiRu::GetSubcarrierGroup() method.
void RunOne(MHz_u width, RuType ruType, std::size_t phyIndex, const SubcarrierGroup &expectedSubcarrierGroup)
Check the subcarrier group as returned by GetSubcarrierGroup() is correct.
WifiModulationClass m_modClass
the modulation class to consider for the test
void DoRun() override
Implementation to actually run this TestCase.
WifiSubcarrierGroupsTest(WifiModulationClass modClass)
Constructor.
RU Specification.
Definition eht-ru.h:34
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 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
RU Specification.
Definition he-ru.h:37
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 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
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Class that keeps track of all information about the current PHY operating channel.
void SetPrimary20Index(uint8_t index)
Set the index of the primary 20 MHz channel (0 indicates the 20 MHz subchannel with the lowest center...
void SetDefault(MHz_u width, WifiStandard standard, WifiPhyBand band)
Set the default channel of the given width and for the given standard and band.
MHz_u GetWidth(std::size_t segment=0) const
Return the channel width for a given frequency segment.
std::set< uint8_t > Get20MHzIndicesCoveringRu(WifiRu::RuSpec ru, MHz_u width) const
Get the channel indices of the minimum subset of 20 MHz channels containing the given RU.
static std::size_t GetNRus(MHz_u bw, RuType ruType, WifiModulationClass mc)
Get the number of distinct RUs of the given type (number of tones) available in a PPDU of the given b...
Definition wifi-ru.cc:132
std::variant< HeRu::RuSpec, EhtRu::RuSpec > RuSpec
variant of the RU specification
Definition wifi-ru.h:27
static std::vector< RuSpec > GetRusOfType(MHz_u bw, RuType ruType, WifiModulationClass mc)
Get the set of distinct RUs of the given type (number of tones) available in an MU PPDU of the given ...
Definition wifi-ru.cc:173
static RuType GetEqualSizedRusForStations(MHz_u bandwidth, std::size_t &nStations, std::size_t &nCentral26TonesRus, WifiModulationClass mc)
Given the channel bandwidth and the number of stations candidate for being assigned an RU,...
Definition wifi-ru.cc:237
static SubcarrierGroup GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex, WifiModulationClass mc)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
Definition wifi-ru.cc:142
static std::vector< RuSpec > GetCentral26TonesRus(MHz_u bw, RuType ruType, WifiModulationClass mc)
Get the set of 26-tone RUs that can be additionally allocated if the given bandwidth is split in RUs ...
Definition wifi-ru.cc:190
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 wifi-ru.cc:207
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211ax
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
WifiRu::RuSpec MakeRuSpec(RuType ruType, std::size_t index, bool primaryOrLow80MHz, std::optional< bool > primary160MHz=std::nullopt)
Create an HE or an EHT RU Specification.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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
STL namespace.
static WifiRuAllocationTestSuite g_wifiRuAllocationTestSuite
the test suite