A Discrete-Event Network Simulator
API
ctrl-headers.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2009 MIRKO BANCHI
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mirko Banchi <mk.banchi@gmail.com>
19 */
20
21#include "ctrl-headers.h"
22#include "wifi-tx-vector.h"
23#include "ns3/he-phy.h"
24#include "wifi-utils.h"
25#include "ns3/address-utils.h"
26#include <algorithm>
27
28namespace ns3 {
29
30
31/***********************************
32 * Block ack request
33 ***********************************/
34
35NS_OBJECT_ENSURE_REGISTERED (CtrlBAckRequestHeader);
36
38 : m_barAckPolicy (false),
39 m_barType (BlockAckReqType::BASIC)
40{
41}
42
44{
45}
46
49{
50 static TypeId tid = TypeId ("ns3::CtrlBAckRequestHeader")
51 .SetParent<Header> ()
52 .SetGroupName ("Wifi")
53 .AddConstructor<CtrlBAckRequestHeader> ()
54 ;
55 return tid;
56}
57
60{
61 return GetTypeId ();
62}
63
64void
65CtrlBAckRequestHeader::Print (std::ostream &os) const
66{
67 os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq << std::dec;
68}
69
72{
73 uint32_t size = 0;
74 size += 2; //Bar control
75 switch (m_barType.m_variant)
76 {
80 size += 2;
81 break;
83 size += (2 + 2) * (m_tidInfo + 1);
84 break;
85 default:
86 NS_FATAL_ERROR ("Invalid BA type");
87 break;
88 }
89 return size;
90}
91
92void
94{
97 switch (m_barType.m_variant)
98 {
103 break;
105 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
106 break;
107 default:
108 NS_FATAL_ERROR ("Invalid BA type");
109 break;
110 }
111}
112
115{
118 switch (m_barType.m_variant)
119 {
124 break;
126 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
127 break;
128 default:
129 NS_FATAL_ERROR ("Invalid BA type");
130 break;
131 }
132 return i.GetDistanceFrom (start);
133}
134
135uint16_t
137{
138 uint16_t res = 0;
139 switch (m_barType.m_variant)
140 {
142 break;
144 res |= (0x02 << 1);
145 break;
147 res |= (0x01 << 1);
148 break;
150 res |= (0x03 << 1);
151 break;
152 default:
153 NS_FATAL_ERROR ("Invalid BA type");
154 break;
155 }
156 res |= (m_tidInfo << 12) & (0xf << 12);
157 return res;
158}
159
160void
162{
163 m_barAckPolicy = ((bar & 0x01) == 1);
164 if (((bar >> 1) & 0x0f) == 0x03)
165 {
167 }
168 else if (((bar >> 1) & 0x0f) == 0x01)
169 {
171 }
172 else if (((bar >> 1) & 0x0f) == 0x02)
173 {
175 }
176 else
177 {
179 }
180 m_tidInfo = (bar >> 12) & 0x0f;
181}
182
183uint16_t
185{
186 return (m_startingSeq << 4) & 0xfff0;
187}
188
189void
191{
192 m_startingSeq = (seqControl >> 4) & 0x0fff;
193}
194
195void
197{
198 m_barAckPolicy = immediateAck;
199}
200
201void
203{
204 m_barType = type;
205}
206
209{
210 return m_barType;
211}
212
213void
215{
216 m_tidInfo = static_cast<uint16_t> (tid);
217}
218
219void
221{
222 m_startingSeq = seq;
223}
224
225bool
227{
228 return m_barAckPolicy;
229}
230
231uint8_t
233{
234 uint8_t tid = static_cast<uint8_t> (m_tidInfo);
235 return tid;
236}
237
238uint16_t
240{
241 return m_startingSeq;
242}
243
244bool
246{
248}
249
250bool
252{
254}
255
256bool
258{
260}
261
262bool
264{
266}
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 ;
294 return tid;
295}
296
297TypeId
299{
300 return GetTypeId ();
301}
302
303void
304CtrlBAckResponseHeader::Print (std::ostream &os) const
305{
307 {
308 os << "TID_INFO=" << m_tidInfo << ", StartingSeq=0x" << std::hex << 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)
315 << ", TID=" << GetTidInfo (i)
316 << ", StartingSeq=0x" << std::hex << m_baInfo[i].m_startingSeq << std::dec << "}";
317 }
318 }
319}
320
323{
324 // This method only makes use of the configured BA type, so that functions like
325 // GetBlockAckSize () can easily return the size of a Block Ack of a given type
326 uint32_t size = 0;
327 size += 2; //BA control
328 switch (m_baType.m_variant)
329 {
333 size += (2 + m_baType.m_bitmapLen[0]);
334 break;
336 size += (2 + 2 + 8) * (m_tidInfo + 1); //Multi-TID block ack
337 break;
339 for (auto& bitmapLen : m_baType.m_bitmapLen)
340 {
341 size += 2 /* AID TID Info */ + (bitmapLen > 0 ? 2 : 0) /* BA SSC */ + bitmapLen;
342 }
343 break;
344 default:
345 NS_FATAL_ERROR ("Invalid BA type");
346 break;
347 }
348 return size;
349}
350
351void
353{
356 switch (m_baType.m_variant)
357 {
362 i = SerializeBitmap (i);
363 break;
365 for (std::size_t index = 0; index < m_baInfo.size (); index++)
366 {
367 i.WriteHtolsbU16 (m_baInfo[index].m_aidTidInfo);
368 if (GetAid11 (index) != 2045)
369 {
370 if (m_baInfo[index].m_bitmap.size () > 0)
371 {
373 i = SerializeBitmap (i, index);
374 }
375 }
376 else
377 {
378 uint32_t reserved = 0;
379 i.WriteHtolsbU32 (reserved);
380 WriteTo (i, m_baInfo[index].m_ra);
381 }
382 }
383 break;
385 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
386 break;
387 default:
388 NS_FATAL_ERROR ("Invalid BA type");
389 break;
390 }
391}
392
395{
398 switch (m_baType.m_variant)
399 {
404 i = DeserializeBitmap (i);
405 break;
407 {
408 std::size_t index = 0;
409 while (i.GetRemainingSize () > 0)
410 {
411 m_baInfo.push_back (BaInfoInstance ());
412 m_baType.m_bitmapLen.push_back (0); // updated by next call to SetStartingSequenceControl
413
414 m_baInfo.back ().m_aidTidInfo = i.ReadLsbtohU16 ();
415
416 if (GetAid11 (index) != 2045)
417 {
418 // the Block Ack Starting Sequence Control and Block Ack Bitmap subfields
419 // are only present in Block acknowledgement context, i.e., if the Ack Type
420 // subfield is set to 0 and the TID subfield is set to a value from 0 to 7.
421 if (!GetAckType (index) && GetTidInfo (index) < 8)
422 {
424 i = DeserializeBitmap (i, index);
425 }
426 }
427 else
428 {
429 i.ReadLsbtohU32 (); // next 4 bytes are reserved
430 ReadFrom (i, m_baInfo.back ().m_ra);
431 // the length of this Per AID TID Info subfield is 12, so set
432 // the bitmap length to 8 to simulate the correct size
433 m_baType.m_bitmapLen.back () = 8;
434 }
435 index++;
436 }
437 }
438 break;
440 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
441 break;
442 default:
443 NS_FATAL_ERROR ("Invalid BA type");
444 break;
445 }
446 return i.GetDistanceFrom (start);
447}
448
449void
451{
452 m_baAckPolicy = immediateAck;
453}
454
455void
457{
458 m_baType = type;
459 m_baInfo.clear ();
460
461 for (auto& bitmapLen : m_baType.m_bitmapLen)
462 {
463 m_baInfo.push_back ({.m_aidTidInfo = 0,
464 .m_startingSeq = 0,
465 .m_bitmap = std::vector<uint8_t> (bitmapLen, 0),
466 .m_ra = Mac48Address ()});
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
510CtrlBAckResponseHeader::GetTidInfo (std::size_t index) const
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
597CtrlBAckResponseHeader::GetAckType (std::size_t index) const
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.size () > 0,
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
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
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 {
897 uint16_t i = IndexInBitmap (seq, index);
898 m_baInfo[index].m_bitmap[i / 8] |= (uint8_t (0x01) << (i % 8));
899 break;
900 }
902 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
903 break;
904 default:
905 NS_FATAL_ERROR ("Invalid BA type");
906 break;
907 }
908}
909
910void
912{
913 NS_ASSERT (frag < 16);
914 if (!IsInBitmap (seq))
915 {
916 return;
917 }
918 switch (m_baType.m_variant)
919 {
921 m_baInfo[0].m_bitmap[IndexInBitmap (seq) * 2 + frag / 8] |= (0x01 << (frag % 8));
922 break;
926 /* We can ignore this...compressed block ack doesn't support
927 acknowledgment of single fragments */
928 break;
930 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
931 break;
932 default:
933 NS_FATAL_ERROR ("Invalid BA type");
934 break;
935 }
936}
937
938bool
939CtrlBAckResponseHeader::IsPacketReceived (uint16_t seq, std::size_t index) const
940{
942 "index can only be non null for Multi-STA Block Ack");
943 NS_ASSERT (index < m_baInfo.size ());
944
946 && GetAckType (index) && GetTidInfo (index) == 14)
947 {
948 // All-ack context
949 return true;
950 }
951 if (!IsInBitmap (seq, index))
952 {
953 return false;
954 }
955 switch (m_baType.m_variant)
956 {
958 /*It's impossible to say if an entire packet was correctly received. */
959 return false;
963 {
964 uint16_t i = IndexInBitmap (seq, index);
965 uint8_t mask = uint8_t (0x01) << (i % 8);
966 return (m_baInfo[index].m_bitmap[i / 8] & mask) != 0;
967 }
969 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
970 break;
971 default:
972 NS_FATAL_ERROR ("Invalid BA type");
973 break;
974 }
975 return false;
976}
977
978bool
979CtrlBAckResponseHeader::IsFragmentReceived (uint16_t seq, uint8_t frag) const
980{
981 NS_ASSERT (frag < 16);
982 if (!IsInBitmap (seq))
983 {
984 return false;
985 }
986 switch (m_baType.m_variant)
987 {
989 return (m_baInfo[0].m_bitmap[IndexInBitmap (seq) * 2 + frag / 8] & (0x01 << (frag % 8))) != 0;
993 /* We can ignore this...compressed block ack doesn't support
994 acknowledgement of single fragments */
995 return false;
997 {
998 NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
999 break;
1000 }
1001 default:
1002 {
1003 NS_FATAL_ERROR ("Invalid BA type");
1004 break;
1005 }
1006 }
1007 return false;
1008}
1009
1010uint16_t
1011CtrlBAckResponseHeader::IndexInBitmap (uint16_t seq, std::size_t index) const
1012{
1013 uint16_t i;
1014 if (seq >= m_baInfo[index].m_startingSeq)
1015 {
1016 i = seq - m_baInfo[index].m_startingSeq;
1017 }
1018 else
1019 {
1020 i = SEQNO_SPACE_SIZE - m_baInfo[index].m_startingSeq + seq;
1021 }
1022
1023 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1024
1026 {
1027 nAckedMpdus = nAckedMpdus / 16;
1028 }
1029
1030 NS_ASSERT (i < nAckedMpdus);
1031 return i;
1032}
1033
1034bool
1035CtrlBAckResponseHeader::IsInBitmap (uint16_t seq, std::size_t index) const
1036{
1038 "index can only be non null for Multi-STA Block Ack");
1039 NS_ASSERT (index < m_baType.m_bitmapLen.size ());
1040
1041 uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1042
1044 {
1045 nAckedMpdus = nAckedMpdus / 16;
1046 }
1047
1048 return (seq - m_baInfo[index].m_startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE < nAckedMpdus;
1049}
1050
1051const std::vector<uint8_t>&
1052CtrlBAckResponseHeader::GetBitmap (std::size_t index) const
1053{
1055 "index can only be non null for Multi-STA Block Ack");
1056 NS_ASSERT (index < m_baInfo.size ());
1057
1058 return m_baInfo[index].m_bitmap;
1059}
1060
1061void
1063{
1065 "index can only be non null for Multi-STA Block Ack");
1066 NS_ASSERT (index < m_baInfo.size ());
1067
1068 m_baInfo[index].m_bitmap.assign (m_baType.m_bitmapLen[index], 0);
1069}
1070
1071
1072/***********************************
1073 * Trigger frame - User Info field
1074 ***********************************/
1075
1077 : m_aid12 (0),
1078 m_ruAllocation (0),
1079 m_ulFecCodingType (false),
1080 m_ulMcs (0),
1081 m_ulDcm (false),
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_aid12 = userInfo.m_aid12;
1105 m_ruAllocation = userInfo.m_ruAllocation;
1107 m_ulMcs = userInfo.m_ulMcs;
1108 m_ulDcm = userInfo.m_ulDcm;
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 AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation << ", MCS=" << +m_ulMcs;
1120}
1121
1124{
1125 uint32_t size = 0;
1126 size += 5; // User Info (excluding Trigger Dependent User Info)
1127
1128 switch (m_triggerType)
1129 {
1130 case BASIC_TRIGGER:
1131 case BFRP_TRIGGER:
1132 size += 1;
1133 break;
1134 case MU_BAR_TRIGGER:
1135 size += m_muBarTriggerDependentUserInfo.GetSerializedSize (); // BAR Control and BAR Information
1136 break;
1137 // The Trigger Dependent User Info subfield is not present in the other variants
1138 }
1139
1140 return size;
1141}
1142
1145{
1146 NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1147 NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1148 NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1149
1151
1152 uint32_t userInfo = 0; // User Info except the MSB
1153 userInfo |= (m_aid12 & 0x0fff);
1154 userInfo |= (m_ruAllocation << 12);
1155 userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1156 userInfo |= (m_ulMcs & 0x0f) << 21;
1157 userInfo |= (m_ulDcm ? 1 << 25 : 0);
1158
1159 if (m_aid12 != 0 && m_aid12 != 2045)
1160 {
1161 userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1162 userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1163 }
1164 else
1165 {
1166 userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1167 userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1168 }
1169
1170 i.WriteHtolsbU32 (userInfo);
1171 // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and the
1172 // Reserved bit. Given how m_ulTargetRssi is set, writing m_ulTargetRssi
1173 // leads to setting the Reserved bit to zero
1175
1177 {
1179 }
1180 else if (m_triggerType == MU_BAR_TRIGGER)
1181 {
1184 }
1185
1186 return i;
1187}
1188
1191{
1192 NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1193 NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1194 NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1195
1197
1198 uint32_t userInfo = i.ReadLsbtohU32 ();
1199
1200 m_aid12 = userInfo & 0x0fff;
1201 NS_ABORT_MSG_IF (m_aid12 == 4095, "Cannot deserialize a Padding field");
1202 m_ruAllocation = (userInfo >> 12) & 0xff;
1203 m_ulFecCodingType = (userInfo >> 20) & 0x01;
1204 m_ulMcs = (userInfo >> 21) & 0x0f;
1205 m_ulDcm = (userInfo >> 25) & 0x01;
1206
1207 if (m_aid12 != 0 && m_aid12 != 2045)
1208 {
1209 m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1210 m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1211 }
1212 else
1213 {
1214 m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1215 m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1216 }
1217
1218 m_ulTargetRssi = i.ReadU8 () & 0x7f; // B39 is reserved
1219
1221 {
1223 }
1224 else if (m_triggerType == MU_BAR_TRIGGER)
1225 {
1227 i.Next (len);
1228 }
1229
1230 return i;
1231}
1232
1235{
1236 return static_cast<TriggerFrameType> (m_triggerType);
1237}
1238
1239void
1241{
1242 m_aid12 = aid & 0x0fff;
1243}
1244
1245uint16_t
1247{
1248 return m_aid12;
1249}
1250
1251bool
1253{
1254 return (m_aid12 == 0);
1255}
1256
1257bool
1259{
1260 return (m_aid12 == 2045);
1261}
1262
1263void
1265{
1266 NS_ABORT_MSG_IF (ru.GetIndex () == 0, "Valid indices start at 1");
1267
1268 switch (ru.GetRuType ())
1269 {
1270 case HeRu::RU_26_TONE:
1271 m_ruAllocation = ru.GetIndex () - 1;
1272 break;
1273 case HeRu::RU_52_TONE:
1274 m_ruAllocation = ru.GetIndex () + 36;
1275 break;
1276 case HeRu::RU_106_TONE:
1277 m_ruAllocation = ru.GetIndex () + 52;
1278 break;
1279 case HeRu::RU_242_TONE:
1280 m_ruAllocation = ru.GetIndex () + 60;
1281 break;
1282 case HeRu::RU_484_TONE:
1283 m_ruAllocation = ru.GetIndex () + 64;
1284 break;
1285 case HeRu::RU_996_TONE:
1286 m_ruAllocation = 67;
1287 break;
1289 m_ruAllocation = 68;
1290 break;
1291 default:
1292 NS_FATAL_ERROR ("RU type unknown.");
1293 break;
1294 }
1295
1296 NS_ABORT_MSG_IF (m_ruAllocation > 68, "Reserved value.");
1297
1298 m_ruAllocation <<= 1;
1299 if (!ru.GetPrimary80MHz ())
1300 {
1302 }
1303}
1304
1307{
1308 HeRu::RuType ruType;
1309 std::size_t index;
1310
1311 bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1312
1313 uint8_t val = m_ruAllocation >> 1;
1314
1315 if (val < 37)
1316 {
1317 ruType = HeRu::RU_26_TONE;
1318 index = val + 1;
1319 }
1320 else if (val < 53)
1321 {
1322 ruType = HeRu::RU_52_TONE;
1323 index = val - 36;
1324 }
1325 else if (val < 61)
1326 {
1327 ruType = HeRu::RU_106_TONE;
1328 index = val - 52;
1329 }
1330 else if (val < 65)
1331 {
1332 ruType = HeRu::RU_242_TONE;
1333 index = val - 60;
1334 }
1335 else if (val < 67)
1336 {
1337 ruType = HeRu::RU_484_TONE;
1338 index = val - 64;
1339 }
1340 else if (val == 67)
1341 {
1342 ruType = HeRu::RU_996_TONE;
1343 index = 1;
1344 }
1345 else if (val == 68)
1346 {
1347 ruType = HeRu::RU_2x996_TONE;
1348 index = 1;
1349 }
1350 else
1351 {
1352 NS_FATAL_ERROR ("Reserved value.");
1353 }
1354
1355 return HeRu::RuSpec (ruType, index, primary80MHz);
1356}
1357
1358void
1360{
1361 m_ulFecCodingType = ldpc;
1362}
1363
1364bool
1366{
1367 return m_ulFecCodingType;
1368}
1369
1370void
1372{
1373 NS_ABORT_MSG_IF (mcs > 11, "Invalid MCS index");
1374 m_ulMcs = mcs;
1375}
1376
1377uint8_t
1379{
1380 return m_ulMcs;
1381}
1382
1383void
1385{
1386 m_ulDcm = dcm;
1387}
1388
1389bool
1391{
1392 return m_ulDcm;
1393}
1394
1395void
1396CtrlTriggerUserInfoField::SetSsAllocation (uint8_t startingSs, uint8_t nSs)
1397{
1398 NS_ABORT_MSG_IF (m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1399 NS_ABORT_MSG_IF (!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1400 NS_ABORT_MSG_IF (!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1401
1402 m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1403 m_bits26To31.ssAllocation.nSs = nSs - 1;
1404}
1405
1406uint8_t
1408{
1409 if (m_aid12 == 0 || m_aid12 == 2045)
1410 {
1411 return 1;
1412 }
1413 return m_bits26To31.ssAllocation.startingSs + 1;
1414}
1415
1416uint8_t
1418{
1419 if (m_aid12 == 0 || m_aid12 == 2045)
1420 {
1421 return 1;
1422 }
1423 return m_bits26To31.ssAllocation.nSs + 1;
1424}
1425
1426void
1428{
1429 NS_ABORT_MSG_IF (m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1430 NS_ABORT_MSG_IF (!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1431
1432 m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1433 m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1434}
1435
1436uint8_t
1438{
1439 NS_ABORT_MSG_IF (m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1440
1441 return m_bits26To31.raRuInformation.nRaRu + 1;
1442}
1443
1444bool
1446{
1447 NS_ABORT_MSG_IF (m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1448
1449 return m_bits26To31.raRuInformation.moreRaRu;
1450}
1451
1452void
1454{
1455 m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1456}
1457
1458void
1460{
1461 NS_ABORT_MSG_IF (dBm < -110 || dBm > -20, "Invalid values for signal power");
1462
1463 m_ulTargetRssi = static_cast<uint8_t> (110 + dBm);
1464}
1465
1466bool
1468{
1469 return (m_ulTargetRssi == 127);
1470}
1471
1472int8_t
1474{
1475 NS_ABORT_MSG_IF (m_ulTargetRssi == 127, "STA must use its max TX power");
1476
1477 return static_cast<int8_t> (m_ulTargetRssi) - 110;
1478}
1479
1480void
1481CtrlTriggerUserInfoField::SetBasicTriggerDepUserInfo (uint8_t spacingFactor, uint8_t tidLimit, AcIndex prefAc)
1482{
1483 NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1484
1485 m_basicTriggerDependentUserInfo = (spacingFactor & 0x03)
1486 | (tidLimit & 0x07) << 2
1487 // B5 is reserved
1488 | (prefAc & 0x03) << 6;
1489}
1490
1491uint8_t
1493{
1494 NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1495
1496 return m_basicTriggerDependentUserInfo & 0x03;
1497}
1498
1499uint8_t
1501{
1502 NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1503
1504 return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1505}
1506
1507AcIndex
1509{
1510 NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1511
1512 return AcIndex ((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1513}
1514
1515void
1517{
1518 NS_ABORT_MSG_IF (m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1521 "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1523}
1524
1527{
1528 NS_ABORT_MSG_IF (m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1529
1531}
1532
1533/***********************************
1534 * Trigger frame
1535 ***********************************/
1536
1538
1540 : m_triggerType (0),
1541 m_ulLength (0),
1542 m_moreTF (false),
1543 m_csRequired (false),
1544 m_ulBandwidth (0),
1545 m_giAndLtfType (0),
1546 m_apTxPower (0),
1547 m_ulSpatialReuse (0)
1548{
1549}
1550
1553{
1554 m_triggerType = type;
1555 SetUlBandwidth (txVector.GetChannelWidth ());
1556 SetUlLength (txVector.GetLength ());
1557 uint16_t gi = txVector.GetGuardInterval ();
1558 if (gi == 800 || gi == 1600)
1559 {
1560 m_giAndLtfType = 1;
1561 }
1562 else
1563 {
1564 m_giAndLtfType = 2;
1565 }
1566 for (auto& userInfo : txVector.GetHeMuUserInfoMap ())
1567 {
1569 ui.SetAid12 (userInfo.first);
1570 ui.SetRuAllocation (userInfo.second.ru);
1571 ui.SetUlMcs (userInfo.second.mcs.GetMcsValue ());
1572 ui.SetSsAllocation (1, userInfo.second.nss); // MU-MIMO is not supported
1573 }
1574}
1575
1577{
1578}
1579
1582{
1583 // check for self-assignment
1584 if (&trigger == this)
1585 {
1586 return *this;
1587 }
1588
1589 m_triggerType = trigger.m_triggerType;
1590 m_ulLength = trigger.m_ulLength;
1591 m_moreTF = trigger.m_moreTF;
1592 m_csRequired = trigger.m_csRequired;
1593 m_ulBandwidth = trigger.m_ulBandwidth;
1595 m_apTxPower = trigger.m_apTxPower;
1597 m_userInfoFields.clear ();
1599 return *this;
1600}
1601
1602TypeId
1604{
1605 static TypeId tid = TypeId ("ns3::CtrlTriggerHeader")
1606 .SetParent<Header> ()
1607 .SetGroupName ("Wifi")
1608 .AddConstructor<CtrlTriggerHeader> ()
1609 ;
1610 return tid;
1611}
1612
1613TypeId
1615{
1616 return GetTypeId ();
1617}
1618
1619void
1620CtrlTriggerHeader::Print (std::ostream &os) const
1621{
1622 os << "TriggerType=" << GetTypeString () << ", Bandwidth=" << +GetUlBandwidth ()
1623 << ", UL Length=" << m_ulLength;
1624
1625 for (auto& ui : m_userInfoFields)
1626 {
1627 ui.Print (os);
1628 }
1629}
1630
1633{
1634 uint32_t size = 0;
1635 size += 8; // Common Info (excluding Trigger Dependent Common Info)
1636
1637 // Add the size of the Trigger Dependent Common Info subfield
1639 {
1640 size += 4;
1641 }
1642
1643 for (auto& ui : m_userInfoFields)
1644 {
1645 size += ui.GetSerializedSize ();
1646 }
1647
1648 size += 2; // Padding field
1649
1650 return size;
1651}
1652
1653void
1655{
1656 NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1657 NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1658 NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1659
1661
1662 uint64_t commonInfo = 0;
1663 commonInfo |= (m_triggerType & 0x0f);
1664 commonInfo |= (m_ulLength & 0x0fff) << 4;
1665 commonInfo |= (m_moreTF ? 1 << 16 : 0);
1666 commonInfo |= (m_csRequired ? 1 << 17 : 0);
1667 commonInfo |= (m_ulBandwidth & 0x03) << 18;
1668 commonInfo |= (m_giAndLtfType & 0x03) << 20;
1669 commonInfo |= static_cast<uint64_t> (m_apTxPower & 0x3f) << 28;
1670 commonInfo |= static_cast<uint64_t> (m_ulSpatialReuse) << 37;
1671
1672 i.WriteHtolsbU64 (commonInfo);
1673
1674 for (auto& ui : m_userInfoFields)
1675 {
1676 i = ui.Serialize (i);
1677 }
1678
1679 i.WriteHtolsbU16 (0xffff); // Padding field, used as delimiter
1680}
1681
1684{
1686
1687 uint64_t commonInfo = i.ReadLsbtohU64 ();
1688
1689 m_triggerType = (commonInfo & 0x0f);
1690 m_ulLength = (commonInfo >> 4) & 0x0fff;
1691 m_moreTF = (commonInfo >> 16) & 0x01;
1692 m_csRequired = (commonInfo >> 17) & 0x01;
1693 m_ulBandwidth = (commonInfo >> 18) & 0x03;
1694 m_giAndLtfType = (commonInfo >> 20) & 0x03;
1695 m_apTxPower = (commonInfo >> 28) & 0x3f;
1696 m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1697 m_userInfoFields.clear ();
1698
1699 NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1700 NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1701 NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1702
1703 bool isPadding = false;
1704
1705 // We always add a Padding field (of two octets of all 1s) as delimiter
1706 while (!isPadding)
1707 {
1708 // read the first 2 bytes to check if we encountered the Padding field
1709 if (i.ReadU16 () == 0xffff)
1710 {
1711 isPadding = true;
1712 }
1713 else
1714 {
1715 // go back 2 bytes to deserialize the User Info field from the beginning
1716 i.Prev (2);
1718 i = ui.Deserialize (i);
1719 }
1720 }
1721
1722 return i.GetDistanceFrom (start);
1723}
1724
1725void
1727{
1728 m_triggerType = type;
1729}
1730
1733{
1734 return static_cast<TriggerFrameType> (m_triggerType);
1735}
1736
1737const char *
1739{
1740 return GetTypeString (GetType ());
1741}
1742
1743const char *
1745{
1746#define FOO(x) \
1747case x: \
1748 return # x; \
1749 break;
1750
1751 switch (type)
1752 {
1754 FOO (BFRP_TRIGGER);
1757 FOO (BSRP_TRIGGER);
1759 FOO (BQRP_TRIGGER);
1760 FOO (NFRP_TRIGGER);
1761 default:
1762 return "ERROR";
1763 }
1764#undef FOO
1765}
1766
1767bool
1769{
1770 return (m_triggerType == BASIC_TRIGGER);
1771}
1772
1773bool
1775{
1776 return (m_triggerType == BFRP_TRIGGER);
1777}
1778
1779bool
1781{
1782 return (m_triggerType == MU_BAR_TRIGGER);
1783}
1784
1785bool
1787{
1788 return (m_triggerType == MU_RTS_TRIGGER);
1789}
1790
1791bool
1793{
1794 return (m_triggerType == BSRP_TRIGGER);
1795}
1796
1797bool
1799{
1801}
1802
1803bool
1805{
1806 return (m_triggerType == BQRP_TRIGGER);
1807}
1808
1809bool
1811{
1812 return (m_triggerType == NFRP_TRIGGER);
1813}
1814
1815void
1817{
1818 m_ulLength = (len & 0x0fff);
1819}
1820
1821uint16_t
1823{
1824 return m_ulLength;
1825}
1826
1829{
1830 auto userInfoIt = FindUserInfoWithAid (staId);
1831 NS_ASSERT (userInfoIt != end ());
1832
1833 WifiTxVector v;
1837 v.SetLength (GetUlLength ());
1838 v.SetHeMuUserInfo (staId, {userInfoIt->GetRuAllocation (),
1839 HePhy::GetHeMcs (userInfoIt->GetUlMcs ()),
1840 userInfoIt->GetNss ()});
1841 return v;
1842}
1843
1844void
1846{
1847 m_moreTF = more;
1848}
1849
1850bool
1852{
1853 return m_moreTF;
1854}
1855
1856void
1858{
1859 m_csRequired = cs;
1860}
1861
1862bool
1864{
1865 return m_csRequired;
1866}
1867
1868void
1870{
1871 switch (bw)
1872 {
1873 case 20:
1874 m_ulBandwidth = 0;
1875 break;
1876 case 40:
1877 m_ulBandwidth = 1;
1878 break;
1879 case 80:
1880 m_ulBandwidth = 2;
1881 break;
1882 case 160:
1883 m_ulBandwidth = 3;
1884 break;
1885 default:
1886 NS_FATAL_ERROR ("Bandwidth value not allowed.");
1887 break;
1888 }
1889}
1890
1891uint16_t
1893{
1894 return (1 << m_ulBandwidth) * 20;
1895}
1896
1897void
1898CtrlTriggerHeader::SetGiAndLtfType (uint16_t guardInterval, uint8_t ltfType)
1899{
1900 if (ltfType == 1 && guardInterval == 1600)
1901 {
1902 m_giAndLtfType = 0;
1903 }
1904 else if (ltfType == 2 && guardInterval == 1600)
1905 {
1906 m_giAndLtfType = 1;
1907 }
1908 else if (ltfType == 4 && guardInterval == 3200)
1909 {
1910 m_giAndLtfType = 2;
1911 }
1912 else
1913 {
1914 NS_FATAL_ERROR ("Invalid combination of GI and LTF type");
1915 }
1916}
1917
1918uint16_t
1920{
1921 if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
1922 {
1923 return 1600;
1924 }
1925 else if (m_giAndLtfType == 2)
1926 {
1927 return 3200;
1928 }
1929 else
1930 {
1931 NS_FATAL_ERROR ("Invalid value for GI And LTF Type subfield");
1932 }
1933}
1934
1935uint8_t
1937{
1938 if (m_giAndLtfType == 0)
1939 {
1940 return 1;
1941 }
1942 else if (m_giAndLtfType == 1)
1943 {
1944 return 2;
1945 }
1946 else if (m_giAndLtfType == 2)
1947 {
1948 return 4;
1949 }
1950 else
1951 {
1952 NS_FATAL_ERROR ("Invalid value for GI And LTF Type subfield");
1953 }
1954}
1955
1956void
1958{
1959 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
1960 NS_ABORT_MSG_IF (power < -20 || power > 40, "Out of range power values");
1961
1962 m_apTxPower = static_cast<uint8_t> (power + 20);
1963}
1964
1965int8_t
1967{
1968 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
1969 return static_cast<int8_t> (m_apTxPower) - 20;
1970}
1971
1972void
1974{
1975 m_ulSpatialReuse = sr;
1976}
1977
1978uint16_t
1980{
1981 return m_ulSpatialReuse;
1982}
1983
1986{
1987 // make a copy of this Trigger Frame and remove the User Info fields from the copy
1988 CtrlTriggerHeader trigger (*this);
1989 trigger.m_userInfoFields.clear ();
1990 return trigger;
1991}
1992
1995{
1996 m_userInfoFields.emplace_back (m_triggerType);
1997 return m_userInfoFields.back ();
1998}
1999
2002{
2003 NS_ABORT_MSG_IF (userInfo.GetType () != m_triggerType,
2004 "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2005 m_userInfoFields.push_back (userInfo);
2006 return m_userInfoFields.back ();
2007}
2008
2011{
2012 return m_userInfoFields.begin ();
2013}
2014
2017{
2018 return m_userInfoFields.end ();
2019}
2020
2023{
2024 return m_userInfoFields.begin ();
2025}
2026
2029{
2030 return m_userInfoFields.end ();
2031}
2032
2033std::size_t
2035{
2036 return m_userInfoFields.size ();
2037}
2038
2041{
2042 // the lambda function returns true if a User Info field has the AID12 subfield
2043 // equal to the given aid12 value
2044 return std::find_if (start, end (), [aid12] (const CtrlTriggerUserInfoField& ui) -> bool
2045 { return (ui.GetAid12 () == aid12); });
2046}
2047
2050{
2051 return FindUserInfoWithAid (m_userInfoFields.begin (), aid12);
2052}
2053
2056{
2057 return FindUserInfoWithAid (start, 0);
2058}
2059
2062{
2063 return FindUserInfoWithAid (0);
2064}
2065
2068{
2069 return FindUserInfoWithAid (start, 2045);
2070}
2071
2074{
2075 return FindUserInfoWithAid (2045);
2076}
2077
2078bool
2080{
2081 // check that allocated RUs do not overlap
2082 // TODO This is not a problem in case of UL MU-MIMO
2083 std::vector<HeRu::RuSpec> prevRus;
2084
2085 for (auto& ui : m_userInfoFields)
2086 {
2087 if (HeRu::DoesOverlap (GetUlBandwidth (), ui.GetRuAllocation (), prevRus))
2088 {
2089 return false;
2090 }
2091 prevRus.push_back (ui.GetRuAllocation ());
2092 }
2093 return true;
2094}
2095
2096} //namespace ns3
iterator in a Buffer instance
Definition: buffer.h:99
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:911
uint32_t ReadLsbtohU32(void)
Definition: buffer.cc:1077
void WriteU8(uint8_t data)
Definition: buffer.h:869
uint32_t GetRemainingSize(void) const
Definition: buffer.cc:1166
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:918
void Next(void)
go forward by one byte
Definition: buffer.h:845
uint16_t ReadU16(void)
Definition: buffer.h:1029
uint8_t ReadU8(void)
Definition: buffer.h:1021
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:927
uint16_t ReadLsbtohU16(void)
Definition: buffer.cc:1066
void Prev(void)
go backward by one byte
Definition: buffer.h:851
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1094
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:788
Headers for BlockAckRequest.
Definition: ctrl-headers.h:49
BlockAckReqType GetType(void) const
Return the BlockAckRequest type.
bool IsMultiTid(void) const
Check if the current Ack Policy has Multi-TID Block Ack.
void Serialize(Buffer::Iterator start) const override
Definition: ctrl-headers.cc:93
uint16_t m_startingSeq
starting seq
Definition: ctrl-headers.h:185
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:182
uint16_t m_tidInfo
TID info.
Definition: ctrl-headers.h:184
TypeId GetInstanceTypeId(void) const override
Get the most derived TypeId for this Object.
Definition: ctrl-headers.cc:59
bool MustSendHtImmediateAck(void) const
Check if the current Ack Policy is immediate.
void Print(std::ostream &os) const override
Definition: ctrl-headers.cc:65
bool IsCompressed(void) const
Check if the current Ack Policy is Compressed Block Ack and not multi-TID.
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
static TypeId GetTypeId(void)
Get the type ID.
Definition: ctrl-headers.cc:48
BlockAckReqType m_barType
BAR type.
Definition: ctrl-headers.h:183
void SetStartingSequenceControl(uint16_t seqControl)
Set the starting sequence control with the given sequence control value.
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
uint32_t Deserialize(Buffer::Iterator start) override
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 GetStartingSequenceControl(void) const
Return the starting sequence control.
uint32_t GetSerializedSize(void) const override
Definition: ctrl-headers.cc:71
void SetBarControl(uint16_t bar)
Set the Block Ack control.
bool IsBasic(void) const
Check if the current Ack Policy is Basic Block Ack (i.e.
bool IsExtendedCompressed(void) const
Check if the current Ack Policy is Extended Compressed Block Ack.
uint16_t GetBarControl(void) const
Return the Block Ack control.
Headers for BlockAck response.
Definition: ctrl-headers.h:202
void SetBaControl(uint16_t ba)
Set the Block Ack control.
uint32_t GetSerializedSize(void) const
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 ...
uint16_t GetBaControl(void) const
Return the Block Ack control.
uint16_t GetStartingSequenceControl(std::size_t index=0) const
Return the value of the Starting Sequence Control subfield.
bool IsCompressed(void) const
Check if the current BA policy is Compressed Block Ack.
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
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...
static TypeId GetTypeId(void)
Get the type ID.
Buffer::Iterator SerializeBitmap(Buffer::Iterator start, std::size_t index=0) const
Serialize bitmap to the given buffer.
bool IsBasic(void) const
Check if the current BA policy is Basic 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...
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
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...
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...
TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
std::size_t GetNPerAidTidInfoSubfields(void) const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack.
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 SetType(BlockAckType type)
Set the block ack type.
BlockAckType GetType(void) const
Return the block ack type ID.
uint32_t Deserialize(Buffer::Iterator start)
bool MustSendHtImmediateAck(void) const
Check if the current Ack Policy is immediate.
void SetReceivedFragment(uint16_t seq, uint8_t frag)
Set the bitmap that the packet with the given sequence number and fragment number was received.
bool IsExtendedCompressed(void) const
Check if the current BA policy is Extended Compressed Block Ack.
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(void) 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
bool IsMultiSta(void) const
Check if the BlockAck frame variant is Multi-STA Block Ack.
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 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...
void Print(std::ostream &os) const
Headers for Trigger frames.
Definition: ctrl-headers.h:886
int8_t GetApTxPower(void) const
Get the power value (dBm) indicated by the AP TX Power subfield of the Common Info field.
ConstIterator begin(void) const
Get a const iterator pointing to the first User Info field in the list.
CtrlTriggerUserInfoField & AddUserInfoField(void)
Append a new User Info field to this Trigger frame and return a non-const reference to it.
uint32_t GetSerializedSize(void) const
bool IsBsrp(void) const
Check if this is a Buffer Status Report Poll Trigger frame.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
CtrlTriggerHeader GetCommonInfoField(void) const
Get a copy of the Common Info field of this Trigger frame.
bool GetMoreTF(void) const
Get the More TF subfield of the Common Info field.
bool IsBqrp(void) const
Check if this is a Bandwidth Query Report Poll Trigger frame.
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...
static TypeId GetTypeId(void)
Get the type ID.
void Serialize(Buffer::Iterator start) const
bool IsMuRts(void) const
Check if this is a MU-RTS Trigger frame.
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
bool IsValid(void) const
Check the validity of this Trigger frame.
uint16_t GetUlBandwidth(void) const
Get the bandwidth of the solicited HE TB PPDU.
std::size_t GetNUserInfoFields(void) const
Get the number of User Info fields in this Trigger Frame.
std::list< CtrlTriggerUserInfoField >::const_iterator ConstIterator
User Info fields list const iterator.
uint8_t m_triggerType
Common Info field.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
void Print(std::ostream &os) const
uint16_t GetUlSpatialReuse(void) const
Get the UL Spatial Reuse subfield of the Common Info field.
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...
const char * GetTypeString(void) const
Return a string corresponding to the Trigger Frame type.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
ConstIterator end(void) const
Get a const iterator indicating past-the-last User Info field in the list.
uint16_t m_ulLength
Value for the L-SIG Length field.
TriggerFrameType GetType(void) const
Get the Trigger Frame type.
bool m_csRequired
Carrier Sense required.
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
bool GetCsRequired(void) const
Get the CS Required subfield of the Common Info field.
bool IsMuBar(void) const
Check if this is a MU-BAR Trigger frame.
bool IsNfrp(void) const
Check if this is a NDP Feedback Report Poll Trigger frame.
uint8_t GetLtfType(void) const
Get the LTF type of the solicited HE TB PPDU.
uint32_t Deserialize(Buffer::Iterator start)
std::list< CtrlTriggerUserInfoField > m_userInfoFields
List of User Info fields.
bool m_moreTF
True if a subsequent Trigger frame follows.
uint16_t GetUlLength(void) const
Get the UL Length subfield of the Common Info field.
bool IsBasic(void) const
Check if this is a Basic Trigger frame.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
uint8_t m_ulBandwidth
UL BW subfield.
bool IsBfrp(void) const
Check if this is a Beamforming Report Poll Trigger frame.
std::list< CtrlTriggerUserInfoField >::iterator Iterator
User Info fields list iterator.
ConstIterator FindUserInfoWithRaRuAssociated(void) const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
ConstIterator FindUserInfoWithRaRuUnassociated(void) const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
uint16_t GetGuardInterval(void) const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
bool IsGcrMuBar(void) const
Check if this is a Groupcast with Retries (GCR) MU-BAR Trigger frame.
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:582
bool HasRaRuForAssociatedSta(void) const
Check if this User Info field allocates a Random Access RU for stations associated with the AP that t...
uint8_t GetStartingSs(void) const
Get the starting spatial stream.
uint8_t startingSs
Starting spatial stream.
Definition: ctrl-headers.h:846
HeRu::RuSpec GetRuAllocation(void) const
Get the RU specified by the RU Allocation subfield.
const CtrlBAckRequestHeader & GetMuBarTriggerDepUserInfo(void) const
Get the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
uint8_t m_triggerType
Trigger frame type.
Definition: ctrl-headers.h:856
int8_t GetUlTargetRssi(void) const
Get the expected receive signal power for the solicited HE TB PPDU.
void Print(std::ostream &os) const
Print the content of this User Info field.
bool IsUlTargetRssiMaxTxPower(void) const
Return true if the UL Target RSSI subfield indicates to the station to transmit an HE TB PPDU respons...
uint8_t nRaRu
Number of Random Access RUs.
Definition: ctrl-headers.h:851
uint16_t GetAid12(void) const
Get the value of the AID12 subfield.
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.
AcIndex GetPreferredAc(void) const
Get the Preferred AC subfield.
CtrlTriggerUserInfoField(uint8_t triggerType)
Constructor.
uint8_t GetTidAggregationLimit(void) const
Get the TID Aggregation Limit.
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
bool HasRaRuForUnassociatedSta(void) const
Check if this User Info field allocates a Random Access RU for stations not associated with the AP th...
bool GetUlDcm(void) const
Get the UL DCM subfield, which indicates whether or not DCM is used.
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:837
uint8_t nSs
Number of spatial streams.
Definition: ctrl-headers.h:847
uint8_t m_basicTriggerDependentUserInfo
Basic Trigger variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:857
uint8_t m_ulMcs
MCS to be used by the addressed station.
Definition: ctrl-headers.h:840
uint8_t m_ruAllocation
RU Allocation.
Definition: ctrl-headers.h:838
bool GetUlFecCodingType(void) const
Get the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
uint8_t GetNRaRus(void) const
Get the number of contiguous RUs for Random Access.
Buffer::Iterator Serialize(Buffer::Iterator start) const
Serialize the User Info field to the given buffer.
uint32_t GetSerializedSize(void) const
Get the expected size of this User Info field.
bool m_ulDcm
whether or not to use Dual Carrier Modulation
Definition: ctrl-headers.h:841
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
TriggerFrameType GetType(void) const
Get the type of the Trigger Frame this User Info field belongs to.
void SetUlTargetRssiMaxTxPower(void)
Set the UL Target RSSI subfield to indicate to the station to transmit an HE TB PPDU response at its ...
CtrlTriggerUserInfoField & operator=(const CtrlTriggerUserInfoField &userInfo)
Copy assignment operator.
uint8_t GetUlMcs(void) const
Get the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
uint8_t GetNss(void) const
Get the number of spatial streams.
uint8_t GetMpduMuSpacingFactor(void) const
Get the MPDU MU spacing factor.
uint8_t m_ulTargetRssi
Expected receive signal power.
Definition: ctrl-headers.h:855
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.
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:852
bool m_ulFecCodingType
UL FEC Coding Type.
Definition: ctrl-headers.h:839
bool GetMoreRaRu(void) const
Return true if more RA-RUs are allocated in subsequent Trigger frames that are sent before the end of...
CtrlBAckRequestHeader m_muBarTriggerDependentUserInfo
MU-BAR variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:858
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:962
RU Specification.
Definition: he-ru.h:68
RuType GetRuType(void) const
Get the RU type.
Definition: he-ru.cc:167
bool GetPrimary80MHz(void) const
Get the primary 80 MHz flag.
Definition: he-ru.cc:181
std::size_t GetIndex(void) const
Get the RU index.
Definition: he-ru.cc:174
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:352
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
@ RU_26_TONE
Definition: he-ru.h:43
@ RU_484_TONE
Definition: he-ru.h:47
@ RU_996_TONE
Definition: he-ru.h:48
@ RU_106_TONE
Definition: he-ru.h:45
@ RU_52_TONE
Definition: he-ru.h:44
@ RU_242_TONE
Definition: he-ru.h:46
@ RU_2x996_TONE
Definition: he-ru.h:49
Protocol header serialization and deserialization.
Definition: header.h:43
an EUI-48 address
Definition: mac48-address.h:44
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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.
uint16_t GetLength(void) const
Get the LENGTH field of the L-SIG.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
uint16_t GetChannelWidth(void) const
uint16_t GetGuardInterval(void) 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:67
#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:88
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#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:45
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:71
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:561
@ WIFI_PREAMBLE_HE_TB
@ NFRP_TRIGGER
Definition: ctrl-headers.h:569
@ BFRP_TRIGGER
Definition: ctrl-headers.h:563
@ MU_RTS_TRIGGER
Definition: ctrl-headers.h:565
@ GCR_MU_BAR_TRIGGER
Definition: ctrl-headers.h:567
@ MU_BAR_TRIGGER
Definition: ctrl-headers.h:564
@ BASIC_TRIGGER
Definition: ctrl-headers.h:562
@ BQRP_TRIGGER
Definition: ctrl-headers.h:568
@ BSRP_TRIGGER
Definition: ctrl-headers.h:566
Every class exported by the ns3 library is enclosed in the ns3 namespace.
const uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:131
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.
def start()
Definition: core.py:1853
The different BlockAckRequest variants.
enum Variant m_variant
Block Ack Request variant.
The different BlockAck variants.
enum 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