A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-eht-info-elems-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Stefano Avallone <stavallo@unina.it>
18 */
19
20#include "ns3/address-utils.h"
21#include "ns3/header-serialization-test.h"
22#include "ns3/log.h"
23#include "ns3/mgt-headers.h"
24#include "ns3/multi-link-element.h"
25#include "ns3/reduced-neighbor-report.h"
26#include "ns3/simulator.h"
27#include "ns3/tid-to-link-mapping-element.h"
28#include "ns3/wifi-phy-operating-channel.h"
29#include "ns3/wifi-utils.h"
30
31#include <optional>
32#include <set>
33#include <sstream>
34#include <vector>
35
36using namespace ns3;
37
38NS_LOG_COMPONENT_DEFINE("WifiEhtInfoElemsTest");
39
40/**
41 * \ingroup wifi-test
42 * \ingroup tests
43 *
44 * \brief Test Multi-Link Element (Basic variant) serialization and deserialization
45 */
47{
48 public:
49 /**
50 * Constructor
51 */
54
55 /**
56 * Get a Multi-Link Element including the given Common Info field and the
57 * given Per-STA Profile Subelements
58 *
59 * \param commonInfo the given Common Info field
60 * \param subelements the given set of Per-STA Profile Subelements
61 * \return a Multi-Link Element
62 */
64 const CommonInfoBasicMle& commonInfo,
65 std::vector<MultiLinkElement::PerStaProfileSubelement> subelements);
66
67 private:
68 void DoRun() override;
69
70 MgtAssocRequestHeader m_outerAssoc; //!< the frame containing the MLE
71};
72
75 "Check serialization and deserialization of Basic variant Multi-Link elements")
76{
77}
78
80{
81}
82
85 const CommonInfoBasicMle& commonInfo,
86 std::vector<MultiLinkElement::PerStaProfileSubelement> subelements)
87{
89 mle.SetMldMacAddress(commonInfo.m_mldMacAddress);
90 if (commonInfo.m_linkIdInfo.has_value())
91 {
92 mle.SetLinkIdInfo(*commonInfo.m_linkIdInfo);
93 }
94 if (commonInfo.m_bssParamsChangeCount.has_value())
95 {
97 }
98 if (commonInfo.m_mediumSyncDelayInfo.has_value())
99 {
101 MicroSeconds(32 * commonInfo.m_mediumSyncDelayInfo->mediumSyncDuration));
103 commonInfo.m_mediumSyncDelayInfo->mediumSyncOfdmEdThreshold - 72);
105 commonInfo.m_mediumSyncDelayInfo->mediumSyncMaxNTxops + 1);
106 }
107 if (commonInfo.m_emlCapabilities.has_value())
108 {
109 auto padding = commonInfo.m_emlCapabilities->emlsrPaddingDelay;
110 mle.SetEmlsrPaddingDelay(MicroSeconds(padding == 0 ? 0 : (1 << (4 + padding))));
111 auto transitionD = commonInfo.m_emlCapabilities->emlsrTransitionDelay;
112 mle.SetEmlsrTransitionDelay(MicroSeconds(transitionD == 0 ? 0 : (1 << (3 + transitionD))));
113 auto transitionT = commonInfo.m_emlCapabilities->transitionTimeout;
114 mle.SetTransitionTimeout(MicroSeconds(transitionT == 0 ? 0 : (1 << (6 + transitionT))));
115 }
116
117 for (std::size_t i = 0; i < subelements.size(); ++i)
118 {
120 mle.GetPerStaProfile(i) = std::move(subelements[i]);
121 }
122
123 return mle;
124}
125
126void
128{
129 CommonInfoBasicMle commonInfo = {
130 .m_mldMacAddress = Mac48Address("01:23:45:67:89:ab"),
131 };
132
133 // Common Info with MLD MAC address
135
136 commonInfo.m_linkIdInfo = 3;
137
138 // Adding Link ID Info
140
141 commonInfo.m_bssParamsChangeCount = 1;
142
143 // Adding BSS Parameters Change Count
145
146 commonInfo.m_mediumSyncDelayInfo =
148 .mediumSyncOfdmEdThreshold = 4,
149 .mediumSyncMaxNTxops = 5};
150
151 // Adding Medium Sync Delay Information
153
155 .emlsrPaddingDelay = 4,
156 .emlsrTransitionDelay = 5,
157 .transitionTimeout = 10};
158
159 // Adding Medium Sync Delay Information
161
162 /**
163 * To test the serialization/deserialization of Per-STA Profile subelements, we include
164 * the Multi-Link Element in an Association Request frame
165 */
166
167 CapabilityInformation capabilities;
168 capabilities.SetShortPreamble(true);
169 capabilities.SetShortSlotTime(true);
170 capabilities.SetEss();
171
173 m_outerAssoc.Capabilities() = capabilities;
174 m_outerAssoc.Get<Ssid>() = Ssid("MySsid");
175
176 AllSupportedRates rates;
177 rates.AddSupportedRate(6e6);
178 rates.AddSupportedRate(9e6);
179 rates.AddSupportedRate(12e6);
180 rates.AddSupportedRate(18e6);
181 rates.AddSupportedRate(24e6);
182 rates.AddSupportedRate(36e6);
183 rates.AddSupportedRate(48e6);
184 rates.AddSupportedRate(54e6);
185 // extended rates
186 rates.AddSupportedRate(1e6);
187 rates.AddSupportedRate(2e6);
188
189 m_outerAssoc.Get<SupportedRates>() = rates.rates;
191
192 EhtCapabilities ehtCapabilities;
193 for (auto maxMcs : {7, 9, 11, 13})
194 {
196 maxMcs,
197 1);
199 maxMcs,
200 1);
201 }
202
203 m_outerAssoc.Get<HeCapabilities>().emplace();
204 m_outerAssoc.Get<EhtCapabilities>() = ehtCapabilities;
205
206 // The Association Request included in the first Per-STA Profile subelement is identical
207 // to the containing frame, so that all the IEs are inherited and the Per-STA Profile
208 // does not contain any Information Element.
209
211 perStaProfile1.SetLinkId(3);
212 perStaProfile1.SetCompleteProfile();
213 perStaProfile1.SetAssocRequest(m_outerAssoc);
214
215 /* Association Request included in the second Per-STA Profile subelement */
217 assoc.Capabilities() = capabilities;
218 // we simulate a "mistake" by adding an Ssid IE, which cannot be included in the
219 // Per-STA Profile subelement. We will check that this Ssid is not serialized
220 assoc.Get<Ssid>() = Ssid("OtherSsid");
221 // another "mistake" of the same type, except that a TID-To-Link Mapping element
222 // is not included in the containing frame
223 assoc.Get<TidToLinkMapping>().emplace_back();
224 // the SupportedRates IE is the same (hence not serialized) as in the containing frame,
225 // while the ExtendedSupportedRatesIE is different (hence serialized)
226 rates.AddSupportedRate(5.5e6);
227 rates.AddSupportedRate(11e6);
228 assoc.Get<SupportedRates>() = rates.rates;
229 assoc.Get<ExtendedSupportedRatesIE>() = rates.extendedRates;
230 // a VhtCapabilities IE is not present in the containing frame, hence it is serialized
231 assoc.Get<VhtCapabilities>().emplace();
232 // HeCapabilities IE is present in the containing frame and in the Per-STA Profile subelement,
233 // hence it is not serialized
234 assoc.Get<HeCapabilities>().emplace();
235 // EhtCapabilities IE is present in the containing frame but not in the Per-STA Profile
236 // subelement, hence it is listed in a Non-Inheritance element
237
239 perStaProfile2.SetLinkId(0);
240 perStaProfile2.SetCompleteProfile();
241 perStaProfile2.SetStaMacAddress(Mac48Address("ba:98:76:54:32:10"));
242 perStaProfile2.SetAssocRequest(assoc);
243
244 // The Association Request included in the third Per-STA Profile subelement has the
245 // EHT Capabilities element (which is inherited and not serialized) but it does not have the
246 // Ssid element, which is not listed in the Non-Inheritance element because it shall not
247 // appear in a Per-STA Profile subelement.
248 assoc.Get<Ssid>().reset();
249 assoc.Get<EhtCapabilities>() = ehtCapabilities;
250
251 auto perStaProfile3 = perStaProfile2;
252 perStaProfile3.SetAssocRequest(assoc);
253
254 // Adding MLE with two Per-STA Profile Subelements
256 GetMultiLinkElement(commonInfo, {perStaProfile1, perStaProfile2, perStaProfile3});
257
258 // first, check that serialization/deserialization of the whole Association Request works
260
261 // now, "manually" serialize and deserialize the header to check that the expected elements
262 // have been serialized
263 Buffer buffer;
264 buffer.AddAtStart(m_outerAssoc.GetSerializedSize());
265 m_outerAssoc.Serialize(buffer.Begin());
266
267 auto i = buffer.Begin();
269 i.ReadLsbtohU16(); // Listen interval
270
271 auto tmp = i;
272 i = Ssid().DeserializeIfPresent(tmp);
273 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "Ssid element not present");
274
276 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "SupportedRates element not present");
277
279 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp),
280 0,
281 "ExtendedSupportedRatesIE element not present");
282
284 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "HeCapabilities element not present");
285
286 // deserialize Multi-Link Element
287 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(), IE_EXTENSION, "IE_EXTENSION expected at the begin of MLE");
288 i.ReadU8(); // length
289 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
291 "IE_EXT_MULTI_LINK_ELEMENT expected");
292
293 uint16_t mlControl = i.ReadLsbtohU16();
294 auto nBytes = CommonInfoBasicMle().Deserialize(i, mlControl >> 4);
295 i.Next(nBytes);
296
297 // first Per-STA Profile subelement
298 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
300 "PER_STA_PROFILE_SUBELEMENT_ID expected");
301 i.ReadU8(); // length
302 i.ReadLsbtohU16(); // STA Control field
303 i.ReadU8(); // STA Info Length
304 // no STA address
306 // no Information Element
307
308 // second Per-STA Profile subelement
309 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
311 "PER_STA_PROFILE_SUBELEMENT_ID expected");
312 i.ReadU8(); // length
313 i.ReadLsbtohU16(); // STA Control field
314 i.ReadU8(); // STA Info Length
315 Mac48Address address;
316 ReadFrom(i, address);
318 // no Listen interval
319 // Ssid element not present (as mandated by specs)
320 // SupportedRates not present because it is inherited
321
323 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp),
324 0,
325 "ExtendedSupportedRatesIE element not present");
326
328 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "VhtCapabilities element not present");
329
330 // HeCapabilities not present because it is inherited
331 NonInheritance nonInheritance;
332 i = nonInheritance.DeserializeIfPresent(tmp = i);
333 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "Non-Inheritance element not present");
335 true,
336 "Non-Inheritance does not indicate EhtCapabilities");
337 NS_TEST_EXPECT_MSG_EQ(nonInheritance.m_elemIdList.size(),
338 0,
339 "Unexpected size for Elem ID list of Non-Inheritance element");
340 NS_TEST_EXPECT_MSG_EQ(nonInheritance.m_elemIdExtList.size(),
341 1,
342 "Unexpected size for Elem ID list of Non-Inheritance element");
343
344 // third Per-STA Profile subelement
345 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
347 "PER_STA_PROFILE_SUBELEMENT_ID expected");
348 i.ReadU8(); // length
349 i.ReadLsbtohU16(); // STA Control field
350 i.ReadU8(); // STA Info Length
351 ReadFrom(i, address);
353 // no Listen interval
354 // Ssid element not present (as mandated by specs)
355 // SupportedRates not present because it is inherited
356
358 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp),
359 0,
360 "ExtendedSupportedRatesIE element not present");
361
363 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "VhtCapabilities element not present");
364
365 // HeCapabilities not present because it is inherited
366 // EhtCapabilities not present because it is inherited
367
368 // the Multi-Link Element is done, we shall now find the EHT Capabilities of the
369 // containing Association Request frame
370 ehtCapabilities = EhtCapabilities(true, m_outerAssoc.Get<HeCapabilities>().value());
371 i = ehtCapabilities.DeserializeIfPresent(tmp = i);
372 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "EhtCapabilities element not present");
373
374 /**
375 * Yet another test: use the Deserialize method of the management frame and check that
376 * inherited Information Elements have been copied
377 */
379 auto count = frame.Deserialize(buffer.Begin());
380
381 NS_TEST_EXPECT_MSG_EQ(count, buffer.GetSize(), "Unexpected number of deserialized bytes");
382
383 // containing frame
384 NS_TEST_EXPECT_MSG_EQ(frame.Get<Ssid>().has_value(),
385 true,
386 "Containing frame should have SSID IE");
387 NS_TEST_EXPECT_MSG_EQ(frame.Get<SupportedRates>().has_value(),
388 true,
389 "Containing frame should have Supported Rates IE");
390 NS_TEST_EXPECT_MSG_EQ(frame.Get<ExtendedSupportedRatesIE>().has_value(),
391 true,
392 "Containing frame should have Extended Supported Rates IE");
393 NS_TEST_EXPECT_MSG_EQ(frame.Get<HtCapabilities>().has_value(),
394 false,
395 "Containing frame should not have HT Capabilities IE");
396 NS_TEST_EXPECT_MSG_EQ(frame.Get<ExtendedCapabilities>().has_value(),
397 false,
398 "Containing frame should not have Extended Capabilities IE");
399 NS_TEST_EXPECT_MSG_EQ(frame.Get<VhtCapabilities>().has_value(),
400 false,
401 "Containing frame should not have VHT Capabilities IE");
402 NS_TEST_EXPECT_MSG_EQ(frame.Get<HeCapabilities>().has_value(),
403 true,
404 "Containing frame should have HE Capabilities IE");
405 NS_TEST_EXPECT_MSG_EQ(frame.Get<MultiLinkElement>().has_value(),
406 true,
407 "Containing frame should have Multi-Link Element IE");
408 NS_TEST_EXPECT_MSG_EQ(frame.Get<EhtCapabilities>().has_value(),
409 true,
410 "Containing frame should have EHT Capabilities IE");
411 NS_TEST_EXPECT_MSG_EQ(frame.Get<TidToLinkMapping>().empty(),
412 true,
413 "Containing frame should not have TID-to-Link Mapping IE");
414
415 auto& mle = frame.Get<MultiLinkElement>().value();
416
417 NS_TEST_EXPECT_MSG_EQ(mle.GetNPerStaProfileSubelements(),
418 3,
419 "Unexpected number of Per-STA Profile subelements");
420
421 // frame in first Per-STA Profile subelement has inherited all the IEs but SSID and
422 // Multi-Link Element IEs
423 auto& perSta1 = mle.GetPerStaProfile(0);
424 NS_TEST_EXPECT_MSG_EQ(perSta1.HasAssocRequest(),
425 true,
426 "First Per-STA Profile should contain an Association Request frame");
427 auto& perSta1Frame =
428 std::get<std::reference_wrapper<MgtAssocRequestHeader>>(perSta1.GetAssocRequest()).get();
429
430 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<Ssid>().has_value(),
431 false,
432 "Frame in first Per-STA Profile should not have SSID IE");
433 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<SupportedRates>().has_value(),
434 true,
435 "Frame in first Per-STA Profile should have Supported Rates IE");
437 (perSta1Frame.Get<SupportedRates>() == frame.Get<SupportedRates>()),
438 true,
439 "Supported Rates IE not correctly inherited by frame in first Per-STA Profile");
440 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<ExtendedSupportedRatesIE>().has_value(),
441 true,
442 "Frame in first Per-STA Profile should have Extended Supported Rates IE");
444 (perSta1Frame.Get<ExtendedSupportedRatesIE>() == frame.Get<ExtendedSupportedRatesIE>()),
445 true,
446 "Extended Supported Rates IE not correctly inherited by frame in first Per-STA Profile");
447 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<HtCapabilities>().has_value(),
448 false,
449 "Frame in first Per-STA Profile should not have HT Capabilities IE");
451 perSta1Frame.Get<ExtendedCapabilities>().has_value(),
452 false,
453 "Frame in first Per-STA Profile should not have Extended Capabilities IE");
454 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<VhtCapabilities>().has_value(),
455 false,
456 "Frame in first Per-STA Profile should not have VHT Capabilities IE");
457 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<HeCapabilities>().has_value(),
458 true,
459 "Frame in first Per-STA Profile should have HE Capabilities IE");
461 (perSta1Frame.Get<HeCapabilities>() == frame.Get<HeCapabilities>()),
462 true,
463 "HE Capabilities IE not correctly inherited by frame in first Per-STA Profile");
464 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<MultiLinkElement>().has_value(),
465 false,
466 "Frame in first Per-STA Profile should not have Multi-Link Element IE");
467 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<EhtCapabilities>().has_value(),
468 true,
469 "Frame in first Per-STA Profile should have EHT Capabilities IE");
471 (perSta1Frame.Get<EhtCapabilities>() == frame.Get<EhtCapabilities>()),
472 true,
473 "EHT Capabilities IE not correctly inherited by frame in first Per-STA Profile");
474 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<TidToLinkMapping>().empty(),
475 true,
476 "Frame in first Per-STA Profile should not have TID-to-Link Mapping IE");
477
478 // frame in second Per-STA Profile subelement includes VHT Capabilities IE and has inherited
479 // all the IEs but SSID IE, Multi-Link Element IE, Extended Supported Rates IE (different
480 // than in containing frame) and EHT Capabilities IE (listed in Non-Inheritance IE).
481 auto& perSta2 = mle.GetPerStaProfile(1);
482 NS_TEST_EXPECT_MSG_EQ(perSta2.HasAssocRequest(),
483 true,
484 "Second Per-STA Profile should contain an Association Request frame");
485 auto& perSta2Frame =
486 std::get<std::reference_wrapper<MgtAssocRequestHeader>>(perSta2.GetAssocRequest()).get();
487
488 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<Ssid>().has_value(),
489 false,
490 "Frame in second Per-STA Profile should not have SSID IE");
491 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<SupportedRates>().has_value(),
492 true,
493 "Frame in second Per-STA Profile should have Supported Rates IE");
495 (perSta2Frame.Get<SupportedRates>() == frame.Get<SupportedRates>()),
496 true,
497 "Supported Rates IE not correctly inherited by frame in second Per-STA Profile");
499 perSta2Frame.Get<ExtendedSupportedRatesIE>().has_value(),
500 true,
501 "Frame in second Per-STA Profile should have Extended Supported Rates IE");
503 (perSta2Frame.Get<ExtendedSupportedRatesIE>() == frame.Get<ExtendedSupportedRatesIE>()),
504 false,
505 "Extended Supported Rates IE should have not been inherited by frame in second Per-STA "
506 "Profile");
507 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<HtCapabilities>().has_value(),
508 false,
509 "Frame in second Per-STA Profile should not have HT Capabilities IE");
511 perSta2Frame.Get<ExtendedCapabilities>().has_value(),
512 false,
513 "Frame in second Per-STA Profile should not have Extended Capabilities IE");
514 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<VhtCapabilities>().has_value(),
515 true,
516 "Frame in second Per-STA Profile should have VHT Capabilities IE");
517 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<HeCapabilities>().has_value(),
518 true,
519 "Frame in second Per-STA Profile should have HE Capabilities IE");
521 (perSta2Frame.Get<HeCapabilities>() == frame.Get<HeCapabilities>()),
522 true,
523 "HE Capabilities IE not correctly inherited by frame in second Per-STA Profile");
524 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<MultiLinkElement>().has_value(),
525 false,
526 "Frame in second Per-STA Profile should not have Multi-Link Element IE");
528 perSta2Frame.Get<EhtCapabilities>().has_value(),
529 false,
530 "Frame in second Per-STA Profile should have not inherited EHT Capabilities IE");
531 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<TidToLinkMapping>().empty(),
532 true,
533 "Frame in second Per-STA Profile should not have TID-to-Link Mapping IE");
534
535 // frame in third Per-STA Profile subelement includes VHT Capabilities IE and has inherited
536 // all the IEs but SSID IE, Multi-Link Element IE and Extended Supported Rates IE (different
537 // than in containing frame).
538 auto& perSta3 = mle.GetPerStaProfile(2);
539 NS_TEST_EXPECT_MSG_EQ(perSta3.HasAssocRequest(),
540 true,
541 "Third Per-STA Profile should contain an Association Request frame");
542 auto& perSta3Frame =
543 std::get<std::reference_wrapper<MgtAssocRequestHeader>>(perSta3.GetAssocRequest()).get();
544
545 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<Ssid>().has_value(),
546 false,
547 "Frame in third Per-STA Profile should not have SSID IE");
548 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<SupportedRates>().has_value(),
549 true,
550 "Frame in third Per-STA Profile should have Supported Rates IE");
552 (perSta3Frame.Get<SupportedRates>() == frame.Get<SupportedRates>()),
553 true,
554 "Supported Rates IE not correctly inherited by frame in third Per-STA Profile");
555 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<ExtendedSupportedRatesIE>().has_value(),
556 true,
557 "Frame in third Per-STA Profile should have Extended Supported Rates IE");
559 (perSta3Frame.Get<ExtendedSupportedRatesIE>() == frame.Get<ExtendedSupportedRatesIE>()),
560 false,
561 "Extended Supported Rates IE should have not been inherited by frame in third Per-STA "
562 "Profile");
563 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<HtCapabilities>().has_value(),
564 false,
565 "Frame in third Per-STA Profile should not have HT Capabilities IE");
567 perSta3Frame.Get<ExtendedCapabilities>().has_value(),
568 false,
569 "Frame in third Per-STA Profile should not have Extended Capabilities IE");
570 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<VhtCapabilities>().has_value(),
571 true,
572 "Frame in third Per-STA Profile should have VHT Capabilities IE");
573 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<HeCapabilities>().has_value(),
574 true,
575 "Frame in third Per-STA Profile should have HE Capabilities IE");
577 (perSta3Frame.Get<HeCapabilities>() == frame.Get<HeCapabilities>()),
578 true,
579 "HE Capabilities IE not correctly inherited by frame in third Per-STA Profile");
580 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<MultiLinkElement>().has_value(),
581 false,
582 "Frame in third Per-STA Profile should not have Multi-Link Element IE");
584 perSta3Frame.Get<EhtCapabilities>().has_value(),
585 true,
586 "Frame in third Per-STA Profile should have inherited EHT Capabilities IE");
588 (perSta3Frame.Get<EhtCapabilities>() == frame.Get<EhtCapabilities>()),
589 true,
590 "EHT Capabilities IE not correctly inherited by frame in third Per-STA Profile");
591 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<TidToLinkMapping>().empty(),
592 true,
593 "Frame in third Per-STA Profile should not have TID-to-Link Mapping IE");
594}
595
596/**
597 * \ingroup wifi-test
598 * \ingroup tests
599 *
600 * \brief Test Reduced Neighbor Report serialization and deserialization
601 */
603{
604 public:
605 /**
606 * Constructor
607 */
610
611 /// typedef for const iterator on the set of available channels
613
614 /**
615 * Get a Reduced Neighbor Report element including the given operating channels
616 *
617 * \param channel2_4It a channel in the 2.4 GHz band
618 * \param channel5It a channel in the 5 GHz band
619 * \param channel6It a channel in the 6 GHz band
620 * \return a Reduced Neighbor Report element
621 */
623 PhyOpChannelIt channel5It,
624 PhyOpChannelIt channel6It);
625
626 private:
627 void DoRun() override;
628};
629
632 "Check serialization and deserialization of Reduced Neighbor Report elements")
633{
634}
635
637{
638}
639
642 PhyOpChannelIt channel5It,
643 PhyOpChannelIt channel6It)
644{
646
647 std::stringstream info;
648
649 if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
650 {
651 WifiPhyOperatingChannel channel(channel2_4It);
652
653 info << "{Ch=" << +channel.GetNumber() << ", Bw=" << channel.GetWidth() << ", 2.4 GHz} ";
654 rnr.AddNbrApInfoField();
655 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
656 rnr.SetOperatingChannel(nbrId, channel);
657 // Add a TBTT Information Field
658 rnr.AddTbttInformationField(nbrId);
659 rnr.SetBssid(nbrId, 0, Mac48Address("00:00:00:00:00:24"));
660 rnr.SetShortSsid(nbrId, 0, 0);
661 rnr.SetBssParameters(nbrId, 0, 10);
662 rnr.SetPsd20MHz(nbrId, 0, 50);
663 rnr.SetMldParameters(nbrId, 0, 0, 2, 3);
664 }
665
666 if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
667 {
668 WifiPhyOperatingChannel channel(channel5It);
669
670 info << "{Ch=" << +channel.GetNumber() << ", Bw=" << channel.GetWidth() << ", 5 GHz} ";
671 rnr.AddNbrApInfoField();
672 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
673 rnr.SetOperatingChannel(nbrId, channel);
674 // Add a TBTT Information Field
675 rnr.AddTbttInformationField(nbrId);
676 rnr.SetBssid(nbrId, 0, Mac48Address("00:00:00:00:00:05"));
677 rnr.SetShortSsid(nbrId, 0, 0);
678 rnr.SetBssParameters(nbrId, 0, 20);
679 rnr.SetPsd20MHz(nbrId, 0, 60);
680 rnr.SetMldParameters(nbrId, 0, 0, 3, 4);
681 // Add another TBTT Information Field
682 rnr.AddTbttInformationField(nbrId);
683 rnr.SetBssid(nbrId, 1, Mac48Address("00:00:00:00:01:05"));
684 rnr.SetShortSsid(nbrId, 1, 0);
685 rnr.SetBssParameters(nbrId, 1, 30);
686 rnr.SetPsd20MHz(nbrId, 1, 70);
687 rnr.SetMldParameters(nbrId, 1, 0, 4, 5);
688 }
689
690 if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
691 {
692 WifiPhyOperatingChannel channel(channel6It);
693
694 info << "{Ch=" << +channel.GetNumber() << ", Bw=" << channel.GetWidth() << ", 6 GHz} ";
695 rnr.AddNbrApInfoField();
696 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
697 rnr.SetOperatingChannel(nbrId, channel);
698 // Add a TBTT Information Field
699 rnr.AddTbttInformationField(nbrId);
700 rnr.SetBssid(nbrId, 0, Mac48Address("00:00:00:00:00:06"));
701 rnr.SetShortSsid(nbrId, 0, 0);
702 rnr.SetBssParameters(nbrId, 0, 40);
703 rnr.SetPsd20MHz(nbrId, 0, 80);
704 rnr.SetMldParameters(nbrId, 0, 0, 5, 6);
705 }
706
707 NS_LOG_DEBUG(info.str());
708 return rnr;
709}
710
711void
713{
714 PhyOpChannelIt channel2_4It;
715 PhyOpChannelIt channel5It;
716 PhyOpChannelIt channel6It;
717 channel2_4It = channel5It = channel6It = WifiPhyOperatingChannel::m_frequencyChannels.cbegin();
718
719 // Test all available frequency channels
720 while (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend() ||
723 {
724 if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
725 {
726 channel2_4It = WifiPhyOperatingChannel::FindFirst(0,
727 0,
728 0,
731 channel2_4It);
732 }
733 if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
734 {
736 0,
737 0,
740 channel5It);
741 }
742 if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
743 {
745 0,
746 0,
749 channel6It);
750 }
751
752 TestHeaderSerialization(GetReducedNeighborReport(channel2_4It, channel5It, channel6It));
753
754 // advance all channel iterators
755 if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
756 {
757 channel2_4It++;
758 }
759 if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
760 {
761 channel5It++;
762 }
763 if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
764 {
765 channel6It++;
766 }
767 }
768}
769
770/**
771 * \ingroup wifi-test
772 * \ingroup tests
773 *
774 * \brief Test serialization and deserialization of EHT capabilities IE
775 */
777{
778 public:
779 /**
780 * Constructor
781 * \param is2_4Ghz whether the PHY is operating in 2.4 GHz
782 * \param channelWidth the supported channel width in MHz
783 */
784 WifiEhtCapabilitiesIeTest(bool is2_4Ghz, uint16_t channelWidth);
785 ~WifiEhtCapabilitiesIeTest() override = default;
786
787 /**
788 * Generate the HE capabilities IE.
789 *
790 * \return the generated HE capabilities IE
791 */
793
794 /**
795 * Generate the EHT capabilities IE.
796 *
797 * \param maxMpduLength the maximum MPDU length in bytes
798 * \param maxAmpduSize the maximum A-MPDU size in bytes
799 * \param maxSupportedMcs the maximum EHT MCS supported by the PHY
800 * \return the generated EHT capabilities IE
801 */
802 EhtCapabilities GetEhtCapabilities(uint16_t maxMpduLength,
803 uint32_t maxAmpduSize,
804 uint8_t maxSupportedMcs) const;
805
806 /**
807 * Serialize the EHT capabilities in a buffer.
808 *
809 * \param ehtCapabilities the EHT capabilities
810 * \return the buffer in which the EHT capabilities has been serialized
811 */
812 Buffer SerializeIntoBuffer(const EhtCapabilities& ehtCapabilities);
813
814 /**
815 * Check that the given buffer contains the given value at the given position.
816 *
817 * \param buffer the given buffer
818 * \param position the given position (starting at 0)
819 * \param value the given value
820 */
821 void CheckSerializedByte(const Buffer& buffer, uint32_t position, uint8_t value);
822
823 /**
824 * Check the content of the EHT MAC Capabilities Information subfield.
825 *
826 * \param buffer the buffer containing the serialized EHT capabilities
827 * \param expectedValueFirstByte the expected value for the first byte
828 */
829 void CheckEhtMacCapabilitiesInformation(const Buffer& buffer, uint8_t expectedValueFirstByte);
830
831 /**
832 * Check the content of the EHT PHY Capabilities Information subfield.
833 *
834 * \param buffer the buffer containing the serialized EHT capabilities
835 * \param expectedValueSixthByte the expected value for the sixth byte
836 */
837 void CheckEhtPhyCapabilitiesInformation(const Buffer& buffer, uint8_t expectedValueSixthByte);
838
839 /**
840 * Check the content of the Supported EHT-MCS And NSS Set subfield.
841 * \param maxSupportedMcs the maximum EHT MCS supported by the PHY
842 *
843 * \param buffer the buffer containing the serialized EHT capabilities
844 */
845 void CheckSupportedEhtMcsAndNssSet(const Buffer& buffer, uint8_t maxSupportedMcs);
846
847 private:
848 void DoRun() override;
849
850 bool m_is2_4Ghz; //!< whether the PHY is operating in 2.4 GHz
851 uint16_t m_channelWidth; //!< Supported channel width by the PHY (in MHz)
852};
853
854WifiEhtCapabilitiesIeTest ::WifiEhtCapabilitiesIeTest(bool is2_4Ghz, uint16_t channelWidth)
855 : HeaderSerializationTestCase{"Check serialization and deserialization of EHT capabilities IE"},
856 m_is2_4Ghz{is2_4Ghz},
857 m_channelWidth{channelWidth}
858{
859}
860
863{
864 HeCapabilities capabilities;
865 uint8_t channelWidthSet = 0;
866 if ((m_channelWidth >= 40) && m_is2_4Ghz)
867 {
868 channelWidthSet |= 0x01;
869 }
870 if ((m_channelWidth >= 80) && !m_is2_4Ghz)
871 {
872 channelWidthSet |= 0x02;
873 }
874 if ((m_channelWidth >= 160) && !m_is2_4Ghz)
875 {
876 channelWidthSet |= 0x04;
877 }
878 capabilities.SetChannelWidthSet(channelWidthSet);
879 return capabilities;
880}
881
884 uint32_t maxAmpduSize,
885 uint8_t maxSupportedMcs) const
886{
887 EhtCapabilities capabilities;
888
889 if (m_is2_4Ghz)
890 {
891 capabilities.SetMaxMpduLength(maxMpduLength);
892 }
893 // round to the next power of two minus one
894 maxAmpduSize = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduSize + 1)))) - 1;
895 // The maximum A-MPDU length in EHT capabilities elements ranges from 2^23-1 to 2^24-1
896 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduSize, 8388607U), 16777215U));
897
899 (maxSupportedMcs >= 12) ? 1 : 0;
901 (maxSupportedMcs >= 12) ? 1 : 0;
902 if (m_channelWidth == 20)
903 {
904 for (auto maxMcs : {7, 9, 11, 13})
905 {
907 maxMcs,
908 maxMcs <= maxSupportedMcs ? 1 : 0);
910 maxMcs,
911 maxMcs <= maxSupportedMcs ? 2 : 0);
912 }
913 }
914 else
915 {
916 for (auto maxMcs : {9, 11, 13})
917 {
918 capabilities.SetSupportedRxEhtMcsAndNss(
920 maxMcs,
921 maxMcs <= maxSupportedMcs ? 3 : 0);
922 capabilities.SetSupportedTxEhtMcsAndNss(
924 maxMcs,
925 maxMcs <= maxSupportedMcs ? 4 : 0);
926 }
927 }
928 if (m_channelWidth >= 160)
929 {
930 for (auto maxMcs : {9, 11, 13})
931 {
933 maxMcs,
934 maxMcs <= maxSupportedMcs ? 2 : 0);
936 maxMcs,
937 maxMcs <= maxSupportedMcs ? 1 : 0);
938 }
939 }
940 if (m_channelWidth == 320)
941 {
942 capabilities.m_phyCapabilities.support320MhzIn6Ghz = 1;
943 for (auto maxMcs : {9, 11, 13})
944 {
946 maxMcs,
947 maxMcs <= maxSupportedMcs ? 4 : 0);
949 maxMcs,
950 maxMcs <= maxSupportedMcs ? 3 : 0);
951 }
952 }
953 else
954 {
955 capabilities.m_phyCapabilities.support320MhzIn6Ghz = 0;
956 }
957
958 return capabilities;
959}
960
961Buffer
963{
964 Buffer buffer;
965 buffer.AddAtStart(ehtCapabilities.GetSerializedSize());
966 ehtCapabilities.Serialize(buffer.Begin());
967 return buffer;
968}
969
970void
972 uint32_t position,
973 uint8_t value)
974{
975 Buffer::Iterator it = buffer.Begin();
976 it.Next(position);
977 uint8_t byte = it.ReadU8();
978 NS_TEST_EXPECT_MSG_EQ(+byte, +value, "Unexpected byte at pos=" << position);
979}
980
981void
983 uint8_t expectedValueFirstByte)
984{
985 CheckSerializedByte(buffer, 3, expectedValueFirstByte);
986 CheckSerializedByte(buffer, 4, 0x00);
987}
988
989void
991 uint8_t expectedValueSixthByte)
992{
993 CheckSerializedByte(buffer, 5, (m_channelWidth == 320) ? 0x02 : 0x00);
994 CheckSerializedByte(buffer, 6, 0x00);
995 CheckSerializedByte(buffer, 7, 0x00);
996 CheckSerializedByte(buffer, 8, 0x00);
997 CheckSerializedByte(buffer, 9, 0x00);
998 CheckSerializedByte(buffer, 10, expectedValueSixthByte);
999 CheckSerializedByte(buffer, 11, 0x00);
1000 CheckSerializedByte(buffer, 12, 0x00);
1001 CheckSerializedByte(buffer, 13, 0x00);
1002}
1003
1004void
1006 uint8_t maxSupportedMcs)
1007{
1008 if (m_channelWidth == 20)
1009 {
1010 CheckSerializedByte(buffer, 14, 0x21); // first byte of Supported EHT-MCS And NSS Set
1012 buffer,
1013 15,
1014 maxSupportedMcs >= 8 ? 0x21 : 0x00); // second byte of Supported EHT-MCS And NSS Set
1016 buffer,
1017 16,
1018 maxSupportedMcs >= 10 ? 0x21 : 0x00); // third byte of Supported EHT-MCS And NSS Set
1020 buffer,
1021 17,
1022 maxSupportedMcs >= 12 ? 0x21 : 0x00); // fourth byte of Supported EHT-MCS And NSS Set
1023 }
1024 else
1025 {
1026 CheckSerializedByte(buffer, 14, 0x43); // first byte of Supported EHT-MCS And NSS Set
1028 buffer,
1029 15,
1030 maxSupportedMcs >= 10 ? 0x43 : 0x00); // second byte of Supported EHT-MCS And NSS Set
1032 buffer,
1033 16,
1034 maxSupportedMcs >= 12 ? 0x43 : 0x00); // third byte of Supported EHT-MCS And NSS Set
1035 }
1036 if (m_channelWidth >= 160)
1037 {
1038 CheckSerializedByte(buffer, 17, 0x12); // first byte of EHT-MCS Map (BW = 160 MHz)
1040 buffer,
1041 18,
1042 maxSupportedMcs >= 10 ? 0x12 : 0x00); // second byte of EHT-MCS Map (BW = 160 MHz)
1044 buffer,
1045 19,
1046 maxSupportedMcs >= 12 ? 0x12 : 0x00); // third byte of EHT-MCS Map (BW = 160 MHz)
1047 }
1048 if (m_channelWidth == 320)
1049 {
1050 CheckSerializedByte(buffer, 20, 0x34); // first byte of EHT-MCS Map (BW = 320 MHz)
1052 buffer,
1053 21,
1054 maxSupportedMcs >= 10 ? 0x34 : 0x00); // second byte of EHT-MCS Map (BW = 320 MHz)
1056 buffer,
1057 22,
1058 maxSupportedMcs >= 12 ? 0x34 : 0x00); // third byte of EHT-MCS Map (BW = 320 MHz)
1059 }
1060}
1061
1062void
1064{
1065 uint8_t maxMcs = 0;
1066 uint16_t expectedEhtMcsAndNssSetSize = 0;
1067 switch (m_channelWidth)
1068 {
1069 case 20:
1070 expectedEhtMcsAndNssSetSize = 4;
1071 break;
1072 case 40:
1073 case 80:
1074 expectedEhtMcsAndNssSetSize = 3;
1075 break;
1076 case 160:
1077 expectedEhtMcsAndNssSetSize = (2 * 3);
1078 break;
1079 case 320:
1080 expectedEhtMcsAndNssSetSize = (3 * 3);
1081 break;
1082 default:
1083 NS_ASSERT_MSG(false, "Invalid upper channel width " << m_channelWidth);
1084 }
1085
1086 uint16_t expectedSize = 1 + // Element ID
1087 1 + // Length
1088 1 + // Element ID Extension
1089 2 + // EHT MAC Capabilities Information
1090 9 + // EHT PHY Capabilities Information
1091 expectedEhtMcsAndNssSetSize; // Supported EHT-MCS And NSS Set
1092
1095
1096 {
1097 maxMcs = 11;
1098 HeCapabilities heCapabilities = GetHeCapabilities();
1099 EhtCapabilities ehtCapabilities = GetEhtCapabilities(3895, 65535, maxMcs);
1100
1101 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1102 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1103
1104 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1105 expectedSize,
1106 "Unexpected header size");
1107
1108 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1109
1111
1113
1114 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1115
1116 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1117 }
1118
1119 {
1120 maxMcs = 11;
1121 HeCapabilities heCapabilities = GetHeCapabilities();
1122 EhtCapabilities ehtCapabilities = GetEhtCapabilities(11454, 65535, maxMcs);
1123
1124 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1125 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1126
1127 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1128 expectedSize,
1129 "Unexpected header size");
1130
1131 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1132
1133 CheckEhtMacCapabilitiesInformation(buffer, m_is2_4Ghz ? 0x80 : 0x00);
1134
1136
1137 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1138
1139 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1140 }
1141
1142 {
1143 maxMcs = 13;
1144 HeCapabilities heCapabilities = GetHeCapabilities();
1145 EhtCapabilities ehtCapabilities = GetEhtCapabilities(3895, 65535, maxMcs);
1146
1147 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1148 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1149
1150 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1151 expectedSize,
1152 "Unexpected header size");
1153
1154 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1155
1157
1159
1160 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1161
1162 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1163 }
1164
1165 {
1166 maxMcs = 11;
1167 HeCapabilities heCapabilities = GetHeCapabilities();
1168 EhtCapabilities ehtCapabilities = GetEhtCapabilities(3895, 65535, maxMcs);
1169
1170 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1171 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1172
1173 std::vector<std::pair<uint8_t, uint8_t>> ppeThresholds;
1174 ppeThresholds.emplace_back(1, 2); // NSS1 242-tones RU
1175 ppeThresholds.emplace_back(2, 3); // NSS1 484-tones RU
1176 ppeThresholds.emplace_back(3, 4); // NSS2 242-tones RU
1177 ppeThresholds.emplace_back(4, 3); // NSS2 484-tones RU
1178 ppeThresholds.emplace_back(3, 2); // NSS3 242-tones RU
1179 ppeThresholds.emplace_back(2, 1); // NSS3 484-tones RU
1180 ehtCapabilities.SetPpeThresholds(2, 0x03, ppeThresholds);
1181
1182 expectedSize += 6;
1183
1184 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1185 expectedSize,
1186 "Unexpected header size");
1187
1188 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1189
1191
1193
1194 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1195
1196 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1197 }
1198}
1199
1200/**
1201 * \ingroup wifi-test
1202 * \ingroup tests
1203 *
1204 * \brief Test TID-To-Link Mapping information element serialization and deserialization
1205 */
1207{
1208 public:
1209 /**
1210 * Constructor
1211 *
1212 * \param direction The direction for the TID-to-link mapping
1213 * \param mappingSwitchTime the Mapping Switching Time
1214 * \param expectedDuration the Expected Duration
1215 * \param mappings A TID-indexed map of the link sets the TIDs are mapped to
1216 */
1218 std::optional<Time> mappingSwitchTime,
1219 std::optional<Time> expectedDuration,
1220 const WifiTidLinkMapping& mappings);
1221
1222 ~TidToLinkMappingElementTest() override = default;
1223
1224 private:
1225 void DoSetup() override;
1226 void DoRun() override;
1227
1228 WifiDirection m_direction; ///< the direction for the TID-to-link mapping
1229 std::optional<Time> m_mappingSwitchTime; ///< the Mapping Switching Time
1230 std::optional<Time> m_expectedDuration; ///< the Expected Duration
1231 WifiTidLinkMapping m_mappings; ///< maps TIDs to link sets
1232 TidToLinkMapping m_tidToLinkMapping; ///< TID-To-Link Mapping element
1233};
1234
1236 std::optional<Time> mappingSwitchTime,
1237 std::optional<Time> expectedDuration,
1238 const WifiTidLinkMapping& mappings)
1240 "Check serialization and deserialization of TID-To-Link Mapping elements"),
1241 m_direction(direction),
1242 m_mappingSwitchTime(mappingSwitchTime),
1243 m_expectedDuration(expectedDuration),
1244 m_mappings(mappings)
1245{
1246}
1247
1248void
1250{
1253
1255 {
1257 std::optional<Time> encoded = m_tidToLinkMapping.GetMappingSwitchTime();
1258 NS_TEST_ASSERT_MSG_EQ(encoded.has_value(), true, "Mapping Switch Time should be present");
1260 *encoded,
1261 "Incorrect Mapping Switch Time value");
1262 }
1264 {
1266 std::optional<Time> encoded = m_tidToLinkMapping.GetExpectedDuration();
1267 NS_TEST_ASSERT_MSG_EQ(encoded.has_value(), true, "Expected Duration should be present");
1268 NS_TEST_EXPECT_MSG_EQ(*m_expectedDuration, *encoded, "Incorrect Expected Duration value");
1269 }
1270
1271 for (const auto& [tid, linkSet] : m_mappings)
1272 {
1276 true,
1277 "Incorrect link set for TID " << +tid);
1278 }
1279}
1280
1281void
1283{
1285
1287}
1288
1289/**
1290 * \ingroup wifi-test
1291 * \ingroup tests
1292 *
1293 * \brief Test EHT Operation information element serialization and deserialization
1294 */
1296{
1297 public:
1298 /**
1299 * Constructor
1300 *
1301 * \param params the EHT Operation Parameters field
1302 * \param rxMaxNss0_7 RX max NSS that supports EHT MCS 0-7
1303 * \param txMaxNss0_7 TX max NSS that supports EHT MCS 0-7
1304 * \param rxMaxNss8_9 RX max NSS that supports EHT MCS 8-9
1305 * \param txMaxNss8_9 TX max NSS that supports EHT MCS 8-9
1306 * \param rxMaxNss10_11 RX max NSS that supports EHT MCS 10-11
1307 * \param txMaxNss10_11 TX max NSS that supports EHT MCS 10-11
1308 * \param rxMaxNss12_13 RX max NSS that supports EHT MCS 12-13
1309 * \param txMaxNss12_13 TX max NSS that supports EHT MCS 12-13
1310 * \param opInfo the EHT Operation Information field
1311 */
1313 uint8_t rxMaxNss0_7,
1314 uint8_t txMaxNss0_7,
1315 uint8_t rxMaxNss8_9,
1316 uint8_t txMaxNss8_9,
1317 uint8_t rxMaxNss10_11,
1318 uint8_t txMaxNss10_11,
1319 uint8_t rxMaxNss12_13,
1320 uint8_t txMaxNss12_13,
1321 std::optional<EhtOperation::EhtOpInfo> opInfo);
1322
1323 ~EhtOperationElementTest() override = default;
1324
1325 private:
1326 void DoRun() override;
1327
1328 EhtOperation m_ehtOperation; ///< EHT Operation element
1329};
1330
1332 uint8_t rxMaxNss0_7,
1333 uint8_t txMaxNss0_7,
1334 uint8_t rxMaxNss8_9,
1335 uint8_t txMaxNss8_9,
1336 uint8_t rxMaxNss10_11,
1337 uint8_t txMaxNss10_11,
1338 uint8_t rxMaxNss12_13,
1339 uint8_t txMaxNss12_13,
1340 std::optional<EhtOperation::EhtOpInfo> opInfo)
1342 "Check serialization and deserialization of EHT Operation elements")
1343{
1344 m_ehtOperation.m_params = params;
1345 m_ehtOperation.SetMaxRxNss(rxMaxNss0_7, 0, 7);
1346 m_ehtOperation.SetMaxTxNss(txMaxNss0_7, 0, 7);
1347 m_ehtOperation.SetMaxRxNss(rxMaxNss8_9, 8, 9);
1348 m_ehtOperation.SetMaxTxNss(txMaxNss8_9, 8, 9);
1349 m_ehtOperation.SetMaxRxNss(rxMaxNss10_11, 10, 11);
1350 m_ehtOperation.SetMaxTxNss(txMaxNss10_11, 10, 11);
1351 m_ehtOperation.SetMaxRxNss(rxMaxNss12_13, 12, 13);
1352 m_ehtOperation.SetMaxTxNss(txMaxNss12_13, 12, 13);
1353 m_ehtOperation.m_opInfo = opInfo;
1354}
1355
1356void
1358{
1360}
1361
1362/**
1363 * \ingroup wifi-test
1364 * \ingroup tests
1365 *
1366 * \brief wifi EHT Information Elements Test Suite
1367 */
1369{
1370 public:
1372};
1373
1375 : TestSuite("wifi-eht-info-elems", Type::UNIT)
1376{
1377 AddTestCase(new BasicMultiLinkElementTest(), TestCase::Duration::QUICK);
1378 AddTestCase(new ReducedNeighborReportTest(), TestCase::Duration::QUICK);
1379 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 20), TestCase::Duration::QUICK);
1380 AddTestCase(new WifiEhtCapabilitiesIeTest(true, 20), TestCase::Duration::QUICK);
1381 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 80), TestCase::Duration::QUICK);
1382 AddTestCase(new WifiEhtCapabilitiesIeTest(true, 40), TestCase::Duration::QUICK);
1383 AddTestCase(new WifiEhtCapabilitiesIeTest(true, 80), TestCase::Duration::QUICK);
1384 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 160), TestCase::Duration::QUICK);
1385 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 320), TestCase::Duration::QUICK);
1387 new TidToLinkMappingElementTest(WifiDirection::DOWNLINK, std::nullopt, std::nullopt, {}),
1388 TestCase::Duration::QUICK);
1389 AddTestCase(new TidToLinkMappingElementTest(WifiDirection::UPLINK,
1390 MicroSeconds(500 * 1024),
1391 MicroSeconds(300 * 1024),
1392 {{3, std::set<uint8_t>{0, 4, 6}}}),
1393 TestCase::Duration::QUICK);
1395 WifiDirection::BOTH_DIRECTIONS,
1396 std::nullopt,
1397 MicroSeconds(100 * 1024),
1398 {{3, std::set<uint8_t>{0, 4, 6}}, {6, std::set<uint8_t>{3, 7, 11, 14}}}),
1399 TestCase::Duration::QUICK);
1400 AddTestCase(new TidToLinkMappingElementTest(WifiDirection::DOWNLINK,
1401 MicroSeconds(100 * 1024),
1402 std::nullopt,
1403 {{0, std::set<uint8_t>{0, 1, 2}},
1404 {1, std::set<uint8_t>{3, 4, 5}},
1405 {2, std::set<uint8_t>{6, 7}},
1406 {3, std::set<uint8_t>{8, 9, 10}},
1407 {4, std::set<uint8_t>{11, 12, 13}},
1408 {5, std::set<uint8_t>{14}},
1409 {6, std::set<uint8_t>{1, 3, 6}},
1410 {7, std::set<uint8_t>{11, 14}}}),
1411 TestCase::Duration::QUICK);
1412 AddTestCase(new EhtOperationElementTest({0, 0, 0, 0, 0}, 1, 2, 3, 4, 5, 6, 7, 8, std::nullopt),
1413 TestCase::Duration::QUICK);
1414 AddTestCase(new EhtOperationElementTest({1, 0, 0, 1, 0},
1415 1,
1416 2,
1417 3,
1418 4,
1419 5,
1420 6,
1421 7,
1422 8,
1423 EhtOperation::EhtOpInfo{{1}, 3, 5}),
1424 TestCase::Duration::QUICK);
1425 AddTestCase(new EhtOperationElementTest({1, 1, 1, 1, 2},
1426 1,
1427 2,
1428 3,
1429 4,
1430 5,
1431 6,
1432 7,
1433 8,
1434 EhtOperation::EhtOpInfo{{2}, 4, 6, 3000}),
1435 TestCase::Duration::QUICK);
1436}
1437
Test EHT Operation information element serialization and deserialization.
void DoRun() override
Implementation to actually run this TestCase.
EhtOperationElementTest(const EhtOperation::EhtOpParams &params, uint8_t rxMaxNss0_7, uint8_t txMaxNss0_7, uint8_t rxMaxNss8_9, uint8_t txMaxNss8_9, uint8_t rxMaxNss10_11, uint8_t txMaxNss10_11, uint8_t rxMaxNss12_13, uint8_t txMaxNss12_13, std::optional< EhtOperation::EhtOpInfo > opInfo)
Constructor.
EhtOperation m_ehtOperation
EHT Operation element.
~EhtOperationElementTest() override=default
Test Reduced Neighbor Report serialization and deserialization.
ReducedNeighborReport GetReducedNeighborReport(PhyOpChannelIt channel2_4It, PhyOpChannelIt channel5It, PhyOpChannelIt channel6It)
Get a Reduced Neighbor Report element including the given operating channels.
void DoRun() override
Implementation to actually run this TestCase.
WifiPhyOperatingChannel::ConstIterator PhyOpChannelIt
typedef for const iterator on the set of available channels
Test serialization and deserialization of EHT capabilities IE.
void CheckSerializedByte(const Buffer &buffer, uint32_t position, uint8_t value)
Check that the given buffer contains the given value at the given position.
void DoRun() override
Implementation to actually run this TestCase.
HeCapabilities GetHeCapabilities() const
Generate the HE capabilities IE.
bool m_is2_4Ghz
whether the PHY is operating in 2.4 GHz
void CheckSupportedEhtMcsAndNssSet(const Buffer &buffer, uint8_t maxSupportedMcs)
Check the content of the Supported EHT-MCS And NSS Set subfield.
~WifiEhtCapabilitiesIeTest() override=default
Buffer SerializeIntoBuffer(const EhtCapabilities &ehtCapabilities)
Serialize the EHT capabilities in a buffer.
uint16_t m_channelWidth
Supported channel width by the PHY (in MHz)
EhtCapabilities GetEhtCapabilities(uint16_t maxMpduLength, uint32_t maxAmpduSize, uint8_t maxSupportedMcs) const
Generate the EHT capabilities IE.
void CheckEhtMacCapabilitiesInformation(const Buffer &buffer, uint8_t expectedValueFirstByte)
Check the content of the EHT MAC Capabilities Information subfield.
void CheckEhtPhyCapabilitiesInformation(const Buffer &buffer, uint8_t expectedValueSixthByte)
Check the content of the EHT PHY Capabilities Information subfield.
wifi EHT Information Elements Test Suite
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
uint16_t ReadLsbtohU16()
Definition: buffer.cc:1064
void Next()
go forward by one byte
Definition: buffer.h:853
automatically resized byte buffer
Definition: buffer.h:94
uint32_t GetSize() const
Definition: buffer.h:1068
void AddAtStart(uint32_t start)
Definition: buffer.cc:314
Buffer::Iterator Begin() const
Definition: buffer.h:1074
void SetEss()
Set the Extended Service Set (ESS) bit in the capability information field.
void SetShortSlotTime(bool shortSlotTime)
Set the short slot time bit in the capability information field.
void SetShortPreamble(bool shortPreamble)
Set the short preamble bit in the capability information field.
Buffer::Iterator Deserialize(Buffer::Iterator start)
Deserialize capability information from the given buffer.
The IEEE 802.11be EHT Capabilities.
void SetPpeThresholds(uint8_t nssPe, uint8_t ruIndexBitmask, const std::vector< std::pair< uint8_t, uint8_t > > &ppeThresholds)
Set the EHT PPE threshold info subfield.
void SetMaxMpduLength(uint16_t length)
Set the maximum MPDU length.
void SetSupportedTxEhtMcsAndNss(EhtMcsAndNssSet::EhtMcsMapType mapType, uint8_t upperMcs, uint8_t maxNss)
Set a subfield of the Supported EHT-MCS And NSS Set.
EhtPhyCapabilities m_phyCapabilities
EHT PHY Capabilities Info subfield.
uint8_t GetHighestSupportedTxMcs(EhtMcsAndNssSet::EhtMcsMapType mapType)
Get the highest supported TX MCS for a given EHT-MCS map type.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum A-MPDU length.
void SetSupportedRxEhtMcsAndNss(EhtMcsAndNssSet::EhtMcsMapType mapType, uint8_t upperMcs, uint8_t maxNss)
Set a subfield of the Supported EHT-MCS And NSS Set.
uint8_t GetHighestSupportedRxMcs(EhtMcsAndNssSet::EhtMcsMapType mapType)
Get the highest supported RX MCS for a given EHT-MCS map type.
EHT Operation Information Element.
Definition: eht-operation.h:66
void SetMaxTxNss(uint8_t maxNss, uint8_t mcsStart, uint8_t mcsEnd)
Set the max Tx NSS for input MCS index range.
void SetMaxRxNss(uint8_t maxNss, uint8_t mcsStart, uint8_t mcsEnd)
Set the max Rx NSS for input MCS index range.
EhtOpParams m_params
EHT Operation Parameters.
std::optional< EhtOpInfo > m_opInfo
EHT Operation Information.
The Extended Capabilities Information Element.
The Extended Supported Rates Information Element.
The IEEE 802.11ax HE Capabilities.
void SetChannelWidthSet(uint8_t channelWidthSet)
Set channel width set.
Subclass of TestCase class adding the ability to test the serialization and deserialization of a Head...
void TestHeaderSerialization(const T &hdr, Args &&... args)
Serialize the given header in a buffer, then create a new header by deserializing from the buffer and...
The HT Capabilities Information Element.
an EUI-48 address
Definition: mac48-address.h:46
Implement the header for management frames of type association request.
Definition: mgt-headers.h:157
CapabilityInformation & Capabilities()
Definition: mgt-headers.cc:193
void SetListenInterval(uint16_t interval)
Set the listen interval.
Definition: mgt-headers.cc:181
The IEEE 802.11 Non-Inheritance Information Element.
std::set< uint8_t > m_elemIdList
list of unique Element ID values (in increasing order)
bool IsPresent(uint8_t elemId, uint8_t elemIdExt=0) const
std::set< uint8_t > m_elemIdExtList
list of unique Element ID Extension values
The Reduced Neighbor Report element.
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
void SetMldParameters(std::size_t nbrApInfoId, std::size_t index, uint8_t mldId, uint8_t linkId, uint8_t changeSequence)
Set the MLD Parameters subfield of the i-th TBTT Information field of the given Neighbor AP Informati...
void SetShortSsid(std::size_t nbrApInfoId, std::size_t index, uint32_t shortSsid)
Set the Short SSID field of the i-th TBTT Information field of the given Neighbor AP Information fiel...
void SetBssid(std::size_t nbrApInfoId, std::size_t index, Mac48Address bssid)
Set the BSSID field of the i-th TBTT Information field of the given Neighbor AP Information field.
void SetPsd20MHz(std::size_t nbrApInfoId, std::size_t index, uint8_t psd20MHz)
Set the 20 MHz PSD field of the i-th TBTT Information field of the given Neighbor AP Information fiel...
void AddNbrApInfoField()
Add a Neighbor AP Information field.
void SetBssParameters(std::size_t nbrApInfoId, std::size_t index, uint8_t bssParameters)
Set the BSS Parameters field of the i-th TBTT Information field of the given Neighbor AP Information ...
void AddTbttInformationField(std::size_t nbrApInfoId)
Add a TBTT Information fields to the TBTT Information Set field of the given Neighbor AP Information ...
void SetOperatingChannel(std::size_t nbrApInfoId, const WifiPhyOperatingChannel &channel)
Set the Operating Class and the Channel Number fields of the given Neighbor AP Information field base...
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
The Supported Rates Information Element.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
The IEEE 802.11ac VHT Capabilities.
uint16_t GetSerializedSize() const
Get the size of the serialized IE including Element ID and length fields (for every element this IE i...
Buffer::Iterator Serialize(Buffer::Iterator i) const
Serialize entire IE including Element ID and length fields.
Buffer::Iterator DeserializeIfPresent(Buffer::Iterator i)
Deserialize entire IE (which may possibly be fragmented into multiple elements) if it is present.
Class that keeps track of all information about the current PHY operating channel.
static const std::set< FrequencyChannelInfo > m_frequencyChannels
Available frequency channels.
static ConstIterator FindFirst(uint8_t number, uint16_t frequency, uint16_t width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first channel matching the specified parameters.
std::set< FrequencyChannelInfo >::const_iterator ConstIterator
Typedef for a const iterator pointing to a channel in the set of available channels.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:145
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:957
#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:252
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
@ WIFI_STANDARD_80211be
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
Definition: wifi-phy-band.h:39
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
Definition: wifi-phy-band.h:35
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
WifiDirection
Wifi direction.
Definition: wifi-utils.h:43
std::map< uint8_t, std::set< uint8_t > > WifiTidLinkMapping
TID-indexed map of the link set to which the TID is mapped.
Definition: wifi-utils.h:74
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.
Struct containing all supported rates.
SupportedRates rates
supported rates
std::optional< ExtendedSupportedRatesIE > extendedRates
supported extended rates
void AddSupportedRate(uint64_t bs)
Add the given rate to the supported rates.
Medium Synchronization Delay Information subfield.
uint8_t mediumSyncDuration
Medium Synchronization Duration.
Common Info field of the Basic Multi-Link element.
std::optional< EmlCapabilities > m_emlCapabilities
EML Capabilities.
uint8_t Deserialize(Buffer::Iterator start, uint16_t presence)
Deserialize the Common Info field.
void SetMediumSyncOfdmEdThreshold(int8_t threshold)
Set the Medium Synchronization OFDM ED Threshold subfield of the Medium Synchronization Delay Informa...
std::optional< MediumSyncDelayInfo > m_mediumSyncDelayInfo
Medium Synchronization Delay Information.
void SetMediumSyncDelayTimer(Time delay)
Set the Medium Synchronization Duration subfield of the Medium Synchronization Delay Information in t...
Mac48Address m_mldMacAddress
Subfields.
std::optional< uint8_t > m_bssParamsChangeCount
BSS Parameters Change Count.
void SetMediumSyncMaxNTxops(uint8_t nTxops)
Set the Medium Synchronization Maximum Number of TXOPs subfield of the Medium Synchronization Delay I...
std::optional< uint8_t > m_linkIdInfo
Link ID Info.
EHT Operation Information subfield IEEE 802.11be D2.0 Figure 9-1002c.
EHT Operation Parameters subfield IEEE 802.11be D2.0 Figure 9-1002b.
Definition: eht-operation.h:73
uint8_t support320MhzIn6Ghz
Support For 320 MHz In 6 GHz.
uint8_t supportTx1024And4096QamForRuSmallerThan242Tones
Tx 1024-QAM And 4096-QAM < 242-tone RU Support.
uint8_t supportRx1024And4096QamForRuSmallerThan242Tones
Rx 1024-QAM And 4096-QAM < 242-tone RU Support.
static WifiEhtInfoElemsTestSuite g_wifiEhtInfoElemsTestSuite
the test suite
#define IE_EXT_EHT_CAPABILITIES
#define IE_EXTENSION
#define IE_EXT_MULTI_LINK_ELEMENT