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 uint8_t 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
723 // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
724 // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
726 {
727 if (m_baType.m_bitmapLen[0] == 32)
728 {
729 ret |= 0x0004;
730 }
731 }
733 {
734 NS_ASSERT(m_baInfo.size() == m_baType.m_bitmapLen.size());
735 NS_ASSERT_MSG(!m_baInfo[index].m_bitmap.empty(),
736 "This Per AID TID Info subfield has no Starting Sequence Control subfield");
737
738 if (m_baType.m_bitmapLen[index] == 16)
739 {
740 ret |= 0x0002;
741 }
742 else if (m_baType.m_bitmapLen[index] == 32)
743 {
744 ret |= 0x0004;
745 }
746 else if (m_baType.m_bitmapLen[index] == 4)
747 {
748 ret |= 0x0006;
749 }
750 }
751 return ret;
752}
753
754void
755CtrlBAckResponseHeader::SetStartingSequenceControl(uint16_t seqControl, std::size_t index)
756{
758 "index can only be non null for Multi-STA Block Ack");
759 NS_ASSERT(index < m_baInfo.size());
760
761 // The Fragment Number subfield encodes the length of the bitmap for
762 // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
763 // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
765 {
766 if ((seqControl & 0x0001) == 1)
767 {
768 NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
769 }
770 if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 0)
771 {
773 }
774 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
775 {
777 }
778 else
779 {
780 NS_FATAL_ERROR("Reserved configurations");
781 }
782 }
784 {
785 if ((seqControl & 0x0001) == 1)
786 {
787 NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
788 }
789 uint8_t bitmapLen = 0;
790 if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 0)
791 {
792 bitmapLen = 8;
793 }
794 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 1)
795 {
796 bitmapLen = 16;
797 }
798 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
799 {
800 bitmapLen = 32;
801 }
802 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 3)
803 {
804 bitmapLen = 4;
805 }
806 else
807 {
808 NS_FATAL_ERROR("Reserved configurations");
809 }
810 m_baType.m_bitmapLen[index] = bitmapLen;
811 m_baInfo[index].m_bitmap.assign(bitmapLen, 0);
812 }
813
814 m_baInfo[index].m_startingSeq = (seqControl >> 4) & 0x0fff;
815}
816
819{
821 "index can only be non null for Multi-STA Block Ack");
822 NS_ASSERT(index < m_baInfo.size());
823
824 Buffer::Iterator i = start;
825 switch (m_baType.m_variant)
826 {
831 for (const auto& byte : m_baInfo[index].m_bitmap)
832 {
833 i.WriteU8(byte);
834 }
835 break;
837 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
838 break;
839 default:
840 NS_FATAL_ERROR("Invalid BA type");
841 break;
842 }
843 return i;
844}
845
848{
850 "index can only be non null for Multi-STA Block Ack");
851 NS_ASSERT(index < m_baInfo.size());
852
853 Buffer::Iterator i = start;
854 switch (m_baType.m_variant)
855 {
860 for (uint8_t j = 0; j < m_baType.m_bitmapLen[index]; j++)
861 {
862 m_baInfo[index].m_bitmap[j] = i.ReadU8();
863 }
864 break;
866 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
867 break;
868 default:
869 NS_FATAL_ERROR("Invalid BA type");
870 break;
871 }
872 return i;
873}
874
875void
876CtrlBAckResponseHeader::SetReceivedPacket(uint16_t seq, std::size_t index)
877{
879 "index can only be non null for Multi-STA Block Ack");
880 NS_ASSERT(index < m_baInfo.size());
881
882 if (!IsInBitmap(seq, index))
883 {
884 return;
885 }
886 switch (m_baType.m_variant)
887 {
889 /* To set correctly basic block ack bitmap we need fragment number too.
890 So if it's not specified, we consider packet not fragmented. */
891 m_baInfo[index].m_bitmap[IndexInBitmap(seq) * 2] |= 0x01;
892 break;
896 uint16_t i = IndexInBitmap(seq, index);
897 m_baInfo[index].m_bitmap[i / 8] |= (uint8_t(0x01) << (i % 8));
898 break;
899 }
901 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
902 break;
903 default:
904 NS_FATAL_ERROR("Invalid BA type");
905 break;
906 }
907}
908
909void
911{
912 NS_ASSERT(frag < 16);
913 if (!IsInBitmap(seq))
914 {
915 return;
916 }
917 switch (m_baType.m_variant)
918 {
920 m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] |= (0x01 << (frag % 8));
921 break;
925 /* We can ignore this...compressed block ack doesn't support
926 acknowledgment of single fragments */
927 break;
929 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
930 break;
931 default:
932 NS_FATAL_ERROR("Invalid BA type");
933 break;
934 }
935}
936
937bool
938CtrlBAckResponseHeader::IsPacketReceived(uint16_t seq, std::size_t index) const
939{
941 "index can only be non null for Multi-STA Block Ack");
942 NS_ASSERT(index < m_baInfo.size());
943
945 GetTidInfo(index) == 14)
946 {
947 // All-ack context
948 return true;
949 }
950 if (!IsInBitmap(seq, index))
951 {
952 return false;
953 }
954 switch (m_baType.m_variant)
955 {
957 /*It's impossible to say if an entire packet was correctly received. */
958 return false;
962 uint16_t i = IndexInBitmap(seq, index);
963 uint8_t mask = uint8_t(0x01) << (i % 8);
964 return (m_baInfo[index].m_bitmap[i / 8] & mask) != 0;
965 }
967 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
968 break;
969 default:
970 NS_FATAL_ERROR("Invalid BA type");
971 break;
972 }
973 return false;
974}
975
976bool
977CtrlBAckResponseHeader::IsFragmentReceived(uint16_t seq, uint8_t frag) const
978{
979 NS_ASSERT(frag < 16);
980 if (!IsInBitmap(seq))
981 {
982 return false;
983 }
984 switch (m_baType.m_variant)
985 {
987 return (m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] & (0x01 << (frag % 8))) !=
988 0;
992 /* We can ignore this...compressed block ack doesn't support
993 acknowledgement of single fragments */
994 return false;
996 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
997 break;
998 }
999 default: {
1000 NS_FATAL_ERROR("Invalid BA type");
1001 break;
1002 }
1003 }
1004 return false;
1005}
1006
1007uint16_t
1008CtrlBAckResponseHeader::IndexInBitmap(uint16_t seq, std::size_t index) const
1009{
1010 uint16_t i;
1011 if (seq >= m_baInfo[index].m_startingSeq)
1012 {
1013 i = seq - m_baInfo[index].m_startingSeq;
1014 }
1015 else
1016 {
1017 i = SEQNO_SPACE_SIZE - m_baInfo[index].m_startingSeq + seq;
1018 }
1019
1020 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1021
1023 {
1024 nAckedMpdus = nAckedMpdus / 16;
1025 }
1026
1027 NS_ASSERT(i < nAckedMpdus);
1028 return i;
1029}
1030
1031bool
1032CtrlBAckResponseHeader::IsInBitmap(uint16_t seq, std::size_t index) const
1033{
1035 "index can only be non null for Multi-STA Block Ack");
1036 NS_ASSERT(index < m_baType.m_bitmapLen.size());
1037
1038 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1039
1041 {
1042 nAckedMpdus = nAckedMpdus / 16;
1043 }
1044
1045 return (seq - m_baInfo[index].m_startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE <
1046 nAckedMpdus;
1047}
1048
1049const std::vector<uint8_t>&
1051{
1053 "index can only be non null for Multi-STA Block Ack");
1054 NS_ASSERT(index < m_baInfo.size());
1055
1056 return m_baInfo[index].m_bitmap;
1057}
1058
1059void
1061{
1063 "index can only be non null for Multi-STA Block Ack");
1064 NS_ASSERT(index < m_baInfo.size());
1065
1066 m_baInfo[index].m_bitmap.assign(m_baType.m_bitmapLen[index], 0);
1067}
1068
1069/***********************************
1070 * Trigger frame - User Info field
1071 ***********************************/
1072
1074 TriggerFrameVariant variant)
1075 : m_variant(variant),
1076 m_aid12(0),
1077 m_ruAllocation(0),
1078 m_ulFecCodingType(false),
1079 m_ulMcs(0),
1080 m_ulDcm(false),
1081 m_ps160(true),
1082 m_ulTargetRssi(0),
1083 m_triggerType(triggerType),
1084 m_basicTriggerDependentUserInfo(0)
1085{
1086 memset(&m_bits26To31, 0, sizeof(m_bits26To31));
1087}
1088
1090{
1091}
1092
1095{
1096 NS_ABORT_MSG_IF(m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1097
1098 // check for self-assignment
1099 if (&userInfo == this)
1100 {
1101 return *this;
1102 }
1103
1104 m_variant = userInfo.m_variant;
1105 m_aid12 = userInfo.m_aid12;
1106 m_ruAllocation = userInfo.m_ruAllocation;
1108 m_ulMcs = userInfo.m_ulMcs;
1109 m_ulDcm = userInfo.m_ulDcm;
1110 m_ps160 = userInfo.m_ps160;
1111 m_bits26To31 = userInfo.m_bits26To31;
1112 m_ulTargetRssi = userInfo.m_ulTargetRssi;
1115 return *this;
1116}
1117
1118void
1119CtrlTriggerUserInfoField::Print(std::ostream& os) const
1120{
1121 os << ", USER_INFO " << (m_variant == TriggerFrameVariant::HE ? "HE" : "EHT")
1122 << " variant AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation
1123 << ", MCS=" << +m_ulMcs;
1124}
1125
1128{
1129 uint32_t size = 0;
1130 size += 5; // User Info (excluding Trigger Dependent User Info)
1131
1132 switch (m_triggerType)
1133 {
1136 size += 1;
1137 break;
1139 size +=
1140 m_muBarTriggerDependentUserInfo.GetSerializedSize(); // BAR Control and BAR Information
1141 break;
1142 default:;
1143 // The Trigger Dependent User Info subfield is not present in the other variants
1144 }
1145
1146 return size;
1147}
1148
1151{
1153 "BFRP Trigger frame is not supported");
1155 "GCR-MU-BAR Trigger frame is not supported");
1157 "NFRP Trigger frame is not supported");
1158
1159 Buffer::Iterator i = start;
1160
1161 uint32_t userInfo = 0; // User Info except the MSB
1162 userInfo |= (m_aid12 & 0x0fff);
1163 userInfo |= (m_ruAllocation << 12);
1164 userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1165 userInfo |= (m_ulMcs & 0x0f) << 21;
1167 {
1168 userInfo |= (m_ulDcm ? 1 << 25 : 0);
1169 }
1170
1171 if (m_aid12 != 0 && m_aid12 != 2045)
1172 {
1173 userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1174 userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1175 }
1176 else
1177 {
1178 userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1179 userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1180 }
1181
1182 i.WriteHtolsbU32(userInfo);
1183 // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and B39, which is
1184 // reserved in the HE variant and the PS160 subfield in the EHT variant.
1185 uint8_t bit32To39 = m_ulTargetRssi;
1187 {
1188 bit32To39 |= (m_ps160 ? 1 << 7 : 0);
1189 }
1190
1191 i.WriteU8(bit32To39);
1192
1194 {
1196 }
1198 {
1201 }
1202
1203 return i;
1204}
1205
1208{
1210 "BFRP Trigger frame is not supported");
1212 "GCR-MU-BAR Trigger frame is not supported");
1214 "NFRP Trigger frame is not supported");
1215
1216 Buffer::Iterator i = start;
1217
1218 uint32_t userInfo = i.ReadLsbtohU32();
1219
1220 m_aid12 = userInfo & 0x0fff;
1221 NS_ABORT_MSG_IF(m_aid12 == 4095, "Cannot deserialize a Padding field");
1222 m_ruAllocation = (userInfo >> 12) & 0xff;
1223 m_ulFecCodingType = (userInfo >> 20) & 0x01;
1224 m_ulMcs = (userInfo >> 21) & 0x0f;
1226 {
1227 m_ulDcm = (userInfo >> 25) & 0x01;
1228 }
1229
1230 if (m_aid12 != 0 && m_aid12 != 2045)
1231 {
1232 m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1233 m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1234 }
1235 else
1236 {
1237 m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1238 m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1239 }
1240
1241 uint8_t bit32To39 = i.ReadU8();
1242 m_ulTargetRssi = bit32To39 & 0x7f; // B39 is reserved in HE variant
1244 {
1245 m_ps160 = (bit32To39 >> 7) == 1;
1246 }
1247
1249 {
1251 }
1253 {
1255 i.Next(len);
1256 }
1257
1258 return i;
1259}
1260
1263{
1264 return m_triggerType;
1265}
1266
1269{
1270 switch (m_variant)
1271 {
1273 return WIFI_PREAMBLE_HE_TB;
1275 return WIFI_PREAMBLE_EHT_TB;
1276 default:
1277 NS_ABORT_MSG("Unexpected variant: " << +static_cast<uint8_t>(m_variant));
1278 }
1279 return WIFI_PREAMBLE_LONG; // to silence warning
1280}
1281
1282void
1284{
1285 m_aid12 = aid & 0x0fff;
1286}
1287
1288uint16_t
1290{
1291 return m_aid12;
1292}
1293
1294bool
1296{
1297 return (m_aid12 == 0);
1298}
1299
1300bool
1302{
1303 return (m_aid12 == 2045);
1304}
1305
1306void
1308{
1309 NS_ABORT_MSG_IF(ru.GetIndex() == 0, "Valid indices start at 1");
1311 "SetMuRtsRuAllocation() must be used for MU-RTS");
1312
1313 switch (ru.GetRuType())
1314 {
1315 case HeRu::RU_26_TONE:
1316 m_ruAllocation = ru.GetIndex() - 1;
1317 break;
1318 case HeRu::RU_52_TONE:
1319 m_ruAllocation = ru.GetIndex() + 36;
1320 break;
1321 case HeRu::RU_106_TONE:
1322 m_ruAllocation = ru.GetIndex() + 52;
1323 break;
1324 case HeRu::RU_242_TONE:
1325 m_ruAllocation = ru.GetIndex() + 60;
1326 break;
1327 case HeRu::RU_484_TONE:
1328 m_ruAllocation = ru.GetIndex() + 64;
1329 break;
1330 case HeRu::RU_996_TONE:
1331 m_ruAllocation = 67;
1332 break;
1334 m_ruAllocation = 68;
1335 break;
1336 default:
1337 NS_FATAL_ERROR("RU type unknown.");
1338 break;
1339 }
1340
1341 NS_ABORT_MSG_IF(m_ruAllocation > 68, "Reserved value.");
1342
1343 m_ruAllocation <<= 1;
1344 if (!ru.GetPrimary80MHz())
1345 {
1347 }
1348}
1349
1352{
1354 "GetMuRtsRuAllocation() must be used for MU-RTS");
1355
1356 HeRu::RuType ruType;
1357 std::size_t index;
1358
1359 bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1360
1361 uint8_t val = m_ruAllocation >> 1;
1362
1363 if (val < 37)
1364 {
1365 ruType = HeRu::RU_26_TONE;
1366 index = val + 1;
1367 }
1368 else if (val < 53)
1369 {
1370 ruType = HeRu::RU_52_TONE;
1371 index = val - 36;
1372 }
1373 else if (val < 61)
1374 {
1375 ruType = HeRu::RU_106_TONE;
1376 index = val - 52;
1377 }
1378 else if (val < 65)
1379 {
1380 ruType = HeRu::RU_242_TONE;
1381 index = val - 60;
1382 }
1383 else if (val < 67)
1384 {
1385 ruType = HeRu::RU_484_TONE;
1386 index = val - 64;
1387 }
1388 else if (val == 67)
1389 {
1390 ruType = HeRu::RU_996_TONE;
1391 index = 1;
1392 }
1393 else if (val == 68)
1394 {
1395 ruType = HeRu::RU_2x996_TONE;
1396 index = 1;
1397 }
1398 else
1399 {
1400 NS_FATAL_ERROR("Reserved value.");
1401 }
1402
1403 return HeRu::RuSpec(ruType, index, primary80MHz);
1404}
1405
1406void
1408{
1410 "SetMuRtsRuAllocation() can only be used for MU-RTS");
1412 value < 61 || value > 68,
1413 "Value "
1414 << +value
1415 << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1416
1417 m_ruAllocation = (value << 1);
1418 if (value == 68)
1419 {
1420 // set B0 for 160 MHz and 80+80 MHz indication
1422 }
1423}
1424
1425uint8_t
1427{
1429 "GetMuRtsRuAllocation() can only be used for MU-RTS");
1430 uint8_t value = (m_ruAllocation >> 1);
1432 value < 61 || value > 68,
1433 "Value "
1434 << +value
1435 << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1436 return value;
1437}
1438
1439void
1441{
1442 m_ulFecCodingType = ldpc;
1443}
1444
1445bool
1447{
1448 return m_ulFecCodingType;
1449}
1450
1451void
1453{
1454 NS_ABORT_MSG_IF(mcs > 11, "Invalid MCS index");
1455 m_ulMcs = mcs;
1456}
1457
1458uint8_t
1460{
1461 return m_ulMcs;
1462}
1463
1464void
1466{
1467 NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1468 m_ulDcm = dcm;
1469}
1470
1471bool
1473{
1474 NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1475 return m_ulDcm;
1476}
1477
1478void
1479CtrlTriggerUserInfoField::SetSsAllocation(uint8_t startingSs, uint8_t nSs)
1480{
1481 NS_ABORT_MSG_IF(m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1482 NS_ABORT_MSG_IF(!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1483 NS_ABORT_MSG_IF(!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1484
1485 m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1486 m_bits26To31.ssAllocation.nSs = nSs - 1;
1487}
1488
1489uint8_t
1491{
1492 if (m_aid12 == 0 || m_aid12 == 2045)
1493 {
1494 return 1;
1495 }
1496 return m_bits26To31.ssAllocation.startingSs + 1;
1497}
1498
1499uint8_t
1501{
1502 if (m_aid12 == 0 || m_aid12 == 2045)
1503 {
1504 return 1;
1505 }
1506 return m_bits26To31.ssAllocation.nSs + 1;
1507}
1508
1509void
1511{
1512 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1513 NS_ABORT_MSG_IF(!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1514
1515 m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1516 m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1517}
1518
1519uint8_t
1521{
1522 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1523
1524 return m_bits26To31.raRuInformation.nRaRu + 1;
1525}
1526
1527bool
1529{
1530 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1531
1532 return m_bits26To31.raRuInformation.moreRaRu;
1533}
1534
1535void
1537{
1538 m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1539}
1540
1541void
1543{
1544 NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
1545
1546 m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
1547}
1548
1549bool
1551{
1552 return (m_ulTargetRssi == 127);
1553}
1554
1555int8_t
1557{
1558 NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
1559
1560 return static_cast<int8_t>(m_ulTargetRssi) - 110;
1561}
1562
1563void
1565 uint8_t tidLimit,
1566 AcIndex prefAc)
1567{
1568 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1569
1570 m_basicTriggerDependentUserInfo = (spacingFactor & 0x03) |
1571 (tidLimit & 0x07) << 2
1572 // B5 is reserved
1573 | (prefAc & 0x03) << 6;
1574}
1575
1576uint8_t
1578{
1579 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1580
1581 return m_basicTriggerDependentUserInfo & 0x03;
1582}
1583
1584uint8_t
1586{
1587 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1588
1589 return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1590}
1591
1592AcIndex
1594{
1595 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1596
1597 return AcIndex((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1598}
1599
1600void
1602{
1604 "Not a MU-BAR Trigger frame");
1607 "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1609}
1610
1613{
1615 "Not a MU-BAR Trigger frame");
1616
1618}
1619
1620/***********************************
1621 * Trigger frame
1622 ***********************************/
1623
1625
1627 : m_variant(TriggerFrameVariant::HE),
1628 m_triggerType(TriggerFrameType::BASIC_TRIGGER),
1629 m_ulLength(0),
1630 m_moreTF(false),
1631 m_csRequired(false),
1632 m_ulBandwidth(0),
1633 m_giAndLtfType(0),
1634 m_apTxPower(0),
1635 m_ulSpatialReuse(0),
1636 m_padding(0)
1637{
1638}
1639
1642{
1644 "This constructor cannot be used for MU-RTS");
1645
1646 switch (txVector.GetPreambleType())
1647 {
1650 break;
1653 break;
1654 default:
1655 NS_ABORT_MSG("Cannot create a TF out of a TXVECTOR with preamble type: "
1656 << txVector.GetPreambleType());
1657 }
1658
1659 m_triggerType = type;
1660 SetUlBandwidth(txVector.GetChannelWidth());
1661 SetUlLength(txVector.GetLength());
1662 uint16_t gi = txVector.GetGuardInterval();
1663 if (gi == 800 || gi == 1600)
1664 {
1665 m_giAndLtfType = 1;
1666 }
1667 else
1668 {
1669 m_giAndLtfType = 2;
1670 }
1671 for (auto& userInfo : txVector.GetHeMuUserInfoMap())
1672 {
1674 ui.SetAid12(userInfo.first);
1675 ui.SetRuAllocation(userInfo.second.ru);
1676 ui.SetUlMcs(userInfo.second.mcs);
1677 ui.SetSsAllocation(1, userInfo.second.nss); // MU-MIMO is not supported
1678 }
1679}
1680
1682{
1683}
1684
1687{
1688 // check for self-assignment
1689 if (&trigger == this)
1690 {
1691 return *this;
1692 }
1693
1694 m_variant = trigger.m_variant;
1695 m_triggerType = trigger.m_triggerType;
1696 m_ulLength = trigger.m_ulLength;
1697 m_moreTF = trigger.m_moreTF;
1698 m_csRequired = trigger.m_csRequired;
1699 m_ulBandwidth = trigger.m_ulBandwidth;
1701 m_apTxPower = trigger.m_apTxPower;
1703 m_padding = trigger.m_padding;
1704 m_userInfoFields.clear();
1706 return *this;
1707}
1708
1709TypeId
1711{
1712 static TypeId tid = TypeId("ns3::CtrlTriggerHeader")
1713 .SetParent<Header>()
1714 .SetGroupName("Wifi")
1715 .AddConstructor<CtrlTriggerHeader>();
1716 return tid;
1717}
1718
1719TypeId
1721{
1722 return GetTypeId();
1723}
1724
1725void
1726CtrlTriggerHeader::Print(std::ostream& os) const
1727{
1728 os << "TriggerType=" << GetTypeString() << ", Bandwidth=" << +GetUlBandwidth()
1729 << ", UL Length=" << m_ulLength;
1730
1731 for (auto& ui : m_userInfoFields)
1732 {
1733 ui.Print(os);
1734 }
1735}
1736
1737void
1739{
1741 "Cannot change Common Info field variant if User Info fields are present");
1742 m_variant = variant;
1743}
1744
1747{
1748 return m_variant;
1749}
1750
1753{
1754 uint32_t size = 0;
1755 size += 8; // Common Info (excluding Trigger Dependent Common Info)
1756
1757 // Add the size of the Trigger Dependent Common Info subfield
1759 {
1760 size += 4;
1761 }
1762
1763 for (auto& ui : m_userInfoFields)
1764 {
1765 size += ui.GetSerializedSize();
1766 }
1767
1768 size += m_padding;
1769
1770 return size;
1771}
1772
1773void
1775{
1777 "BFRP Trigger frame is not supported");
1779 "GCR-MU-BAR Trigger frame is not supported");
1781 "NFRP Trigger frame is not supported");
1782
1783 Buffer::Iterator i = start;
1784
1785 uint64_t commonInfo = 0;
1786 commonInfo |= (static_cast<uint8_t>(m_triggerType) & 0x0f);
1787 commonInfo |= (m_ulLength & 0x0fff) << 4;
1788 commonInfo |= (m_moreTF ? 1 << 16 : 0);
1789 commonInfo |= (m_csRequired ? 1 << 17 : 0);
1790 commonInfo |= (m_ulBandwidth & 0x03) << 18;
1791 commonInfo |= (m_giAndLtfType & 0x03) << 20;
1792 commonInfo |= static_cast<uint64_t>(m_apTxPower & 0x3f) << 28;
1793 commonInfo |= static_cast<uint64_t>(m_ulSpatialReuse) << 37;
1795 {
1796 uint64_t ulHeSigA2 = 0x01ff; // nine bits equal to 1
1797 commonInfo |= ulHeSigA2 << 54;
1798 }
1799
1800 i.WriteHtolsbU64(commonInfo);
1801
1802 for (auto& ui : m_userInfoFields)
1803 {
1804 i = ui.Serialize(i);
1805 }
1806
1807 for (std::size_t count = 0; count < m_padding; count++)
1808 {
1809 i.WriteU8(0xff); // Padding field
1810 }
1811}
1812
1815{
1816 Buffer::Iterator i = start;
1817
1818 uint64_t commonInfo = i.ReadLsbtohU64();
1819
1820 m_triggerType = static_cast<TriggerFrameType>(commonInfo & 0x0f);
1821 m_ulLength = (commonInfo >> 4) & 0x0fff;
1822 m_moreTF = (commonInfo >> 16) & 0x01;
1823 m_csRequired = (commonInfo >> 17) & 0x01;
1824 m_ulBandwidth = (commonInfo >> 18) & 0x03;
1825 m_giAndLtfType = (commonInfo >> 20) & 0x03;
1826 m_apTxPower = (commonInfo >> 28) & 0x3f;
1827 m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1828 uint8_t bit54and55 = (commonInfo >> 54) & 0x03;
1830 m_userInfoFields.clear();
1831 m_padding = 0;
1832
1834 "BFRP Trigger frame is not supported");
1836 "GCR-MU-BAR Trigger frame is not supported");
1838 "NFRP Trigger frame is not supported");
1839
1840 while (i.GetRemainingSize() >= 2)
1841 {
1842 // read the first 2 bytes to check if we encountered the Padding field
1843 if (i.ReadU16() == 0xffff)
1844 {
1845 m_padding = i.GetRemainingSize() + 2;
1846 }
1847 else
1848 {
1849 // go back 2 bytes to deserialize the User Info field from the beginning
1850 i.Prev(2);
1852 i = ui.Deserialize(i);
1853 }
1854 }
1855
1856 return i.GetDistanceFrom(start);
1857}
1858
1859void
1861{
1862 m_triggerType = type;
1863}
1864
1867{
1868 return m_triggerType;
1869}
1870
1871const char*
1873{
1874 return GetTypeString(GetType());
1875}
1876
1877const char*
1879{
1880#define FOO(x) \
1881 case TriggerFrameType::x: \
1882 return #x;
1883
1884 switch (type)
1885 {
1894 default:
1895 return "ERROR";
1896 }
1897#undef FOO
1898}
1899
1900bool
1902{
1904}
1905
1906bool
1908{
1910}
1911
1912bool
1914{
1916}
1917
1918bool
1920{
1922}
1923
1924bool
1926{
1928}
1929
1930bool
1932{
1934}
1935
1936bool
1938{
1940}
1941
1942bool
1944{
1946}
1947
1948void
1950{
1951 m_ulLength = (len & 0x0fff);
1952}
1953
1954uint16_t
1956{
1957 return m_ulLength;
1958}
1959
1962{
1964 "GetHeTbTxVector() cannot be used for MU-RTS");
1965 auto userInfoIt = FindUserInfoWithAid(staId);
1966 NS_ASSERT(userInfoIt != end());
1967
1968 WifiTxVector v;
1969 v.SetPreambleType(userInfoIt->GetPreambleType());
1974 staId,
1975 {userInfoIt->GetRuAllocation(), userInfoIt->GetUlMcs(), userInfoIt->GetNss()});
1976 return v;
1977}
1978
1979void
1981{
1982 m_moreTF = more;
1983}
1984
1985bool
1987{
1988 return m_moreTF;
1989}
1990
1991void
1993{
1994 m_csRequired = cs;
1995}
1996
1997bool
1999{
2000 return m_csRequired;
2001}
2002
2003void
2005{
2006 switch (bw)
2007 {
2008 case 20:
2009 m_ulBandwidth = 0;
2010 break;
2011 case 40:
2012 m_ulBandwidth = 1;
2013 break;
2014 case 80:
2015 m_ulBandwidth = 2;
2016 break;
2017 case 160:
2018 m_ulBandwidth = 3;
2019 break;
2020 default:
2021 NS_FATAL_ERROR("Bandwidth value not allowed.");
2022 break;
2023 }
2024}
2025
2026uint16_t
2028{
2029 return (1 << m_ulBandwidth) * 20;
2030}
2031
2032void
2033CtrlTriggerHeader::SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
2034{
2035 if (ltfType == 1 && guardInterval == 1600)
2036 {
2037 m_giAndLtfType = 0;
2038 }
2039 else if (ltfType == 2 && guardInterval == 1600)
2040 {
2041 m_giAndLtfType = 1;
2042 }
2043 else if (ltfType == 4 && guardInterval == 3200)
2044 {
2045 m_giAndLtfType = 2;
2046 }
2047 else
2048 {
2049 NS_FATAL_ERROR("Invalid combination of GI and LTF type");
2050 }
2051}
2052
2053uint16_t
2055{
2056 if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
2057 {
2058 return 1600;
2059 }
2060 else if (m_giAndLtfType == 2)
2061 {
2062 return 3200;
2063 }
2064 else
2065 {
2066 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2067 }
2068}
2069
2070uint8_t
2072{
2073 if (m_giAndLtfType == 0)
2074 {
2075 return 1;
2076 }
2077 else if (m_giAndLtfType == 1)
2078 {
2079 return 2;
2080 }
2081 else if (m_giAndLtfType == 2)
2082 {
2083 return 4;
2084 }
2085 else
2086 {
2087 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2088 }
2089}
2090
2091void
2093{
2094 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2095 NS_ABORT_MSG_IF(power < -20 || power > 40, "Out of range power values");
2096
2097 m_apTxPower = static_cast<uint8_t>(power + 20);
2098}
2099
2100int8_t
2102{
2103 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2104 return static_cast<int8_t>(m_apTxPower) - 20;
2105}
2106
2107void
2109{
2110 m_ulSpatialReuse = sr;
2111}
2112
2113uint16_t
2115{
2116 return m_ulSpatialReuse;
2117}
2118
2119void
2121{
2122 NS_ABORT_MSG_IF(size == 1, "The Padding field, if present, shall be at least two octets");
2123 m_padding = size;
2124}
2125
2126std::size_t
2128{
2129 return m_padding;
2130}
2131
2134{
2135 // make a copy of this Trigger Frame and remove the User Info fields from the copy
2136 CtrlTriggerHeader trigger(*this);
2137 trigger.m_userInfoFields.clear();
2138 return trigger;
2139}
2140
2143{
2145 return m_userInfoFields.back();
2146}
2147
2150{
2152 userInfo.GetType() != m_triggerType,
2153 "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2154 m_userInfoFields.push_back(userInfo);
2155 return m_userInfoFields.back();
2156}
2157
2160{
2161 return m_userInfoFields.begin();
2162}
2163
2166{
2167 return m_userInfoFields.end();
2168}
2169
2172{
2173 return m_userInfoFields.begin();
2174}
2175
2178{
2179 return m_userInfoFields.end();
2180}
2181
2182std::size_t
2184{
2185 return m_userInfoFields.size();
2186}
2187
2190{
2191 // the lambda function returns true if a User Info field has the AID12 subfield
2192 // equal to the given aid12 value
2193 return std::find_if(start, end(), [aid12](const CtrlTriggerUserInfoField& ui) -> bool {
2194 return (ui.GetAid12() == aid12);
2195 });
2196}
2197
2200{
2201 return FindUserInfoWithAid(m_userInfoFields.begin(), aid12);
2202}
2203
2206{
2207 return FindUserInfoWithAid(start, 0);
2208}
2209
2212{
2213 return FindUserInfoWithAid(0);
2214}
2215
2218{
2219 return FindUserInfoWithAid(start, 2045);
2220}
2221
2224{
2225 return FindUserInfoWithAid(2045);
2226}
2227
2228bool
2230{
2232 {
2233 return true;
2234 }
2235
2236 // check that allocated RUs do not overlap
2237 // TODO This is not a problem in case of UL MU-MIMO
2238 std::vector<HeRu::RuSpec> prevRus;
2239
2240 for (auto& ui : m_userInfoFields)
2241 {
2242 if (HeRu::DoesOverlap(GetUlBandwidth(), ui.GetRuAllocation(), prevRus))
2243 {
2244 return false;
2245 }
2246 prevRus.push_back(ui.GetRuAllocation());
2247 }
2248 return true;
2249}
2250
2251} // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint32_t GetRemainingSize() const
Definition: buffer.cc:1179
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:908
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:916
uint16_t ReadLsbtohU16()
Definition: buffer.cc:1070
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1100
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:926
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:786
void Prev()
go backward by one byte
Definition: buffer.h:860
uint16_t ReadU16()
Definition: buffer.h:1035
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1082
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:460
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:453
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition: he-ru.cc:467
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:625
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:936
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:72
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:133
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