A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
multi-link-element.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
11#include "ns3/address-utils.h"
12#include "ns3/mgt-headers.h"
13
14#include <utility>
15
16namespace ns3
17{
18
19/**
20 * CommonInfoBasicMle
21 */
22
23uint16_t
25{
26 // see Sec. 9.4.2.312.2.1 of 802.11be D1.5
27 return (m_linkIdInfo.has_value() ? 0x0001 : 0x0) |
28 (m_bssParamsChangeCount.has_value() ? 0x0002 : 0x0) |
29 (m_mediumSyncDelayInfo.has_value() ? 0x0004 : 0x0) |
30 (m_emlCapabilities.has_value() ? 0x0008 : 0x0) |
31 (m_mldCapabilities.has_value() ? 0x0010 : 0x0);
32}
33
34uint8_t
36{
37 uint8_t ret = 7; // Common Info Length (1) + MLD MAC Address (6)
38 ret += (m_linkIdInfo.has_value() ? 1 : 0);
39 ret += (m_bssParamsChangeCount.has_value() ? 1 : 0);
40 ret += (m_mediumSyncDelayInfo.has_value() ? 2 : 0);
41 ret += (m_emlCapabilities.has_value() ? 2 : 0);
42 ret += (m_mldCapabilities.has_value() ? 2 : 0);
43 return ret;
44}
45
46void
48{
49 start.WriteU8(GetSize()); // Common Info Length
51 if (m_linkIdInfo.has_value())
52 {
53 start.WriteU8(*m_linkIdInfo & 0x0f);
54 }
55 if (m_bssParamsChangeCount.has_value())
56 {
57 start.WriteU8(*m_bssParamsChangeCount);
58 }
59 if (m_mediumSyncDelayInfo.has_value())
60 {
61 start.WriteU8(m_mediumSyncDelayInfo->mediumSyncDuration);
62 uint8_t val = m_mediumSyncDelayInfo->mediumSyncOfdmEdThreshold |
63 (m_mediumSyncDelayInfo->mediumSyncMaxNTxops << 4);
64 start.WriteU8(val);
65 }
66 if (m_emlCapabilities.has_value())
67 {
68 uint16_t val =
69 m_emlCapabilities->emlsrSupport | (m_emlCapabilities->emlsrPaddingDelay << 1) |
70 (m_emlCapabilities->emlsrTransitionDelay << 4) |
71 (m_emlCapabilities->emlmrSupport << 7) | (m_emlCapabilities->emlmrDelay << 8) |
72 (m_emlCapabilities->transitionTimeout << 11);
73 start.WriteHtolsbU16(val);
74 }
75 if (m_mldCapabilities.has_value())
76 {
77 uint16_t val =
78 m_mldCapabilities->maxNSimultaneousLinks | (m_mldCapabilities->srsSupport << 4) |
79 (m_mldCapabilities->tidToLinkMappingSupport << 5) |
80 (m_mldCapabilities->freqSepForStrApMld << 7) | (m_mldCapabilities->aarSupport << 12);
81 start.WriteHtolsbU16(val);
82 }
83}
84
85uint8_t
87{
88 Buffer::Iterator i = start;
89
90 uint8_t length = i.ReadU8();
92 uint8_t count = 7;
93
94 if ((presence & 0x0001) != 0)
95 {
96 m_linkIdInfo = i.ReadU8() & 0x0f;
97 count++;
98 }
99 if ((presence & 0x0002) != 0)
100 {
102 count++;
103 }
104 if ((presence & 0x0004) != 0)
105 {
107 m_mediumSyncDelayInfo->mediumSyncDuration = i.ReadU8();
108 uint8_t val = i.ReadU8();
109 m_mediumSyncDelayInfo->mediumSyncOfdmEdThreshold = val & 0x0f;
110 m_mediumSyncDelayInfo->mediumSyncMaxNTxops = (val >> 4) & 0x0f;
111 count += 2;
112 }
113 if ((presence & 0x0008) != 0)
114 {
116 uint16_t val = i.ReadLsbtohU16();
117 m_emlCapabilities->emlsrSupport = val & 0x0001;
118 m_emlCapabilities->emlsrPaddingDelay = (val >> 1) & 0x0007;
119 m_emlCapabilities->emlsrTransitionDelay = (val >> 4) & 0x0007;
120 m_emlCapabilities->emlmrSupport = (val >> 7) & 0x0001;
121 m_emlCapabilities->emlmrDelay = (val >> 8) & 0x0007;
122 m_emlCapabilities->transitionTimeout = (val >> 11) & 0x000f;
123 count += 2;
124 }
125 if ((presence & 0x0010) != 0)
126 {
128 uint16_t val = i.ReadLsbtohU16();
129 m_mldCapabilities->maxNSimultaneousLinks = val & 0x000f;
130 m_mldCapabilities->srsSupport = (val >> 4) & 0x0001;
131 m_mldCapabilities->tidToLinkMappingSupport = (val >> 5) & 0x0003;
132 m_mldCapabilities->freqSepForStrApMld = (val >> 7) & 0x001f;
133 m_mldCapabilities->aarSupport = (val >> 12) & 0x0001;
134 count += 2;
135 }
136
137 NS_ABORT_MSG_IF(count != length,
138 "Common Info Length (" << +length
139 << ") differs "
140 "from actual number of bytes read ("
141 << +count << ")");
142 return count;
143}
144
145uint8_t
147{
148 auto delayUs = delay.GetMicroSeconds();
149
150 if (delayUs == 0)
151 {
152 return 0;
153 }
154
155 for (uint8_t i = 1; i <= 4; i++)
156 {
157 if (1 << (i + 4) == delayUs)
158 {
159 return i;
160 }
161 }
162
163 NS_ABORT_MSG("Value not allowed (" << delay.As(Time::US) << ")");
164 return 0;
165}
166
167Time
169{
170 NS_ABORT_MSG_IF(value > 4, "Value not allowed (" << +value << ")");
171 if (value == 0)
172 {
173 return MicroSeconds(0);
174 }
175 return MicroSeconds(1 << (4 + value));
176}
177
178uint8_t
180{
181 auto delayUs = delay.GetMicroSeconds();
182
183 if (delayUs == 0)
184 {
185 return 0;
186 }
187
188 for (uint8_t i = 1; i <= 5; i++)
189 {
190 if (1 << (i + 3) == delayUs)
191 {
192 return i;
193 }
194 }
195
196 NS_ABORT_MSG("Value not allowed (" << delay.As(Time::US) << ")");
197 return 0;
198}
199
200Time
202{
203 NS_ABORT_MSG_IF(value > 5, "Value not allowed (" << +value << ")");
204 if (value == 0)
205 {
206 return MicroSeconds(0);
207 }
208 return MicroSeconds(1 << (3 + value));
209}
210
211void
213{
214 int64_t delayUs = delay.GetMicroSeconds();
215 NS_ABORT_MSG_IF(delayUs % 32 != 0, "Delay must be a multiple of 32 microseconds");
216 delayUs /= 32;
217
218 if (!m_mediumSyncDelayInfo.has_value())
219 {
221 }
222 m_mediumSyncDelayInfo->mediumSyncDuration = (delayUs & 0xff);
223}
224
225Time
231
232void
234{
235 NS_ABORT_MSG_IF(threshold < -72 || threshold > -62, "Threshold may range from -72 to -62 dBm");
236 uint8_t value = 72 + threshold;
237
238 if (!m_mediumSyncDelayInfo.has_value())
239 {
241 }
243}
244
245int8_t
247{
249 return (m_mediumSyncDelayInfo->mediumSyncOfdmEdThreshold) - 72;
250}
251
252void
254{
255 NS_ASSERT_MSG(nTxops < 16, "Value " << +nTxops << "cannot be encoded in 4 bits");
256
257 if (!m_mediumSyncDelayInfo.has_value())
258 {
260 }
261
262 if (nTxops == 0)
263 {
264 // no limit on max number of TXOPs
266 return;
267 }
268
269 m_mediumSyncDelayInfo->mediumSyncMaxNTxops = --nTxops;
270}
271
272std::optional<uint8_t>
274{
276 uint8_t nTxops = m_mediumSyncDelayInfo->mediumSyncMaxNTxops;
277 if (nTxops == 15)
278 {
279 return std::nullopt;
280 }
281 return nTxops + 1;
282}
283
284/**
285 * MultiLinkElement
286 */
288 : m_containingFrame(frame),
289 m_commonInfo(std::in_place_type<std::monostate>) // initialize as UNSET
290{
291}
292
294 : MultiLinkElement(frame)
295{
296 NS_ASSERT(variant != UNSET);
297 SetVariant(variant);
298}
299
302{
303 return IE_EXTENSION;
304}
305
311
314{
315 return static_cast<Variant>(m_commonInfo.index());
316}
317
318void
320{
321 NS_ABORT_MSG_IF(GetVariant() != UNSET, "Multi-Link Element variant already set");
322 NS_ABORT_MSG_IF(variant == UNSET, "Invalid variant");
323
324 switch (variant)
325 {
326 case BASIC_VARIANT:
328 break;
329 default:
330 NS_ABORT_MSG("Unsupported variant: " << +variant);
331 }
332}
333
336{
337 return std::get<BASIC_VARIANT>(m_commonInfo);
338}
339
342{
343 return std::get<BASIC_VARIANT>(m_commonInfo);
344}
345
346void
348{
349 std::get<BASIC_VARIANT>(m_commonInfo).m_mldMacAddress = address;
350}
351
354{
355 return std::get<BASIC_VARIANT>(m_commonInfo).m_mldMacAddress;
356}
357
358void
360{
361 std::get<BASIC_VARIANT>(m_commonInfo).m_linkIdInfo = (linkIdInfo & 0x0f);
362}
363
364bool
366{
367 return std::get<BASIC_VARIANT>(m_commonInfo).m_linkIdInfo.has_value();
368}
369
370uint8_t
372{
373 return std::get<BASIC_VARIANT>(m_commonInfo).m_linkIdInfo.value();
374}
375
376void
378{
379 std::get<BASIC_VARIANT>(m_commonInfo).m_bssParamsChangeCount = count;
380}
381
382bool
384{
385 return std::get<BASIC_VARIANT>(m_commonInfo).m_bssParamsChangeCount.has_value();
386}
387
388uint8_t
390{
391 return std::get<BASIC_VARIANT>(m_commonInfo).m_bssParamsChangeCount.value();
392}
393
394void
396{
397 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
398 if (!emlCapabilities.has_value())
399 {
400 emlCapabilities = CommonInfoBasicMle::EmlCapabilities{};
401 }
402 emlCapabilities->emlsrSupport = supported ? 1 : 0;
403}
404
405void
407{
408 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
409 if (!emlCapabilities.has_value())
410 {
411 emlCapabilities = CommonInfoBasicMle::EmlCapabilities{};
412 }
414}
415
416void
418{
419 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
420 if (!emlCapabilities.has_value())
421 {
422 emlCapabilities = CommonInfoBasicMle::EmlCapabilities{};
423 }
425}
426
427void
429{
430 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
431 if (!emlCapabilities.has_value())
432 {
433 emlCapabilities = CommonInfoBasicMle::EmlCapabilities{};
434 }
435 auto timeoutUs = timeout.GetMicroSeconds();
436
437 if (timeoutUs == 0)
438 {
439 emlCapabilities->transitionTimeout = 0;
440 }
441 else
442 {
443 uint8_t i;
444 for (i = 1; i <= 10; i++)
445 {
446 if (1 << (i + 6) == timeoutUs)
447 {
448 emlCapabilities->transitionTimeout = i;
449 break;
450 }
451 }
452 NS_ABORT_MSG_IF(i > 10, "Value not allowed (" << timeout.As(Time::US) << ")");
453 }
454}
455
456bool
458{
459 return std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities.has_value();
460}
461
462bool
464{
465 return std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities->emlsrSupport;
466}
467
468Time
470{
471 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
472 NS_ASSERT(emlCapabilities);
473 return CommonInfoBasicMle::DecodeEmlsrPaddingDelay(emlCapabilities->emlsrPaddingDelay);
474}
475
476Time
478{
479 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
480 NS_ASSERT(emlCapabilities);
481 return CommonInfoBasicMle::DecodeEmlsrTransitionDelay(emlCapabilities->emlsrTransitionDelay);
482}
483
484Time
486{
487 auto& emlCapabilities = std::get<BASIC_VARIANT>(m_commonInfo).m_emlCapabilities;
488 NS_ASSERT(emlCapabilities);
489 if (emlCapabilities->transitionTimeout == 0)
490 {
491 return MicroSeconds(0);
492 }
493 return MicroSeconds(1 << (6 + emlCapabilities->transitionTimeout));
494}
495
497 : m_variant(variant),
498 m_staControl(0)
499{
500}
501
503 const PerStaProfileSubelement& perStaProfile)
504 : m_variant(perStaProfile.m_variant),
505 m_staControl(perStaProfile.m_staControl),
506 m_staMacAddress(perStaProfile.m_staMacAddress)
507{
508 // deep copy of the STA Profile field
509 auto staProfileCopy = [&](auto&& frame) {
510 using Ptr = std::decay_t<decltype(frame)>;
511 if constexpr (std::is_same_v<Ptr, std::monostate>)
512 {
513 return;
514 }
515 else
516 {
517 using T = std::decay_t<decltype(*frame.get())>;
518 m_staProfile = std::make_unique<T>(*frame.get());
519 }
520 };
521 std::visit(staProfileCopy, perStaProfile.m_staProfile);
522}
523
526{
527 // check for self-assignment
528 if (&perStaProfile == this)
529 {
530 return *this;
531 }
532
533 m_variant = perStaProfile.m_variant;
534 m_staControl = perStaProfile.m_staControl;
535 m_staMacAddress = perStaProfile.m_staMacAddress;
536
537 // deep copy of the STA Profile field
538 auto staProfileCopy = [&](auto&& frame) {
539 using Ptr = std::decay_t<decltype(frame)>;
540 if constexpr (std::is_same_v<Ptr, std::monostate>)
541 {
542 return;
543 }
544 else
545 {
546 using T = std::decay_t<decltype(*frame.get())>;
547 m_staProfile = std::make_unique<T>(*frame.get());
548 }
549 };
550 std::visit(staProfileCopy, perStaProfile.m_staProfile);
551
552 return *this;
553}
554
555void
557{
558 m_staControl &= 0xfff0; // reset Link ID subfield in the STA Control field
559 m_staControl |= (linkId & 0x0f);
560}
561
562uint8_t
564{
565 return static_cast<uint8_t>(m_staControl & 0x000f);
566}
567
568void
573
574bool
576{
577 return (m_staControl & 0x0010) != 0;
578}
579
580void
582{
583 NS_ABORT_IF(m_variant != BASIC_VARIANT);
584 m_staMacAddress = address;
585 m_staControl |= 0x0020;
586}
587
588bool
590{
591 return (m_staControl & 0x0020) != 0;
592}
593
596{
597 NS_ABORT_IF(!HasStaMacAddress());
598 return m_staMacAddress;
599}
600
601void
603 const std::variant<MgtAssocRequestHeader, MgtReassocRequestHeader>& assoc)
604{
605 std::visit(
606 [&](auto&& frame) {
607 m_staProfile = std::make_unique<std::decay_t<decltype(frame)>>(frame);
608 },
609 assoc);
610}
611
612void
614 std::variant<MgtAssocRequestHeader, MgtReassocRequestHeader>&& assoc)
615{
616 std::visit(
617 [&](auto&& frame) {
618 using T = std::decay_t<decltype(frame)>;
619 m_staProfile = std::make_unique<T>(std::forward<T>(frame));
620 },
621 assoc);
622}
623
624bool
626{
627 return std::holds_alternative<std::unique_ptr<MgtAssocRequestHeader>>(m_staProfile);
628}
629
630bool
632{
633 return std::holds_alternative<std::unique_ptr<MgtReassocRequestHeader>>(m_staProfile);
634}
635
638{
639 if (HasAssocRequest())
640 {
641 return *std::get<std::unique_ptr<MgtAssocRequestHeader>>(m_staProfile);
642 }
643 NS_ABORT_UNLESS(HasReassocRequest());
644 return *std::get<std::unique_ptr<MgtReassocRequestHeader>>(m_staProfile);
645}
646
647void
649{
650 m_staProfile = std::make_unique<MgtAssocResponseHeader>(assoc);
651}
652
653void
655{
656 m_staProfile = std::make_unique<MgtAssocResponseHeader>(std::move(assoc));
657}
658
659bool
661{
662 return std::holds_alternative<std::unique_ptr<MgtAssocResponseHeader>>(m_staProfile);
663}
664
667{
668 NS_ABORT_IF(!HasAssocResponse());
669 return *std::get<std::unique_ptr<MgtAssocResponseHeader>>(m_staProfile);
670}
671
672uint8_t
674{
675 uint8_t ret = 1; // STA Info Length
676
677 if (HasStaMacAddress())
678 {
679 ret += 6;
680 }
681 // TODO add other subfields of the STA Info field
682 return ret;
683}
684
690
691uint16_t
693{
694 uint16_t ret = 2; // STA Control field
695
696 ret += GetStaInfoLength();
697
698 auto staProfileSize = [&](auto&& frame) {
699 using T = std::decay_t<decltype(frame)>;
700 if constexpr (std::is_same_v<T, std::monostate>)
701 {
702 NS_ASSERT_MSG(std::holds_alternative<std::monostate>(m_containingFrame),
703 "Missing management frame for Per-STA Profile subelement");
704 return static_cast<uint32_t>(0);
705 }
706 else
707 {
708 using U = std::decay_t<decltype(*frame)>;
710 std::holds_alternative<std::reference_wrapper<const U>>(m_containingFrame),
711 "Containing frame type and frame type in Per-STA Profile do not match");
712 const auto& containing = std::get<std::reference_wrapper<const U>>(m_containingFrame);
713 return frame->GetSerializedSizeInPerStaProfile(containing);
714 }
715 };
716 ret += std::visit(staProfileSize, m_staProfile);
717
718 return ret;
719}
720
721void
723{
724 start.WriteHtolsbU16(m_staControl);
725 start.WriteU8(GetStaInfoLength());
726
727 if (HasStaMacAddress())
728 {
729 WriteTo(start, m_staMacAddress);
730 }
731 // TODO add other subfields of the STA Info field
732 auto staProfileSerialize = [&](auto&& frame) {
733 using T = std::decay_t<decltype(frame)>;
734 if constexpr (std::is_same_v<T, std::monostate>)
735 {
736 NS_ASSERT_MSG(std::holds_alternative<std::monostate>(m_containingFrame),
737 "Missing management frame for Per-STA Profile subelement");
738 return;
739 }
740 else
741 {
742 using U = std::decay_t<decltype(*frame)>;
744 std::holds_alternative<std::reference_wrapper<const U>>(m_containingFrame),
745 "Containing frame type and frame type in Per-STA Profile do not match");
746 const auto& containing = std::get<std::reference_wrapper<const U>>(m_containingFrame);
747 frame->SerializeInPerStaProfile(start, containing);
748 }
749 };
750 std::visit(staProfileSerialize, m_staProfile);
751}
752
753uint16_t
755 uint16_t length)
756{
757 Buffer::Iterator i = start;
758
759 m_staControl = i.ReadLsbtohU16();
760 i.ReadU8(); // STA Info Length
761
762 if (HasStaMacAddress())
763 {
764 ReadFrom(i, m_staMacAddress);
765 }
766
767 // TODO add other subfields of the STA Info field
768 uint16_t count = i.GetDistanceFrom(start);
769
770 NS_ASSERT_MSG(count <= length,
771 "Bytes read (" << count << ") exceed expected number (" << length << ")");
772
773 if (count == length)
774 {
775 return count;
776 }
777
778 auto staProfileDeserialize = [&](auto&& frame) {
779 using T = std::decay_t<decltype(frame)>;
780 if constexpr (!std::is_same_v<T, std::monostate>)
781 {
782 using U = std::decay_t<decltype(frame.get())>;
783 U assoc;
784 count += assoc.DeserializeFromPerStaProfile(i, length - count, frame.get());
785 m_staProfile = std::make_unique<U>(std::move(assoc));
786 }
787 };
788 std::visit(staProfileDeserialize, m_containingFrame);
789
790 return count;
791}
792
793void
795{
796 auto variant = GetVariant();
797 NS_ABORT_IF(variant == UNSET);
798 m_perStaProfileSubelements.emplace_back(variant);
799}
800
801std::size_t
806
809{
810 return m_perStaProfileSubelements.at(i);
811}
812
815{
816 return m_perStaProfileSubelements.at(i);
817}
818
819uint16_t
821{
822 uint16_t ret = 3; // ElementIdExt (1) + Multi-Link Control (2)
823
824 // add the Common Info field size (dependent on the Multi-Link Element variant)
825 ret += std::visit(
826 [](auto&& arg) -> uint8_t {
827 using T = std::decay_t<decltype(arg)>;
828 if constexpr (std::is_same_v<T, std::monostate>)
829 {
830 NS_ABORT_MSG("Multi-Link Element variant not set");
831 return 0;
832 }
833 else
834 {
835 return arg.GetSize();
836 }
837 },
839
840 for (const auto& subelement : m_perStaProfileSubelements)
841 {
842 subelement.m_containingFrame = m_containingFrame;
843 ret += subelement.GetSerializedSize();
844 }
845
846 return ret;
847}
848
849void
851{
852 // serialize the Multi-Link Control and Common Info fields
853 std::visit(
854 [this, &start](auto&& arg) {
855 using T = std::decay_t<decltype(arg)>;
856 if constexpr (std::is_same_v<T, std::monostate>)
857 {
858 NS_ABORT_MSG("Multi-Link Element variant not set");
859 }
860 else
861 {
862 uint16_t mlControl =
863 static_cast<uint8_t>(GetVariant()) + (arg.GetPresenceBitmap() << 4);
864 start.WriteHtolsbU16(mlControl);
865 arg.Serialize(start);
866 }
867 },
869
870 for (const auto& subelement : m_perStaProfileSubelements)
871 {
872 start = subelement.Serialize(start);
873 }
874}
875
876uint16_t
878{
879 Buffer::Iterator i = start;
880 uint16_t count = 0;
881
882 uint16_t mlControl = i.ReadLsbtohU16();
883 count += 2;
884
885 SetVariant(static_cast<Variant>(mlControl & 0x0007));
886 uint16_t presence = mlControl >> 4;
887
888 uint8_t nBytes = std::visit(
889 [&i, &presence](auto&& arg) -> uint8_t {
890 using T = std::decay_t<decltype(arg)>;
891 if constexpr (std::is_same_v<T, std::monostate>)
892 {
893 NS_ABORT_MSG("Multi-Link Element variant not set");
894 return 0;
895 }
896 else
897 {
898 return arg.Deserialize(i, presence);
899 }
900 },
902 i.Next(nBytes);
903 count += nBytes;
904
905 while (count < length)
906 {
907 switch (static_cast<SubElementId>(i.PeekU8()))
908 {
911 auto& perStaProfile = GetPerStaProfile(GetNPerStaProfileSubelements() - 1);
912 perStaProfile.m_containingFrame = m_containingFrame;
913 i = perStaProfile.Deserialize(i);
914 count = i.GetDistanceFrom(start);
915 }
916 break;
917 default:
918 NS_ABORT_MSG("Unsupported Subelement ID: " << +i.PeekU8());
919 }
920 }
921
922 return count;
923}
924
925} // namespace ns3
iterator in a Buffer instance
Definition buffer.h:89
uint16_t ReadLsbtohU16()
Definition buffer.cc:1053
uint32_t GetDistanceFrom(const Iterator &o) const
Definition buffer.cc:769
void Next()
go forward by one byte
Definition buffer.h:842
an EUI-48 address
Implement the header for management frames of type association and reassociation response.
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
@ US
microsecond
Definition nstime.h:107
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:402
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_UNLESS(cond)
Abnormal program termination if a condition is false.
Definition abort.h:118
#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
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1332
Variant
Multi-Link element variants.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
std::variant< std::reference_wrapper< MgtAssocRequestHeader >, std::reference_wrapper< MgtReassocRequestHeader > > AssocReqRefVariant
variant holding a reference to a (Re)Association Request
Definition ap-wifi-mac.h:48
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.
STL namespace.
ns3::Time timeout
uint8_t emlsrPaddingDelay
EMLSR Padding Delay.
uint8_t emlsrTransitionDelay
EMLSR Transition Delay.
Medium Synchronization Delay Information subfield.
uint8_t mediumSyncOfdmEdThreshold
Medium Synchronization OFDM ED Threshold.
uint8_t mediumSyncDuration
Medium Synchronization Duration.
uint8_t mediumSyncMaxNTxops
Medium Synchronization MAximum Number of TXOPs.
Common Info field of the Basic Multi-Link element.
uint16_t GetPresenceBitmap() const
Get the Presence Bitmap subfield of the Common Info field.
uint8_t GetSize() const
Get the size of the serialized Common Info field.
static uint8_t EncodeEmlsrTransitionDelay(Time delay)
static Time DecodeEmlsrTransitionDelay(uint8_t value)
std::optional< EmlCapabilities > m_emlCapabilities
EML Capabilities.
uint8_t Deserialize(Buffer::Iterator start, uint16_t presence)
Deserialize the Common Info field.
std::optional< uint8_t > GetMediumSyncMaxNTxops() const
Get the maximum number of TXOPs a non-AP STA is allowed to attempt to initiate while the MediumSyncDe...
int8_t GetMediumSyncOfdmEdThreshold() const
Get the Medium Synchronization OFDM ED Threshold in dBm.
std::optional< MldCapabilities > m_mldCapabilities
MLD Capabilities.
void SetMediumSyncOfdmEdThreshold(int8_t threshold)
Set the Medium Synchronization OFDM ED Threshold subfield of the Medium Synchronization Delay Informa...
static Time DecodeEmlsrPaddingDelay(uint8_t value)
void Serialize(Buffer::Iterator &start) const
Serialize the Common Info field.
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...
Time GetMediumSyncDelayTimer() const
Get 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.
static uint8_t EncodeEmlsrPaddingDelay(Time delay)
#define IE_EXTENSION
#define IE_EXT_MULTI_LINK_ELEMENT