A Discrete-Event Network Simulator
API
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 
36 using namespace ns3;
37 
38 NS_LOG_COMPONENT_DEFINE("WifiEhtInfoElemsTest");
39 
47 {
48  public:
53  ~BasicMultiLinkElementTest() override;
54 
63  MultiLinkElement GetMultiLinkElement(
64  const CommonInfoBasicMle& commonInfo,
65  std::vector<MultiLinkElement::PerStaProfileSubelement> subelements);
66 
67  private:
68  void DoRun() override;
69 
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 {
88  MultiLinkElement mle(MultiLinkElement::BASIC_VARIANT);
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 
126 void
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 
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  {
195  ehtCapabilities.SetSupportedRxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_20_MHZ_ONLY,
196  maxMcs,
197  1);
198  ehtCapabilities.SetSupportedTxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_20_MHZ_ONLY,
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 
210  MultiLinkElement::PerStaProfileSubelement perStaProfile1(MultiLinkElement::BASIC_VARIANT);
211  perStaProfile1.SetLinkId(3);
212  perStaProfile1.SetCompleteProfile();
213  perStaProfile1.SetAssocRequest(m_outerAssoc);
214 
215  /* Association Request included in the second Per-STA Profile subelement */
216  MgtAssocRequestHeader assoc;
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 
238  MultiLinkElement::PerStaProfileSubelement perStaProfile2(MultiLinkElement::BASIC_VARIANT);
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 
275  i = SupportedRates().DeserializeIfPresent(tmp = i);
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 
283  i = HeCapabilities().DeserializeIfPresent(tmp = i);
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(),
299  MultiLinkElement::PER_STA_PROFILE_SUBELEMENT_ID,
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(),
310  MultiLinkElement::PER_STA_PROFILE_SUBELEMENT_ID,
311  "PER_STA_PROFILE_SUBELEMENT_ID expected");
312  i.ReadU8(); // length
313  i.ReadLsbtohU16(); // STA Control field
314  i.ReadU8(); // STA Info Length
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 
327  i = VhtCapabilities().DeserializeIfPresent(tmp = i);
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(),
346  MultiLinkElement::PER_STA_PROFILE_SUBELEMENT_ID,
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 
362  i = VhtCapabilities().DeserializeIfPresent(tmp = i);
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 
378  MgtAssocRequestHeader frame;
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 
603 {
604  public:
609  ~ReducedNeighborReportTest() override;
610 
613 
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 
711 void
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() ||
721  channel5It != WifiPhyOperatingChannel::m_frequencyChannels.cend() ||
722  channel6It != 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  {
735  channel5It = WifiPhyOperatingChannel::FindFirst(0,
736  0,
737  0,
740  channel5It);
741  }
742  if (channel6It != WifiPhyOperatingChannel::m_frequencyChannels.cend())
743  {
744  channel6It = WifiPhyOperatingChannel::FindFirst(0,
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 
777 {
778  public:
784  WifiEhtCapabilitiesIeTest(bool is2_4Ghz, uint16_t channelWidth);
785  ~WifiEhtCapabilitiesIeTest() override = default;
786 
793 
802  EhtCapabilities GetEhtCapabilities(uint16_t maxMpduLength,
803  uint32_t maxAmpduSize,
804  uint8_t maxSupportedMcs) const;
805 
812  Buffer SerializeIntoBuffer(const EhtCapabilities& ehtCapabilities);
813 
821  void CheckSerializedByte(const Buffer& buffer, uint32_t position, uint8_t value);
822 
829  void CheckEhtMacCapabilitiesInformation(const Buffer& buffer, uint8_t expectedValueFirstByte);
830 
837  void CheckEhtPhyCapabilitiesInformation(const Buffer& buffer, uint8_t expectedValueSixthByte);
838 
845  void CheckSupportedEhtMcsAndNssSet(const Buffer& buffer, uint8_t maxSupportedMcs);
846 
847  private:
848  void DoRun() override;
849 
850  bool m_is2_4Ghz;
851  uint16_t m_channelWidth;
852 };
853 
854 WifiEhtCapabilitiesIeTest ::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  {
906  capabilities.SetSupportedRxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_20_MHZ_ONLY,
907  maxMcs,
908  maxMcs <= maxSupportedMcs ? 1 : 0);
909  capabilities.SetSupportedTxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_20_MHZ_ONLY,
910  maxMcs,
911  maxMcs <= maxSupportedMcs ? 2 : 0);
912  }
913  }
914  else
915  {
916  for (auto maxMcs : {9, 11, 13})
917  {
918  capabilities.SetSupportedRxEhtMcsAndNss(
919  EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_NOT_LARGER_THAN_80_MHZ,
920  maxMcs,
921  maxMcs <= maxSupportedMcs ? 3 : 0);
922  capabilities.SetSupportedTxEhtMcsAndNss(
923  EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_NOT_LARGER_THAN_80_MHZ,
924  maxMcs,
925  maxMcs <= maxSupportedMcs ? 4 : 0);
926  }
927  }
928  if (m_channelWidth >= 160)
929  {
930  for (auto maxMcs : {9, 11, 13})
931  {
932  capabilities.SetSupportedRxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_160_MHZ,
933  maxMcs,
934  maxMcs <= maxSupportedMcs ? 2 : 0);
935  capabilities.SetSupportedTxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_160_MHZ,
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  {
945  capabilities.SetSupportedRxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_320_MHZ,
946  maxMcs,
947  maxMcs <= maxSupportedMcs ? 4 : 0);
948  capabilities.SetSupportedTxEhtMcsAndNss(EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_320_MHZ,
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 
961 Buffer
963 {
964  Buffer buffer;
965  buffer.AddAtStart(ehtCapabilities.GetSerializedSize());
966  ehtCapabilities.Serialize(buffer.Begin());
967  return buffer;
968 }
969 
970 void
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 
981 void
983  uint8_t expectedValueFirstByte)
984 {
985  CheckSerializedByte(buffer, 3, expectedValueFirstByte);
986  CheckSerializedByte(buffer, 4, 0x00);
987 }
988 
989 void
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 
1004 void
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 
1062 void
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 
1093  auto mapType = m_channelWidth == 20 ? EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_20_MHZ_ONLY
1094  : EhtMcsAndNssSet::EHT_MCS_MAP_TYPE_NOT_LARGER_THAN_80_MHZ;
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 
1110  CheckEhtMacCapabilitiesInformation(buffer, 0x00);
1111 
1112  CheckEhtPhyCapabilitiesInformation(buffer, 0x00);
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 
1135  CheckEhtPhyCapabilitiesInformation(buffer, 0x00);
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 
1156  CheckEhtMacCapabilitiesInformation(buffer, 0x00);
1157 
1158  CheckEhtPhyCapabilitiesInformation(buffer, 0x06);
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 
1190  CheckEhtMacCapabilitiesInformation(buffer, 0x00);
1191 
1192  CheckEhtPhyCapabilitiesInformation(buffer, 0x08);
1193 
1194  CheckSupportedEhtMcsAndNssSet(buffer, maxMcs);
1195 
1196  TestHeaderSerialization(ehtCapabilities, m_is2_4Ghz, heCapabilities);
1197  }
1198 }
1199 
1207 {
1208  public:
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 
1229  std::optional<Time> m_mappingSwitchTime;
1230  std::optional<Time> m_expectedDuration;
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 
1248 void
1250 {
1253 
1254  if (m_mappingSwitchTime)
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  }
1263  if (m_expectedDuration)
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 
1281 void
1283 {
1285 
1286  Simulator::Destroy();
1287 }
1288 
1296 {
1297  public:
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 
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 {
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 
1356 void
1358 {
1360 }
1361 
1369 {
1370  public:
1372 };
1373 
1375  : TestSuite("wifi-eht-info-elems", UNIT)
1376 {
1377  AddTestCase(new BasicMultiLinkElementTest(), TestCase::QUICK);
1378  AddTestCase(new ReducedNeighborReportTest(), TestCase::QUICK);
1379  AddTestCase(new WifiEhtCapabilitiesIeTest(false, 20), TestCase::QUICK);
1380  AddTestCase(new WifiEhtCapabilitiesIeTest(true, 20), TestCase::QUICK);
1381  AddTestCase(new WifiEhtCapabilitiesIeTest(false, 80), TestCase::QUICK);
1382  AddTestCase(new WifiEhtCapabilitiesIeTest(true, 40), TestCase::QUICK);
1383  AddTestCase(new WifiEhtCapabilitiesIeTest(true, 80), TestCase::QUICK);
1384  AddTestCase(new WifiEhtCapabilitiesIeTest(false, 160), TestCase::QUICK);
1385  AddTestCase(new WifiEhtCapabilitiesIeTest(false, 320), TestCase::QUICK);
1386  AddTestCase(
1387  new TidToLinkMappingElementTest(WifiDirection::DOWNLINK, std::nullopt, std::nullopt, {}),
1388  TestCase::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::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::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::QUICK);
1412  AddTestCase(new EhtOperationElementTest({0, 0, 0, 0, 0}, 1, 2, 3, 4, 5, 6, 7, 8, std::nullopt),
1413  TestCase::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::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::QUICK);
1436 }
1437 
#define min(a, b)
Definition: 80211b.c:41
#define max(a, b)
Definition: 80211b.c:42
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.
WifiEhtCapabilitiesIeTest(bool is2_4Ghz, uint16_t channelWidth)
Constructor.
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 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.
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.
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...
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
The Supported Rates Information Element.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
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.
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:144
#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:956
#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:251
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
address
Definition: first.py:47
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition: json.h:4023
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.
value
Definition: second.py:48
channel
Definition: third.py:88
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
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