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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
9#include "ns3/address-utils.h"
10#include "ns3/header-serialization-test.h"
11#include "ns3/log.h"
12#include "ns3/mgt-headers.h"
13#include "ns3/multi-link-element.h"
14#include "ns3/reduced-neighbor-report.h"
15#include "ns3/simulator.h"
16#include "ns3/tid-to-link-mapping-element.h"
17#include "ns3/wifi-phy-operating-channel.h"
18#include "ns3/wifi-utils.h"
19
20#include <optional>
21#include <set>
22#include <sstream>
23#include <vector>
24
25using namespace ns3;
26
27NS_LOG_COMPONENT_DEFINE("WifiEhtInfoElemsTest");
28
29/**
30 * @ingroup wifi-test
31 * @ingroup tests
32 *
33 * @brief Test Multi-Link Element (Basic variant) serialization and deserialization
34 */
36{
37 public:
38 /**
39 * Constructor
40 */
43
44 /**
45 * Get a Multi-Link Element including the given Common Info field and the
46 * given Per-STA Profile Subelements
47 *
48 * @param commonInfo the given Common Info field
49 * @param subelements the given set of Per-STA Profile Subelements
50 * @return a Multi-Link Element
51 */
53 const CommonInfoBasicMle& commonInfo,
54 std::vector<MultiLinkElement::PerStaProfileSubelement> subelements);
55
56 private:
57 void DoRun() override;
58
59 MgtAssocRequestHeader m_outerAssoc; //!< the frame containing the MLE
60};
61
64 "Check serialization and deserialization of Basic variant Multi-Link elements")
65{
66}
67
71
74 const CommonInfoBasicMle& commonInfo,
75 std::vector<MultiLinkElement::PerStaProfileSubelement> subelements)
76{
78 mle.SetMldMacAddress(commonInfo.m_mldMacAddress);
79 if (commonInfo.m_linkIdInfo.has_value())
80 {
81 mle.SetLinkIdInfo(*commonInfo.m_linkIdInfo);
82 }
83 if (commonInfo.m_bssParamsChangeCount.has_value())
84 {
86 }
87 if (commonInfo.m_mediumSyncDelayInfo.has_value())
88 {
90 MicroSeconds(32 * commonInfo.m_mediumSyncDelayInfo->mediumSyncDuration));
92 commonInfo.m_mediumSyncDelayInfo->mediumSyncOfdmEdThreshold - 72);
94 commonInfo.m_mediumSyncDelayInfo->mediumSyncMaxNTxops + 1);
95 }
96 if (commonInfo.m_emlCapabilities.has_value())
97 {
98 auto padding = commonInfo.m_emlCapabilities->emlsrPaddingDelay;
99 mle.SetEmlsrPaddingDelay(MicroSeconds(padding == 0 ? 0 : (1 << (4 + padding))));
100 auto transitionD = commonInfo.m_emlCapabilities->emlsrTransitionDelay;
101 mle.SetEmlsrTransitionDelay(MicroSeconds(transitionD == 0 ? 0 : (1 << (3 + transitionD))));
102 auto transitionT = commonInfo.m_emlCapabilities->transitionTimeout;
103 mle.SetTransitionTimeout(MicroSeconds(transitionT == 0 ? 0 : (1 << (6 + transitionT))));
104 }
105
106 for (std::size_t i = 0; i < subelements.size(); ++i)
107 {
109 mle.GetPerStaProfile(i) = std::move(subelements[i]);
110 }
111
112 return mle;
113}
114
115void
117{
118 CommonInfoBasicMle commonInfo = {
119 .m_mldMacAddress = Mac48Address("01:23:45:67:89:ab"),
120 };
121
122 // Common Info with MLD MAC address
124
125 commonInfo.m_linkIdInfo = 3;
126
127 // Adding Link ID Info
129
130 commonInfo.m_bssParamsChangeCount = 1;
131
132 // Adding BSS Parameters Change Count
134
135 commonInfo.m_mediumSyncDelayInfo =
137 .mediumSyncOfdmEdThreshold = 4,
138 .mediumSyncMaxNTxops = 5};
139
140 // Adding Medium Sync Delay Information
142
144 .emlsrPaddingDelay = 4,
145 .emlsrTransitionDelay = 5,
146 .transitionTimeout = 10};
147
148 // Adding Medium Sync Delay Information
150
151 /**
152 * To test the serialization/deserialization of Per-STA Profile subelements, we include
153 * the Multi-Link Element in an Association Request frame
154 */
155
156 CapabilityInformation capabilities;
157 capabilities.SetShortPreamble(true);
158 capabilities.SetShortSlotTime(true);
159 capabilities.SetEss();
160
162 m_outerAssoc.Capabilities() = capabilities;
163 m_outerAssoc.Get<Ssid>() = Ssid("MySsid");
164
165 AllSupportedRates rates;
166 rates.AddSupportedRate(6e6);
167 rates.AddSupportedRate(9e6);
168 rates.AddSupportedRate(12e6);
169 rates.AddSupportedRate(18e6);
170 rates.AddSupportedRate(24e6);
171 rates.AddSupportedRate(36e6);
172 rates.AddSupportedRate(48e6);
173 rates.AddSupportedRate(54e6);
174 // extended rates
175 rates.AddSupportedRate(1e6);
176 rates.AddSupportedRate(2e6);
177
178 m_outerAssoc.Get<SupportedRates>() = rates.rates;
180
181 EhtCapabilities ehtCapabilities;
182 for (auto maxMcs : {7, 9, 11, 13})
183 {
185 maxMcs,
186 1);
188 maxMcs,
189 1);
190 }
191
192 m_outerAssoc.Get<HeCapabilities>().emplace();
193 m_outerAssoc.Get<EhtCapabilities>() = ehtCapabilities;
194
195 // The Association Request included in the first Per-STA Profile subelement is identical
196 // to the containing frame, so that all the IEs are inherited and the Per-STA Profile
197 // does not contain any Information Element.
198
200 perStaProfile1.SetLinkId(3);
201 perStaProfile1.SetCompleteProfile();
202 perStaProfile1.SetAssocRequest(m_outerAssoc);
203
204 /* Association Request included in the second Per-STA Profile subelement */
206 assoc.Capabilities() = capabilities;
207 // we simulate a "mistake" by adding an Ssid IE, which cannot be included in the
208 // Per-STA Profile subelement. We will check that this Ssid is not serialized
209 assoc.Get<Ssid>() = Ssid("OtherSsid");
210 // another "mistake" of the same type, except that a TID-To-Link Mapping element
211 // is not included in the containing frame
212 assoc.Get<TidToLinkMapping>().emplace_back();
213 // the SupportedRates IE is the same (hence not serialized) as in the containing frame,
214 // while the ExtendedSupportedRatesIE is different (hence serialized)
215 rates.AddSupportedRate(5.5e6);
216 rates.AddSupportedRate(11e6);
217 assoc.Get<SupportedRates>() = rates.rates;
218 assoc.Get<ExtendedSupportedRatesIE>() = rates.extendedRates;
219 // a VhtCapabilities IE is not present in the containing frame, hence it is serialized
220 assoc.Get<VhtCapabilities>().emplace();
221 // HeCapabilities IE is present in the containing frame and in the Per-STA Profile subelement,
222 // hence it is not serialized
223 assoc.Get<HeCapabilities>().emplace();
224 // EhtCapabilities IE is present in the containing frame but not in the Per-STA Profile
225 // subelement, hence it is listed in a Non-Inheritance element
226
228 perStaProfile2.SetLinkId(0);
229 perStaProfile2.SetCompleteProfile();
230 perStaProfile2.SetStaMacAddress(Mac48Address("ba:98:76:54:32:10"));
231 perStaProfile2.SetAssocRequest(assoc);
232
233 // The Association Request included in the third Per-STA Profile subelement has the
234 // EHT Capabilities element (which is inherited and not serialized) but it does not have the
235 // Ssid element, which is not listed in the Non-Inheritance element because it shall not
236 // appear in a Per-STA Profile subelement.
237 assoc.Get<Ssid>().reset();
238 assoc.Get<EhtCapabilities>() = ehtCapabilities;
239
240 auto perStaProfile3 = perStaProfile2;
241 perStaProfile3.SetAssocRequest(assoc);
242
243 // Adding MLE with two Per-STA Profile Subelements
245 GetMultiLinkElement(commonInfo, {perStaProfile1, perStaProfile2, perStaProfile3});
246
247 // first, check that serialization/deserialization of the whole Association Request works
249
250 // now, "manually" serialize and deserialize the header to check that the expected elements
251 // have been serialized
252 Buffer buffer;
253 buffer.AddAtStart(m_outerAssoc.GetSerializedSize());
254 m_outerAssoc.Serialize(buffer.Begin());
255
256 auto i = buffer.Begin();
258 i.ReadLsbtohU16(); // Listen interval
259
260 auto tmp = i;
261 i = Ssid().DeserializeIfPresent(tmp);
262 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "Ssid element not present");
263
265 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "SupportedRates element not present");
266
268 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp),
269 0,
270 "ExtendedSupportedRatesIE element not present");
271
273 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "HeCapabilities element not present");
274
275 // deserialize Multi-Link Element
276 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(), IE_EXTENSION, "IE_EXTENSION expected at the begin of MLE");
277 i.ReadU8(); // length
278 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
280 "IE_EXT_MULTI_LINK_ELEMENT expected");
281
282 uint16_t mlControl = i.ReadLsbtohU16();
283 auto nBytes = CommonInfoBasicMle().Deserialize(i, mlControl >> 4);
284 i.Next(nBytes);
285
286 // first Per-STA Profile subelement
287 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
289 "PER_STA_PROFILE_SUBELEMENT_ID expected");
290 i.ReadU8(); // length
291 i.ReadLsbtohU16(); // STA Control field
292 i.ReadU8(); // STA Info Length
293 // no STA address
295 // no Information Element
296
297 // second 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 Mac48Address address;
305 ReadFrom(i, address);
307 // no Listen interval
308 // Ssid element not present (as mandated by specs)
309 // SupportedRates not present because it is inherited
310
312 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp),
313 0,
314 "ExtendedSupportedRatesIE element not present");
315
317 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "VhtCapabilities element not present");
318
319 // HeCapabilities not present because it is inherited
320 NonInheritance nonInheritance;
321 i = nonInheritance.DeserializeIfPresent(tmp = i);
322 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "Non-Inheritance element not present");
324 true,
325 "Non-Inheritance does not indicate EhtCapabilities");
326 NS_TEST_EXPECT_MSG_EQ(nonInheritance.m_elemIdList.size(),
327 0,
328 "Unexpected size for Elem ID list of Non-Inheritance element");
329 NS_TEST_EXPECT_MSG_EQ(nonInheritance.m_elemIdExtList.size(),
330 1,
331 "Unexpected size for Elem ID list of Non-Inheritance element");
332
333 // third Per-STA Profile subelement
334 NS_TEST_EXPECT_MSG_EQ(i.ReadU8(),
336 "PER_STA_PROFILE_SUBELEMENT_ID expected");
337 i.ReadU8(); // length
338 i.ReadLsbtohU16(); // STA Control field
339 i.ReadU8(); // STA Info Length
340 ReadFrom(i, address);
342 // no Listen interval
343 // Ssid element not present (as mandated by specs)
344 // SupportedRates not present because it is inherited
345
347 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp),
348 0,
349 "ExtendedSupportedRatesIE element not present");
350
352 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "VhtCapabilities element not present");
353
354 // HeCapabilities not present because it is inherited
355 // EhtCapabilities not present because it is inherited
356
357 // the Multi-Link Element is done, we shall now find the EHT Capabilities of the
358 // containing Association Request frame
359 ehtCapabilities = EhtCapabilities(true, m_outerAssoc.Get<HeCapabilities>().value());
360 i = ehtCapabilities.DeserializeIfPresent(tmp = i);
361 NS_TEST_EXPECT_MSG_GT(i.GetDistanceFrom(tmp), 0, "EhtCapabilities element not present");
362
363 /**
364 * Yet another test: use the Deserialize method of the management frame and check that
365 * inherited Information Elements have been copied
366 */
368 auto count = frame.Deserialize(buffer.Begin());
369
370 NS_TEST_EXPECT_MSG_EQ(count, buffer.GetSize(), "Unexpected number of deserialized bytes");
371
372 // containing frame
373 NS_TEST_EXPECT_MSG_EQ(frame.Get<Ssid>().has_value(),
374 true,
375 "Containing frame should have SSID IE");
376 NS_TEST_EXPECT_MSG_EQ(frame.Get<SupportedRates>().has_value(),
377 true,
378 "Containing frame should have Supported Rates IE");
379 NS_TEST_EXPECT_MSG_EQ(frame.Get<ExtendedSupportedRatesIE>().has_value(),
380 true,
381 "Containing frame should have Extended Supported Rates IE");
382 NS_TEST_EXPECT_MSG_EQ(frame.Get<HtCapabilities>().has_value(),
383 false,
384 "Containing frame should not have HT Capabilities IE");
385 NS_TEST_EXPECT_MSG_EQ(frame.Get<ExtendedCapabilities>().has_value(),
386 false,
387 "Containing frame should not have Extended Capabilities IE");
388 NS_TEST_EXPECT_MSG_EQ(frame.Get<VhtCapabilities>().has_value(),
389 false,
390 "Containing frame should not have VHT Capabilities IE");
391 NS_TEST_EXPECT_MSG_EQ(frame.Get<HeCapabilities>().has_value(),
392 true,
393 "Containing frame should have HE Capabilities IE");
394 NS_TEST_EXPECT_MSG_EQ(frame.Get<MultiLinkElement>().has_value(),
395 true,
396 "Containing frame should have Multi-Link Element IE");
397 NS_TEST_EXPECT_MSG_EQ(frame.Get<EhtCapabilities>().has_value(),
398 true,
399 "Containing frame should have EHT Capabilities IE");
400 NS_TEST_EXPECT_MSG_EQ(frame.Get<TidToLinkMapping>().empty(),
401 true,
402 "Containing frame should not have TID-to-Link Mapping IE");
403
404 auto& mle = frame.Get<MultiLinkElement>().value();
405
406 NS_TEST_EXPECT_MSG_EQ(mle.GetNPerStaProfileSubelements(),
407 3,
408 "Unexpected number of Per-STA Profile subelements");
409
410 // frame in first Per-STA Profile subelement has inherited all the IEs but SSID and
411 // Multi-Link Element IEs
412 auto& perSta1 = mle.GetPerStaProfile(0);
413 NS_TEST_EXPECT_MSG_EQ(perSta1.HasAssocRequest(),
414 true,
415 "First Per-STA Profile should contain an Association Request frame");
416 auto& perSta1Frame =
417 std::get<std::reference_wrapper<MgtAssocRequestHeader>>(perSta1.GetAssocRequest()).get();
418
419 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<Ssid>().has_value(),
420 false,
421 "Frame in first Per-STA Profile should not have SSID IE");
422 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<SupportedRates>().has_value(),
423 true,
424 "Frame in first Per-STA Profile should have Supported Rates IE");
426 (perSta1Frame.Get<SupportedRates>() == frame.Get<SupportedRates>()),
427 true,
428 "Supported Rates IE not correctly inherited by frame in first Per-STA Profile");
429 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<ExtendedSupportedRatesIE>().has_value(),
430 true,
431 "Frame in first Per-STA Profile should have Extended Supported Rates IE");
433 (perSta1Frame.Get<ExtendedSupportedRatesIE>() == frame.Get<ExtendedSupportedRatesIE>()),
434 true,
435 "Extended Supported Rates IE not correctly inherited by frame in first Per-STA Profile");
436 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<HtCapabilities>().has_value(),
437 false,
438 "Frame in first Per-STA Profile should not have HT Capabilities IE");
440 perSta1Frame.Get<ExtendedCapabilities>().has_value(),
441 false,
442 "Frame in first Per-STA Profile should not have Extended Capabilities IE");
443 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<VhtCapabilities>().has_value(),
444 false,
445 "Frame in first Per-STA Profile should not have VHT Capabilities IE");
446 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<HeCapabilities>().has_value(),
447 true,
448 "Frame in first Per-STA Profile should have HE Capabilities IE");
450 (perSta1Frame.Get<HeCapabilities>() == frame.Get<HeCapabilities>()),
451 true,
452 "HE Capabilities IE not correctly inherited by frame in first Per-STA Profile");
453 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<MultiLinkElement>().has_value(),
454 false,
455 "Frame in first Per-STA Profile should not have Multi-Link Element IE");
456 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<EhtCapabilities>().has_value(),
457 true,
458 "Frame in first Per-STA Profile should have EHT Capabilities IE");
460 (perSta1Frame.Get<EhtCapabilities>() == frame.Get<EhtCapabilities>()),
461 true,
462 "EHT Capabilities IE not correctly inherited by frame in first Per-STA Profile");
463 NS_TEST_EXPECT_MSG_EQ(perSta1Frame.Get<TidToLinkMapping>().empty(),
464 true,
465 "Frame in first Per-STA Profile should not have TID-to-Link Mapping IE");
466
467 // frame in second Per-STA Profile subelement includes VHT Capabilities IE and has inherited
468 // all the IEs but SSID IE, Multi-Link Element IE, Extended Supported Rates IE (different
469 // than in containing frame) and EHT Capabilities IE (listed in Non-Inheritance IE).
470 auto& perSta2 = mle.GetPerStaProfile(1);
471 NS_TEST_EXPECT_MSG_EQ(perSta2.HasAssocRequest(),
472 true,
473 "Second Per-STA Profile should contain an Association Request frame");
474 auto& perSta2Frame =
475 std::get<std::reference_wrapper<MgtAssocRequestHeader>>(perSta2.GetAssocRequest()).get();
476
477 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<Ssid>().has_value(),
478 false,
479 "Frame in second Per-STA Profile should not have SSID IE");
480 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<SupportedRates>().has_value(),
481 true,
482 "Frame in second Per-STA Profile should have Supported Rates IE");
484 (perSta2Frame.Get<SupportedRates>() == frame.Get<SupportedRates>()),
485 true,
486 "Supported Rates IE not correctly inherited by frame in second Per-STA Profile");
488 perSta2Frame.Get<ExtendedSupportedRatesIE>().has_value(),
489 true,
490 "Frame in second Per-STA Profile should have Extended Supported Rates IE");
492 (perSta2Frame.Get<ExtendedSupportedRatesIE>() == frame.Get<ExtendedSupportedRatesIE>()),
493 false,
494 "Extended Supported Rates IE should have not been inherited by frame in second Per-STA "
495 "Profile");
496 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<HtCapabilities>().has_value(),
497 false,
498 "Frame in second Per-STA Profile should not have HT Capabilities IE");
500 perSta2Frame.Get<ExtendedCapabilities>().has_value(),
501 false,
502 "Frame in second Per-STA Profile should not have Extended Capabilities IE");
503 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<VhtCapabilities>().has_value(),
504 true,
505 "Frame in second Per-STA Profile should have VHT Capabilities IE");
506 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<HeCapabilities>().has_value(),
507 true,
508 "Frame in second Per-STA Profile should have HE Capabilities IE");
510 (perSta2Frame.Get<HeCapabilities>() == frame.Get<HeCapabilities>()),
511 true,
512 "HE Capabilities IE not correctly inherited by frame in second Per-STA Profile");
513 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<MultiLinkElement>().has_value(),
514 false,
515 "Frame in second Per-STA Profile should not have Multi-Link Element IE");
517 perSta2Frame.Get<EhtCapabilities>().has_value(),
518 false,
519 "Frame in second Per-STA Profile should have not inherited EHT Capabilities IE");
520 NS_TEST_EXPECT_MSG_EQ(perSta2Frame.Get<TidToLinkMapping>().empty(),
521 true,
522 "Frame in second Per-STA Profile should not have TID-to-Link Mapping IE");
523
524 // frame in third Per-STA Profile subelement includes VHT Capabilities IE and has inherited
525 // all the IEs but SSID IE, Multi-Link Element IE and Extended Supported Rates IE (different
526 // than in containing frame).
527 auto& perSta3 = mle.GetPerStaProfile(2);
528 NS_TEST_EXPECT_MSG_EQ(perSta3.HasAssocRequest(),
529 true,
530 "Third Per-STA Profile should contain an Association Request frame");
531 auto& perSta3Frame =
532 std::get<std::reference_wrapper<MgtAssocRequestHeader>>(perSta3.GetAssocRequest()).get();
533
534 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<Ssid>().has_value(),
535 false,
536 "Frame in third Per-STA Profile should not have SSID IE");
537 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<SupportedRates>().has_value(),
538 true,
539 "Frame in third Per-STA Profile should have Supported Rates IE");
541 (perSta3Frame.Get<SupportedRates>() == frame.Get<SupportedRates>()),
542 true,
543 "Supported Rates IE not correctly inherited by frame in third Per-STA Profile");
544 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<ExtendedSupportedRatesIE>().has_value(),
545 true,
546 "Frame in third Per-STA Profile should have Extended Supported Rates IE");
548 (perSta3Frame.Get<ExtendedSupportedRatesIE>() == frame.Get<ExtendedSupportedRatesIE>()),
549 false,
550 "Extended Supported Rates IE should have not been inherited by frame in third Per-STA "
551 "Profile");
552 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<HtCapabilities>().has_value(),
553 false,
554 "Frame in third Per-STA Profile should not have HT Capabilities IE");
556 perSta3Frame.Get<ExtendedCapabilities>().has_value(),
557 false,
558 "Frame in third Per-STA Profile should not have Extended Capabilities IE");
559 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<VhtCapabilities>().has_value(),
560 true,
561 "Frame in third Per-STA Profile should have VHT Capabilities IE");
562 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<HeCapabilities>().has_value(),
563 true,
564 "Frame in third Per-STA Profile should have HE Capabilities IE");
566 (perSta3Frame.Get<HeCapabilities>() == frame.Get<HeCapabilities>()),
567 true,
568 "HE Capabilities IE not correctly inherited by frame in third Per-STA Profile");
569 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<MultiLinkElement>().has_value(),
570 false,
571 "Frame in third Per-STA Profile should not have Multi-Link Element IE");
573 perSta3Frame.Get<EhtCapabilities>().has_value(),
574 true,
575 "Frame in third Per-STA Profile should have inherited EHT Capabilities IE");
577 (perSta3Frame.Get<EhtCapabilities>() == frame.Get<EhtCapabilities>()),
578 true,
579 "EHT Capabilities IE not correctly inherited by frame in third Per-STA Profile");
580 NS_TEST_EXPECT_MSG_EQ(perSta3Frame.Get<TidToLinkMapping>().empty(),
581 true,
582 "Frame in third Per-STA Profile should not have TID-to-Link Mapping IE");
583}
584
585/**
586 * @ingroup wifi-test
587 * @ingroup tests
588 *
589 * @brief Test Reduced Neighbor Report serialization and deserialization
590 */
592{
593 public:
594 /**
595 * Constructor
596 */
599
600 /// typedef for const iterator on the set of available channels
602
603 /**
604 * Get a Reduced Neighbor Report element including the given operating channels
605 *
606 * @param channel2_4It a channel in the 2.4 GHz band
607 * @param channel5It a channel in the 5 GHz band
608 * @param channel6It a channel in the 6 GHz band
609 * @return a Reduced Neighbor Report element
610 */
612 PhyOpChannelIt channel5It,
613 PhyOpChannelIt channel6It);
614
615 private:
616 void DoRun() override;
617};
618
621 "Check serialization and deserialization of Reduced Neighbor Report elements")
622{
623}
624
628
631 PhyOpChannelIt channel5It,
632 PhyOpChannelIt channel6It)
633{
635
636 std::stringstream info;
637
638 if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
639 {
640 WifiPhyOperatingChannel channel(channel2_4It);
641
642 info << "{Ch=" << +channel.GetNumber() << ", Bw=" << channel.GetWidth() << ", 2.4 GHz} ";
643 rnr.AddNbrApInfoField();
644 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
645 rnr.SetOperatingChannel(nbrId, channel);
646 // Add a TBTT Information Field
647 rnr.AddTbttInformationField(nbrId);
648 rnr.SetBssid(nbrId, 0, Mac48Address("00:00:00:00:00:24"));
649 rnr.SetShortSsid(nbrId, 0, 0);
650 rnr.SetBssParameters(nbrId, 0, 10);
651 rnr.SetPsd20MHz(nbrId, 0, 50);
652 rnr.SetMldParameters(nbrId, 0, 0, 2, 3);
653 }
654
655 if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
656 {
657 WifiPhyOperatingChannel channel(channel5It);
658
659 info << "{Ch=" << +channel.GetNumber() << ", Bw=" << channel.GetWidth() << ", 5 GHz} ";
660 rnr.AddNbrApInfoField();
661 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
662 rnr.SetOperatingChannel(nbrId, channel);
663 // Add a TBTT Information Field
664 rnr.AddTbttInformationField(nbrId);
665 rnr.SetBssid(nbrId, 0, Mac48Address("00:00:00:00:00:05"));
666 rnr.SetShortSsid(nbrId, 0, 0);
667 rnr.SetBssParameters(nbrId, 0, 20);
668 rnr.SetPsd20MHz(nbrId, 0, 60);
669 rnr.SetMldParameters(nbrId, 0, 0, 3, 4);
670 // Add another TBTT Information Field
671 rnr.AddTbttInformationField(nbrId);
672 rnr.SetBssid(nbrId, 1, Mac48Address("00:00:00:00:01:05"));
673 rnr.SetShortSsid(nbrId, 1, 0);
674 rnr.SetBssParameters(nbrId, 1, 30);
675 rnr.SetPsd20MHz(nbrId, 1, 70);
676 rnr.SetMldParameters(nbrId, 1, 0, 4, 5);
677 }
678
679 if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
680 {
681 WifiPhyOperatingChannel channel(channel6It);
682
683 info << "{Ch=" << +channel.GetNumber() << ", Bw=" << channel.GetWidth() << ", 6 GHz} ";
684 rnr.AddNbrApInfoField();
685 std::size_t nbrId = rnr.GetNNbrApInfoFields() - 1;
686 rnr.SetOperatingChannel(nbrId, channel);
687 // Add a TBTT Information Field
688 rnr.AddTbttInformationField(nbrId);
689 rnr.SetBssid(nbrId, 0, Mac48Address("00:00:00:00:00:06"));
690 rnr.SetShortSsid(nbrId, 0, 0);
691 rnr.SetBssParameters(nbrId, 0, 40);
692 rnr.SetPsd20MHz(nbrId, 0, 80);
693 rnr.SetMldParameters(nbrId, 0, 0, 5, 6);
694 }
695
696 NS_LOG_DEBUG(info.str());
697 return rnr;
698}
699
700void
702{
703 PhyOpChannelIt channel2_4It;
704 PhyOpChannelIt channel5It;
705 PhyOpChannelIt channel6It;
706 channel2_4It = channel5It = channel6It = WifiPhyOperatingChannel::m_frequencyChannels.cbegin();
707
708 // Test all available frequency channels
709 while (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend() ||
712 {
713 if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
714 {
715 channel2_4It = WifiPhyOperatingChannel::FindFirst(0,
716 0,
717 0,
720 channel2_4It);
721 }
722 if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
723 {
725 0,
726 0,
729 channel5It);
730 }
731 if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
732 {
734 0,
735 0,
738 channel6It);
739 }
740
741 TestHeaderSerialization(GetReducedNeighborReport(channel2_4It, channel5It, channel6It));
742
743 // advance all channel iterators
744 if (channel2_4It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
745 {
746 channel2_4It++;
747 }
748 if (channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
749 {
750 channel5It++;
751 }
752 if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
753 {
754 channel6It++;
755 }
756 }
757}
758
759/**
760 * @ingroup wifi-test
761 * @ingroup tests
762 *
763 * @brief Test serialization and deserialization of EHT capabilities IE
764 */
766{
767 public:
768 /**
769 * Constructor
770 * @param is2_4Ghz whether the PHY is operating in 2.4 GHz
771 * @param channelWidth the supported channel width
772 */
773 WifiEhtCapabilitiesIeTest(bool is2_4Ghz, MHz_u channelWidth);
774 ~WifiEhtCapabilitiesIeTest() override = default;
775
776 /**
777 * Generate the HE capabilities IE.
778 *
779 * @return the generated HE capabilities IE
780 */
782
783 /**
784 * Generate the EHT capabilities IE.
785 *
786 * @param maxMpduLength the maximum MPDU length in bytes
787 * @param maxAmpduSize the maximum A-MPDU size in bytes
788 * @param maxSupportedMcs the maximum EHT MCS supported by the PHY
789 * @return the generated EHT capabilities IE
790 */
791 EhtCapabilities GetEhtCapabilities(uint16_t maxMpduLength,
792 uint32_t maxAmpduSize,
793 uint8_t maxSupportedMcs) const;
794
795 /**
796 * Serialize the EHT capabilities in a buffer.
797 *
798 * @param ehtCapabilities the EHT capabilities
799 * @return the buffer in which the EHT capabilities has been serialized
800 */
801 Buffer SerializeIntoBuffer(const EhtCapabilities& ehtCapabilities);
802
803 /**
804 * Check that the given buffer contains the given value at the given position.
805 *
806 * @param buffer the given buffer
807 * @param position the given position (starting at 0)
808 * @param value the given value
809 */
810 void CheckSerializedByte(const Buffer& buffer, uint32_t position, uint8_t value);
811
812 /**
813 * Check the content of the EHT MAC Capabilities Information subfield.
814 *
815 * @param buffer the buffer containing the serialized EHT capabilities
816 * @param expectedValueFirstByte the expected value for the first byte
817 */
818 void CheckEhtMacCapabilitiesInformation(const Buffer& buffer, uint8_t expectedValueFirstByte);
819
820 /**
821 * Check the content of the EHT PHY Capabilities Information subfield.
822 *
823 * @param buffer the buffer containing the serialized EHT capabilities
824 * @param expectedValueSixthByte the expected value for the sixth byte
825 */
826 void CheckEhtPhyCapabilitiesInformation(const Buffer& buffer, uint8_t expectedValueSixthByte);
827
828 /**
829 * Check the content of the Supported EHT-MCS And NSS Set subfield.
830 * @param maxSupportedMcs the maximum EHT MCS supported by the PHY
831 *
832 * @param buffer the buffer containing the serialized EHT capabilities
833 */
834 void CheckSupportedEhtMcsAndNssSet(const Buffer& buffer, uint8_t maxSupportedMcs);
835
836 private:
837 void DoRun() override;
838
839 bool m_is2_4Ghz; //!< whether the PHY is operating in 2.4 GHz
840 MHz_u m_channelWidth; //!< Supported channel width by the PHY
841};
842
843WifiEhtCapabilitiesIeTest ::WifiEhtCapabilitiesIeTest(bool is2_4Ghz, MHz_u channelWidth)
844 : HeaderSerializationTestCase{"Check serialization and deserialization of EHT capabilities IE"},
845 m_is2_4Ghz{is2_4Ghz},
846 m_channelWidth{channelWidth}
847{
848}
849
852{
853 HeCapabilities capabilities;
854 uint8_t channelWidthSet = 0;
855 if ((m_channelWidth >= 40) && m_is2_4Ghz)
856 {
857 channelWidthSet |= 0x01;
858 }
859 if ((m_channelWidth >= 80) && !m_is2_4Ghz)
860 {
861 channelWidthSet |= 0x02;
862 }
863 if ((m_channelWidth >= 160) && !m_is2_4Ghz)
864 {
865 channelWidthSet |= 0x04;
866 }
867 capabilities.SetChannelWidthSet(channelWidthSet);
868 return capabilities;
869}
870
873 uint32_t maxAmpduSize,
874 uint8_t maxSupportedMcs) const
875{
876 EhtCapabilities capabilities;
877
878 if (m_is2_4Ghz)
879 {
880 capabilities.SetMaxMpduLength(maxMpduLength);
881 }
882 // round to the next power of two minus one
883 maxAmpduSize = (1UL << static_cast<uint32_t>(std::ceil(std::log2(maxAmpduSize + 1)))) - 1;
884 // The maximum A-MPDU length in EHT capabilities elements ranges from 2^23-1 to 2^24-1
885 capabilities.SetMaxAmpduLength(std::min(std::max(maxAmpduSize, 8388607U), 16777215U));
886
888 (maxSupportedMcs >= 12) ? 1 : 0;
890 (maxSupportedMcs >= 12) ? 1 : 0;
891 if (m_channelWidth == 20)
892 {
893 for (auto maxMcs : {7, 9, 11, 13})
894 {
896 maxMcs,
897 maxMcs <= maxSupportedMcs ? 1 : 0);
899 maxMcs,
900 maxMcs <= maxSupportedMcs ? 2 : 0);
901 }
902 }
903 else
904 {
905 for (auto maxMcs : {9, 11, 13})
906 {
907 capabilities.SetSupportedRxEhtMcsAndNss(
909 maxMcs,
910 maxMcs <= maxSupportedMcs ? 3 : 0);
911 capabilities.SetSupportedTxEhtMcsAndNss(
913 maxMcs,
914 maxMcs <= maxSupportedMcs ? 4 : 0);
915 }
916 }
917 if (m_channelWidth >= 160)
918 {
919 for (auto maxMcs : {9, 11, 13})
920 {
922 maxMcs,
923 maxMcs <= maxSupportedMcs ? 2 : 0);
925 maxMcs,
926 maxMcs <= maxSupportedMcs ? 1 : 0);
927 }
928 }
929 if (m_channelWidth == 320)
930 {
931 capabilities.m_phyCapabilities.support320MhzIn6Ghz = 1;
932 for (auto maxMcs : {9, 11, 13})
933 {
935 maxMcs,
936 maxMcs <= maxSupportedMcs ? 4 : 0);
938 maxMcs,
939 maxMcs <= maxSupportedMcs ? 3 : 0);
940 }
941 }
942 else
943 {
944 capabilities.m_phyCapabilities.support320MhzIn6Ghz = 0;
945 }
946
947 return capabilities;
948}
949
950Buffer
952{
953 Buffer buffer;
954 buffer.AddAtStart(ehtCapabilities.GetSerializedSize());
955 ehtCapabilities.Serialize(buffer.Begin());
956 return buffer;
957}
958
959void
961 uint32_t position,
962 uint8_t value)
963{
964 Buffer::Iterator it = buffer.Begin();
965 it.Next(position);
966 uint8_t byte = it.ReadU8();
967 NS_TEST_EXPECT_MSG_EQ(+byte, +value, "Unexpected byte at pos=" << position);
968}
969
970void
972 uint8_t expectedValueFirstByte)
973{
974 CheckSerializedByte(buffer, 3, expectedValueFirstByte);
975 CheckSerializedByte(buffer, 4, 0x00);
976}
977
978void
980 uint8_t expectedValueSixthByte)
981{
982 CheckSerializedByte(buffer, 5, (m_channelWidth == 320) ? 0x02 : 0x00);
983 CheckSerializedByte(buffer, 6, 0x00);
984 CheckSerializedByte(buffer, 7, 0x00);
985 CheckSerializedByte(buffer, 8, 0x00);
986 CheckSerializedByte(buffer, 9, 0x00);
987 CheckSerializedByte(buffer, 10, expectedValueSixthByte);
988 CheckSerializedByte(buffer, 11, 0x00);
989 CheckSerializedByte(buffer, 12, 0x00);
990 CheckSerializedByte(buffer, 13, 0x00);
991}
992
993void
995 uint8_t maxSupportedMcs)
996{
997 if (m_channelWidth == 20)
998 {
999 CheckSerializedByte(buffer, 14, 0x21); // first byte of Supported EHT-MCS And NSS Set
1001 buffer,
1002 15,
1003 maxSupportedMcs >= 8 ? 0x21 : 0x00); // second byte of Supported EHT-MCS And NSS Set
1005 buffer,
1006 16,
1007 maxSupportedMcs >= 10 ? 0x21 : 0x00); // third byte of Supported EHT-MCS And NSS Set
1009 buffer,
1010 17,
1011 maxSupportedMcs >= 12 ? 0x21 : 0x00); // fourth byte of Supported EHT-MCS And NSS Set
1012 }
1013 else
1014 {
1015 CheckSerializedByte(buffer, 14, 0x43); // first byte of Supported EHT-MCS And NSS Set
1017 buffer,
1018 15,
1019 maxSupportedMcs >= 10 ? 0x43 : 0x00); // second byte of Supported EHT-MCS And NSS Set
1021 buffer,
1022 16,
1023 maxSupportedMcs >= 12 ? 0x43 : 0x00); // third byte of Supported EHT-MCS And NSS Set
1024 }
1025 if (m_channelWidth >= 160)
1026 {
1027 CheckSerializedByte(buffer, 17, 0x12); // first byte of EHT-MCS Map (BW = 160 MHz)
1029 buffer,
1030 18,
1031 maxSupportedMcs >= 10 ? 0x12 : 0x00); // second byte of EHT-MCS Map (BW = 160 MHz)
1033 buffer,
1034 19,
1035 maxSupportedMcs >= 12 ? 0x12 : 0x00); // third byte of EHT-MCS Map (BW = 160 MHz)
1036 }
1037 if (m_channelWidth == 320)
1038 {
1039 CheckSerializedByte(buffer, 20, 0x34); // first byte of EHT-MCS Map (BW = 320 MHz)
1041 buffer,
1042 21,
1043 maxSupportedMcs >= 10 ? 0x34 : 0x00); // second byte of EHT-MCS Map (BW = 320 MHz)
1045 buffer,
1046 22,
1047 maxSupportedMcs >= 12 ? 0x34 : 0x00); // third byte of EHT-MCS Map (BW = 320 MHz)
1048 }
1049}
1050
1051void
1053{
1054 uint8_t maxMcs = 0;
1055 uint16_t expectedEhtMcsAndNssSetSize = 0;
1056 switch (static_cast<uint16_t>(m_channelWidth))
1057 {
1058 case 20:
1059 expectedEhtMcsAndNssSetSize = 4;
1060 break;
1061 case 40:
1062 case 80:
1063 expectedEhtMcsAndNssSetSize = 3;
1064 break;
1065 case 160:
1066 expectedEhtMcsAndNssSetSize = (2 * 3);
1067 break;
1068 case 320:
1069 expectedEhtMcsAndNssSetSize = (3 * 3);
1070 break;
1071 default:
1072 NS_ASSERT_MSG(false, "Invalid upper channel width " << m_channelWidth);
1073 }
1074
1075 uint16_t expectedSize = 1 + // Element ID
1076 1 + // Length
1077 1 + // Element ID Extension
1078 2 + // EHT MAC Capabilities Information
1079 9 + // EHT PHY Capabilities Information
1080 expectedEhtMcsAndNssSetSize; // Supported EHT-MCS And NSS Set
1081
1084
1085 {
1086 maxMcs = 11;
1087 HeCapabilities heCapabilities = GetHeCapabilities();
1088 EhtCapabilities ehtCapabilities = GetEhtCapabilities(3895, 65535, maxMcs);
1089
1090 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1091 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1092
1093 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1094 expectedSize,
1095 "Unexpected header size");
1096
1097 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1098
1100
1102
1103 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1104
1105 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1106 }
1107
1108 {
1109 maxMcs = 11;
1110 HeCapabilities heCapabilities = GetHeCapabilities();
1111 EhtCapabilities ehtCapabilities = GetEhtCapabilities(11454, 65535, maxMcs);
1112
1113 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1114 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1115
1116 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1117 expectedSize,
1118 "Unexpected header size");
1119
1120 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1121
1122 CheckEhtMacCapabilitiesInformation(buffer, m_is2_4Ghz ? 0x80 : 0x00);
1123
1125
1126 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1127
1128 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1129 }
1130
1131 {
1132 maxMcs = 13;
1133 HeCapabilities heCapabilities = GetHeCapabilities();
1134 EhtCapabilities ehtCapabilities = GetEhtCapabilities(3895, 65535, maxMcs);
1135
1136 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1137 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1138
1139 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1140 expectedSize,
1141 "Unexpected header size");
1142
1143 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1144
1146
1148
1149 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1150
1151 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1152 }
1153
1154 {
1155 maxMcs = 11;
1156 HeCapabilities heCapabilities = GetHeCapabilities();
1157 EhtCapabilities ehtCapabilities = GetEhtCapabilities(3895, 65535, maxMcs);
1158
1159 NS_ASSERT(ehtCapabilities.GetHighestSupportedRxMcs(mapType) == maxMcs);
1160 NS_ASSERT(ehtCapabilities.GetHighestSupportedTxMcs(mapType) == maxMcs);
1161
1162 std::vector<std::pair<uint8_t, uint8_t>> ppeThresholds;
1163 ppeThresholds.emplace_back(1, 2); // NSS1 242-tones RU
1164 ppeThresholds.emplace_back(2, 3); // NSS1 484-tones RU
1165 ppeThresholds.emplace_back(3, 4); // NSS2 242-tones RU
1166 ppeThresholds.emplace_back(4, 3); // NSS2 484-tones RU
1167 ppeThresholds.emplace_back(3, 2); // NSS3 242-tones RU
1168 ppeThresholds.emplace_back(2, 1); // NSS3 484-tones RU
1169 ehtCapabilities.SetPpeThresholds(2, 0x03, ppeThresholds);
1170
1171 expectedSize += 6;
1172
1173 NS_TEST_EXPECT_MSG_EQ(ehtCapabilities.GetSerializedSize(),
1174 expectedSize,
1175 "Unexpected header size");
1176
1177 Buffer buffer = SerializeIntoBuffer(ehtCapabilities);
1178
1180
1182
1183 CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1184
1185 TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1186 }
1187}
1188
1189/**
1190 * @ingroup wifi-test
1191 * @ingroup tests
1192 *
1193 * @brief Test TID-To-Link Mapping information element serialization and deserialization
1194 */
1196{
1197 public:
1198 /**
1199 * Constructor
1200 *
1201 * @param direction The direction for the TID-to-link mapping
1202 * @param mappingSwitchTime the Mapping Switching Time
1203 * @param expectedDuration the Expected Duration
1204 * @param mappings A TID-indexed map of the link sets the TIDs are mapped to
1205 */
1207 std::optional<Time> mappingSwitchTime,
1208 std::optional<Time> expectedDuration,
1209 const WifiTidLinkMapping& mappings);
1210
1211 ~TidToLinkMappingElementTest() override = default;
1212
1213 private:
1214 void DoSetup() override;
1215 void DoRun() override;
1216
1217 WifiDirection m_direction; ///< the direction for the TID-to-link mapping
1218 std::optional<Time> m_mappingSwitchTime; ///< the Mapping Switching Time
1219 std::optional<Time> m_expectedDuration; ///< the Expected Duration
1220 WifiTidLinkMapping m_mappings; ///< maps TIDs to link sets
1221 TidToLinkMapping m_tidToLinkMapping; ///< TID-To-Link Mapping element
1222};
1223
1225 std::optional<Time> mappingSwitchTime,
1226 std::optional<Time> expectedDuration,
1227 const WifiTidLinkMapping& mappings)
1229 "Check serialization and deserialization of TID-To-Link Mapping elements"),
1230 m_direction(direction),
1231 m_mappingSwitchTime(mappingSwitchTime),
1232 m_expectedDuration(expectedDuration),
1233 m_mappings(mappings)
1234{
1235}
1236
1237void
1239{
1242
1244 {
1246 std::optional<Time> encoded = m_tidToLinkMapping.GetMappingSwitchTime();
1247 NS_TEST_ASSERT_MSG_EQ(encoded.has_value(), true, "Mapping Switch Time should be present");
1249 *encoded,
1250 "Incorrect Mapping Switch Time value");
1251 }
1253 {
1255 std::optional<Time> encoded = m_tidToLinkMapping.GetExpectedDuration();
1256 NS_TEST_ASSERT_MSG_EQ(encoded.has_value(), true, "Expected Duration should be present");
1257 NS_TEST_EXPECT_MSG_EQ(*m_expectedDuration, *encoded, "Incorrect Expected Duration value");
1258 }
1259
1260 for (const auto& [tid, linkSet] : m_mappings)
1261 {
1265 true,
1266 "Incorrect link set for TID " << +tid);
1267 }
1268}
1269
1270void
1277
1278/**
1279 * @ingroup wifi-test
1280 * @ingroup tests
1281 *
1282 * @brief Test EHT Operation information element serialization and deserialization
1283 */
1285{
1286 public:
1287 /**
1288 * Constructor
1289 *
1290 * @param params the EHT Operation Parameters field
1291 * @param rxMaxNss0_7 RX max NSS that supports EHT MCS 0-7
1292 * @param txMaxNss0_7 TX max NSS that supports EHT MCS 0-7
1293 * @param rxMaxNss8_9 RX max NSS that supports EHT MCS 8-9
1294 * @param txMaxNss8_9 TX max NSS that supports EHT MCS 8-9
1295 * @param rxMaxNss10_11 RX max NSS that supports EHT MCS 10-11
1296 * @param txMaxNss10_11 TX max NSS that supports EHT MCS 10-11
1297 * @param rxMaxNss12_13 RX max NSS that supports EHT MCS 12-13
1298 * @param txMaxNss12_13 TX max NSS that supports EHT MCS 12-13
1299 * @param opInfo the EHT Operation Information field
1300 */
1302 uint8_t rxMaxNss0_7,
1303 uint8_t txMaxNss0_7,
1304 uint8_t rxMaxNss8_9,
1305 uint8_t txMaxNss8_9,
1306 uint8_t rxMaxNss10_11,
1307 uint8_t txMaxNss10_11,
1308 uint8_t rxMaxNss12_13,
1309 uint8_t txMaxNss12_13,
1310 std::optional<EhtOperation::EhtOpInfo> opInfo);
1311
1312 ~EhtOperationElementTest() override = default;
1313
1314 private:
1315 void DoRun() override;
1316
1317 EhtOperation m_ehtOperation; ///< EHT Operation element
1318};
1319
1321 uint8_t rxMaxNss0_7,
1322 uint8_t txMaxNss0_7,
1323 uint8_t rxMaxNss8_9,
1324 uint8_t txMaxNss8_9,
1325 uint8_t rxMaxNss10_11,
1326 uint8_t txMaxNss10_11,
1327 uint8_t rxMaxNss12_13,
1328 uint8_t txMaxNss12_13,
1329 std::optional<EhtOperation::EhtOpInfo> opInfo)
1331 "Check serialization and deserialization of EHT Operation elements")
1332{
1333 m_ehtOperation.m_params = params;
1334 m_ehtOperation.SetMaxRxNss(rxMaxNss0_7, 0, 7);
1335 m_ehtOperation.SetMaxTxNss(txMaxNss0_7, 0, 7);
1336 m_ehtOperation.SetMaxRxNss(rxMaxNss8_9, 8, 9);
1337 m_ehtOperation.SetMaxTxNss(txMaxNss8_9, 8, 9);
1338 m_ehtOperation.SetMaxRxNss(rxMaxNss10_11, 10, 11);
1339 m_ehtOperation.SetMaxTxNss(txMaxNss10_11, 10, 11);
1340 m_ehtOperation.SetMaxRxNss(rxMaxNss12_13, 12, 13);
1341 m_ehtOperation.SetMaxTxNss(txMaxNss12_13, 12, 13);
1342 m_ehtOperation.m_opInfo = opInfo;
1343}
1344
1345void
1350
1351/**
1352 * @ingroup wifi-test
1353 * @ingroup tests
1354 *
1355 * @brief wifi EHT Information Elements Test Suite
1356 */
1358{
1359 public:
1361};
1362
1364 : TestSuite("wifi-eht-info-elems", Type::UNIT)
1365{
1366 AddTestCase(new BasicMultiLinkElementTest(), TestCase::Duration::QUICK);
1367 AddTestCase(new ReducedNeighborReportTest(), TestCase::Duration::QUICK);
1368 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 20), TestCase::Duration::QUICK);
1369 AddTestCase(new WifiEhtCapabilitiesIeTest(true, 20), TestCase::Duration::QUICK);
1370 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 80), TestCase::Duration::QUICK);
1371 AddTestCase(new WifiEhtCapabilitiesIeTest(true, 40), TestCase::Duration::QUICK);
1372 AddTestCase(new WifiEhtCapabilitiesIeTest(true, 80), TestCase::Duration::QUICK);
1373 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 160), TestCase::Duration::QUICK);
1374 AddTestCase(new WifiEhtCapabilitiesIeTest(false, 320), TestCase::Duration::QUICK);
1376 new TidToLinkMappingElementTest(WifiDirection::DOWNLINK, std::nullopt, std::nullopt, {}),
1377 TestCase::Duration::QUICK);
1378 AddTestCase(new TidToLinkMappingElementTest(WifiDirection::UPLINK,
1379 MicroSeconds(500 * 1024),
1380 MicroSeconds(300 * 1024),
1381 {{3, std::set<uint8_t>{0, 4, 6}}}),
1382 TestCase::Duration::QUICK);
1384 WifiDirection::BOTH_DIRECTIONS,
1385 std::nullopt,
1386 MicroSeconds(100 * 1024),
1387 {{3, std::set<uint8_t>{0, 4, 6}}, {6, std::set<uint8_t>{3, 7, 11, 14}}}),
1388 TestCase::Duration::QUICK);
1389 AddTestCase(new TidToLinkMappingElementTest(WifiDirection::DOWNLINK,
1390 MicroSeconds(100 * 1024),
1391 std::nullopt,
1392 {{0, std::set<uint8_t>{0, 1, 2}},
1393 {1, std::set<uint8_t>{3, 4, 5}},
1394 {2, std::set<uint8_t>{6, 7}},
1395 {3, std::set<uint8_t>{8, 9, 10}},
1396 {4, std::set<uint8_t>{11, 12, 13}},
1397 {5, std::set<uint8_t>{14}},
1398 {6, std::set<uint8_t>{1, 3, 6}},
1399 {7, std::set<uint8_t>{11, 14}}}),
1400 TestCase::Duration::QUICK);
1401 AddTestCase(new EhtOperationElementTest({0, 0, 0, 0, 0}, 1, 2, 3, 4, 5, 6, 7, 8, std::nullopt),
1402 TestCase::Duration::QUICK);
1403 AddTestCase(new EhtOperationElementTest({1, 0, 0, 1, 0},
1404 1,
1405 2,
1406 3,
1407 4,
1408 5,
1409 6,
1410 7,
1411 8,
1412 EhtOperation::EhtOpInfo{{1}, 3, 5}),
1413 TestCase::Duration::QUICK);
1414 AddTestCase(new EhtOperationElementTest({1, 1, 1, 1, 2},
1415 1,
1416 2,
1417 3,
1418 4,
1419 5,
1420 6,
1421 7,
1422 8,
1423 EhtOperation::EhtOpInfo{{2}, 4, 6, 3000}),
1424 TestCase::Duration::QUICK);
1425}
1426
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.
WifiEhtCapabilitiesIeTest(bool is2_4Ghz, MHz_u channelWidth)
Constructor.
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
MHz_u m_channelWidth
Supported channel width by the PHY.
Buffer SerializeIntoBuffer(const EhtCapabilities &ehtCapabilities)
Serialize the EHT capabilities in a buffer.
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:89
uint16_t ReadLsbtohU16()
Definition buffer.cc:1053
void Next()
go forward by one byte
Definition buffer.h:842
automatically resized byte buffer
Definition buffer.h:83
uint32_t GetSize() const
Definition buffer.h:1057
void AddAtStart(uint32_t start)
Definition buffer.cc:303
Buffer::Iterator Begin() const
Definition buffer.h:1063
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.
uint8_t GetHighestSupportedTxMcs(EhtMcsAndNssSet::EhtMcsMapType mapType) const
Get the highest supported TX MCS for a given EHT-MCS map type.
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 GetHighestSupportedRxMcs(EhtMcsAndNssSet::EhtMcsMapType mapType) const
Get the highest supported RX 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.
EHT Operation Information Element.
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
Implement the header for management frames of type association request.
CapabilityInformation & Capabilities()
void SetListenInterval(uint16_t interval)
Set the listen interval.
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:131
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
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:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
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.
std::set< FrequencyChannelInfo >::const_iterator ConstIterator
Typedef for a const iterator pointing to a channel in the set of available channels.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_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:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#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:134
#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:946
#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
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1368
@ WIFI_STANDARD_80211be
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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:66
WifiDirection
Wifi direction.
Definition wifi-utils.h:35
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.
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