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 else if (channel.GetWidth() == MHz_u{320})
149 {
150 operatingClass = 137;
151 }
152 break;
154 default:
155 NS_ABORT_MSG("The provided channel has an unspecified PHY band");
156 break;
157 }
158
159 NS_ABORT_MSG_IF(operatingClass == 0,
160 "Operating class not found for channel number "
161 << +channelNumber << " width " << channel.GetWidth() << " MHz "
162 << "band " << channel.GetPhyBand());
163
164 // find the primary channel number
165 MHz_u startingFreq{0};
166
167 switch (channel.GetPhyBand())
168 {
170 startingFreq = MHz_u{2407};
171 break;
173 startingFreq = MHz_u{5000};
174 break;
176 startingFreq = MHz_u{5950};
177 break;
179 default:
180 NS_ABORT_MSG("The provided channel has an unspecified PHY band");
181 break;
182 }
183
184 uint8_t primaryChannelNumber =
185 (channel.GetPrimaryChannelCenterFrequency(MHz_u{20}) - startingFreq) / MHz_u{5};
186
187 m_nbrApInfoFields.at(nbrApInfoId).operatingClass = operatingClass;
188 m_nbrApInfoFields.at(nbrApInfoId).channelNumber = primaryChannelNumber;
189}
190
192ReducedNeighborReport::GetOperatingChannel(std::size_t nbrApInfoId) const
193{
194 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
195
197 MHz_u width{0};
198
199 switch (m_nbrApInfoFields.at(nbrApInfoId).operatingClass)
200 {
201 case 81:
203 width = MHz_u{20};
204 break;
205 case 83:
207 width = MHz_u{40};
208 break;
209 case 115:
210 case 118:
211 case 121:
212 case 125:
213 band = WIFI_PHY_BAND_5GHZ;
214 width = MHz_u{20};
215 break;
216 case 116:
217 case 119:
218 case 122:
219 case 126:
220 band = WIFI_PHY_BAND_5GHZ;
221 width = MHz_u{40};
222 break;
223 case 128:
224 band = WIFI_PHY_BAND_5GHZ;
225 width = MHz_u{80};
226 break;
227 case 129:
228 band = WIFI_PHY_BAND_5GHZ;
229 width = MHz_u{160};
230 break;
231 case 131:
232 band = WIFI_PHY_BAND_6GHZ;
233 width = MHz_u{20};
234 break;
235 case 132:
236 band = WIFI_PHY_BAND_6GHZ;
237 width = MHz_u{40};
238 break;
239 case 133:
240 band = WIFI_PHY_BAND_6GHZ;
241 width = MHz_u{80};
242 break;
243 case 134:
244 band = WIFI_PHY_BAND_6GHZ;
245 width = MHz_u{160};
246 break;
247 case 137:
248 band = WIFI_PHY_BAND_6GHZ;
249 width = MHz_u{320};
250 break;
251 default:
252 break;
253 }
254
255 NS_ABORT_IF(band == WIFI_PHY_BAND_UNSPECIFIED || width == MHz_u{0});
256
257 MHz_u startingFreq{0};
258
259 switch (band)
260 {
262 startingFreq = MHz_u{2407};
263 break;
265 startingFreq = MHz_u{5000};
266 break;
268 startingFreq = MHz_u{5950};
269 break;
271 default:
272 NS_ABORT_MSG("Unspecified band");
273 break;
274 }
275
276 uint8_t primaryChannelNumber = m_nbrApInfoFields.at(nbrApInfoId).channelNumber;
277 auto primaryChannelCenterFrequency = startingFreq + primaryChannelNumber * MHz_u{5};
278
279 uint8_t channelNumber = 0;
280 MHz_u frequency{0};
281
282 for (const auto& channel : WifiPhyOperatingChannel::m_frequencyChannels)
283 {
284 if (channel.width == width && channel.type == FrequencyChannelType::OFDM &&
285 channel.band == band &&
286 primaryChannelCenterFrequency > (channel.frequency - (width / 2)) &&
287 primaryChannelCenterFrequency < (channel.frequency + (width / 2)))
288 {
289 // the center frequency of the primary channel falls into the frequency
290 // range of this channel
291 bool found = false;
292
293 if (band != WIFI_PHY_BAND_2_4GHZ)
294 {
295 found = true;
296 }
297 else
298 {
299 // frequency channels overlap in the 2.4 GHz band, hence we have to check
300 // that the given primary channel center frequency can be the center frequency
301 // of the primary20 channel of the channel under consideration
302 switch (static_cast<uint16_t>(width))
303 {
304 case 20:
305 if (channel.frequency == primaryChannelCenterFrequency)
306 {
307 found = true;
308 }
309 break;
310 case 40:
311 if ((channel.frequency == primaryChannelCenterFrequency + MHz_u{10}) ||
312 (channel.frequency == primaryChannelCenterFrequency - MHz_u{10}))
313 {
314 found = true;
315 }
316 break;
317 default:
318 NS_ABORT_MSG("No channel of width " << width << " MHz in the 2.4 GHz band");
319 }
320 }
321
322 if (found)
323 {
324 channelNumber = channel.number;
325 frequency = channel.frequency;
326 break;
327 }
328 }
329 }
330
331 NS_ABORT_IF(channelNumber == 0 || frequency == MHz_u{0});
332
333 WifiPhyOperatingChannel channel;
334 channel.Set({{channelNumber, frequency, width, band}}, WIFI_STANDARD_UNSPECIFIED);
335
336 const auto channelLowestFreq = frequency - width / 2;
337 const auto primaryChannelLowestFreq = primaryChannelCenterFrequency - MHz_u{10};
338 channel.SetPrimary20Index(Count20MHzSubchannels(channelLowestFreq, primaryChannelLowestFreq));
339
340 return channel;
341}
342
343std::size_t
344ReducedNeighborReport::GetNTbttInformationFields(std::size_t nbrApInfoId) const
345{
346 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
347 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size();
348}
349
350void
351ReducedNeighborReport::AddTbttInformationField(std::size_t nbrApInfoId)
352{
353 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
354 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.emplace_back();
355}
356
357void
358ReducedNeighborReport::WriteTbttInformationLength(std::size_t nbrApInfoId) const
359{
360 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
361
362 uint8_t length = 0; // reserved value
363
364 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
365
366 if (it->hasBssid && !it->hasShortSsid && !it->hasBssParams && !it->has20MHzPsd &&
367 !it->hasMldParams)
368 {
369 length = 7;
370 }
371 else if (it->hasBssid && it->hasShortSsid && it->hasBssParams && it->has20MHzPsd &&
372 it->hasMldParams)
373 {
374 length = 16;
375 }
376 else
377 {
378 NS_ABORT_MSG("Unsupported TBTT Information field contents");
379 }
380
381 // set the TBTT Information Length field
382 it->tbttInfoHdr.tbttInfoLength = length;
383}
384
385void
386ReducedNeighborReport::ReadTbttInformationLength(std::size_t nbrApInfoId)
387{
388 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
389
390 auto it = std::next(m_nbrApInfoFields.begin(), nbrApInfoId);
391
392 switch (it->tbttInfoHdr.tbttInfoLength)
393 {
394 case 7:
395 it->hasBssid = true;
396 it->hasShortSsid = false;
397 it->hasBssParams = false;
398 it->has20MHzPsd = false;
399 it->hasMldParams = false;
400 break;
401 case 16:
402 it->hasBssid = true;
403 it->hasShortSsid = true;
404 it->hasBssParams = true;
405 it->has20MHzPsd = true;
406 it->hasMldParams = true;
407 break;
408 default:
410 "Unsupported TBTT Information Length value: " << it->tbttInfoHdr.tbttInfoLength);
411 }
412}
413
414void
415ReducedNeighborReport::SetBssid(std::size_t nbrApInfoId, std::size_t index, Mac48Address bssid)
416{
417 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
418 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
419
420 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid = bssid;
421
422 m_nbrApInfoFields.at(nbrApInfoId).hasBssid = true;
423}
424
425bool
426ReducedNeighborReport::HasBssid(std::size_t nbrApInfoId) const
427{
428 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
429
430 return m_nbrApInfoFields.at(nbrApInfoId).hasBssid;
431}
432
434ReducedNeighborReport::GetBssid(std::size_t nbrApInfoId, std::size_t index) const
435{
436 NS_ASSERT(HasBssid(nbrApInfoId));
437 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
438
439 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssid;
440}
441
442void
443ReducedNeighborReport::SetShortSsid(std::size_t nbrApInfoId, std::size_t index, uint32_t shortSsid)
444{
445 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
446 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
447
448 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid = shortSsid;
449
450 m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid = true;
451}
452
453bool
454ReducedNeighborReport::HasShortSsid(std::size_t nbrApInfoId) const
455{
456 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
457
458 return m_nbrApInfoFields.at(nbrApInfoId).hasShortSsid;
459}
460
462ReducedNeighborReport::GetShortSsid(std::size_t nbrApInfoId, std::size_t index) const
463{
464 NS_ASSERT(HasShortSsid(nbrApInfoId));
465 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
466
467 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).shortSsid;
468}
469
470void
471ReducedNeighborReport::SetBssParameters(std::size_t nbrApInfoId,
472 std::size_t index,
473 uint8_t bssParameters)
474{
475 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
476 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
477
478 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters = bssParameters;
479
480 m_nbrApInfoFields.at(nbrApInfoId).hasBssParams = true;
481}
482
483bool
484ReducedNeighborReport::HasBssParameters(std::size_t nbrApInfoId) const
485{
486 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
487
488 return m_nbrApInfoFields.at(nbrApInfoId).hasBssParams;
489}
490
491uint8_t
492ReducedNeighborReport::GetBssParameters(std::size_t nbrApInfoId, std::size_t index) const
493{
494 NS_ASSERT(HasBssParameters(nbrApInfoId));
495 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
496
497 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).bssParameters;
498}
499
500void
501ReducedNeighborReport::SetPsd20MHz(std::size_t nbrApInfoId, std::size_t index, uint8_t psd20MHz)
502{
503 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
504 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
505
506 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz = psd20MHz;
507
508 m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd = true;
509}
510
511bool
512ReducedNeighborReport::HasPsd20MHz(std::size_t nbrApInfoId) const
513{
514 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
515
516 return m_nbrApInfoFields.at(nbrApInfoId).has20MHzPsd;
517}
518
519uint8_t
520ReducedNeighborReport::GetPsd20MHz(std::size_t nbrApInfoId, std::size_t index) const
521{
522 NS_ASSERT(HasPsd20MHz(nbrApInfoId));
523 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
524
525 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).psd20MHz;
526}
527
528void
529ReducedNeighborReport::SetMldParameters(std::size_t nbrApInfoId,
530 std::size_t index,
531 const MldParameters& mldParams)
532{
533 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
534 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
535
536 auto it = std::next(m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.begin(), index);
537 it->mldParameters = mldParams;
538
539 m_nbrApInfoFields.at(nbrApInfoId).hasMldParams = true;
540}
541
542bool
543ReducedNeighborReport::HasMldParameters(std::size_t nbrApInfoId) const
544{
545 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
546
547 return m_nbrApInfoFields.at(nbrApInfoId).hasMldParams;
548}
549
551ReducedNeighborReport::GetMldParameters(std::size_t nbrApInfoId, std::size_t index) const
552{
553 NS_ASSERT(HasMldParameters(nbrApInfoId));
554 NS_ASSERT(index < m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size());
555
556 return m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.at(index).mldParameters;
557}
558
559void
560ReducedNeighborReport::WriteTbttInformationCount(std::size_t nbrApInfoId) const
561{
562 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
563 NS_ASSERT(!m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.empty());
564
565 // set the TBTT Information Count field
566 m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount =
567 m_nbrApInfoFields.at(nbrApInfoId).tbttInformationSet.size() - 1;
568}
569
570uint8_t
571ReducedNeighborReport::ReadTbttInformationCount(std::size_t nbrApInfoId) const
572{
573 NS_ASSERT(nbrApInfoId < m_nbrApInfoFields.size());
574
575 return 1 + m_nbrApInfoFields.at(nbrApInfoId).tbttInfoHdr.tbttInfoCount;
576}
577
578uint16_t
579ReducedNeighborReport::GetInformationFieldSize() const
580{
581 uint16_t size = 0;
582
583 for (const auto& neighborApInfo : m_nbrApInfoFields)
584 {
585 size += 4;
586
587 size += 1 * neighborApInfo.tbttInformationSet.size();
588
589 if (neighborApInfo.hasBssid)
590 {
591 size += 6 * neighborApInfo.tbttInformationSet.size();
592 }
593 if (neighborApInfo.hasShortSsid)
594 {
595 size += 4 * neighborApInfo.tbttInformationSet.size();
596 }
597 if (neighborApInfo.hasBssParams)
598 {
599 size += 1 * neighborApInfo.tbttInformationSet.size();
600 }
601 if (neighborApInfo.has20MHzPsd)
602 {
603 size += 1 * neighborApInfo.tbttInformationSet.size();
604 }
605 if (neighborApInfo.hasMldParams)
606 {
607 size += 3 * neighborApInfo.tbttInformationSet.size();
608 }
609 }
610
611 return size;
612}
613
614void
615ReducedNeighborReport::SerializeInformationField(Buffer::Iterator start) const
616{
617 for (std::size_t id = 0; id < m_nbrApInfoFields.size(); ++id)
618 {
619 WriteTbttInformationCount(id);
620 WriteTbttInformationLength(id);
621 }
622
623 for (auto& neighborApInfo : m_nbrApInfoFields)
624 {
625 // serialize the TBTT Information Header
626 uint16_t tbttInfoHdr = 0;
627 tbttInfoHdr |= neighborApInfo.tbttInfoHdr.type;
628 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.filtered << 2);
629 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoCount << 4);
630 tbttInfoHdr |= (neighborApInfo.tbttInfoHdr.tbttInfoLength << 8);
631 start.WriteHtolsbU16(tbttInfoHdr);
632
633 start.WriteU8(neighborApInfo.operatingClass);
634 start.WriteU8(neighborApInfo.channelNumber);
635
636 for (const auto& tbttInformation : neighborApInfo.tbttInformationSet)
637 {
638 start.WriteU8(tbttInformation.neighborApTbttOffset);
639
640 if (neighborApInfo.hasBssid)
641 {
642 WriteTo(start, tbttInformation.bssid);
643 }
644 if (neighborApInfo.hasShortSsid)
645 {
646 start.WriteHtolsbU32(tbttInformation.shortSsid);
647 }
648 if (neighborApInfo.hasBssParams)
649 {
650 start.WriteU8(tbttInformation.bssParameters);
651 }
652 if (neighborApInfo.has20MHzPsd)
653 {
654 start.WriteU8(tbttInformation.psd20MHz);
655 }
656 if (neighborApInfo.hasMldParams)
657 {
658 start.WriteU8(tbttInformation.mldParameters.apMldId);
659 uint16_t other = 0;
660 other |= (tbttInformation.mldParameters.linkId & 0x0f);
661 other |= (tbttInformation.mldParameters.bssParamsChangeCount << 4);
662 other |= (tbttInformation.mldParameters.allUpdates << 12);
663 other |= (tbttInformation.mldParameters.disabledLink << 13);
664 start.WriteHtolsbU16(other);
665 }
666 }
667 }
668}
669
670uint16_t
671ReducedNeighborReport::DeserializeInformationField(Buffer::Iterator start, uint16_t length)
672{
673 Buffer::Iterator i = start;
674 uint16_t count = 0;
675
676 while (count < length)
677 {
678 AddNbrApInfoField();
679
680 auto tbttInfoHdr = i.ReadLsbtohU16();
681 m_nbrApInfoFields.back().tbttInfoHdr.type = tbttInfoHdr & 0x0003;
682 m_nbrApInfoFields.back().tbttInfoHdr.filtered = (tbttInfoHdr >> 2) & 0x0001;
683 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoCount = (tbttInfoHdr >> 4) & 0x000f;
684 m_nbrApInfoFields.back().tbttInfoHdr.tbttInfoLength = (tbttInfoHdr >> 8) & 0x00ff;
685
686 m_nbrApInfoFields.back().operatingClass = i.ReadU8();
687 m_nbrApInfoFields.back().channelNumber = i.ReadU8();
688 count += 4;
689
690 std::size_t neighborId = m_nbrApInfoFields.size() - 1;
691 ReadTbttInformationLength(neighborId);
692
693 for (uint8_t j = 0; j < ReadTbttInformationCount(neighborId); j++)
694 {
695 AddTbttInformationField(neighborId);
696
697 m_nbrApInfoFields.back().tbttInformationSet.back().neighborApTbttOffset = i.ReadU8();
698 count++;
699
700 if (m_nbrApInfoFields.back().hasBssid)
701 {
702 ReadFrom(i, m_nbrApInfoFields.back().tbttInformationSet.back().bssid);
703 count += 6;
704 }
705 if (m_nbrApInfoFields.back().hasShortSsid)
706 {
707 m_nbrApInfoFields.back().tbttInformationSet.back().shortSsid = i.ReadLsbtohU32();
708 count += 4;
709 }
710 if (m_nbrApInfoFields.back().hasBssParams)
711 {
712 m_nbrApInfoFields.back().tbttInformationSet.back().bssParameters = i.ReadU8();
713 count += 1;
714 }
715 if (m_nbrApInfoFields.back().has20MHzPsd)
716 {
717 m_nbrApInfoFields.back().tbttInformationSet.back().psd20MHz = i.ReadU8();
718 count += 1;
719 }
720 if (m_nbrApInfoFields.back().hasMldParams)
721 {
722 auto& mldParams = m_nbrApInfoFields.back().tbttInformationSet.back().mldParameters;
723 mldParams.apMldId = i.ReadU8();
724 uint16_t other = i.ReadLsbtohU16();
725 count += 3;
726 mldParams.linkId = other & 0x000f;
727 mldParams.bssParamsChangeCount = (other >> 4) & 0x00ff;
728 mldParams.allUpdates = (other >> 12) & 0x01;
729 mldParams.disabledLink = (other >> 13) & 0x01;
730 }
731 }
732 }
733
734 return count;
735}
736
737void
738ReducedNeighborReport::Print(std::ostream& os) const
739{
740 os << "Reduced Neighbor Report=[";
741 for (const auto& neighborApInfo : m_nbrApInfoFields)
742 {
743 os << "{Operating Class: " << +neighborApInfo.operatingClass
744 << ", Channel Number: " << +neighborApInfo.channelNumber
745 << ", TBTT Information Count: " << +neighborApInfo.tbttInfoHdr.tbttInfoCount
746 << ", TBTT Information Length: " << +neighborApInfo.tbttInfoHdr.tbttInfoLength << "}, ";
747 }
748 os << "]";
749}
750
751} // 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:138
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