A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ctrl-headers.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 MIRKO BANCHI
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: Mirko Banchi <mk.banchi@gmail.com>
18 */
19
20#include "ctrl-headers.h"
21
22#include "wifi-tx-vector.h"
23#include "wifi-utils.h"
24
25#include "ns3/address-utils.h"
26#include "ns3/he-phy.h"
27
28#include <algorithm>
29
30namespace ns3
31{
32
33/***********************************
34 * Block ack request
35 ***********************************/
36
37NS_OBJECT_ENSURE_REGISTERED(CtrlBAckRequestHeader);
38
40 : m_barAckPolicy(false),
41 m_barType(BlockAckReqType::BASIC)
42{
43}
44
46{
47}
48
51{
52 static TypeId tid = TypeId("ns3::CtrlBAckRequestHeader")
54 .SetGroupName("Wifi")
55 .AddConstructor<CtrlBAckRequestHeader>();
56 return tid;
57}
58
61{
62 return GetTypeId();
63}
64
65void
66CtrlBAckRequestHeader::Print(std::ostream& os) const
67{
68 os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq << std::dec;
69}
70
73{
74 uint32_t size = 0;
75 size += 2; // Bar control
76 switch (m_barType.m_variant)
77 {
81 size += 2;
82 break;
84 size += (2 + 2) * (m_tidInfo + 1);
85 break;
86 default:
87 NS_FATAL_ERROR("Invalid BA type");
88 break;
89 }
90 return size;
91}
92
93void
95{
96 Buffer::Iterator i = start;
98 switch (m_barType.m_variant)
99 {
104 break;
106 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
107 break;
108 default:
109 NS_FATAL_ERROR("Invalid BA type");
110 break;
111 }
112}
113
116{
117 Buffer::Iterator i = start;
119 switch (m_barType.m_variant)
120 {
125 break;
127 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
128 break;
129 default:
130 NS_FATAL_ERROR("Invalid BA type");
131 break;
132 }
133 return i.GetDistanceFrom(start);
134}
135
136uint16_t
138{
139 uint16_t res = 0;
140 switch (m_barType.m_variant)
141 {
143 break;
145 res |= (0x02 << 1);
146 break;
148 res |= (0x01 << 1);
149 break;
151 res |= (0x03 << 1);
152 break;
153 default:
154 NS_FATAL_ERROR("Invalid BA type");
155 break;
156 }
157 res |= (m_tidInfo << 12) & (0xf << 12);
158 return res;
159}
160
161void
163{
164 m_barAckPolicy = ((bar & 0x01) == 1);
165 if (((bar >> 1) & 0x0f) == 0x03)
166 {
168 }
169 else if (((bar >> 1) & 0x0f) == 0x01)
170 {
172 }
173 else if (((bar >> 1) & 0x0f) == 0x02)
174 {
176 }
177 else
178 {
180 }
181 m_tidInfo = (bar >> 12) & 0x0f;
182}
183
184uint16_t
186{
187 return (m_startingSeq << 4) & 0xfff0;
188}
189
190void
192{
193 m_startingSeq = (seqControl >> 4) & 0x0fff;
194}
195
196void
198{
199 m_barAckPolicy = immediateAck;
200}
201
202void
204{
205 m_barType = type;
206}
207
210{
211 return m_barType;
212}
213
214void
216{
217 m_tidInfo = static_cast<uint16_t>(tid);
218}
219
220void
222{
223 m_startingSeq = seq;
224}
225
226bool
228{
229 return m_barAckPolicy;
230}
231
232uint8_t
234{
235 auto tid = static_cast<uint8_t>(m_tidInfo);
236 return tid;
237}
238
239uint16_t
241{
242 return m_startingSeq;
243}
244
245bool
247{
249}
250
251bool
253{
255}
256
257bool
259{
261}
262
263bool
265{
267}
268
269/***********************************
270 * Block ack response
271 ***********************************/
272
274
276 : m_baAckPolicy(false),
277 m_tidInfo(0)
278{
280}
281
283{
284}
285
286TypeId
288{
289 static TypeId tid = TypeId("ns3::CtrlBAckResponseHeader")
290 .SetParent<Header>()
291 .SetGroupName("Wifi")
292 .AddConstructor<CtrlBAckResponseHeader>();
293 return tid;
294}
295
296TypeId
298{
299 return GetTypeId();
300}
301
302void
303CtrlBAckResponseHeader::Print(std::ostream& os) const
304{
306 {
307 os << "TID_INFO=" << m_tidInfo << ", StartingSeq=0x" << std::hex
308 << m_baInfo[0].m_startingSeq << std::dec;
309 }
310 else
311 {
312 for (std::size_t i = 0; i < m_baInfo.size(); i++)
313 {
314 os << "{AID=" << GetAid11(i) << ", TID=" << GetTidInfo(i) << ", StartingSeq=0x"
315 << std::hex << m_baInfo[i].m_startingSeq << std::dec << "}";
316 }
317 }
318}
319
322{
323 // This method only makes use of the configured BA type, so that functions like
324 // GetBlockAckSize () can easily return the size of a Block Ack of a given type
325 uint32_t size = 0;
326 size += 2; // BA control
327 switch (m_baType.m_variant)
328 {
332 size += (2 + m_baType.m_bitmapLen[0]);
333 break;
335 size += (2 + 2 + 8) * (m_tidInfo + 1); // Multi-TID block ack
336 break;
338 for (auto& bitmapLen : m_baType.m_bitmapLen)
339 {
340 size += 2 /* AID TID Info */ + (bitmapLen > 0 ? 2 : 0) /* BA SSC */ + bitmapLen;
341 }
342 break;
343 default:
344 NS_FATAL_ERROR("Invalid BA type");
345 break;
346 }
347 return size;
348}
349
350void
352{
353 Buffer::Iterator i = start;
355 switch (m_baType.m_variant)
356 {
361 i = SerializeBitmap(i);
362 break;
364 for (std::size_t index = 0; index < m_baInfo.size(); index++)
365 {
366 i.WriteHtolsbU16(m_baInfo[index].m_aidTidInfo);
367 if (GetAid11(index) != 2045)
368 {
369 if (!m_baInfo[index].m_bitmap.empty())
370 {
372 i = SerializeBitmap(i, index);
373 }
374 }
375 else
376 {
377 uint32_t reserved = 0;
378 i.WriteHtolsbU32(reserved);
379 WriteTo(i, m_baInfo[index].m_ra);
380 }
381 }
382 break;
384 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
385 break;
386 default:
387 NS_FATAL_ERROR("Invalid BA type");
388 break;
389 }
390}
391
394{
395 Buffer::Iterator i = start;
397 switch (m_baType.m_variant)
398 {
403 i = DeserializeBitmap(i);
404 break;
406 std::size_t index = 0;
407 while (i.GetRemainingSize() > 0)
408 {
409 m_baInfo.emplace_back();
410 m_baType.m_bitmapLen.push_back(0); // updated by next call to SetStartingSequenceControl
411
412 m_baInfo.back().m_aidTidInfo = i.ReadLsbtohU16();
413
414 if (GetAid11(index) != 2045)
415 {
416 // the Block Ack Starting Sequence Control and Block Ack Bitmap subfields
417 // are only present in Block acknowledgement context, i.e., if the Ack Type
418 // subfield is set to 0 and the TID subfield is set to a value from 0 to 7.
419 if (!GetAckType(index) && GetTidInfo(index) < 8)
420 {
422 i = DeserializeBitmap(i, index);
423 }
424 }
425 else
426 {
427 i.ReadLsbtohU32(); // next 4 bytes are reserved
428 ReadFrom(i, m_baInfo.back().m_ra);
429 // the length of this Per AID TID Info subfield is 12, so set
430 // the bitmap length to 8 to simulate the correct size
431 m_baType.m_bitmapLen.back() = 8;
432 }
433 index++;
434 }
435 }
436 break;
438 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
439 break;
440 default:
441 NS_FATAL_ERROR("Invalid BA type");
442 break;
443 }
444 return i.GetDistanceFrom(start);
445}
446
447void
449{
450 m_baAckPolicy = immediateAck;
451}
452
453void
455{
456 m_baType = type;
457 m_baInfo.clear();
458
459 for (auto& bitmapLen : m_baType.m_bitmapLen)
460 {
461 BaInfoInstance baInfoInstance{.m_aidTidInfo = 0,
462 .m_startingSeq = 0,
463 .m_bitmap = std::vector<uint8_t>(bitmapLen, 0),
464 .m_ra = Mac48Address()};
465
466 m_baInfo.emplace_back(baInfoInstance);
467 }
468}
469
472{
473 return m_baType;
474}
475
476void
477CtrlBAckResponseHeader::SetTidInfo(uint8_t tid, std::size_t index)
478{
480 "index can only be non null for Multi-STA Block Ack");
481 NS_ASSERT(index < m_baInfo.size());
482
484 {
485 m_tidInfo = static_cast<uint16_t>(tid);
486 }
487 else
488 {
489 m_baInfo[index].m_aidTidInfo |= ((static_cast<uint16_t>(tid) & 0x000f) << 12);
490 }
491}
492
493void
494CtrlBAckResponseHeader::SetStartingSequence(uint16_t seq, std::size_t index)
495{
497 "index can only be non null for Multi-STA Block Ack");
498 NS_ASSERT(index < m_baInfo.size());
499
500 m_baInfo[index].m_startingSeq = seq;
501}
502
503bool
505{
506 return m_baAckPolicy;
507}
508
509uint8_t
511{
513 "index can only be non null for Multi-STA Block Ack");
514 NS_ASSERT(index < m_baInfo.size());
515
516 uint8_t tid = 0;
517
519 {
520 tid = static_cast<uint8_t>(m_tidInfo);
521 }
522 else
523 {
524 tid = static_cast<uint8_t>((m_baInfo[index].m_aidTidInfo >> 12) & 0x000f);
525 }
526 return tid;
527}
528
529uint16_t
531{
533 "index can only be non null for Multi-STA Block Ack");
534 NS_ASSERT(index < m_baInfo.size());
535
536 return m_baInfo[index].m_startingSeq;
537}
538
539bool
541{
543}
544
545bool
547{
549}
550
551bool
553{
555}
556
557bool
559{
561}
562
563bool
565{
567}
568
569void
570CtrlBAckResponseHeader::SetAid11(uint16_t aid, std::size_t index)
571{
573
574 m_baInfo[index].m_aidTidInfo |= (aid & 0x07ff);
575}
576
577uint16_t
578CtrlBAckResponseHeader::GetAid11(std::size_t index) const
579{
581
582 return m_baInfo[index].m_aidTidInfo & 0x07ff;
583}
584
585void
586CtrlBAckResponseHeader::SetAckType(bool type, std::size_t index)
587{
589
590 if (type)
591 {
592 m_baInfo[index].m_aidTidInfo |= (1 << 11);
593 }
594}
595
596bool
598{
600
601 return ((m_baInfo[index].m_aidTidInfo >> 11) & 0x0001) != 0;
602}
603
604void
606{
607 NS_ASSERT(GetAid11(index) == 2045);
608
609 m_baInfo[index].m_ra = ra;
610}
611
614{
615 NS_ASSERT(GetAid11(index) == 2045);
616
617 return m_baInfo[index].m_ra;
618}
619
620std::size_t
622{
624 return m_baInfo.size();
625}
626
627std::vector<uint32_t>
629{
631
632 std::vector<uint32_t> ret;
633 ret.reserve(m_baInfo.size());
634 for (uint32_t i = 0; i < m_baInfo.size(); i++)
635 {
636 if (GetAid11(i) == aid)
637 {
638 ret.push_back(i);
639 }
640 }
641 return ret;
642}
643
644uint16_t
646{
647 uint16_t res = 0;
648 if (m_baAckPolicy)
649 {
650 res |= 0x1;
651 }
652 switch (m_baType.m_variant)
653 {
655 break;
657 res |= (0x02 << 1);
658 break;
660 res |= (0x01 << 1);
661 break;
663 res |= (0x03 << 1);
664 break;
666 res |= (0x0b << 1);
667 break;
668 default:
669 NS_FATAL_ERROR("Invalid BA type");
670 break;
671 }
673 {
674 res |= (m_tidInfo << 12) & (0xf << 12);
675 }
676 return res;
677}
678
679void
681{
682 m_baAckPolicy = ((ba & 0x01) == 1);
683 if (((ba >> 1) & 0x0f) == 0x03)
684 {
686 }
687 else if (((ba >> 1) & 0x0f) == 0x01)
688 {
690 }
691 else if (((ba >> 1) & 0x0f) == 0x02)
692 {
694 }
695 else if (((ba >> 1) & 0x0f) == 0)
696 {
698 }
699 else if (((ba >> 1) & 0x0f) == 0x0b)
700 {
702 }
703 else
704 {
705 NS_FATAL_ERROR("Invalid BA type");
706 }
708 {
709 m_tidInfo = (ba >> 12) & 0x0f;
710 }
711}
712
713uint16_t
715{
717 "index can only be non null for Multi-STA Block Ack");
718 NS_ASSERT(index < m_baInfo.size());
719
720 uint16_t ret = (m_baInfo[index].m_startingSeq << 4) & 0xfff0;
721
722 // The Fragment Number subfield encodes the length of the bitmap for Compressed and Multi-STA
723 // variants (see sections 9.3.1.8.2 and 9.3.1.8.7 of 802.11ax-2021 and 802.11be Draft 4.0).
724 // Note that Fragmentation Level 3 is not supported.
726 {
727 switch (m_baType.m_bitmapLen[0])
728 {
729 case 8:
730 // do nothing
731 break;
732 case 32:
733 ret |= 0x0004;
734 break;
735 case 64:
736 ret |= 0x0008;
737 break;
738 case 128:
739 ret |= 0x000a;
740 break;
741 default:
742 NS_ABORT_MSG("Unsupported bitmap length: " << +m_baType.m_bitmapLen[0] << " bytes");
743 }
744 }
746 {
747 NS_ASSERT(m_baInfo.size() == m_baType.m_bitmapLen.size());
748 NS_ASSERT_MSG(!m_baInfo[index].m_bitmap.empty(),
749 "This Per AID TID Info subfield has no Starting Sequence Control subfield");
750
751 switch (m_baType.m_bitmapLen[index])
752 {
753 case 8:
754 // do nothing
755 break;
756 case 16:
757 ret |= 0x0002;
758 break;
759 case 32:
760 ret |= 0x0004;
761 break;
762 case 4:
763 ret |= 0x0006;
764 break;
765 case 64:
766 ret |= 0x0008;
767 break;
768 case 128:
769 ret |= 0x000a;
770 break;
771 default:
772 NS_ABORT_MSG("Unsupported bitmap length: " << +m_baType.m_bitmapLen[index] << " bytes");
773 }
774 }
775 return ret;
776}
777
778void
779CtrlBAckResponseHeader::SetStartingSequenceControl(uint16_t seqControl, std::size_t index)
780{
782 "index can only be non null for Multi-STA Block Ack");
783 NS_ASSERT(index < m_baInfo.size());
784
785 // The Fragment Number subfield encodes the length of the bitmap for Compressed and Multi-STA
786 // variants (see sections 9.3.1.8.2 and 9.3.1.8.7 of 802.11ax-2021 and 802.11be Draft 4.0).
787 // Note that Fragmentation Level 3 is not supported.
789 {
790 uint16_t fragNumber = seqControl & 0x000f;
791
792 if ((fragNumber & 0x0001) == 1)
793 {
794 NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
795 }
796 switch (fragNumber)
797 {
798 case 0:
800 break;
801 case 4:
803 break;
804 case 8:
806 break;
807 case 10:
809 break;
810 default:
811 NS_ABORT_MSG("Unsupported fragment number: " << fragNumber);
812 }
813 }
815 {
816 uint16_t fragNumber = seqControl & 0x000f;
817
818 if ((fragNumber & 0x0001) == 1)
819 {
820 NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
821 }
822 uint8_t bitmapLen = 0;
823 switch (fragNumber)
824 {
825 case 0:
826 bitmapLen = 8;
827 break;
828 case 2:
829 bitmapLen = 16;
830 break;
831 case 4:
832 bitmapLen = 32;
833 break;
834 case 6:
835 bitmapLen = 4;
836 break;
837 case 8:
838 bitmapLen = 64;
839 break;
840 case 10:
841 bitmapLen = 128;
842 break;
843 default:
844 NS_ABORT_MSG("Unsupported fragment number: " << fragNumber);
845 }
846 m_baType.m_bitmapLen[index] = bitmapLen;
847 m_baInfo[index].m_bitmap.assign(bitmapLen, 0);
848 }
849
850 m_baInfo[index].m_startingSeq = (seqControl >> 4) & 0x0fff;
851}
852
855{
857 "index can only be non null for Multi-STA Block Ack");
858 NS_ASSERT(index < m_baInfo.size());
859
860 Buffer::Iterator i = start;
861 switch (m_baType.m_variant)
862 {
867 for (const auto& byte : m_baInfo[index].m_bitmap)
868 {
869 i.WriteU8(byte);
870 }
871 break;
873 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
874 break;
875 default:
876 NS_FATAL_ERROR("Invalid BA type");
877 break;
878 }
879 return i;
880}
881
884{
886 "index can only be non null for Multi-STA Block Ack");
887 NS_ASSERT(index < m_baInfo.size());
888
889 Buffer::Iterator i = start;
890 switch (m_baType.m_variant)
891 {
896 for (uint8_t j = 0; j < m_baType.m_bitmapLen[index]; j++)
897 {
898 m_baInfo[index].m_bitmap[j] = i.ReadU8();
899 }
900 break;
902 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
903 break;
904 default:
905 NS_FATAL_ERROR("Invalid BA type");
906 break;
907 }
908 return i;
909}
910
911void
912CtrlBAckResponseHeader::SetReceivedPacket(uint16_t seq, std::size_t index)
913{
915 "index can only be non null for Multi-STA Block Ack");
916 NS_ASSERT(index < m_baInfo.size());
917
918 if (!IsInBitmap(seq, index))
919 {
920 return;
921 }
922 switch (m_baType.m_variant)
923 {
925 /* To set correctly basic block ack bitmap we need fragment number too.
926 So if it's not specified, we consider packet not fragmented. */
927 m_baInfo[index].m_bitmap[IndexInBitmap(seq) * 2] |= 0x01;
928 break;
932 uint16_t i = IndexInBitmap(seq, index);
933 m_baInfo[index].m_bitmap[i / 8] |= (uint8_t(0x01) << (i % 8));
934 break;
935 }
937 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
938 break;
939 default:
940 NS_FATAL_ERROR("Invalid BA type");
941 break;
942 }
943}
944
945void
947{
948 NS_ASSERT(frag < 16);
949 if (!IsInBitmap(seq))
950 {
951 return;
952 }
953 switch (m_baType.m_variant)
954 {
956 m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] |= (0x01 << (frag % 8));
957 break;
961 /* We can ignore this...compressed block ack doesn't support
962 acknowledgment of single fragments */
963 break;
965 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
966 break;
967 default:
968 NS_FATAL_ERROR("Invalid BA type");
969 break;
970 }
971}
972
973bool
974CtrlBAckResponseHeader::IsPacketReceived(uint16_t seq, std::size_t index) const
975{
977 "index can only be non null for Multi-STA Block Ack");
978 NS_ASSERT(index < m_baInfo.size());
979
981 GetTidInfo(index) == 14)
982 {
983 // All-ack context
984 return true;
985 }
986 if (!IsInBitmap(seq, index))
987 {
988 return false;
989 }
990 switch (m_baType.m_variant)
991 {
993 /*It's impossible to say if an entire packet was correctly received. */
994 return false;
998 uint16_t i = IndexInBitmap(seq, index);
999 uint8_t mask = uint8_t(0x01) << (i % 8);
1000 return (m_baInfo[index].m_bitmap[i / 8] & mask) != 0;
1001 }
1003 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
1004 break;
1005 default:
1006 NS_FATAL_ERROR("Invalid BA type");
1007 break;
1008 }
1009 return false;
1010}
1011
1012bool
1013CtrlBAckResponseHeader::IsFragmentReceived(uint16_t seq, uint8_t frag) const
1014{
1015 NS_ASSERT(frag < 16);
1016 if (!IsInBitmap(seq))
1017 {
1018 return false;
1019 }
1020 switch (m_baType.m_variant)
1021 {
1023 return (m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] & (0x01 << (frag % 8))) !=
1024 0;
1028 /* We can ignore this...compressed block ack doesn't support
1029 acknowledgement of single fragments */
1030 return false;
1032 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
1033 break;
1034 }
1035 default: {
1036 NS_FATAL_ERROR("Invalid BA type");
1037 break;
1038 }
1039 }
1040 return false;
1041}
1042
1043uint16_t
1044CtrlBAckResponseHeader::IndexInBitmap(uint16_t seq, std::size_t index) const
1045{
1046 uint16_t i;
1047 if (seq >= m_baInfo[index].m_startingSeq)
1048 {
1049 i = seq - m_baInfo[index].m_startingSeq;
1050 }
1051 else
1052 {
1053 i = SEQNO_SPACE_SIZE - m_baInfo[index].m_startingSeq + seq;
1054 }
1055
1056 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1057
1059 {
1060 nAckedMpdus = nAckedMpdus / 16;
1061 }
1062
1063 NS_ASSERT(i < nAckedMpdus);
1064 return i;
1065}
1066
1067bool
1068CtrlBAckResponseHeader::IsInBitmap(uint16_t seq, std::size_t index) const
1069{
1071 "index can only be non null for Multi-STA Block Ack");
1072 NS_ASSERT(index < m_baType.m_bitmapLen.size());
1073
1074 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1075
1077 {
1078 nAckedMpdus = nAckedMpdus / 16;
1079 }
1080
1081 return (seq - m_baInfo[index].m_startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE <
1082 nAckedMpdus;
1083}
1084
1085const std::vector<uint8_t>&
1087{
1089 "index can only be non null for Multi-STA Block Ack");
1090 NS_ASSERT(index < m_baInfo.size());
1091
1092 return m_baInfo[index].m_bitmap;
1093}
1094
1095void
1097{
1099 "index can only be non null for Multi-STA Block Ack");
1100 NS_ASSERT(index < m_baInfo.size());
1101
1102 m_baInfo[index].m_bitmap.assign(m_baType.m_bitmapLen[index], 0);
1103}
1104
1105/***********************************
1106 * Trigger frame - User Info field
1107 ***********************************/
1108
1110 TriggerFrameVariant variant)
1111 : m_variant(variant),
1112 m_aid12(0),
1113 m_ruAllocation(0),
1114 m_ulFecCodingType(false),
1115 m_ulMcs(0),
1116 m_ulDcm(false),
1117 m_ps160(true),
1118 m_ulTargetRssi(0),
1119 m_triggerType(triggerType),
1120 m_basicTriggerDependentUserInfo(0)
1121{
1122 memset(&m_bits26To31, 0, sizeof(m_bits26To31));
1123}
1124
1126{
1127}
1128
1131{
1132 NS_ABORT_MSG_IF(m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1133
1134 // check for self-assignment
1135 if (&userInfo == this)
1136 {
1137 return *this;
1138 }
1139
1140 m_variant = userInfo.m_variant;
1141 m_aid12 = userInfo.m_aid12;
1142 m_ruAllocation = userInfo.m_ruAllocation;
1144 m_ulMcs = userInfo.m_ulMcs;
1145 m_ulDcm = userInfo.m_ulDcm;
1146 m_ps160 = userInfo.m_ps160;
1147 m_bits26To31 = userInfo.m_bits26To31;
1148 m_ulTargetRssi = userInfo.m_ulTargetRssi;
1151 return *this;
1152}
1153
1154void
1155CtrlTriggerUserInfoField::Print(std::ostream& os) const
1156{
1157 os << ", USER_INFO " << (m_variant == TriggerFrameVariant::HE ? "HE" : "EHT")
1158 << " variant AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation
1159 << ", MCS=" << +m_ulMcs;
1160}
1161
1164{
1165 uint32_t size = 0;
1166 size += 5; // User Info (excluding Trigger Dependent User Info)
1167
1168 switch (m_triggerType)
1169 {
1172 size += 1;
1173 break;
1175 size +=
1176 m_muBarTriggerDependentUserInfo.GetSerializedSize(); // BAR Control and BAR Information
1177 break;
1178 default:;
1179 // The Trigger Dependent User Info subfield is not present in the other variants
1180 }
1181
1182 return size;
1183}
1184
1187{
1189 "BFRP Trigger frame is not supported");
1191 "GCR-MU-BAR Trigger frame is not supported");
1193 "NFRP Trigger frame is not supported");
1194
1195 Buffer::Iterator i = start;
1196
1197 uint32_t userInfo = 0; // User Info except the MSB
1198 userInfo |= (m_aid12 & 0x0fff);
1199 userInfo |= (m_ruAllocation << 12);
1200 userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1201 userInfo |= (m_ulMcs & 0x0f) << 21;
1203 {
1204 userInfo |= (m_ulDcm ? 1 << 25 : 0);
1205 }
1206
1207 if (m_aid12 != 0 && m_aid12 != 2045)
1208 {
1209 userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1210 userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1211 }
1212 else
1213 {
1214 userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1215 userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1216 }
1217
1218 i.WriteHtolsbU32(userInfo);
1219 // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and B39, which is
1220 // reserved in the HE variant and the PS160 subfield in the EHT variant.
1221 uint8_t bit32To39 = m_ulTargetRssi;
1223 {
1224 bit32To39 |= (m_ps160 ? 1 << 7 : 0);
1225 }
1226
1227 i.WriteU8(bit32To39);
1228
1230 {
1232 }
1234 {
1237 }
1238
1239 return i;
1240}
1241
1244{
1246 "BFRP Trigger frame is not supported");
1248 "GCR-MU-BAR Trigger frame is not supported");
1250 "NFRP Trigger frame is not supported");
1251
1252 Buffer::Iterator i = start;
1253
1254 uint32_t userInfo = i.ReadLsbtohU32();
1255
1256 m_aid12 = userInfo & 0x0fff;
1257 NS_ABORT_MSG_IF(m_aid12 == 4095, "Cannot deserialize a Padding field");
1258 m_ruAllocation = (userInfo >> 12) & 0xff;
1259 m_ulFecCodingType = (userInfo >> 20) & 0x01;
1260 m_ulMcs = (userInfo >> 21) & 0x0f;
1262 {
1263 m_ulDcm = (userInfo >> 25) & 0x01;
1264 }
1265
1266 if (m_aid12 != 0 && m_aid12 != 2045)
1267 {
1268 m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1269 m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1270 }
1271 else
1272 {
1273 m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1274 m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1275 }
1276
1277 uint8_t bit32To39 = i.ReadU8();
1278 m_ulTargetRssi = bit32To39 & 0x7f; // B39 is reserved in HE variant
1280 {
1281 m_ps160 = (bit32To39 >> 7) == 1;
1282 }
1283
1285 {
1287 }
1289 {
1291 i.Next(len);
1292 }
1293
1294 return i;
1295}
1296
1299{
1300 return m_triggerType;
1301}
1302
1305{
1306 switch (m_variant)
1307 {
1309 return WIFI_PREAMBLE_HE_TB;
1311 return WIFI_PREAMBLE_EHT_TB;
1312 default:
1313 NS_ABORT_MSG("Unexpected variant: " << +static_cast<uint8_t>(m_variant));
1314 }
1315 return WIFI_PREAMBLE_LONG; // to silence warning
1316}
1317
1318void
1320{
1321 m_aid12 = aid & 0x0fff;
1322}
1323
1324uint16_t
1326{
1327 return m_aid12;
1328}
1329
1330bool
1332{
1333 return (m_aid12 == 0);
1334}
1335
1336bool
1338{
1339 return (m_aid12 == 2045);
1340}
1341
1342void
1344{
1345 NS_ABORT_MSG_IF(ru.GetIndex() == 0, "Valid indices start at 1");
1347 "SetMuRtsRuAllocation() must be used for MU-RTS");
1348
1349 switch (ru.GetRuType())
1350 {
1351 case HeRu::RU_26_TONE:
1352 m_ruAllocation = ru.GetIndex() - 1;
1353 break;
1354 case HeRu::RU_52_TONE:
1355 m_ruAllocation = ru.GetIndex() + 36;
1356 break;
1357 case HeRu::RU_106_TONE:
1358 m_ruAllocation = ru.GetIndex() + 52;
1359 break;
1360 case HeRu::RU_242_TONE:
1361 m_ruAllocation = ru.GetIndex() + 60;
1362 break;
1363 case HeRu::RU_484_TONE:
1364 m_ruAllocation = ru.GetIndex() + 64;
1365 break;
1366 case HeRu::RU_996_TONE:
1367 m_ruAllocation = 67;
1368 break;
1370 m_ruAllocation = 68;
1371 break;
1372 default:
1373 NS_FATAL_ERROR("RU type unknown.");
1374 break;
1375 }
1376
1377 NS_ABORT_MSG_IF(m_ruAllocation > 68, "Reserved value.");
1378
1379 m_ruAllocation <<= 1;
1380 if (!ru.GetPrimary80MHz())
1381 {
1383 }
1384}
1385
1388{
1390 "GetMuRtsRuAllocation() must be used for MU-RTS");
1391
1392 HeRu::RuType ruType;
1393 std::size_t index;
1394
1395 bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1396
1397 uint8_t val = m_ruAllocation >> 1;
1398
1399 if (val < 37)
1400 {
1401 ruType = HeRu::RU_26_TONE;
1402 index = val + 1;
1403 }
1404 else if (val < 53)
1405 {
1406 ruType = HeRu::RU_52_TONE;
1407 index = val - 36;
1408 }
1409 else if (val < 61)
1410 {
1411 ruType = HeRu::RU_106_TONE;
1412 index = val - 52;
1413 }
1414 else if (val < 65)
1415 {
1416 ruType = HeRu::RU_242_TONE;
1417 index = val - 60;
1418 }
1419 else if (val < 67)
1420 {
1421 ruType = HeRu::RU_484_TONE;
1422 index = val - 64;
1423 }
1424 else if (val == 67)
1425 {
1426 ruType = HeRu::RU_996_TONE;
1427 index = 1;
1428 }
1429 else if (val == 68)
1430 {
1431 ruType = HeRu::RU_2x996_TONE;
1432 index = 1;
1433 }
1434 else
1435 {
1436 NS_FATAL_ERROR("Reserved value.");
1437 }
1438
1439 return HeRu::RuSpec(ruType, index, primary80MHz);
1440}
1441
1442void
1444{
1446 "SetMuRtsRuAllocation() can only be used for MU-RTS");
1448 value < 61 || value > 68,
1449 "Value "
1450 << +value
1451 << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1452
1453 m_ruAllocation = (value << 1);
1454 if (value == 68)
1455 {
1456 // set B0 for 160 MHz and 80+80 MHz indication
1458 }
1459}
1460
1461uint8_t
1463{
1465 "GetMuRtsRuAllocation() can only be used for MU-RTS");
1466 uint8_t value = (m_ruAllocation >> 1);
1468 value < 61 || value > 68,
1469 "Value "
1470 << +value
1471 << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1472 return value;
1473}
1474
1475void
1477{
1478 m_ulFecCodingType = ldpc;
1479}
1480
1481bool
1483{
1484 return m_ulFecCodingType;
1485}
1486
1487void
1489{
1490 uint8_t maxMcs = m_variant == TriggerFrameVariant::EHT ? 13 : 11;
1491 NS_ABORT_MSG_IF(mcs > maxMcs, "Invalid MCS index");
1492 m_ulMcs = mcs;
1493}
1494
1495uint8_t
1497{
1498 return m_ulMcs;
1499}
1500
1501void
1503{
1504 NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1505 m_ulDcm = dcm;
1506}
1507
1508bool
1510{
1511 NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1512 return m_ulDcm;
1513}
1514
1515void
1516CtrlTriggerUserInfoField::SetSsAllocation(uint8_t startingSs, uint8_t nSs)
1517{
1518 NS_ABORT_MSG_IF(m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1519 NS_ABORT_MSG_IF(!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1520 NS_ABORT_MSG_IF(!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1521
1522 m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1523 m_bits26To31.ssAllocation.nSs = nSs - 1;
1524}
1525
1526uint8_t
1528{
1529 if (m_aid12 == 0 || m_aid12 == 2045)
1530 {
1531 return 1;
1532 }
1533 return m_bits26To31.ssAllocation.startingSs + 1;
1534}
1535
1536uint8_t
1538{
1539 if (m_aid12 == 0 || m_aid12 == 2045)
1540 {
1541 return 1;
1542 }
1543 return m_bits26To31.ssAllocation.nSs + 1;
1544}
1545
1546void
1548{
1549 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1550 NS_ABORT_MSG_IF(!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1551
1552 m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1553 m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1554}
1555
1556uint8_t
1558{
1559 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1560
1561 return m_bits26To31.raRuInformation.nRaRu + 1;
1562}
1563
1564bool
1566{
1567 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1568
1569 return m_bits26To31.raRuInformation.moreRaRu;
1570}
1571
1572void
1574{
1575 m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1576}
1577
1578void
1580{
1581 NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
1582
1583 m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
1584}
1585
1586bool
1588{
1589 return (m_ulTargetRssi == 127);
1590}
1591
1592int8_t
1594{
1595 NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
1596
1597 return static_cast<int8_t>(m_ulTargetRssi) - 110;
1598}
1599
1600void
1602 uint8_t tidLimit,
1603 AcIndex prefAc)
1604{
1605 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1606
1607 m_basicTriggerDependentUserInfo = (spacingFactor & 0x03) |
1608 (tidLimit & 0x07) << 2
1609 // B5 is reserved
1610 | (prefAc & 0x03) << 6;
1611}
1612
1613uint8_t
1615{
1616 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1617
1618 return m_basicTriggerDependentUserInfo & 0x03;
1619}
1620
1621uint8_t
1623{
1624 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1625
1626 return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1627}
1628
1629AcIndex
1631{
1632 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1633
1634 return AcIndex((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1635}
1636
1637void
1639{
1641 "Not a MU-BAR Trigger frame");
1644 "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1646}
1647
1650{
1652 "Not a MU-BAR Trigger frame");
1653
1655}
1656
1657/***********************************
1658 * Trigger frame
1659 ***********************************/
1660
1662
1664 : m_variant(TriggerFrameVariant::HE),
1665 m_triggerType(TriggerFrameType::BASIC_TRIGGER),
1666 m_ulLength(0),
1667 m_moreTF(false),
1668 m_csRequired(false),
1669 m_ulBandwidth(0),
1670 m_giAndLtfType(0),
1671 m_apTxPower(0),
1672 m_ulSpatialReuse(0),
1673 m_padding(0)
1674{
1675}
1676
1679{
1681 "This constructor cannot be used for MU-RTS");
1682
1683 switch (txVector.GetPreambleType())
1684 {
1687 break;
1690 break;
1691 default:
1692 NS_ABORT_MSG("Cannot create a TF out of a TXVECTOR with preamble type: "
1693 << txVector.GetPreambleType());
1694 }
1695
1696 m_triggerType = type;
1697 SetUlBandwidth(txVector.GetChannelWidth());
1698 SetUlLength(txVector.GetLength());
1699 uint16_t gi = txVector.GetGuardInterval();
1700 if (gi == 800 || gi == 1600)
1701 {
1702 m_giAndLtfType = 1;
1703 }
1704 else
1705 {
1706 m_giAndLtfType = 2;
1707 }
1708 for (auto& userInfo : txVector.GetHeMuUserInfoMap())
1709 {
1711 ui.SetAid12(userInfo.first);
1712 ui.SetRuAllocation(userInfo.second.ru);
1713 ui.SetUlMcs(userInfo.second.mcs);
1714 ui.SetSsAllocation(1, userInfo.second.nss); // MU-MIMO is not supported
1715 }
1716}
1717
1719{
1720}
1721
1724{
1725 // check for self-assignment
1726 if (&trigger == this)
1727 {
1728 return *this;
1729 }
1730
1731 m_variant = trigger.m_variant;
1732 m_triggerType = trigger.m_triggerType;
1733 m_ulLength = trigger.m_ulLength;
1734 m_moreTF = trigger.m_moreTF;
1735 m_csRequired = trigger.m_csRequired;
1736 m_ulBandwidth = trigger.m_ulBandwidth;
1738 m_apTxPower = trigger.m_apTxPower;
1740 m_padding = trigger.m_padding;
1741 m_userInfoFields.clear();
1743 return *this;
1744}
1745
1746TypeId
1748{
1749 static TypeId tid = TypeId("ns3::CtrlTriggerHeader")
1750 .SetParent<Header>()
1751 .SetGroupName("Wifi")
1752 .AddConstructor<CtrlTriggerHeader>();
1753 return tid;
1754}
1755
1756TypeId
1758{
1759 return GetTypeId();
1760}
1761
1762void
1763CtrlTriggerHeader::Print(std::ostream& os) const
1764{
1765 os << "TriggerType=" << GetTypeString() << ", Bandwidth=" << +GetUlBandwidth()
1766 << ", UL Length=" << m_ulLength;
1767
1768 for (auto& ui : m_userInfoFields)
1769 {
1770 ui.Print(os);
1771 }
1772}
1773
1774void
1776{
1778 "Cannot change Common Info field variant if User Info fields are present");
1779 m_variant = variant;
1780}
1781
1784{
1785 return m_variant;
1786}
1787
1790{
1791 uint32_t size = 0;
1792 size += 8; // Common Info (excluding Trigger Dependent Common Info)
1793
1794 // Add the size of the Trigger Dependent Common Info subfield
1796 {
1797 size += 4;
1798 }
1799
1800 for (auto& ui : m_userInfoFields)
1801 {
1802 size += ui.GetSerializedSize();
1803 }
1804
1805 size += m_padding;
1806
1807 return size;
1808}
1809
1810void
1812{
1814 "BFRP Trigger frame is not supported");
1816 "GCR-MU-BAR Trigger frame is not supported");
1818 "NFRP Trigger frame is not supported");
1819
1820 Buffer::Iterator i = start;
1821
1822 uint64_t commonInfo = 0;
1823 commonInfo |= (static_cast<uint8_t>(m_triggerType) & 0x0f);
1824 commonInfo |= (m_ulLength & 0x0fff) << 4;
1825 commonInfo |= (m_moreTF ? 1 << 16 : 0);
1826 commonInfo |= (m_csRequired ? 1 << 17 : 0);
1827 commonInfo |= (m_ulBandwidth & 0x03) << 18;
1828 commonInfo |= (m_giAndLtfType & 0x03) << 20;
1829 commonInfo |= static_cast<uint64_t>(m_apTxPower & 0x3f) << 28;
1830 commonInfo |= static_cast<uint64_t>(m_ulSpatialReuse) << 37;
1832 {
1833 uint64_t ulHeSigA2 = 0x01ff; // nine bits equal to 1
1834 commonInfo |= ulHeSigA2 << 54;
1835 }
1836
1837 i.WriteHtolsbU64(commonInfo);
1838
1839 for (auto& ui : m_userInfoFields)
1840 {
1841 i = ui.Serialize(i);
1842 }
1843
1844 for (std::size_t count = 0; count < m_padding; count++)
1845 {
1846 i.WriteU8(0xff); // Padding field
1847 }
1848}
1849
1852{
1853 Buffer::Iterator i = start;
1854
1855 uint64_t commonInfo = i.ReadLsbtohU64();
1856
1857 m_triggerType = static_cast<TriggerFrameType>(commonInfo & 0x0f);
1858 m_ulLength = (commonInfo >> 4) & 0x0fff;
1859 m_moreTF = (commonInfo >> 16) & 0x01;
1860 m_csRequired = (commonInfo >> 17) & 0x01;
1861 m_ulBandwidth = (commonInfo >> 18) & 0x03;
1862 m_giAndLtfType = (commonInfo >> 20) & 0x03;
1863 m_apTxPower = (commonInfo >> 28) & 0x3f;
1864 m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1865 uint8_t bit54and55 = (commonInfo >> 54) & 0x03;
1867 m_userInfoFields.clear();
1868 m_padding = 0;
1869
1871 "BFRP Trigger frame is not supported");
1873 "GCR-MU-BAR Trigger frame is not supported");
1875 "NFRP Trigger frame is not supported");
1876
1877 while (i.GetRemainingSize() >= 2)
1878 {
1879 // read the first 2 bytes to check if we encountered the Padding field
1880 if (i.ReadU16() == 0xffff)
1881 {
1882 m_padding = i.GetRemainingSize() + 2;
1883 }
1884 else
1885 {
1886 // go back 2 bytes to deserialize the User Info field from the beginning
1887 i.Prev(2);
1889 i = ui.Deserialize(i);
1890 }
1891 }
1892
1893 return i.GetDistanceFrom(start);
1894}
1895
1896void
1898{
1899 m_triggerType = type;
1900}
1901
1904{
1905 return m_triggerType;
1906}
1907
1908const char*
1910{
1911 return GetTypeString(GetType());
1912}
1913
1914const char*
1916{
1917#define FOO(x) \
1918 case TriggerFrameType::x: \
1919 return #x;
1920
1921 switch (type)
1922 {
1931 default:
1932 return "ERROR";
1933 }
1934#undef FOO
1935}
1936
1937bool
1939{
1941}
1942
1943bool
1945{
1947}
1948
1949bool
1951{
1953}
1954
1955bool
1957{
1959}
1960
1961bool
1963{
1965}
1966
1967bool
1969{
1971}
1972
1973bool
1975{
1977}
1978
1979bool
1981{
1983}
1984
1985void
1987{
1988 m_ulLength = (len & 0x0fff);
1989}
1990
1991uint16_t
1993{
1994 return m_ulLength;
1995}
1996
1999{
2001 "GetHeTbTxVector() cannot be used for MU-RTS");
2002 auto userInfoIt = FindUserInfoWithAid(staId);
2003 NS_ASSERT(userInfoIt != end());
2004
2005 WifiTxVector v;
2006 v.SetPreambleType(userInfoIt->GetPreambleType());
2011 staId,
2012 {userInfoIt->GetRuAllocation(), userInfoIt->GetUlMcs(), userInfoIt->GetNss()});
2013 return v;
2014}
2015
2016void
2018{
2019 m_moreTF = more;
2020}
2021
2022bool
2024{
2025 return m_moreTF;
2026}
2027
2028void
2030{
2031 m_csRequired = cs;
2032}
2033
2034bool
2036{
2037 return m_csRequired;
2038}
2039
2040void
2042{
2043 switch (bw)
2044 {
2045 case 20:
2046 m_ulBandwidth = 0;
2047 break;
2048 case 40:
2049 m_ulBandwidth = 1;
2050 break;
2051 case 80:
2052 m_ulBandwidth = 2;
2053 break;
2054 case 160:
2055 m_ulBandwidth = 3;
2056 break;
2057 default:
2058 NS_FATAL_ERROR("Bandwidth value not allowed.");
2059 break;
2060 }
2061}
2062
2063uint16_t
2065{
2066 return (1 << m_ulBandwidth) * 20;
2067}
2068
2069void
2070CtrlTriggerHeader::SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
2071{
2072 if (ltfType == 1 && guardInterval == 1600)
2073 {
2074 m_giAndLtfType = 0;
2075 }
2076 else if (ltfType == 2 && guardInterval == 1600)
2077 {
2078 m_giAndLtfType = 1;
2079 }
2080 else if (ltfType == 4 && guardInterval == 3200)
2081 {
2082 m_giAndLtfType = 2;
2083 }
2084 else
2085 {
2086 NS_FATAL_ERROR("Invalid combination of GI and LTF type");
2087 }
2088}
2089
2090uint16_t
2092{
2093 if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
2094 {
2095 return 1600;
2096 }
2097 else if (m_giAndLtfType == 2)
2098 {
2099 return 3200;
2100 }
2101 else
2102 {
2103 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2104 }
2105}
2106
2107uint8_t
2109{
2110 if (m_giAndLtfType == 0)
2111 {
2112 return 1;
2113 }
2114 else if (m_giAndLtfType == 1)
2115 {
2116 return 2;
2117 }
2118 else if (m_giAndLtfType == 2)
2119 {
2120 return 4;
2121 }
2122 else
2123 {
2124 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2125 }
2126}
2127
2128void
2130{
2131 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2132 NS_ABORT_MSG_IF(power < -20 || power > 40, "Out of range power values");
2133
2134 m_apTxPower = static_cast<uint8_t>(power + 20);
2135}
2136
2137int8_t
2139{
2140 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2141 return static_cast<int8_t>(m_apTxPower) - 20;
2142}
2143
2144void
2146{
2147 m_ulSpatialReuse = sr;
2148}
2149
2150uint16_t
2152{
2153 return m_ulSpatialReuse;
2154}
2155
2156void
2158{
2159 NS_ABORT_MSG_IF(size == 1, "The Padding field, if present, shall be at least two octets");
2160 m_padding = size;
2161}
2162
2163std::size_t
2165{
2166 return m_padding;
2167}
2168
2171{
2172 // make a copy of this Trigger Frame and remove the User Info fields from the copy
2173 CtrlTriggerHeader trigger(*this);
2174 trigger.m_userInfoFields.clear();
2175 return trigger;
2176}
2177
2180{
2182 return m_userInfoFields.back();
2183}
2184
2187{
2189 userInfo.GetType() != m_triggerType,
2190 "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2191 m_userInfoFields.push_back(userInfo);
2192 return m_userInfoFields.back();
2193}
2194
2197{
2198 return m_userInfoFields.begin();
2199}
2200
2203{
2204 return m_userInfoFields.end();
2205}
2206
2209{
2210 return m_userInfoFields.begin();
2211}
2212
2215{
2216 return m_userInfoFields.end();
2217}
2218
2219std::size_t
2221{
2222 return m_userInfoFields.size();
2223}
2224
2227{
2228 // the lambda function returns true if a User Info field has the AID12 subfield
2229 // equal to the given aid12 value
2230 return std::find_if(start, end(), [aid12](const CtrlTriggerUserInfoField& ui) -> bool {
2231 return (ui.GetAid12() == aid12);
2232 });
2233}
2234
2237{
2238 return FindUserInfoWithAid(m_userInfoFields.begin(), aid12);
2239}
2240
2243{
2244 return FindUserInfoWithAid(start, 0);
2245}
2246
2249{
2250 return FindUserInfoWithAid(0);
2251}
2252
2255{
2256 return FindUserInfoWithAid(start, 2045);
2257}
2258
2261{
2262 return FindUserInfoWithAid(2045);
2263}
2264
2265bool
2267{
2269 {
2270 return true;
2271 }
2272
2273 // check that allocated RUs do not overlap
2274 // TODO This is not a problem in case of UL MU-MIMO
2275 std::vector<HeRu::RuSpec> prevRus;
2276
2277 for (auto& ui : m_userInfoFields)
2278 {
2279 if (HeRu::DoesOverlap(GetUlBandwidth(), ui.GetRuAllocation(), prevRus))
2280 {
2281 return false;
2282 }
2283 prevRus.push_back(ui.GetRuAllocation());
2284 }
2285 return true;
2286}
2287
2288} // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint32_t GetRemainingSize() const
Definition: buffer.cc:1173
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:902
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:910
uint16_t ReadLsbtohU16()
Definition: buffer.cc:1064
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1094
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:920
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:780
void Prev()
go backward by one byte
Definition: buffer.h:860
uint16_t ReadU16()
Definition: buffer.h:1035
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1076
void Next()
go forward by one byte
Definition: buffer.h:853
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
uint16_t GetStartingSequence() const
Return the starting sequence number.
uint32_t GetSerializedSize() const override
Definition: ctrl-headers.cc:72
void Serialize(Buffer::Iterator start) const override
Definition: ctrl-headers.cc:94
uint16_t m_startingSeq
starting seq
Definition: ctrl-headers.h:187
bool m_barAckPolicy
The LSB bit of the BAR control field is used only for the HT (High Throughput) delayed block ack conf...
Definition: ctrl-headers.h:184
uint16_t m_tidInfo
TID info.
Definition: ctrl-headers.h:186
uint8_t GetTidInfo() const
Return the Traffic ID (TID).
bool IsExtendedCompressed() const
Check if the current Ack Policy is Extended Compressed Block Ack.
void Print(std::ostream &os) const override
Definition: ctrl-headers.cc:66
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
BlockAckReqType m_barType
BAR type.
Definition: ctrl-headers.h:185
void SetStartingSequenceControl(uint16_t seqControl)
Set the starting sequence control with the given sequence control value.
bool IsMultiTid() const
Check if the current Ack Policy has Multi-TID Block Ack.
BlockAckReqType GetType() const
Return the BlockAckRequest type.
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
uint32_t Deserialize(Buffer::Iterator start) override
bool IsCompressed() const
Check if the current Ack Policy is Compressed Block Ack and not multi-TID.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
uint16_t GetBarControl() const
Return the Block Ack control.
static TypeId GetTypeId()
Get the type ID.
Definition: ctrl-headers.cc:50
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: ctrl-headers.cc:60
uint16_t GetStartingSequenceControl() const
Return the starting sequence control.
void SetBarControl(uint16_t bar)
Set the Block Ack control.
bool MustSendHtImmediateAck() const
Check if the current Ack Policy is immediate.
bool IsBasic() const
Check if the current Ack Policy is Basic Block Ack (i.e.
Headers for BlockAck response.
Definition: ctrl-headers.h:203
void SetBaControl(uint16_t ba)
Set the Block Ack control.
bool IsExtendedCompressed() const
Check if the current BA policy is Extended Compressed Block Ack.
void SetStartingSequence(uint16_t seq, std::size_t index=0)
For Block Ack variants other than Multi-STA Block Ack, set the starting sequence number to the given ...
uint32_t Deserialize(Buffer::Iterator start) override
uint16_t GetStartingSequenceControl(std::size_t index=0) const
Return the value of the Starting Sequence Control subfield.
BlockAckType m_baType
BA type.
Definition: ctrl-headers.h:530
bool IsFragmentReceived(uint16_t seq, uint8_t frag) const
Check if the packet with the given sequence number and fragment number was acknowledged in this Block...
void Serialize(Buffer::Iterator start) const override
bool IsPacketReceived(uint16_t seq, std::size_t index=0) const
Check if the packet with the given sequence number was acknowledged in this BlockAck response.
void SetStartingSequenceControl(uint16_t seqControl, std::size_t index=0)
Set the Starting Sequence Control subfield with the given sequence control value.
std::vector< uint32_t > FindPerAidTidInfoWithAid(uint16_t aid) const
For Multi-STA Block Acks, get the indices of the Per AID TID Info subfields carrying the given AID in...
Buffer::Iterator SerializeBitmap(Buffer::Iterator start, std::size_t index=0) const
Serialize bitmap to the given buffer.
std::size_t GetNPerAidTidInfoSubfields() const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack.
uint16_t GetStartingSequence(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the starting sequence number.
Mac48Address GetUnassociatedStaAddress(std::size_t index) const
For Multi-STA Block Acks, get the RA subfield of the Per AID TID Info subfield (with AID11 subfield e...
uint8_t GetTidInfo(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the TID_INFO subfield of the BA Control fi...
bool IsBasic() const
Check if the current BA policy is Basic Block Ack.
const std::vector< uint8_t > & GetBitmap(std::size_t index=0) const
Return a const reference to the bitmap from the BlockAck response header.
bool m_baAckPolicy
The LSB bit of the BA control field is used only for the HT (High Throughput) delayed block ack confi...
Definition: ctrl-headers.h:529
bool IsCompressed() const
Check if the current BA policy is Compressed Block Ack.
void SetUnassociatedStaAddress(const Mac48Address &ra, std::size_t index)
For Multi-STA Block Acks, set the RA subfield of the Per AID TID Info subfield (with AID11 subfield e...
bool MustSendHtImmediateAck() const
Check if the current Ack Policy is immediate.
Buffer::Iterator DeserializeBitmap(Buffer::Iterator start, std::size_t index=0)
Deserialize bitmap from the given buffer.
void ResetBitmap(std::size_t index=0)
Reset the bitmap to 0.
void SetAckType(bool type, std::size_t index)
For Multi-STA Block Acks, set the Ack Type subfield of the Per AID TID Info subfield identified by th...
void SetTidInfo(uint8_t tid, std::size_t index=0)
For Block Ack variants other than Multi-STA Block Ack, set the TID_INFO subfield of the BA Control fi...
uint16_t m_tidInfo
TID info (reserved if Multi-STA Block Ack)
Definition: ctrl-headers.h:531
void Print(std::ostream &os) const override
void SetType(BlockAckType type)
Set the block ack type.
uint32_t GetSerializedSize() const override
uint16_t GetBaControl() const
Return the Block Ack control.
BlockAckType GetType() const
Return the block ack type ID.
void SetReceivedFragment(uint16_t seq, uint8_t frag)
Set the bitmap that the packet with the given sequence number and fragment number was received.
static TypeId GetTypeId()
Get the type ID.
void SetReceivedPacket(uint16_t seq, std::size_t index=0)
Record in the bitmap that the packet with the given sequence number was received.
bool IsMultiTid() const
Check if the current BA policy is Multi-TID Block Ack.
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
std::vector< BaInfoInstance > m_baInfo
BA Information field.
Definition: ctrl-headers.h:552
void SetAid11(uint16_t aid, std::size_t index)
For Multi-STA Block Acks, set the AID11 subfield of the Per AID TID Info subfield identified by the g...
bool GetAckType(std::size_t index) const
For Multi-STA Block Acks, get the Ack Type subfield of the Per AID TID Info subfield identified by th...
uint16_t GetAid11(std::size_t index) const
For Multi-STA Block Acks, get the AID11 subfield of the Per AID TID Info subfield identified by the g...
bool IsMultiSta() const
Check if the BlockAck frame variant is Multi-STA Block Ack.
bool IsInBitmap(uint16_t seq, std::size_t index=0) const
Check if sequence number seq can be acknowledged in the bitmap.
uint16_t IndexInBitmap(uint16_t seq, std::size_t index=0) const
This function is used to correctly index in both bitmap and compressed bitmap, one bit or one block o...
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Headers for Trigger frames.
Definition: ctrl-headers.h:942
std::size_t GetPaddingSize() const
CtrlTriggerUserInfoField & AddUserInfoField()
Append a new User Info field to this Trigger frame and return a non-const reference to it.
uint32_t GetSerializedSize() const override
bool IsBasic() const
Check if this is a Basic Trigger frame.
ConstIterator FindUserInfoWithRaRuAssociated() const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
void Print(std::ostream &os) const override
bool IsNfrp() const
Check if this is a NDP Feedback Report Poll Trigger frame.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
ConstIterator end() const
Get a const iterator indicating past-the-last User Info field in the list.
uint16_t GetUlSpatialReuse() const
Get the UL Spatial Reuse subfield of the Common Info field.
std::size_t m_padding
the size in bytes of the Padding field
uint8_t m_giAndLtfType
GI And LTF Type subfield.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
bool IsMuRts() const
Check if this is a MU-RTS Trigger frame.
TriggerFrameType m_triggerType
Trigger type.
void SetPaddingSize(std::size_t size)
Set the size in bytes of the Padding field.
uint32_t Deserialize(Buffer::Iterator start) override
uint16_t GetGuardInterval() const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
bool IsBsrp() const
Check if this is a Buffer Status Report Poll Trigger frame.
TriggerFrameType GetType() const
Get the Trigger Frame type.
bool IsMuBar() const
Check if this is a MU-BAR Trigger frame.
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
ConstIterator FindUserInfoWithRaRuUnassociated() const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
bool IsBfrp() const
Check if this is a Beamforming Report Poll Trigger frame.
ConstIterator begin() const
Get a const iterator pointing to the first User Info field in the list.
std::size_t GetNUserInfoFields() const
Get the number of User Info fields in this Trigger Frame.
uint8_t GetLtfType() const
Get the LTF type of the solicited HE TB PPDU.
bool GetMoreTF() const
Get the More TF subfield of the Common Info field.
std::list< CtrlTriggerUserInfoField >::const_iterator ConstIterator
User Info fields list const iterator.
bool IsBqrp() const
Check if this is a Bandwidth Query Report Poll Trigger frame.
static TypeId GetTypeId()
Get the type ID.
bool IsValid() const
Check the validity of this Trigger frame.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
ConstIterator FindUserInfoWithAid(ConstIterator start, uint16_t aid12) const
Get a const iterator pointing to the first User Info field found (starting from the one pointed to by...
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
const char * GetTypeString() const
Return a string corresponding to the Trigger Frame type.
uint16_t GetUlLength() const
Get the UL Length subfield of the Common Info field.
uint16_t GetUlBandwidth() const
Get the bandwidth of the solicited HE TB PPDU.
TriggerFrameVariant m_variant
Common Info field.
uint16_t m_ulLength
Value for the L-SIG Length field.
bool m_csRequired
Carrier Sense required.
TriggerFrameVariant GetVariant() const
Get the Common Info field variant.
CtrlTriggerHeader GetCommonInfoField() const
Get a copy of the Common Info field of this Trigger frame.
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
std::list< CtrlTriggerUserInfoField > m_userInfoFields
List of User Info fields.
bool m_moreTF
True if a subsequent Trigger frame follows.
void SetVariant(TriggerFrameVariant variant)
Set the Common Info field variant.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
uint8_t m_ulBandwidth
UL BW subfield.
bool GetCsRequired() const
Get the CS Required subfield of the Common Info field.
bool IsGcrMuBar() const
Check if this is a Groupcast with Retries (GCR) MU-BAR Trigger frame.
std::list< CtrlTriggerUserInfoField >::iterator Iterator
User Info fields list iterator.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void Serialize(Buffer::Iterator start) const override
int8_t GetApTxPower() const
Get the power value (dBm) indicated by the AP TX Power subfield of the Common Info field.
uint8_t m_apTxPower
Tx Power used by AP to transmit the Trigger Frame.
CtrlTriggerHeader & operator=(const CtrlTriggerHeader &trigger)
Copy assignment operator.
uint16_t m_ulSpatialReuse
Value for the Spatial Reuse field in HE-SIG-A.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
User Info field of Trigger frames.
Definition: ctrl-headers.h:590
bool GetUlFecCodingType() const
Get the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
bool GetUlDcm() const
Get the UL DCM subfield, which indicates whether or not DCM is used This method can only be used with...
AcIndex GetPreferredAc() const
Get the Preferred AC subfield.
uint8_t GetMpduMuSpacingFactor() const
Get the MPDU MU spacing factor.
int8_t GetUlTargetRssi() const
Get the expected receive signal power for the solicited HE TB PPDU.
uint8_t startingSs
Starting spatial stream.
Definition: ctrl-headers.h:902
TriggerFrameType m_triggerType
Trigger frame type.
Definition: ctrl-headers.h:914
uint8_t GetUlMcs() const
Get the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
WifiPreamble GetPreambleType() const
uint32_t GetSerializedSize() const
Get the expected size of this User Info field.
void SetMuRtsRuAllocation(uint8_t value)
Set the RU Allocation subfield based on the given value for the B7-B1 bits.
CtrlTriggerUserInfoField(TriggerFrameType triggerType, TriggerFrameVariant variant)
Constructor.
void Print(std::ostream &os) const
Print the content of this User Info field.
uint8_t nRaRu
Number of Random Access RUs.
Definition: ctrl-headers.h:908
union ns3::CtrlTriggerUserInfoField::@69 m_bits26To31
Fields occupying bits 26-31 in the User Info field.
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
bool m_ps160
identifies the location of the RU (EHT variant only)
Definition: ctrl-headers.h:897
const CtrlBAckRequestHeader & GetMuBarTriggerDepUserInfo() const
Get the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
bool HasRaRuForUnassociatedSta() const
Check if this User Info field allocates a Random Access RU for stations not associated with the AP th...
void SetUlTargetRssiMaxTxPower()
Set the UL Target RSSI subfield to indicate to the station to transmit an HE TB PPDU response at its ...
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
uint16_t m_aid12
Association ID of the addressed station.
Definition: ctrl-headers.h:892
uint8_t nSs
Number of spatial streams.
Definition: ctrl-headers.h:903
uint8_t m_basicTriggerDependentUserInfo
Basic Trigger variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:915
TriggerFrameVariant m_variant
User Info field variant.
Definition: ctrl-headers.h:890
uint8_t GetTidAggregationLimit() const
Get the TID Aggregation Limit.
uint8_t m_ulMcs
MCS to be used by the addressed station.
Definition: ctrl-headers.h:895
TriggerFrameType GetType() const
Get the type of the Trigger Frame this User Info field belongs to.
uint8_t m_ruAllocation
RU Allocation.
Definition: ctrl-headers.h:893
HeRu::RuSpec GetRuAllocation() const
Get the RU specified by the RU Allocation subfield.
uint8_t GetNss() const
Get the number of spatial streams.
bool HasRaRuForAssociatedSta() const
Check if this User Info field allocates a Random Access RU for stations associated with the AP that t...
uint8_t GetMuRtsRuAllocation() const
This method can only be called on MU-RTS Trigger Frames.
uint16_t GetAid12() const
Get the value of the AID12 subfield.
Buffer::Iterator Serialize(Buffer::Iterator start) const
Serialize the User Info field to the given buffer.
uint8_t GetNRaRus() const
Get the number of contiguous RUs for Random Access.
bool m_ulDcm
whether or not to use Dual Carrier Modulation (HE variant only)
Definition: ctrl-headers.h:896
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
uint8_t GetStartingSs() const
Get the starting spatial stream.
CtrlTriggerUserInfoField & operator=(const CtrlTriggerUserInfoField &userInfo)
Copy assignment operator.
uint8_t m_ulTargetRssi
Expected receive signal power.
Definition: ctrl-headers.h:913
void SetRaRuInformation(uint8_t nRaRu, bool moreRaRu)
Set the RA-RU Information subfield, which is present when the AID12 subfield is 0 or 2045.
Buffer::Iterator Deserialize(Buffer::Iterator start)
Deserialize the User Info field from the given buffer.
bool IsUlTargetRssiMaxTxPower() const
Return true if the UL Target RSSI subfield indicates to the station to transmit an HE TB PPDU respons...
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
void SetBasicTriggerDepUserInfo(uint8_t spacingFactor, uint8_t tidLimit, AcIndex prefAc)
Set the Trigger Dependent User Info subfield for Basic Trigger frames.
bool moreRaRu
More RA-RU in subsequent Trigger frames.
Definition: ctrl-headers.h:909
bool m_ulFecCodingType
UL FEC Coding Type.
Definition: ctrl-headers.h:894
CtrlBAckRequestHeader m_muBarTriggerDependentUserInfo
MU-BAR variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:918
bool GetMoreRaRu() const
Return true if more RA-RUs are allocated in subsequent Trigger frames that are sent before the end of...
RU Specification.
Definition: he-ru.h:66
std::size_t GetIndex() const
Get the RU index.
Definition: he-ru.cc:461
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:454
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition: he-ru.cc:468
static bool DoesOverlap(uint16_t bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
Definition: he-ru.cc:626
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
@ RU_26_TONE
Definition: he-ru.h:42
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_52_TONE
Definition: he-ru.h:43
@ RU_242_TONE
Definition: he-ru.h:45
@ RU_2x996_TONE
Definition: he-ru.h:48
Protocol header serialization and deserialization.
Definition: header.h:44
an EUI-48 address
Definition: mac48-address.h:46
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t GetGuardInterval() const
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
uint16_t GetLength() const
Get the LENGTH field of the L-SIG.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
uint16_t GetChannelWidth() const
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define FOO(x)
#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_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
TriggerFrameVariant
The different variants for Common Info field and User Info field of Trigger Frames.
Definition: ctrl-headers.h:576
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:73
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:560
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_EHT_TB
@ WIFI_PREAMBLE_HE_TB
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:185
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.
The different BlockAckRequest variants.
Variant m_variant
Block Ack Request variant.
The different BlockAck variants.
Variant m_variant
Block Ack variant.
std::vector< uint8_t > m_bitmapLen
Length (bytes) of included bitmaps.
The following structure can hold the BA Information field for the Basic and Compressed variants,...
Definition: ctrl-headers.h:542
uint16_t m_aidTidInfo
Reserved for Basic and Compressed Per TID Info subfield for Multi-TID AID TID Info subfield for Multi...
Definition: ctrl-headers.h:543