A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
reduced-neighbor-report.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 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
10
12#include "wifi-utils.h"
13
14#include "ns3/abort.h"
15#include "ns3/address-utils.h"
16
17#include <iterator>
18
19namespace ns3
20{
21
25
31
32std::size_t
37
38void
43
44void
46 const WifiPhyOperatingChannel& channel)
47{
48 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
49
50 uint8_t operatingClass = 0;
51 uint8_t channelNumber = channel.GetNumber();
52
53 // Information taken from Table E-4 of 802.11-2020
54 switch (channel.GetPhyBand())
55 {
57 if (channel.GetWidth() == MHz_u{20})
58 {
59 operatingClass = 81;
60 }
61 else if (channel.GetWidth() == MHz_u{40})
62 {
63 operatingClass = 83;
64 }
65 break;
67 if (channel.GetWidth() == MHz_u{20})
68 {
69 if (channelNumber == 36 || channelNumber == 40 || channelNumber == 44 ||
70 channelNumber == 48)
71 {
72 operatingClass = 115;
73 }
74 else if (channelNumber == 52 || channelNumber == 56 || channelNumber == 60 ||
75 channelNumber == 64)
76 {
77 operatingClass = 118;
78 }
79 else if (channelNumber == 100 || channelNumber == 104 || channelNumber == 108 ||
80 channelNumber == 112 || channelNumber == 116 || channelNumber == 120 ||
81 channelNumber == 124 || channelNumber == 128 || channelNumber == 132 ||
82 channelNumber == 136 || channelNumber == 140 || channelNumber == 144)
83 {
84 operatingClass = 121;
85 }
86 else if (channelNumber == 149 || channelNumber == 153 || channelNumber == 157 ||
87 channelNumber == 161 || channelNumber == 165 || channelNumber == 169 ||
88 channelNumber == 173 || channelNumber == 177 || channelNumber == 181)
89 {
90 operatingClass = 125;
91 }
92 }
93 else if (channel.GetWidth() == MHz_u{40})
94 {
95 if (channelNumber == 38 || channelNumber == 46)
96 {
97 operatingClass = 116;
98 }
99 else if (channelNumber == 54 || channelNumber == 62)
100 {
101 operatingClass = 119;
102 }
103 else if (channelNumber == 102 || channelNumber == 110 || channelNumber == 118 ||
104 channelNumber == 126 || channelNumber == 134 || channelNumber == 142)
105 {
106 operatingClass = 122;
107 }
108 else if (channelNumber == 151 || channelNumber == 159 || channelNumber == 167 ||
109 channelNumber == 175)
110 {
111 operatingClass = 126;
112 }
113 }
114 else if (channel.GetWidth() == MHz_u{80})
115 {
116 if (channelNumber == 42 || channelNumber == 58 || channelNumber == 106 ||
117 channelNumber == 122 || channelNumber == 138 || channelNumber == 155 ||
118 channelNumber == 171)
119 {
120 operatingClass = 128;
121 }
122 }
123 else if (channel.GetWidth() == MHz_u{160})
124 {
125 if (channelNumber == 50 || channelNumber == 114 || channelNumber == 163)
126 {
127 operatingClass = 129;
128 }
129 }
130 break;
132 if (channel.GetWidth() == MHz_u{20})
133 {
134 operatingClass = 131;
135 }
136 else if (channel.GetWidth() == MHz_u{40})
137 {
138 operatingClass = 132;
139 }
140 else if (channel.GetWidth() == MHz_u{80})
141 {
142 operatingClass = 133;
143 }
144 else if (channel.GetWidth() == MHz_u{160})
145 {
146 operatingClass = 134;
147 }
148 break;
150 default:
151 NS_ABORT_MSG("The provided channel has an unspecified PHY band");
152 break;
153 }
154
155 NS_ABORT_MSG_IF(operatingClass == 0,
156 "Operating class not found for channel number "
157 << channelNumber << " width " << channel.GetWidth() << " MHz "
158 << "band " << channel.GetPhyBand());
159
160 // find the primary channel number
161 MHz_u startingFreq{0};
162
163 switch (channel.GetPhyBand())
164 {
166 startingFreq = MHz_u{2407};
167 break;
169 startingFreq = MHz_u{5000};
170 break;
172 startingFreq = MHz_u{5950};
173 break;
175 default:
176 NS_ABORT_MSG("The provided channel has an unspecified PHY band");
177 break;
178 }
179
180 uint8_t primaryChannelNumber =
181 (channel.GetPrimaryChannelCenterFrequency(MHz_u{20}) - startingFreq) / MHz_u{5};
182
183 m_nbrApInfoFields.at(nbrApInfoId).operatingClass = operatingClass;
184 m_nbrApInfoFields.at(nbrApInfoId).channelNumber = primaryChannelNumber;
185}
186
188ReducedNeighborReport::GetOperatingChannel(std::size_t nbrApInfoId) const
189{
190 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
191
193 MHz_u width{0};
194
195 switch (m_nbrApInfoFields.at(nbrApInfoId).operatingClass)
196 {
197 case 81:
199 width = MHz_u{20};
200 break;
201 case 83:
203 width = MHz_u{40};
204 break;
205 case 115:
206 case 118:
207 case 121:
208 case 125:
209 band = WIFI_PHY_BAND_5GHZ;
210 width = MHz_u{20};
211 break;
212 case 116:
213 case 119:
214 case 122:
215 case 126:
216 band = WIFI_PHY_BAND_5GHZ;
217 width = MHz_u{40};
218 break;
219 case 128:
220 band = WIFI_PHY_BAND_5GHZ;
221 width = MHz_u{80};
222 break;
223 case 129:
224 band = WIFI_PHY_BAND_5GHZ;
225 width = MHz_u{160};
226 break;
227 case 131:
228 band = WIFI_PHY_BAND_6GHZ;
229 width = MHz_u{20};
230 break;
231 case 132:
232 band = WIFI_PHY_BAND_6GHZ;
233 width = MHz_u{40};
234 break;
235 case 133:
236 band = WIFI_PHY_BAND_6GHZ;
237 width = MHz_u{80};
238 break;
239 case 134:
240 band = WIFI_PHY_BAND_6GHZ;
241 width = MHz_u{160};
242 break;
243 default:
244 break;
245 }
246
247 NS_ABORT_IF(band == WIFI_PHY_BAND_UNSPECIFIED || width == MHz_u{0});
248
249 MHz_u startingFreq{0};
250
251 switch (band)
252 {
254 startingFreq = MHz_u{2407};
255 break;
257 startingFreq = MHz_u{5000};
258 break;
260 startingFreq = MHz_u{5950};
261 break;
263 default:
264 NS_ABORT_MSG("Unspecified band");
265 break;
266 }
267
268 uint8_t primaryChannelNumber = m_nbrApInfoFields.at(nbrApInfoId).channelNumber;
269 auto primaryChannelCenterFrequency = startingFreq + primaryChannelNumber * MHz_u{5};
270
271 uint8_t channelNumber = 0;
272 MHz_u frequency{0};
273
274 for (const auto& channel : WifiPhyOperatingChannel::m_frequencyChannels)
275 {
276 if (channel.width == width && channel.type == FrequencyChannelType::OFDM &&
277 channel.band == band &&
278 primaryChannelCenterFrequency > (channel.frequency - (width / 2)) &&
279 primaryChannelCenterFrequency < (channel.frequency + (width / 2)))
280 {
281 // the center frequency of the primary channel falls into the frequency
282 // range of this channel
283 bool found = false;
284
285 if (band != WIFI_PHY_BAND_2_4GHZ)
286 {
287 found = true;
288 }
289 else
290 {
291 // frequency channels overlap in the 2.4 GHz band, hence we have to check
292 // that the given primary channel center frequency can be the center frequency
293 // of the primary20 channel of the channel under consideration
294 switch (static_cast<uint16_t>(width))
295 {
296 case 20:
297 if (channel.frequency == primaryChannelCenterFrequency)
298 {
299 found = true;
300 }
301 break;
302 case 40:
303 if ((channel.frequency == primaryChannelCenterFrequency + MHz_u{10}) ||
304 (channel.frequency == primaryChannelCenterFrequency - MHz_u{10}))
305 {
306 found = true;
307 }
308 break;
309 default:
310 NS_ABORT_MSG("No channel of width " << width << " MHz in the 2.4 GHz band");
311 }
312 }
313
314 if (found)
315 {
316 channelNumber = channel.number;
317 frequency = channel.frequency;
318 break;
319 }
320 }
321 }
322
323 NS_ABORT_IF(channelNumber == 0 || frequency == MHz_u{0});
324
325 WifiPhyOperatingChannel channel;
326 channel.Set({{channelNumber, frequency, width, band}}, WIFI_STANDARD_UNSPECIFIED);
327
328 const auto channelLowestFreq = frequency - width / 2;
329 const auto primaryChannelLowestFreq = primaryChannelCenterFrequency - MHz_u{10};
330 channel.SetPrimary20Index(Count20MHzSubchannels(channelLowestFreq, primaryChannelLowestFreq));
331
332 return channel;
333}
334
335std::size_t
336ReducedNeighborReport::GetNTbttInformationFields(std::size_t nbrApInfoId) const
337{
338 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
339 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size();
340}
341
342void
343ReducedNeighborReport::AddTbttInformationField(std::size_t nbrApInfoId)
344{
345 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
346 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.emplace_back();
347}
348
349void
350ReducedNeighborReport::WriteTbttInformationLength(std::size_t nbrApInfoId) const
351{
352 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
353
354 uint8_t length = 0; // reserved value
355
356 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
357
358 if (it->hasBssid && !it->hasShortSsid && !it->hasBssParams && !it->has20MHzPsd &&
359 !it->hasMldParams)
360 {
361 length = 7;
362 }
363 else if (it->hasBssid && it->hasShortSsid && it->hasBssParams && it->has20MHzPsd &&
364 it->hasMldParams)
365 {
366 length = 16;
367 }
368 else
369 {
370 NS_ABORT_MSG("Unsupported TBTT Information field contents");
371 }
372
373 // set the TBTT Information Length field
374 it->tbttInfoHdr.tbttInfoLength = length;
375}
376
377void
378ReducedNeighborReport::ReadTbttInformationLength(std::size_t nbrApInfoId)
379{
380 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
381
382 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
383
384 switch (it->tbttInfoHdr.tbttInfoLength)
385 {
386 case 7:
387 it->hasBssid = true;
388 it->hasShortSsid = false;
389 it->hasBssParams = false;
390 it->has20MHzPsd = false;
391 it->hasMldParams = false;
392 break;
393 case 16:
394 it->hasBssid = true;
395 it->hasShortSsid = true;
396 it->hasBssParams = true;
397 it->has20MHzPsd = true;
398 it->hasMldParams = true;
399 break;
400 default:
402 "Unsupported TBTT Information Length value: " << it->tbttInfoHdr.tbttInfoLength);
403 }
404}
405
406void
407ReducedNeighborReport::SetBssid(std::size_t nbrApInfoId, std::size_t index, Mac48Address bssid)
408{
409 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
410 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
411
412 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid = bssid;
413
414 m_nbrApInfoFields.at(nbrApInfoId).hasBssid = true;
415}
416
417bool
418ReducedNeighborReport::HasBssid(std::size_t nbrApInfoId) const
419{
420 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
421
422 return m_nbrApInfoFields.at(nbrApInfoId).hasBssid;
423}
424
426ReducedNeighborReport::GetBssid(std::size_t nbrApInfoId, std::size_t index) const
427{
428 NS_ASSERT(HasBssid(nbrApInfoId));
429 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
430
431 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid;
432}
433
434void
435ReducedNeighborReport::SetShortSsid(std::size_t nbrApInfoId, std::size_t index, uint32_t shortSsid)
436{
437 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
438 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
439
440 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid = shortSsid;
441
442 m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid = true;
443}
444
445bool
446ReducedNeighborReport::HasShortSsid(std::size_t nbrApInfoId) const
447{
448 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
449
450 return m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid;
451}
452
454ReducedNeighborReport::GetShortSsid(std::size_t nbrApInfoId, std::size_t index) const
455{
456 NS_ASSERT(HasShortSsid(nbrApInfoId));
457 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
458
459 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid;
460}
461
462void
463ReducedNeighborReport::SetBssParameters(std::size_t nbrApInfoId,
464 std::size_t index,
465 uint8_t bssParameters)
466{
467 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
468 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
469
470 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters = bssParameters;
471
472 m_nbrApInfoFields.at(nbrApInfoId).hasBssParams = true;
473}
474
475bool
476ReducedNeighborReport::HasBssParameters(std::size_t nbrApInfoId) const
477{
478 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
479
480 return m_nbrApInfoFields.at(nbrApInfoId).hasBssParams;
481}
482
483uint8_t
484ReducedNeighborReport::GetBssParameters(std::size_t nbrApInfoId, std::size_t index) const
485{
486 NS_ASSERT(HasBssParameters(nbrApInfoId));
487 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
488
489 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters;
490}
491
492void
493ReducedNeighborReport::SetPsd20MHz(std::size_t nbrApInfoId, std::size_t index, uint8_t psd20MHz)
494{
495 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
496 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
497
498 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz = psd20MHz;
499
500 m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd = true;
501}
502
503bool
504ReducedNeighborReport::HasPsd20MHz(std::size_t nbrApInfoId) const
505{
506 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
507
508 return m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd;
509}
510
511uint8_t
512ReducedNeighborReport::GetPsd20MHz(std::size_t nbrApInfoId, std::size_t index) const
513{
514 NS_ASSERT(HasPsd20MHz(nbrApInfoId));
515 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
516
517 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz;
518}
519
520void
521ReducedNeighborReport::SetMldParameters(std::size_t nbrApInfoId,
522 std::size_t index,
523 uint8_t mldId,
524 uint8_t linkId,
525 uint8_t changeCount)
526{
527 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
528 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
529
530 auto it = std::next(m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.begin(), index);
531 it->mldParameters.mldId = mldId;
532 it->mldParameters.linkId = (linkId & 0x0f);
533 it->mldParameters.bssParamsChangeCount = changeCount;
534
535 m_nbrApInfoFields.at(nbrApInfoId).hasMldParams = true;
536}
537
538bool
539ReducedNeighborReport::HasMldParameters(std::size_t nbrApInfoId) const
540{
541 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
542
543 return m_nbrApInfoFields.at(nbrApInfoId).hasMldParams;
544}
545
546uint8_t
547ReducedNeighborReport::GetMldId(std::size_t nbrApInfoId, std::size_t index) const
548{
549 NS_ASSERT(HasMldParameters(nbrApInfoId));
550 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
551
552 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters.mldId;
553}
554
555uint8_t
556ReducedNeighborReport::GetLinkId(std::size_t nbrApInfoId, std::size_t index) const
557{
558 NS_ASSERT(HasMldParameters(nbrApInfoId));
559 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
560
561 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters.linkId &
562 0x0f;
563}
564
565void
566ReducedNeighborReport::WriteTbttInformationCount(std::size_t nbrApInfoId) const
567{
568 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
569 NS_ASSERT(!m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.empty());
570
571 // set the TBTT Information Count field
572 m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount =
573 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size() - 1;
574}
575
576uint8_t
577ReducedNeighborReport::ReadTbttInformationCount(std::size_t nbrApInfoId) const
578{
579 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
580
581 return 1 + m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount;
582}
583
584uint16_t
585ReducedNeighborReport::GetInformationFieldSize() const
586{
587 uint16_t size = 0;
588
589 for (const auto& neighborApInfo : m_nbrApInfoFields)
590 {
591 size += 4;
592
593 size += 1 * neighborApInfo.tbttInformationSet.size();
594
595 if (neighborApInfo.hasBssid)
596 {
597 size += 6 * neighborApInfo.tbttInformationSet.size();
598 }
599 if (neighborApInfo.hasShortSsid)
600 {
601 size += 4 * neighborApInfo.tbttInformationSet.size();
602 }
603 if (neighborApInfo.hasBssParams)
604 {
605 size += 1 * neighborApInfo.tbttInformationSet.size();
606 }
607 if (neighborApInfo.has20MHzPsd)
608 {
609 size += 1 * neighborApInfo.tbttInformationSet.size();
610 }
611 if (neighborApInfo.hasMldParams)
612 {
613 size += 3 * neighborApInfo.tbttInformationSet.size();
614 }
615 }
616
617 return size;
618}
619
620void
621ReducedNeighborReport::SerializeInformationField(Buffer::Iterator start) const
622{
623 for (std::size_t id = 0; id < m_nbrApInfoFields.size(); ++id)
624 {
625 WriteTbttInformationCount(id);
626 WriteTbttInformationLength(id);
627 }
628
629 for (auto& neighborApInfo : m_nbrApInfoFields)
630 {
631 // serialize the TBTT Information Header
632 uint16_t tbttInfoHdr = 0;
633 tbttInfoHdr |= neighborApInfo.tbttInfoHdr.type;
634 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.filtered << 2);
635 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoCount << 4);
636 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoLength << 8);
637 start.WriteHtolsbU16(tbttInfoHdr);
638
639 start.WriteU8(neighborApInfo.operatingClass);
640 start.WriteU8(neighborApInfo.channelNumber);
641
642 for (const auto& tbttInformation : neighborApInfo.tbttInformationSet)
643 {
644 start.WriteU8(tbttInformation.neighborApTbttOffset);
645
646 if (neighborApInfo.hasBssid)
647 {
648 WriteTo(start, tbttInformation.bssid);
649 }
650 if (neighborApInfo.hasShortSsid)
651 {
652 start.WriteHtolsbU32(tbttInformation.shortSsid);
653 }
654 if (neighborApInfo.hasBssParams)
655 {
656 start.WriteU8(tbttInformation.bssParameters);
657 }
658 if (neighborApInfo.has20MHzPsd)
659 {
660 start.WriteU8(tbttInformation.psd20MHz);
661 }
662 if (neighborApInfo.hasMldParams)
663 {
664 start.WriteU8(tbttInformation.mldParameters.mldId);
665 uint16_t other = 0;
666 other |= (tbttInformation.mldParameters.linkId & 0x0f);
667 other |= (tbttInformation.mldParameters.bssParamsChangeCount << 4);
668 start.WriteHtolsbU16(other);
669 }
670 }
671 }
672}
673
674uint16_t
675ReducedNeighborReport::DeserializeInformationField(Buffer::Iterator start, uint16_t length)
676{
677 Buffer::Iterator i = start;
678 uint16_t count = 0;
679
680 while (count < length)
681 {
682 AddNbrApInfoField();
683
684 auto tbttInfoHdr = i.ReadLsbtohU16();
685 m_nbrApInfoFields.back().tbttInfoHdr.type = tbttInfoHdr & 0x0003;
686 m_nbrApInfoFields.back().tbttInfoHdr.filtered = (tbttInfoHdr >> 2) & 0x0001;
687 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoCount = (tbttInfoHdr >> 4) & 0x000f;
688 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoLength = (tbttInfoHdr >> 8) & 0x00ff;
689
690 m_nbrApInfoFields.back().operatingClass = i.ReadU8();
691 m_nbrApInfoFields.back().channelNumber = i.ReadU8();
692 count += 4;
693
694 std::size_t neighborId = m_nbrApInfoFields.size() - 1;
695 ReadTbttInformationLength(neighborId);
696
697 for (uint8_t j = 0; j < ReadTbttInformationCount(neighborId); j++)
698 {
699 AddTbttInformationField(neighborId);
700
701 m_nbrApInfoFields.back().tbttInformationSet.back().neighborApTbttOffset = i.ReadU8();
702 count++;
703
704 if (m_nbrApInfoFields.back().hasBssid)
705 {
706 ReadFrom(i, m_nbrApInfoFields.back().tbttInformationSet.back().bssid);
707 count += 6;
708 }
709 if (m_nbrApInfoFields.back().hasShortSsid)
710 {
711 m_nbrApInfoFields.back().tbttInformationSet.back().shortSsid = i.ReadLsbtohU32();
712 count += 4;
713 }
714 if (m_nbrApInfoFields.back().hasBssParams)
715 {
716 m_nbrApInfoFields.back().tbttInformationSet.back().bssParameters = i.ReadU8();
717 count += 1;
718 }
719 if (m_nbrApInfoFields.back().has20MHzPsd)
720 {
721 m_nbrApInfoFields.back().tbttInformationSet.back().psd20MHz = i.ReadU8();
722 count += 1;
723 }
724 if (m_nbrApInfoFields.back().hasMldParams)
725 {
726 m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters.mldId = i.ReadU8();
727 uint16_t other = i.ReadLsbtohU16();
728 count += 3;
729 m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters.linkId =
730 other & 0x000f;
731 m_nbrApInfoFields.back()
732 .tbttInformationSet.back()
733 .mldParameters.bssParamsChangeCount = (other >> 4) & 0x00ff;
734 }
735 }
736 }
737
738 return count;
739}
740
741} // namespace ns3
iterator in a Buffer instance
Definition buffer.h:89
uint16_t ReadLsbtohU16()
Definition buffer.cc:1053
uint32_t ReadLsbtohU32()
Definition buffer.cc:1065
an EUI-48 address
std::vector< NeighborApInformation > m_nbrApInfoFields
one or more Neighbor AP Information fields
std::size_t GetNNbrApInfoFields() const
Get the number of Neighbor AP Information fields.
WifiInformationElementId ElementId() const override
Get the wifi information element ID.
void AddNbrApInfoField()
Add a Neighbor AP Information field.
WifiPhyOperatingChannel GetOperatingChannel(std::size_t nbrApInfoId) const
Get the operating channel coded into the Operating Class and the Channel Number fields of the given N...
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...
Class that keeps track of all information about the current PHY operating channel.
static const std::set< FrequencyChannelInfo > m_frequencyChannels
Available frequency 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:55
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
WifiPhyBand
Identifies the PHY band.
@ WIFI_STANDARD_UNSPECIFIED
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
@ 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.
double MHz_u
MHz weak type.
Definition wifi-units.h:31
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
Definition wifi-utils.h:134
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
uint8_t WifiInformationElementId
This type is used to represent an Information Element ID.
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.
channel
Definition third.py:77
#define IE_REDUCED_NEIGHBOR_REPORT