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 m_baInfo.push_back({.m_aidTidInfo = 0,
462 .m_startingSeq = 0,
463 .m_bitmap = std::vector<uint8_t>(bitmapLen, 0),
464 .m_ra = Mac48Address()});
465 }
466}
467
470{
471 return m_baType;
472}
473
474void
475CtrlBAckResponseHeader::SetTidInfo(uint8_t tid, std::size_t index)
476{
478 "index can only be non null for Multi-STA Block Ack");
479 NS_ASSERT(index < m_baInfo.size());
480
482 {
483 m_tidInfo = static_cast<uint16_t>(tid);
484 }
485 else
486 {
487 m_baInfo[index].m_aidTidInfo |= ((static_cast<uint16_t>(tid) & 0x000f) << 12);
488 }
489}
490
491void
492CtrlBAckResponseHeader::SetStartingSequence(uint16_t seq, std::size_t index)
493{
495 "index can only be non null for Multi-STA Block Ack");
496 NS_ASSERT(index < m_baInfo.size());
497
498 m_baInfo[index].m_startingSeq = seq;
499}
500
501bool
503{
504 return m_baAckPolicy;
505}
506
507uint8_t
509{
511 "index can only be non null for Multi-STA Block Ack");
512 NS_ASSERT(index < m_baInfo.size());
513
514 uint8_t tid = 0;
515
517 {
518 tid = static_cast<uint8_t>(m_tidInfo);
519 }
520 else
521 {
522 tid = static_cast<uint8_t>((m_baInfo[index].m_aidTidInfo >> 12) & 0x000f);
523 }
524 return tid;
525}
526
527uint16_t
529{
531 "index can only be non null for Multi-STA Block Ack");
532 NS_ASSERT(index < m_baInfo.size());
533
534 return m_baInfo[index].m_startingSeq;
535}
536
537bool
539{
541}
542
543bool
545{
547}
548
549bool
551{
553}
554
555bool
557{
559}
560
561bool
563{
565}
566
567void
568CtrlBAckResponseHeader::SetAid11(uint16_t aid, std::size_t index)
569{
571
572 m_baInfo[index].m_aidTidInfo |= (aid & 0x07ff);
573}
574
575uint16_t
576CtrlBAckResponseHeader::GetAid11(std::size_t index) const
577{
579
580 return m_baInfo[index].m_aidTidInfo & 0x07ff;
581}
582
583void
584CtrlBAckResponseHeader::SetAckType(bool type, std::size_t index)
585{
587
588 if (type)
589 {
590 m_baInfo[index].m_aidTidInfo |= (1 << 11);
591 }
592}
593
594bool
596{
598
599 return ((m_baInfo[index].m_aidTidInfo >> 11) & 0x0001) != 0;
600}
601
602void
604{
605 NS_ASSERT(GetAid11(index) == 2045);
606
607 m_baInfo[index].m_ra = ra;
608}
609
612{
613 NS_ASSERT(GetAid11(index) == 2045);
614
615 return m_baInfo[index].m_ra;
616}
617
618std::size_t
620{
622 return m_baInfo.size();
623}
624
625std::vector<uint32_t>
627{
629
630 std::vector<uint32_t> ret;
631 ret.reserve(m_baInfo.size());
632 for (uint32_t i = 0; i < m_baInfo.size(); i++)
633 {
634 if (GetAid11(i) == aid)
635 {
636 ret.push_back(i);
637 }
638 }
639 return ret;
640}
641
642uint16_t
644{
645 uint16_t res = 0;
646 if (m_baAckPolicy)
647 {
648 res |= 0x1;
649 }
650 switch (m_baType.m_variant)
651 {
653 break;
655 res |= (0x02 << 1);
656 break;
658 res |= (0x01 << 1);
659 break;
661 res |= (0x03 << 1);
662 break;
664 res |= (0x0b << 1);
665 break;
666 default:
667 NS_FATAL_ERROR("Invalid BA type");
668 break;
669 }
671 {
672 res |= (m_tidInfo << 12) & (0xf << 12);
673 }
674 return res;
675}
676
677void
679{
680 m_baAckPolicy = ((ba & 0x01) == 1);
681 if (((ba >> 1) & 0x0f) == 0x03)
682 {
684 }
685 else if (((ba >> 1) & 0x0f) == 0x01)
686 {
688 }
689 else if (((ba >> 1) & 0x0f) == 0x02)
690 {
692 }
693 else if (((ba >> 1) & 0x0f) == 0)
694 {
696 }
697 else if (((ba >> 1) & 0x0f) == 0x0b)
698 {
700 }
701 else
702 {
703 NS_FATAL_ERROR("Invalid BA type");
704 }
706 {
707 m_tidInfo = (ba >> 12) & 0x0f;
708 }
709}
710
711uint16_t
713{
715 "index can only be non null for Multi-STA Block Ack");
716 NS_ASSERT(index < m_baInfo.size());
717
718 uint16_t ret = (m_baInfo[index].m_startingSeq << 4) & 0xfff0;
719
720 // The Fragment Number subfield encodes the length of the bitmap for
721 // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
722 // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
724 {
725 if (m_baType.m_bitmapLen[0] == 32)
726 {
727 ret |= 0x0004;
728 }
729 }
731 {
732 NS_ASSERT(m_baInfo.size() == m_baType.m_bitmapLen.size());
733 NS_ASSERT_MSG(!m_baInfo[index].m_bitmap.empty(),
734 "This Per AID TID Info subfield has no Starting Sequence Control subfield");
735
736 if (m_baType.m_bitmapLen[index] == 16)
737 {
738 ret |= 0x0002;
739 }
740 else if (m_baType.m_bitmapLen[index] == 32)
741 {
742 ret |= 0x0004;
743 }
744 else if (m_baType.m_bitmapLen[index] == 4)
745 {
746 ret |= 0x0006;
747 }
748 }
749 return ret;
750}
751
752void
753CtrlBAckResponseHeader::SetStartingSequenceControl(uint16_t seqControl, std::size_t index)
754{
756 "index can only be non null for Multi-STA Block Ack");
757 NS_ASSERT(index < m_baInfo.size());
758
759 // The Fragment Number subfield encodes the length of the bitmap for
760 // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
761 // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
763 {
764 if ((seqControl & 0x0001) == 1)
765 {
766 NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
767 }
768 if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 0)
769 {
771 }
772 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
773 {
775 }
776 else
777 {
778 NS_FATAL_ERROR("Reserved configurations");
779 }
780 }
782 {
783 if ((seqControl & 0x0001) == 1)
784 {
785 NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
786 }
787 uint8_t bitmapLen = 0;
788 if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 0)
789 {
790 bitmapLen = 8;
791 }
792 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 1)
793 {
794 bitmapLen = 16;
795 }
796 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
797 {
798 bitmapLen = 32;
799 }
800 else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 3)
801 {
802 bitmapLen = 4;
803 }
804 else
805 {
806 NS_FATAL_ERROR("Reserved configurations");
807 }
808 m_baType.m_bitmapLen[index] = bitmapLen;
809 m_baInfo[index].m_bitmap.assign(bitmapLen, 0);
810 }
811
812 m_baInfo[index].m_startingSeq = (seqControl >> 4) & 0x0fff;
813}
814
817{
819 "index can only be non null for Multi-STA Block Ack");
820 NS_ASSERT(index < m_baInfo.size());
821
822 Buffer::Iterator i = start;
823 switch (m_baType.m_variant)
824 {
829 for (const auto& byte : m_baInfo[index].m_bitmap)
830 {
831 i.WriteU8(byte);
832 }
833 break;
835 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
836 break;
837 default:
838 NS_FATAL_ERROR("Invalid BA type");
839 break;
840 }
841 return i;
842}
843
846{
848 "index can only be non null for Multi-STA Block Ack");
849 NS_ASSERT(index < m_baInfo.size());
850
851 Buffer::Iterator i = start;
852 switch (m_baType.m_variant)
853 {
858 for (uint8_t j = 0; j < m_baType.m_bitmapLen[index]; j++)
859 {
860 m_baInfo[index].m_bitmap[j] = i.ReadU8();
861 }
862 break;
864 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
865 break;
866 default:
867 NS_FATAL_ERROR("Invalid BA type");
868 break;
869 }
870 return i;
871}
872
873void
874CtrlBAckResponseHeader::SetReceivedPacket(uint16_t seq, std::size_t index)
875{
877 "index can only be non null for Multi-STA Block Ack");
878 NS_ASSERT(index < m_baInfo.size());
879
880 if (!IsInBitmap(seq, index))
881 {
882 return;
883 }
884 switch (m_baType.m_variant)
885 {
887 /* To set correctly basic block ack bitmap we need fragment number too.
888 So if it's not specified, we consider packet not fragmented. */
889 m_baInfo[index].m_bitmap[IndexInBitmap(seq) * 2] |= 0x01;
890 break;
894 uint16_t i = IndexInBitmap(seq, index);
895 m_baInfo[index].m_bitmap[i / 8] |= (uint8_t(0x01) << (i % 8));
896 break;
897 }
899 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
900 break;
901 default:
902 NS_FATAL_ERROR("Invalid BA type");
903 break;
904 }
905}
906
907void
909{
910 NS_ASSERT(frag < 16);
911 if (!IsInBitmap(seq))
912 {
913 return;
914 }
915 switch (m_baType.m_variant)
916 {
918 m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] |= (0x01 << (frag % 8));
919 break;
923 /* We can ignore this...compressed block ack doesn't support
924 acknowledgment of single fragments */
925 break;
927 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
928 break;
929 default:
930 NS_FATAL_ERROR("Invalid BA type");
931 break;
932 }
933}
934
935bool
936CtrlBAckResponseHeader::IsPacketReceived(uint16_t seq, std::size_t index) const
937{
939 "index can only be non null for Multi-STA Block Ack");
940 NS_ASSERT(index < m_baInfo.size());
941
943 GetTidInfo(index) == 14)
944 {
945 // All-ack context
946 return true;
947 }
948 if (!IsInBitmap(seq, index))
949 {
950 return false;
951 }
952 switch (m_baType.m_variant)
953 {
955 /*It's impossible to say if an entire packet was correctly received. */
956 return false;
960 uint16_t i = IndexInBitmap(seq, index);
961 uint8_t mask = uint8_t(0x01) << (i % 8);
962 return (m_baInfo[index].m_bitmap[i / 8] & mask) != 0;
963 }
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 return false;
972}
973
974bool
975CtrlBAckResponseHeader::IsFragmentReceived(uint16_t seq, uint8_t frag) const
976{
977 NS_ASSERT(frag < 16);
978 if (!IsInBitmap(seq))
979 {
980 return false;
981 }
982 switch (m_baType.m_variant)
983 {
985 return (m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] & (0x01 << (frag % 8))) !=
986 0;
990 /* We can ignore this...compressed block ack doesn't support
991 acknowledgement of single fragments */
992 return false;
994 NS_FATAL_ERROR("Multi-tid block ack is not supported.");
995 break;
996 }
997 default: {
998 NS_FATAL_ERROR("Invalid BA type");
999 break;
1000 }
1001 }
1002 return false;
1003}
1004
1005uint16_t
1006CtrlBAckResponseHeader::IndexInBitmap(uint16_t seq, std::size_t index) const
1007{
1008 uint16_t i;
1009 if (seq >= m_baInfo[index].m_startingSeq)
1010 {
1011 i = seq - m_baInfo[index].m_startingSeq;
1012 }
1013 else
1014 {
1015 i = SEQNO_SPACE_SIZE - m_baInfo[index].m_startingSeq + seq;
1016 }
1017
1018 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1019
1021 {
1022 nAckedMpdus = nAckedMpdus / 16;
1023 }
1024
1025 NS_ASSERT(i < nAckedMpdus);
1026 return i;
1027}
1028
1029bool
1030CtrlBAckResponseHeader::IsInBitmap(uint16_t seq, std::size_t index) const
1031{
1033 "index can only be non null for Multi-STA Block Ack");
1034 NS_ASSERT(index < m_baType.m_bitmapLen.size());
1035
1036 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1037
1039 {
1040 nAckedMpdus = nAckedMpdus / 16;
1041 }
1042
1043 return (seq - m_baInfo[index].m_startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE <
1044 nAckedMpdus;
1045}
1046
1047const std::vector<uint8_t>&
1049{
1051 "index can only be non null for Multi-STA Block Ack");
1052 NS_ASSERT(index < m_baInfo.size());
1053
1054 return m_baInfo[index].m_bitmap;
1055}
1056
1057void
1059{
1061 "index can only be non null for Multi-STA Block Ack");
1062 NS_ASSERT(index < m_baInfo.size());
1063
1064 m_baInfo[index].m_bitmap.assign(m_baType.m_bitmapLen[index], 0);
1065}
1066
1067/***********************************
1068 * Trigger frame - User Info field
1069 ***********************************/
1070
1072 TriggerFrameVariant variant)
1073 : m_variant(variant),
1074 m_aid12(0),
1075 m_ruAllocation(0),
1076 m_ulFecCodingType(false),
1077 m_ulMcs(0),
1078 m_ulDcm(false),
1079 m_ps160(true),
1080 m_ulTargetRssi(0),
1081 m_triggerType(triggerType),
1082 m_basicTriggerDependentUserInfo(0)
1083{
1084 memset(&m_bits26To31, 0, sizeof(m_bits26To31));
1085}
1086
1088{
1089}
1090
1093{
1094 NS_ABORT_MSG_IF(m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1095
1096 // check for self-assignment
1097 if (&userInfo == this)
1098 {
1099 return *this;
1100 }
1101
1102 m_variant = userInfo.m_variant;
1103 m_aid12 = userInfo.m_aid12;
1104 m_ruAllocation = userInfo.m_ruAllocation;
1106 m_ulMcs = userInfo.m_ulMcs;
1107 m_ulDcm = userInfo.m_ulDcm;
1108 m_ps160 = userInfo.m_ps160;
1109 m_bits26To31 = userInfo.m_bits26To31;
1110 m_ulTargetRssi = userInfo.m_ulTargetRssi;
1113 return *this;
1114}
1115
1116void
1117CtrlTriggerUserInfoField::Print(std::ostream& os) const
1118{
1119 os << ", USER_INFO " << (m_variant == TriggerFrameVariant::HE ? "HE" : "EHT")
1120 << " variant AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation
1121 << ", MCS=" << +m_ulMcs;
1122}
1123
1126{
1127 uint32_t size = 0;
1128 size += 5; // User Info (excluding Trigger Dependent User Info)
1129
1130 switch (m_triggerType)
1131 {
1134 size += 1;
1135 break;
1137 size +=
1138 m_muBarTriggerDependentUserInfo.GetSerializedSize(); // BAR Control and BAR Information
1139 break;
1140 default:;
1141 // The Trigger Dependent User Info subfield is not present in the other variants
1142 }
1143
1144 return size;
1145}
1146
1149{
1151 "BFRP Trigger frame is not supported");
1153 "GCR-MU-BAR Trigger frame is not supported");
1155 "NFRP Trigger frame is not supported");
1156
1157 Buffer::Iterator i = start;
1158
1159 uint32_t userInfo = 0; // User Info except the MSB
1160 userInfo |= (m_aid12 & 0x0fff);
1161 userInfo |= (m_ruAllocation << 12);
1162 userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1163 userInfo |= (m_ulMcs & 0x0f) << 21;
1165 {
1166 userInfo |= (m_ulDcm ? 1 << 25 : 0);
1167 }
1168
1169 if (m_aid12 != 0 && m_aid12 != 2045)
1170 {
1171 userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1172 userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1173 }
1174 else
1175 {
1176 userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1177 userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1178 }
1179
1180 i.WriteHtolsbU32(userInfo);
1181 // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and B39, which is
1182 // reserved in the HE variant and the PS160 subfield in the EHT variant.
1183 uint8_t bit32To39 = m_ulTargetRssi;
1185 {
1186 bit32To39 |= (m_ps160 ? 1 << 7 : 0);
1187 }
1188
1189 i.WriteU8(bit32To39);
1190
1192 {
1194 }
1196 {
1199 }
1200
1201 return i;
1202}
1203
1206{
1208 "BFRP Trigger frame is not supported");
1210 "GCR-MU-BAR Trigger frame is not supported");
1212 "NFRP Trigger frame is not supported");
1213
1214 Buffer::Iterator i = start;
1215
1216 uint32_t userInfo = i.ReadLsbtohU32();
1217
1218 m_aid12 = userInfo & 0x0fff;
1219 NS_ABORT_MSG_IF(m_aid12 == 4095, "Cannot deserialize a Padding field");
1220 m_ruAllocation = (userInfo >> 12) & 0xff;
1221 m_ulFecCodingType = (userInfo >> 20) & 0x01;
1222 m_ulMcs = (userInfo >> 21) & 0x0f;
1224 {
1225 m_ulDcm = (userInfo >> 25) & 0x01;
1226 }
1227
1228 if (m_aid12 != 0 && m_aid12 != 2045)
1229 {
1230 m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1231 m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1232 }
1233 else
1234 {
1235 m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1236 m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1237 }
1238
1239 uint8_t bit32To39 = i.ReadU8();
1240 m_ulTargetRssi = bit32To39 & 0x7f; // B39 is reserved in HE variant
1242 {
1243 m_ps160 = (bit32To39 >> 7) == 1;
1244 }
1245
1247 {
1249 }
1251 {
1253 i.Next(len);
1254 }
1255
1256 return i;
1257}
1258
1261{
1262 return m_triggerType;
1263}
1264
1267{
1268 switch (m_variant)
1269 {
1271 return WIFI_PREAMBLE_HE_TB;
1273 return WIFI_PREAMBLE_EHT_TB;
1274 default:
1275 NS_ABORT_MSG("Unexpected variant: " << +static_cast<uint8_t>(m_variant));
1276 }
1277 return WIFI_PREAMBLE_LONG; // to silence warning
1278}
1279
1280void
1282{
1283 m_aid12 = aid & 0x0fff;
1284}
1285
1286uint16_t
1288{
1289 return m_aid12;
1290}
1291
1292bool
1294{
1295 return (m_aid12 == 0);
1296}
1297
1298bool
1300{
1301 return (m_aid12 == 2045);
1302}
1303
1304void
1306{
1307 NS_ABORT_MSG_IF(ru.GetIndex() == 0, "Valid indices start at 1");
1309 "SetMuRtsRuAllocation() must be used for MU-RTS");
1310
1311 switch (ru.GetRuType())
1312 {
1313 case HeRu::RU_26_TONE:
1314 m_ruAllocation = ru.GetIndex() - 1;
1315 break;
1316 case HeRu::RU_52_TONE:
1317 m_ruAllocation = ru.GetIndex() + 36;
1318 break;
1319 case HeRu::RU_106_TONE:
1320 m_ruAllocation = ru.GetIndex() + 52;
1321 break;
1322 case HeRu::RU_242_TONE:
1323 m_ruAllocation = ru.GetIndex() + 60;
1324 break;
1325 case HeRu::RU_484_TONE:
1326 m_ruAllocation = ru.GetIndex() + 64;
1327 break;
1328 case HeRu::RU_996_TONE:
1329 m_ruAllocation = 67;
1330 break;
1332 m_ruAllocation = 68;
1333 break;
1334 default:
1335 NS_FATAL_ERROR("RU type unknown.");
1336 break;
1337 }
1338
1339 NS_ABORT_MSG_IF(m_ruAllocation > 68, "Reserved value.");
1340
1341 m_ruAllocation <<= 1;
1342 if (!ru.GetPrimary80MHz())
1343 {
1345 }
1346}
1347
1350{
1352 "GetMuRtsRuAllocation() must be used for MU-RTS");
1353
1354 HeRu::RuType ruType;
1355 std::size_t index;
1356
1357 bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1358
1359 uint8_t val = m_ruAllocation >> 1;
1360
1361 if (val < 37)
1362 {
1363 ruType = HeRu::RU_26_TONE;
1364 index = val + 1;
1365 }
1366 else if (val < 53)
1367 {
1368 ruType = HeRu::RU_52_TONE;
1369 index = val - 36;
1370 }
1371 else if (val < 61)
1372 {
1373 ruType = HeRu::RU_106_TONE;
1374 index = val - 52;
1375 }
1376 else if (val < 65)
1377 {
1378 ruType = HeRu::RU_242_TONE;
1379 index = val - 60;
1380 }
1381 else if (val < 67)
1382 {
1383 ruType = HeRu::RU_484_TONE;
1384 index = val - 64;
1385 }
1386 else if (val == 67)
1387 {
1388 ruType = HeRu::RU_996_TONE;
1389 index = 1;
1390 }
1391 else if (val == 68)
1392 {
1393 ruType = HeRu::RU_2x996_TONE;
1394 index = 1;
1395 }
1396 else
1397 {
1398 NS_FATAL_ERROR("Reserved value.");
1399 }
1400
1401 return HeRu::RuSpec(ruType, index, primary80MHz);
1402}
1403
1404void
1406{
1408 "SetMuRtsRuAllocation() can only be used for MU-RTS");
1410 value < 61 || value > 68,
1411 "Value "
1412 << +value
1413 << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1414
1415 m_ruAllocation = (value << 1);
1416 if (value == 68)
1417 {
1418 // set B0 for 160 MHz and 80+80 MHz indication
1420 }
1421}
1422
1423uint8_t
1425{
1427 "GetMuRtsRuAllocation() can only be used for MU-RTS");
1428 uint8_t value = (m_ruAllocation >> 1);
1430 value < 61 || value > 68,
1431 "Value "
1432 << +value
1433 << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1434 return value;
1435}
1436
1437void
1439{
1440 m_ulFecCodingType = ldpc;
1441}
1442
1443bool
1445{
1446 return m_ulFecCodingType;
1447}
1448
1449void
1451{
1452 NS_ABORT_MSG_IF(mcs > 11, "Invalid MCS index");
1453 m_ulMcs = mcs;
1454}
1455
1456uint8_t
1458{
1459 return m_ulMcs;
1460}
1461
1462void
1464{
1465 NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1466 m_ulDcm = dcm;
1467}
1468
1469bool
1471{
1472 NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1473 return m_ulDcm;
1474}
1475
1476void
1477CtrlTriggerUserInfoField::SetSsAllocation(uint8_t startingSs, uint8_t nSs)
1478{
1479 NS_ABORT_MSG_IF(m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1480 NS_ABORT_MSG_IF(!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1481 NS_ABORT_MSG_IF(!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1482
1483 m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1484 m_bits26To31.ssAllocation.nSs = nSs - 1;
1485}
1486
1487uint8_t
1489{
1490 if (m_aid12 == 0 || m_aid12 == 2045)
1491 {
1492 return 1;
1493 }
1494 return m_bits26To31.ssAllocation.startingSs + 1;
1495}
1496
1497uint8_t
1499{
1500 if (m_aid12 == 0 || m_aid12 == 2045)
1501 {
1502 return 1;
1503 }
1504 return m_bits26To31.ssAllocation.nSs + 1;
1505}
1506
1507void
1509{
1510 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1511 NS_ABORT_MSG_IF(!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1512
1513 m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1514 m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1515}
1516
1517uint8_t
1519{
1520 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1521
1522 return m_bits26To31.raRuInformation.nRaRu + 1;
1523}
1524
1525bool
1527{
1528 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1529
1530 return m_bits26To31.raRuInformation.moreRaRu;
1531}
1532
1533void
1535{
1536 m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1537}
1538
1539void
1541{
1542 NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
1543
1544 m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
1545}
1546
1547bool
1549{
1550 return (m_ulTargetRssi == 127);
1551}
1552
1553int8_t
1555{
1556 NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
1557
1558 return static_cast<int8_t>(m_ulTargetRssi) - 110;
1559}
1560
1561void
1563 uint8_t tidLimit,
1564 AcIndex prefAc)
1565{
1566 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1567
1568 m_basicTriggerDependentUserInfo = (spacingFactor & 0x03) |
1569 (tidLimit & 0x07) << 2
1570 // B5 is reserved
1571 | (prefAc & 0x03) << 6;
1572}
1573
1574uint8_t
1576{
1577 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1578
1579 return m_basicTriggerDependentUserInfo & 0x03;
1580}
1581
1582uint8_t
1584{
1585 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1586
1587 return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1588}
1589
1590AcIndex
1592{
1593 NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1594
1595 return AcIndex((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1596}
1597
1598void
1600{
1602 "Not a MU-BAR Trigger frame");
1605 "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1607}
1608
1611{
1613 "Not a MU-BAR Trigger frame");
1614
1616}
1617
1618/***********************************
1619 * Trigger frame
1620 ***********************************/
1621
1623
1625 : m_variant(TriggerFrameVariant::HE),
1626 m_triggerType(TriggerFrameType::BASIC_TRIGGER),
1627 m_ulLength(0),
1628 m_moreTF(false),
1629 m_csRequired(false),
1630 m_ulBandwidth(0),
1631 m_giAndLtfType(0),
1632 m_apTxPower(0),
1633 m_ulSpatialReuse(0)
1634{
1635}
1636
1639{
1641 "This constructor cannot be used for MU-RTS");
1642
1643 switch (txVector.GetPreambleType())
1644 {
1647 break;
1650 break;
1651 default:
1652 NS_ABORT_MSG("Cannot create a TF out of a TXVECTOR with preamble type: "
1653 << txVector.GetPreambleType());
1654 }
1655
1656 m_triggerType = type;
1657 SetUlBandwidth(txVector.GetChannelWidth());
1658 SetUlLength(txVector.GetLength());
1659 uint16_t gi = txVector.GetGuardInterval();
1660 if (gi == 800 || gi == 1600)
1661 {
1662 m_giAndLtfType = 1;
1663 }
1664 else
1665 {
1666 m_giAndLtfType = 2;
1667 }
1668 for (auto& userInfo : txVector.GetHeMuUserInfoMap())
1669 {
1671 ui.SetAid12(userInfo.first);
1672 ui.SetRuAllocation(userInfo.second.ru);
1673 ui.SetUlMcs(userInfo.second.mcs);
1674 ui.SetSsAllocation(1, userInfo.second.nss); // MU-MIMO is not supported
1675 }
1676}
1677
1679{
1680}
1681
1684{
1685 // check for self-assignment
1686 if (&trigger == this)
1687 {
1688 return *this;
1689 }
1690
1691 m_variant = trigger.m_variant;
1692 m_triggerType = trigger.m_triggerType;
1693 m_ulLength = trigger.m_ulLength;
1694 m_moreTF = trigger.m_moreTF;
1695 m_csRequired = trigger.m_csRequired;
1696 m_ulBandwidth = trigger.m_ulBandwidth;
1698 m_apTxPower = trigger.m_apTxPower;
1700 m_userInfoFields.clear();
1702 return *this;
1703}
1704
1705TypeId
1707{
1708 static TypeId tid = TypeId("ns3::CtrlTriggerHeader")
1709 .SetParent<Header>()
1710 .SetGroupName("Wifi")
1711 .AddConstructor<CtrlTriggerHeader>();
1712 return tid;
1713}
1714
1715TypeId
1717{
1718 return GetTypeId();
1719}
1720
1721void
1722CtrlTriggerHeader::Print(std::ostream& os) const
1723{
1724 os << "TriggerType=" << GetTypeString() << ", Bandwidth=" << +GetUlBandwidth()
1725 << ", UL Length=" << m_ulLength;
1726
1727 for (auto& ui : m_userInfoFields)
1728 {
1729 ui.Print(os);
1730 }
1731}
1732
1733void
1735{
1737 "Cannot change Common Info field variant if User Info fields are present");
1738 m_variant = variant;
1739}
1740
1743{
1744 return m_variant;
1745}
1746
1749{
1750 uint32_t size = 0;
1751 size += 8; // Common Info (excluding Trigger Dependent Common Info)
1752
1753 // Add the size of the Trigger Dependent Common Info subfield
1755 {
1756 size += 4;
1757 }
1758
1759 for (auto& ui : m_userInfoFields)
1760 {
1761 size += ui.GetSerializedSize();
1762 }
1763
1764 size += 2; // Padding field
1765
1766 return size;
1767}
1768
1769void
1771{
1773 "BFRP Trigger frame is not supported");
1775 "GCR-MU-BAR Trigger frame is not supported");
1777 "NFRP Trigger frame is not supported");
1778
1779 Buffer::Iterator i = start;
1780
1781 uint64_t commonInfo = 0;
1782 commonInfo |= (static_cast<uint8_t>(m_triggerType) & 0x0f);
1783 commonInfo |= (m_ulLength & 0x0fff) << 4;
1784 commonInfo |= (m_moreTF ? 1 << 16 : 0);
1785 commonInfo |= (m_csRequired ? 1 << 17 : 0);
1786 commonInfo |= (m_ulBandwidth & 0x03) << 18;
1787 commonInfo |= (m_giAndLtfType & 0x03) << 20;
1788 commonInfo |= static_cast<uint64_t>(m_apTxPower & 0x3f) << 28;
1789 commonInfo |= static_cast<uint64_t>(m_ulSpatialReuse) << 37;
1791 {
1792 uint64_t ulHeSigA2 = 0x01ff; // nine bits equal to 1
1793 commonInfo |= ulHeSigA2 << 54;
1794 }
1795
1796 i.WriteHtolsbU64(commonInfo);
1797
1798 for (auto& ui : m_userInfoFields)
1799 {
1800 i = ui.Serialize(i);
1801 }
1802
1803 i.WriteHtolsbU16(0xffff); // Padding field, used as delimiter
1804}
1805
1808{
1809 Buffer::Iterator i = start;
1810
1811 uint64_t commonInfo = i.ReadLsbtohU64();
1812
1813 m_triggerType = static_cast<TriggerFrameType>(commonInfo & 0x0f);
1814 m_ulLength = (commonInfo >> 4) & 0x0fff;
1815 m_moreTF = (commonInfo >> 16) & 0x01;
1816 m_csRequired = (commonInfo >> 17) & 0x01;
1817 m_ulBandwidth = (commonInfo >> 18) & 0x03;
1818 m_giAndLtfType = (commonInfo >> 20) & 0x03;
1819 m_apTxPower = (commonInfo >> 28) & 0x3f;
1820 m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1821 uint8_t bit54and55 = (commonInfo >> 54) & 0x03;
1823 m_userInfoFields.clear();
1824
1826 "BFRP Trigger frame is not supported");
1828 "GCR-MU-BAR Trigger frame is not supported");
1830 "NFRP Trigger frame is not supported");
1831
1832 bool isPadding = false;
1833
1834 // We always add a Padding field (of two octets of all 1s) as delimiter
1835 while (!isPadding)
1836 {
1837 // read the first 2 bytes to check if we encountered the Padding field
1838 if (i.ReadU16() == 0xffff)
1839 {
1840 isPadding = true;
1841 }
1842 else
1843 {
1844 // go back 2 bytes to deserialize the User Info field from the beginning
1845 i.Prev(2);
1847 i = ui.Deserialize(i);
1848 }
1849 }
1850
1851 return i.GetDistanceFrom(start);
1852}
1853
1854void
1856{
1857 m_triggerType = type;
1858}
1859
1862{
1863 return m_triggerType;
1864}
1865
1866const char*
1868{
1869 return GetTypeString(GetType());
1870}
1871
1872const char*
1874{
1875#define FOO(x) \
1876 case TriggerFrameType::x: \
1877 return #x; \
1878 break;
1879
1880 switch (type)
1881 {
1890 default:
1891 return "ERROR";
1892 }
1893#undef FOO
1894}
1895
1896bool
1898{
1900}
1901
1902bool
1904{
1906}
1907
1908bool
1910{
1912}
1913
1914bool
1916{
1918}
1919
1920bool
1922{
1924}
1925
1926bool
1928{
1930}
1931
1932bool
1934{
1936}
1937
1938bool
1940{
1942}
1943
1944void
1946{
1947 m_ulLength = (len & 0x0fff);
1948}
1949
1950uint16_t
1952{
1953 return m_ulLength;
1954}
1955
1958{
1960 "GetHeTbTxVector() cannot be used for MU-RTS");
1961 auto userInfoIt = FindUserInfoWithAid(staId);
1962 NS_ASSERT(userInfoIt != end());
1963
1964 WifiTxVector v;
1965 v.SetPreambleType(userInfoIt->GetPreambleType());
1970 staId,
1971 {userInfoIt->GetRuAllocation(), userInfoIt->GetUlMcs(), userInfoIt->GetNss()});
1972 return v;
1973}
1974
1975void
1977{
1978 m_moreTF = more;
1979}
1980
1981bool
1983{
1984 return m_moreTF;
1985}
1986
1987void
1989{
1990 m_csRequired = cs;
1991}
1992
1993bool
1995{
1996 return m_csRequired;
1997}
1998
1999void
2001{
2002 switch (bw)
2003 {
2004 case 20:
2005 m_ulBandwidth = 0;
2006 break;
2007 case 40:
2008 m_ulBandwidth = 1;
2009 break;
2010 case 80:
2011 m_ulBandwidth = 2;
2012 break;
2013 case 160:
2014 m_ulBandwidth = 3;
2015 break;
2016 default:
2017 NS_FATAL_ERROR("Bandwidth value not allowed.");
2018 break;
2019 }
2020}
2021
2022uint16_t
2024{
2025 return (1 << m_ulBandwidth) * 20;
2026}
2027
2028void
2029CtrlTriggerHeader::SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
2030{
2031 if (ltfType == 1 && guardInterval == 1600)
2032 {
2033 m_giAndLtfType = 0;
2034 }
2035 else if (ltfType == 2 && guardInterval == 1600)
2036 {
2037 m_giAndLtfType = 1;
2038 }
2039 else if (ltfType == 4 && guardInterval == 3200)
2040 {
2041 m_giAndLtfType = 2;
2042 }
2043 else
2044 {
2045 NS_FATAL_ERROR("Invalid combination of GI and LTF type");
2046 }
2047}
2048
2049uint16_t
2051{
2052 if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
2053 {
2054 return 1600;
2055 }
2056 else if (m_giAndLtfType == 2)
2057 {
2058 return 3200;
2059 }
2060 else
2061 {
2062 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2063 }
2064}
2065
2066uint8_t
2068{
2069 if (m_giAndLtfType == 0)
2070 {
2071 return 1;
2072 }
2073 else if (m_giAndLtfType == 1)
2074 {
2075 return 2;
2076 }
2077 else if (m_giAndLtfType == 2)
2078 {
2079 return 4;
2080 }
2081 else
2082 {
2083 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2084 }
2085}
2086
2087void
2089{
2090 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2091 NS_ABORT_MSG_IF(power < -20 || power > 40, "Out of range power values");
2092
2093 m_apTxPower = static_cast<uint8_t>(power + 20);
2094}
2095
2096int8_t
2098{
2099 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2100 return static_cast<int8_t>(m_apTxPower) - 20;
2101}
2102
2103void
2105{
2106 m_ulSpatialReuse = sr;
2107}
2108
2109uint16_t
2111{
2112 return m_ulSpatialReuse;
2113}
2114
2117{
2118 // make a copy of this Trigger Frame and remove the User Info fields from the copy
2119 CtrlTriggerHeader trigger(*this);
2120 trigger.m_userInfoFields.clear();
2121 return trigger;
2122}
2123
2126{
2128 return m_userInfoFields.back();
2129}
2130
2133{
2135 userInfo.GetType() != m_triggerType,
2136 "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2137 m_userInfoFields.push_back(userInfo);
2138 return m_userInfoFields.back();
2139}
2140
2143{
2144 return m_userInfoFields.begin();
2145}
2146
2149{
2150 return m_userInfoFields.end();
2151}
2152
2155{
2156 return m_userInfoFields.begin();
2157}
2158
2161{
2162 return m_userInfoFields.end();
2163}
2164
2165std::size_t
2167{
2168 return m_userInfoFields.size();
2169}
2170
2173{
2174 // the lambda function returns true if a User Info field has the AID12 subfield
2175 // equal to the given aid12 value
2176 return std::find_if(start, end(), [aid12](const CtrlTriggerUserInfoField& ui) -> bool {
2177 return (ui.GetAid12() == aid12);
2178 });
2179}
2180
2183{
2184 return FindUserInfoWithAid(m_userInfoFields.begin(), aid12);
2185}
2186
2189{
2190 return FindUserInfoWithAid(start, 0);
2191}
2192
2195{
2196 return FindUserInfoWithAid(0);
2197}
2198
2201{
2202 return FindUserInfoWithAid(start, 2045);
2203}
2204
2207{
2208 return FindUserInfoWithAid(2045);
2209}
2210
2211bool
2213{
2215 {
2216 return true;
2217 }
2218
2219 // check that allocated RUs do not overlap
2220 // TODO This is not a problem in case of UL MU-MIMO
2221 std::vector<HeRu::RuSpec> prevRus;
2222
2223 for (auto& ui : m_userInfoFields)
2224 {
2225 if (HeRu::DoesOverlap(GetUlBandwidth(), ui.GetRuAllocation(), prevRus))
2226 {
2227 return false;
2228 }
2229 prevRus.push_back(ui.GetRuAllocation());
2230 }
2231 return true;
2232}
2233
2234} // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint32_t GetRemainingSize() const
Definition: buffer.cc:1176
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:905
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:913
uint16_t ReadLsbtohU16()
Definition: buffer.cc:1067
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1097
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:923
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:783
void Prev()
go backward by one byte
Definition: buffer.h:860
uint16_t ReadU16()
Definition: buffer.h:1035
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1079
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:945
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.
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.
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
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 ...
union ns3::CtrlTriggerUserInfoField::@72 m_bits26To31
Fields occupying bits 26-31 in the User Info field.
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:442
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:435
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition: he-ru.cc:449
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:607
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:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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.