A Discrete-Event Network Simulator
API
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{
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{
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{
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.size() > 0)
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{
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
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.size() > 0,
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
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
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 : m_aid12(0),
1073 m_ruAllocation(0),
1074 m_ulFecCodingType(false),
1075 m_ulMcs(0),
1076 m_ulDcm(false),
1077 m_ulTargetRssi(0),
1078 m_triggerType(triggerType),
1079 m_basicTriggerDependentUserInfo(0)
1080{
1081 memset(&m_bits26To31, 0, sizeof(m_bits26To31));
1082}
1083
1085{
1086}
1087
1090{
1091 NS_ABORT_MSG_IF(m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1092
1093 // check for self-assignment
1094 if (&userInfo == this)
1095 {
1096 return *this;
1097 }
1098
1099 m_aid12 = userInfo.m_aid12;
1100 m_ruAllocation = userInfo.m_ruAllocation;
1102 m_ulMcs = userInfo.m_ulMcs;
1103 m_ulDcm = userInfo.m_ulDcm;
1104 m_bits26To31 = userInfo.m_bits26To31;
1105 m_ulTargetRssi = userInfo.m_ulTargetRssi;
1108 return *this;
1109}
1110
1111void
1112CtrlTriggerUserInfoField::Print(std::ostream& os) const
1113{
1114 os << ", USER_INFO AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation
1115 << ", MCS=" << +m_ulMcs;
1116}
1117
1120{
1121 uint32_t size = 0;
1122 size += 5; // User Info (excluding Trigger Dependent User Info)
1123
1124 switch (m_triggerType)
1125 {
1126 case BASIC_TRIGGER:
1127 case BFRP_TRIGGER:
1128 size += 1;
1129 break;
1130 case MU_BAR_TRIGGER:
1131 size +=
1132 m_muBarTriggerDependentUserInfo.GetSerializedSize(); // BAR Control and BAR Information
1133 break;
1134 // The Trigger Dependent User Info subfield is not present in the other variants
1135 }
1136
1137 return size;
1138}
1139
1142{
1143 NS_ABORT_MSG_IF(m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1145 "GCR-MU-BAR Trigger frame is not supported");
1146 NS_ABORT_MSG_IF(m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1147
1149
1150 uint32_t userInfo = 0; // User Info except the MSB
1151 userInfo |= (m_aid12 & 0x0fff);
1152 userInfo |= (m_ruAllocation << 12);
1153 userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1154 userInfo |= (m_ulMcs & 0x0f) << 21;
1155 userInfo |= (m_ulDcm ? 1 << 25 : 0);
1156
1157 if (m_aid12 != 0 && m_aid12 != 2045)
1158 {
1159 userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1160 userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1161 }
1162 else
1163 {
1164 userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1165 userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1166 }
1167
1168 i.WriteHtolsbU32(userInfo);
1169 // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and the
1170 // Reserved bit. Given how m_ulTargetRssi is set, writing m_ulTargetRssi
1171 // leads to setting the Reserved bit to zero
1173
1175 {
1177 }
1178 else if (m_triggerType == MU_BAR_TRIGGER)
1179 {
1182 }
1183
1184 return i;
1185}
1186
1189{
1190 NS_ABORT_MSG_IF(m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1192 "GCR-MU-BAR Trigger frame is not supported");
1193 NS_ABORT_MSG_IF(m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1194
1196
1197 uint32_t userInfo = i.ReadLsbtohU32();
1198
1199 m_aid12 = userInfo & 0x0fff;
1200 NS_ABORT_MSG_IF(m_aid12 == 4095, "Cannot deserialize a Padding field");
1201 m_ruAllocation = (userInfo >> 12) & 0xff;
1202 m_ulFecCodingType = (userInfo >> 20) & 0x01;
1203 m_ulMcs = (userInfo >> 21) & 0x0f;
1204 m_ulDcm = (userInfo >> 25) & 0x01;
1205
1206 if (m_aid12 != 0 && m_aid12 != 2045)
1207 {
1208 m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1209 m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1210 }
1211 else
1212 {
1213 m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1214 m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1215 }
1216
1217 m_ulTargetRssi = i.ReadU8() & 0x7f; // B39 is reserved
1218
1220 {
1222 }
1223 else if (m_triggerType == MU_BAR_TRIGGER)
1224 {
1226 i.Next(len);
1227 }
1228
1229 return i;
1230}
1231
1234{
1235 return static_cast<TriggerFrameType>(m_triggerType);
1236}
1237
1238void
1240{
1241 m_aid12 = aid & 0x0fff;
1242}
1243
1244uint16_t
1246{
1247 return m_aid12;
1248}
1249
1250bool
1252{
1253 return (m_aid12 == 0);
1254}
1255
1256bool
1258{
1259 return (m_aid12 == 2045);
1260}
1261
1262void
1264{
1265 NS_ABORT_MSG_IF(ru.GetIndex() == 0, "Valid indices start at 1");
1266
1267 switch (ru.GetRuType())
1268 {
1269 case HeRu::RU_26_TONE:
1270 m_ruAllocation = ru.GetIndex() - 1;
1271 break;
1272 case HeRu::RU_52_TONE:
1273 m_ruAllocation = ru.GetIndex() + 36;
1274 break;
1275 case HeRu::RU_106_TONE:
1276 m_ruAllocation = ru.GetIndex() + 52;
1277 break;
1278 case HeRu::RU_242_TONE:
1279 m_ruAllocation = ru.GetIndex() + 60;
1280 break;
1281 case HeRu::RU_484_TONE:
1282 m_ruAllocation = ru.GetIndex() + 64;
1283 break;
1284 case HeRu::RU_996_TONE:
1285 m_ruAllocation = 67;
1286 break;
1288 m_ruAllocation = 68;
1289 break;
1290 default:
1291 NS_FATAL_ERROR("RU type unknown.");
1292 break;
1293 }
1294
1295 NS_ABORT_MSG_IF(m_ruAllocation > 68, "Reserved value.");
1296
1297 m_ruAllocation <<= 1;
1298 if (!ru.GetPrimary80MHz())
1299 {
1301 }
1302}
1303
1306{
1307 HeRu::RuType ruType;
1308 std::size_t index;
1309
1310 bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1311
1312 uint8_t val = m_ruAllocation >> 1;
1313
1314 if (val < 37)
1315 {
1316 ruType = HeRu::RU_26_TONE;
1317 index = val + 1;
1318 }
1319 else if (val < 53)
1320 {
1321 ruType = HeRu::RU_52_TONE;
1322 index = val - 36;
1323 }
1324 else if (val < 61)
1325 {
1326 ruType = HeRu::RU_106_TONE;
1327 index = val - 52;
1328 }
1329 else if (val < 65)
1330 {
1331 ruType = HeRu::RU_242_TONE;
1332 index = val - 60;
1333 }
1334 else if (val < 67)
1335 {
1336 ruType = HeRu::RU_484_TONE;
1337 index = val - 64;
1338 }
1339 else if (val == 67)
1340 {
1341 ruType = HeRu::RU_996_TONE;
1342 index = 1;
1343 }
1344 else if (val == 68)
1345 {
1346 ruType = HeRu::RU_2x996_TONE;
1347 index = 1;
1348 }
1349 else
1350 {
1351 NS_FATAL_ERROR("Reserved value.");
1352 }
1353
1354 return HeRu::RuSpec(ruType, index, primary80MHz);
1355}
1356
1357void
1359{
1360 m_ulFecCodingType = ldpc;
1361}
1362
1363bool
1365{
1366 return m_ulFecCodingType;
1367}
1368
1369void
1371{
1372 NS_ABORT_MSG_IF(mcs > 11, "Invalid MCS index");
1373 m_ulMcs = mcs;
1374}
1375
1376uint8_t
1378{
1379 return m_ulMcs;
1380}
1381
1382void
1384{
1385 m_ulDcm = dcm;
1386}
1387
1388bool
1390{
1391 return m_ulDcm;
1392}
1393
1394void
1395CtrlTriggerUserInfoField::SetSsAllocation(uint8_t startingSs, uint8_t nSs)
1396{
1397 NS_ABORT_MSG_IF(m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1398 NS_ABORT_MSG_IF(!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1399 NS_ABORT_MSG_IF(!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1400
1401 m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1402 m_bits26To31.ssAllocation.nSs = nSs - 1;
1403}
1404
1405uint8_t
1407{
1408 if (m_aid12 == 0 || m_aid12 == 2045)
1409 {
1410 return 1;
1411 }
1412 return m_bits26To31.ssAllocation.startingSs + 1;
1413}
1414
1415uint8_t
1417{
1418 if (m_aid12 == 0 || m_aid12 == 2045)
1419 {
1420 return 1;
1421 }
1422 return m_bits26To31.ssAllocation.nSs + 1;
1423}
1424
1425void
1427{
1428 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1429 NS_ABORT_MSG_IF(!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1430
1431 m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1432 m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1433}
1434
1435uint8_t
1437{
1438 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1439
1440 return m_bits26To31.raRuInformation.nRaRu + 1;
1441}
1442
1443bool
1445{
1446 NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1447
1448 return m_bits26To31.raRuInformation.moreRaRu;
1449}
1450
1451void
1453{
1454 m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1455}
1456
1457void
1459{
1460 NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
1461
1462 m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
1463}
1464
1465bool
1467{
1468 return (m_ulTargetRssi == 127);
1469}
1470
1471int8_t
1473{
1474 NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
1475
1476 return static_cast<int8_t>(m_ulTargetRssi) - 110;
1477}
1478
1479void
1481 uint8_t tidLimit,
1482 AcIndex prefAc)
1483{
1484 NS_ABORT_MSG_IF(m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1485
1486 m_basicTriggerDependentUserInfo = (spacingFactor & 0x03) |
1487 (tidLimit & 0x07) << 2
1488 // B5 is reserved
1489 | (prefAc & 0x03) << 6;
1490}
1491
1492uint8_t
1494{
1495 NS_ABORT_MSG_IF(m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1496
1497 return m_basicTriggerDependentUserInfo & 0x03;
1498}
1499
1500uint8_t
1502{
1503 NS_ABORT_MSG_IF(m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1504
1505 return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1506}
1507
1508AcIndex
1510{
1511 NS_ABORT_MSG_IF(m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1512
1513 return AcIndex((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1514}
1515
1516void
1518{
1519 NS_ABORT_MSG_IF(m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1522 "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1524}
1525
1528{
1529 NS_ABORT_MSG_IF(m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1530
1532}
1533
1534/***********************************
1535 * Trigger frame
1536 ***********************************/
1537
1539
1541 : m_triggerType(0),
1542 m_ulLength(0),
1543 m_moreTF(false),
1544 m_csRequired(false),
1545 m_ulBandwidth(0),
1546 m_giAndLtfType(0),
1547 m_apTxPower(0),
1548 m_ulSpatialReuse(0)
1549{
1550}
1551
1554{
1556 SetUlBandwidth(txVector.GetChannelWidth());
1557 SetUlLength(txVector.GetLength());
1558 uint16_t gi = txVector.GetGuardInterval();
1559 if (gi == 800 || gi == 1600)
1560 {
1561 m_giAndLtfType = 1;
1562 }
1563 else
1564 {
1565 m_giAndLtfType = 2;
1566 }
1567 for (auto& userInfo : txVector.GetHeMuUserInfoMap())
1568 {
1570 ui.SetAid12(userInfo.first);
1571 ui.SetRuAllocation(userInfo.second.ru);
1572 ui.SetUlMcs(userInfo.second.mcs.GetMcsValue());
1573 ui.SetSsAllocation(1, userInfo.second.nss); // MU-MIMO is not supported
1574 }
1575}
1576
1578{
1579}
1580
1583{
1584 // check for self-assignment
1585 if (&trigger == this)
1586 {
1587 return *this;
1588 }
1589
1590 m_triggerType = trigger.m_triggerType;
1591 m_ulLength = trigger.m_ulLength;
1592 m_moreTF = trigger.m_moreTF;
1593 m_csRequired = trigger.m_csRequired;
1594 m_ulBandwidth = trigger.m_ulBandwidth;
1596 m_apTxPower = trigger.m_apTxPower;
1598 m_userInfoFields.clear();
1600 return *this;
1601}
1602
1603TypeId
1605{
1606 static TypeId tid = TypeId("ns3::CtrlTriggerHeader")
1607 .SetParent<Header>()
1608 .SetGroupName("Wifi")
1609 .AddConstructor<CtrlTriggerHeader>();
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");
1658 "GCR-MU-BAR Trigger frame is not supported");
1659 NS_ABORT_MSG_IF(m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1660
1662
1663 uint64_t commonInfo = 0;
1664 commonInfo |= (m_triggerType & 0x0f);
1665 commonInfo |= (m_ulLength & 0x0fff) << 4;
1666 commonInfo |= (m_moreTF ? 1 << 16 : 0);
1667 commonInfo |= (m_csRequired ? 1 << 17 : 0);
1668 commonInfo |= (m_ulBandwidth & 0x03) << 18;
1669 commonInfo |= (m_giAndLtfType & 0x03) << 20;
1670 commonInfo |= static_cast<uint64_t>(m_apTxPower & 0x3f) << 28;
1671 commonInfo |= static_cast<uint64_t>(m_ulSpatialReuse) << 37;
1672
1673 i.WriteHtolsbU64(commonInfo);
1674
1675 for (auto& ui : m_userInfoFields)
1676 {
1677 i = ui.Serialize(i);
1678 }
1679
1680 i.WriteHtolsbU16(0xffff); // Padding field, used as delimiter
1681}
1682
1685{
1687
1688 uint64_t commonInfo = i.ReadLsbtohU64();
1689
1690 m_triggerType = (commonInfo & 0x0f);
1691 m_ulLength = (commonInfo >> 4) & 0x0fff;
1692 m_moreTF = (commonInfo >> 16) & 0x01;
1693 m_csRequired = (commonInfo >> 17) & 0x01;
1694 m_ulBandwidth = (commonInfo >> 18) & 0x03;
1695 m_giAndLtfType = (commonInfo >> 20) & 0x03;
1696 m_apTxPower = (commonInfo >> 28) & 0x3f;
1697 m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1698 m_userInfoFields.clear();
1699
1700 NS_ABORT_MSG_IF(m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1702 "GCR-MU-BAR Trigger frame is not supported");
1703 NS_ABORT_MSG_IF(m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1704
1705 bool isPadding = false;
1706
1707 // We always add a Padding field (of two octets of all 1s) as delimiter
1708 while (!isPadding)
1709 {
1710 // read the first 2 bytes to check if we encountered the Padding field
1711 if (i.ReadU16() == 0xffff)
1712 {
1713 isPadding = true;
1714 }
1715 else
1716 {
1717 // go back 2 bytes to deserialize the User Info field from the beginning
1718 i.Prev(2);
1720 i = ui.Deserialize(i);
1721 }
1722 }
1723
1724 return i.GetDistanceFrom(start);
1725}
1726
1727void
1729{
1731}
1732
1735{
1736 return static_cast<TriggerFrameType>(m_triggerType);
1737}
1738
1739const char*
1741{
1742 return GetTypeString(GetType());
1743}
1744
1745const char*
1747{
1748#define FOO(x) \
1749 case x: \
1750 return #x; \
1751 break;
1752
1753 switch (type)
1754 {
1763 default:
1764 return "ERROR";
1765 }
1766#undef FOO
1767}
1768
1769bool
1771{
1772 return (m_triggerType == BASIC_TRIGGER);
1773}
1774
1775bool
1777{
1778 return (m_triggerType == BFRP_TRIGGER);
1779}
1780
1781bool
1783{
1784 return (m_triggerType == MU_BAR_TRIGGER);
1785}
1786
1787bool
1789{
1790 return (m_triggerType == MU_RTS_TRIGGER);
1791}
1792
1793bool
1795{
1796 return (m_triggerType == BSRP_TRIGGER);
1797}
1798
1799bool
1801{
1803}
1804
1805bool
1807{
1808 return (m_triggerType == BQRP_TRIGGER);
1809}
1810
1811bool
1813{
1814 return (m_triggerType == NFRP_TRIGGER);
1815}
1816
1817void
1819{
1820 m_ulLength = (len & 0x0fff);
1821}
1822
1823uint16_t
1825{
1826 return m_ulLength;
1827}
1828
1831{
1832 auto userInfoIt = FindUserInfoWithAid(staId);
1833 NS_ASSERT(userInfoIt != end());
1834
1835 WifiTxVector v;
1840 v.SetHeMuUserInfo(staId,
1841 {userInfoIt->GetRuAllocation(),
1842 HePhy::GetHeMcs(userInfoIt->GetUlMcs()),
1843 userInfoIt->GetNss()});
1844 return v;
1845}
1846
1847void
1849{
1850 m_moreTF = more;
1851}
1852
1853bool
1855{
1856 return m_moreTF;
1857}
1858
1859void
1861{
1862 m_csRequired = cs;
1863}
1864
1865bool
1867{
1868 return m_csRequired;
1869}
1870
1871void
1873{
1874 switch (bw)
1875 {
1876 case 20:
1877 m_ulBandwidth = 0;
1878 break;
1879 case 40:
1880 m_ulBandwidth = 1;
1881 break;
1882 case 80:
1883 m_ulBandwidth = 2;
1884 break;
1885 case 160:
1886 m_ulBandwidth = 3;
1887 break;
1888 default:
1889 NS_FATAL_ERROR("Bandwidth value not allowed.");
1890 break;
1891 }
1892}
1893
1894uint16_t
1896{
1897 return (1 << m_ulBandwidth) * 20;
1898}
1899
1900void
1901CtrlTriggerHeader::SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
1902{
1903 if (ltfType == 1 && guardInterval == 1600)
1904 {
1905 m_giAndLtfType = 0;
1906 }
1907 else if (ltfType == 2 && guardInterval == 1600)
1908 {
1909 m_giAndLtfType = 1;
1910 }
1911 else if (ltfType == 4 && guardInterval == 3200)
1912 {
1913 m_giAndLtfType = 2;
1914 }
1915 else
1916 {
1917 NS_FATAL_ERROR("Invalid combination of GI and LTF type");
1918 }
1919}
1920
1921uint16_t
1923{
1924 if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
1925 {
1926 return 1600;
1927 }
1928 else if (m_giAndLtfType == 2)
1929 {
1930 return 3200;
1931 }
1932 else
1933 {
1934 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
1935 }
1936}
1937
1938uint8_t
1940{
1941 if (m_giAndLtfType == 0)
1942 {
1943 return 1;
1944 }
1945 else if (m_giAndLtfType == 1)
1946 {
1947 return 2;
1948 }
1949 else if (m_giAndLtfType == 2)
1950 {
1951 return 4;
1952 }
1953 else
1954 {
1955 NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
1956 }
1957}
1958
1959void
1961{
1962 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
1963 NS_ABORT_MSG_IF(power < -20 || power > 40, "Out of range power values");
1964
1965 m_apTxPower = static_cast<uint8_t>(power + 20);
1966}
1967
1968int8_t
1970{
1971 // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
1972 return static_cast<int8_t>(m_apTxPower) - 20;
1973}
1974
1975void
1977{
1978 m_ulSpatialReuse = sr;
1979}
1980
1981uint16_t
1983{
1984 return m_ulSpatialReuse;
1985}
1986
1989{
1990 // make a copy of this Trigger Frame and remove the User Info fields from the copy
1991 CtrlTriggerHeader trigger(*this);
1992 trigger.m_userInfoFields.clear();
1993 return trigger;
1994}
1995
1998{
1999 m_userInfoFields.emplace_back(m_triggerType);
2000 return m_userInfoFields.back();
2001}
2002
2005{
2007 userInfo.GetType() != m_triggerType,
2008 "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2009 m_userInfoFields.push_back(userInfo);
2010 return m_userInfoFields.back();
2011}
2012
2015{
2016 return m_userInfoFields.begin();
2017}
2018
2021{
2022 return m_userInfoFields.end();
2023}
2024
2027{
2028 return m_userInfoFields.begin();
2029}
2030
2033{
2034 return m_userInfoFields.end();
2035}
2036
2037std::size_t
2039{
2040 return m_userInfoFields.size();
2041}
2042
2045{
2046 // the lambda function returns true if a User Info field has the AID12 subfield
2047 // equal to the given aid12 value
2048 return std::find_if(start, end(), [aid12](const CtrlTriggerUserInfoField& ui) -> bool {
2049 return (ui.GetAid12() == aid12);
2050 });
2051}
2052
2055{
2056 return FindUserInfoWithAid(m_userInfoFields.begin(), aid12);
2057}
2058
2061{
2062 return FindUserInfoWithAid(start, 0);
2063}
2064
2067{
2068 return FindUserInfoWithAid(0);
2069}
2070
2073{
2074 return FindUserInfoWithAid(start, 2045);
2075}
2076
2079{
2080 return FindUserInfoWithAid(2045);
2081}
2082
2083bool
2085{
2086 // check that allocated RUs do not overlap
2087 // TODO This is not a problem in case of UL MU-MIMO
2088 std::vector<HeRu::RuSpec> prevRus;
2089
2090 for (auto& ui : m_userInfoFields)
2091 {
2092 if (HeRu::DoesOverlap(GetUlBandwidth(), ui.GetRuAllocation(), prevRus))
2093 {
2094 return false;
2095 }
2096 prevRus.push_back(ui.GetRuAllocation());
2097 }
2098 return true;
2099}
2100
2101} // 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:51
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:186
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:183
uint16_t m_tidInfo
TID info.
Definition: ctrl-headers.h:185
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:184
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:202
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:529
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:528
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:530
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:551
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:886
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.
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.
uint8_t m_triggerType
Common Info field.
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.
uint16_t m_ulLength
Value for the L-SIG Length field.
bool m_csRequired
Carrier Sense required.
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 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:579
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.
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:843
uint8_t GetUlMcs() const
Get the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
uint8_t m_triggerType
Trigger frame type.
Definition: ctrl-headers.h:855
uint32_t GetSerializedSize() const
Get the expected size of this User Info field.
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:849
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.
CtrlTriggerUserInfoField(uint8_t triggerType)
Constructor.
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:834
uint8_t nSs
Number of spatial streams.
Definition: ctrl-headers.h:844
uint8_t m_basicTriggerDependentUserInfo
Basic Trigger variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:856
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:837
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:835
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...
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
Definition: ctrl-headers.h:838
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:854
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:850
bool m_ulFecCodingType
UL FEC Coding Type.
Definition: ctrl-headers.h:836
CtrlBAckRequestHeader m_muBarTriggerDependentUserInfo
MU-BAR variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:859
bool GetMoreRaRu() const
Return true if more RA-RUs are allocated in subsequent Trigger frames that are sent before the end of...
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:1444
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:620
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.
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:160
#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:74
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:559
@ WIFI_PREAMBLE_HE_TB
@ NFRP_TRIGGER
Definition: ctrl-headers.h:567
@ BFRP_TRIGGER
Definition: ctrl-headers.h:561
@ MU_RTS_TRIGGER
Definition: ctrl-headers.h:563
@ GCR_MU_BAR_TRIGGER
Definition: ctrl-headers.h:565
@ MU_BAR_TRIGGER
Definition: ctrl-headers.h:562
@ BASIC_TRIGGER
Definition: ctrl-headers.h:560
@ BQRP_TRIGGER
Definition: ctrl-headers.h:566
@ BSRP_TRIGGER
Definition: ctrl-headers.h:564
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.
def start()
Definition: core.py:1861
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.