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 
30 namespace ns3
31 {
32 
33 /***********************************
34  * Block ack request
35  ***********************************/
36 
37 NS_OBJECT_ENSURE_REGISTERED(CtrlBAckRequestHeader);
38 
40  : m_barAckPolicy(false),
41  m_barType(BlockAckReqType::BASIC)
42 {
43 }
44 
46 {
47 }
48 
49 TypeId
51 {
52  static TypeId tid = TypeId("ns3::CtrlBAckRequestHeader")
53  .SetParent<Header>()
54  .SetGroupName("Wifi")
55  .AddConstructor<CtrlBAckRequestHeader>();
56  return tid;
57 }
58 
59 TypeId
61 {
62  return GetTypeId();
63 }
64 
65 void
66 CtrlBAckRequestHeader::Print(std::ostream& os) const
67 {
68  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq << std::dec;
69 }
70 
71 uint32_t
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 
93 void
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 
114 uint32_t
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 
136 uint16_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 
161 void
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 
184 uint16_t
186 {
187  return (m_startingSeq << 4) & 0xfff0;
188 }
189 
190 void
192 {
193  m_startingSeq = (seqControl >> 4) & 0x0fff;
194 }
195 
196 void
198 {
199  m_barAckPolicy = immediateAck;
200 }
201 
202 void
204 {
205  m_barType = type;
206 }
207 
210 {
211  return m_barType;
212 }
213 
214 void
216 {
217  m_tidInfo = static_cast<uint16_t>(tid);
218 }
219 
220 void
222 {
223  m_startingSeq = seq;
224 }
225 
226 bool
228 {
229  return m_barAckPolicy;
230 }
231 
232 uint8_t
234 {
235  uint8_t tid = static_cast<uint8_t>(m_tidInfo);
236  return tid;
237 }
238 
239 uint16_t
241 {
242  return m_startingSeq;
243 }
244 
245 bool
247 {
249 }
250 
251 bool
253 {
255 }
256 
257 bool
259 {
261 }
262 
263 bool
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 
286 TypeId
288 {
289  static TypeId tid = TypeId("ns3::CtrlBAckResponseHeader")
290  .SetParent<Header>()
291  .SetGroupName("Wifi")
292  .AddConstructor<CtrlBAckResponseHeader>();
293  return tid;
294 }
295 
296 TypeId
298 {
299  return GetTypeId();
300 }
301 
302 void
303 CtrlBAckResponseHeader::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 
320 uint32_t
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  {
329  case BlockAckType::BASIC:
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 
350 void
352 {
355  switch (m_baType.m_variant)
356  {
357  case BlockAckType::BASIC:
361  i = SerializeBitmap(i);
362  break;
364  for (std::size_t index = 0; index < m_baInfo.size(); index++)
365  {
366  i.WriteHtolsbU16(m_baInfo[index].m_aidTidInfo);
367  if (GetAid11(index) != 2045)
368  {
369  if (!m_baInfo[index].m_bitmap.empty())
370  {
372  i = SerializeBitmap(i, index);
373  }
374  }
375  else
376  {
377  uint32_t reserved = 0;
378  i.WriteHtolsbU32(reserved);
379  WriteTo(i, m_baInfo[index].m_ra);
380  }
381  }
382  break;
384  NS_FATAL_ERROR("Multi-tid block ack is not supported.");
385  break;
386  default:
387  NS_FATAL_ERROR("Invalid BA type");
388  break;
389  }
390 }
391 
392 uint32_t
394 {
397  switch (m_baType.m_variant)
398  {
399  case BlockAckType::BASIC:
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 
447 void
449 {
450  m_baAckPolicy = immediateAck;
451 }
452 
453 void
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 
474 void
475 CtrlBAckResponseHeader::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 
491 void
492 CtrlBAckResponseHeader::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 
501 bool
503 {
504  return m_baAckPolicy;
505 }
506 
507 uint8_t
508 CtrlBAckResponseHeader::GetTidInfo(std::size_t index) const
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 
527 uint16_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 
537 bool
539 {
541 }
542 
543 bool
545 {
547 }
548 
549 bool
551 {
553 }
554 
555 bool
557 {
559 }
560 
561 bool
563 {
565 }
566 
567 void
568 CtrlBAckResponseHeader::SetAid11(uint16_t aid, std::size_t index)
569 {
571 
572  m_baInfo[index].m_aidTidInfo |= (aid & 0x07ff);
573 }
574 
575 uint16_t
576 CtrlBAckResponseHeader::GetAid11(std::size_t index) const
577 {
579 
580  return m_baInfo[index].m_aidTidInfo & 0x07ff;
581 }
582 
583 void
584 CtrlBAckResponseHeader::SetAckType(bool type, std::size_t index)
585 {
587 
588  if (type)
589  {
590  m_baInfo[index].m_aidTidInfo |= (1 << 11);
591  }
592 }
593 
594 bool
595 CtrlBAckResponseHeader::GetAckType(std::size_t index) const
596 {
598 
599  return ((m_baInfo[index].m_aidTidInfo >> 11) & 0x0001) != 0;
600 }
601 
602 void
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 
618 std::size_t
620 {
622  return m_baInfo.size();
623 }
624 
625 std::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 
642 uint16_t
644 {
645  uint16_t res = 0;
646  if (m_baAckPolicy)
647  {
648  res |= 0x1;
649  }
650  switch (m_baType.m_variant)
651  {
652  case BlockAckType::BASIC:
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 
677 void
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 
711 uint16_t
713 {
715  "index can only be non null for Multi-STA Block Ack");
716  NS_ASSERT(index < m_baInfo.size());
717 
718  uint16_t ret = (m_baInfo[index].m_startingSeq << 4) & 0xfff0;
719 
720  // The Fragment Number subfield encodes the length of the bitmap for
721  // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
722  // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
724  {
725  if (m_baType.m_bitmapLen[0] == 32)
726  {
727  ret |= 0x0004;
728  }
729  }
731  {
732  NS_ASSERT(m_baInfo.size() == m_baType.m_bitmapLen.size());
733  NS_ASSERT_MSG(!m_baInfo[index].m_bitmap.empty(),
734  "This Per AID TID Info subfield has no Starting Sequence Control subfield");
735 
736  if (m_baType.m_bitmapLen[index] == 16)
737  {
738  ret |= 0x0002;
739  }
740  else if (m_baType.m_bitmapLen[index] == 32)
741  {
742  ret |= 0x0004;
743  }
744  else if (m_baType.m_bitmapLen[index] == 4)
745  {
746  ret |= 0x0006;
747  }
748  }
749  return ret;
750 }
751 
752 void
753 CtrlBAckResponseHeader::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  {
825  case BlockAckType::BASIC:
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  {
854  case BlockAckType::BASIC:
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 
873 void
874 CtrlBAckResponseHeader::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  {
886  case BlockAckType::BASIC:
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 
907 void
909 {
910  NS_ASSERT(frag < 16);
911  if (!IsInBitmap(seq))
912  {
913  return;
914  }
915  switch (m_baType.m_variant)
916  {
917  case BlockAckType::BASIC:
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 
935 bool
936 CtrlBAckResponseHeader::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  {
954  case BlockAckType::BASIC:
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 
974 bool
975 CtrlBAckResponseHeader::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  {
984  case BlockAckType::BASIC:
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 
1005 uint16_t
1006 CtrlBAckResponseHeader::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 
1029 bool
1030 CtrlBAckResponseHeader::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 
1047 const std::vector<uint8_t>&
1048 CtrlBAckResponseHeader::GetBitmap(std::size_t index) const
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 
1057 void
1059 {
1061  "index can only be non null for Multi-STA Block Ack");
1062  NS_ASSERT(index < m_baInfo.size());
1063 
1064  m_baInfo[index].m_bitmap.assign(m_baType.m_bitmapLen[index], 0);
1065 }
1066 
1067 /***********************************
1068  * Trigger frame - User Info field
1069  ***********************************/
1070 
1072  TriggerFrameVariant variant)
1073  : m_variant(variant),
1074  m_aid12(0),
1075  m_ruAllocation(0),
1076  m_ulFecCodingType(false),
1077  m_ulMcs(0),
1078  m_ulDcm(false),
1079  m_ps160(true),
1080  m_ulTargetRssi(0),
1081  m_triggerType(triggerType),
1082  m_basicTriggerDependentUserInfo(0)
1083 {
1084  memset(&m_bits26To31, 0, sizeof(m_bits26To31));
1085 }
1086 
1088 {
1089 }
1090 
1093 {
1094  NS_ABORT_MSG_IF(m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1095 
1096  // check for self-assignment
1097  if (&userInfo == this)
1098  {
1099  return *this;
1100  }
1101 
1102  m_variant = userInfo.m_variant;
1103  m_aid12 = userInfo.m_aid12;
1104  m_ruAllocation = userInfo.m_ruAllocation;
1106  m_ulMcs = userInfo.m_ulMcs;
1107  m_ulDcm = userInfo.m_ulDcm;
1108  m_ps160 = userInfo.m_ps160;
1109  m_bits26To31 = userInfo.m_bits26To31;
1110  m_ulTargetRssi = userInfo.m_ulTargetRssi;
1113  return *this;
1114 }
1115 
1116 void
1117 CtrlTriggerUserInfoField::Print(std::ostream& os) const
1118 {
1119  os << ", USER_INFO " << (m_variant == TriggerFrameVariant::HE ? "HE" : "EHT")
1120  << " variant AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation
1121  << ", MCS=" << +m_ulMcs;
1122 }
1123 
1124 uint32_t
1126 {
1127  uint32_t size = 0;
1128  size += 5; // User Info (excluding Trigger Dependent User Info)
1129 
1130  switch (m_triggerType)
1131  {
1134  size += 1;
1135  break;
1137  size +=
1138  m_muBarTriggerDependentUserInfo.GetSerializedSize(); // BAR Control and BAR Information
1139  break;
1140  default:;
1141  // The Trigger Dependent User Info subfield is not present in the other variants
1142  }
1143 
1144  return size;
1145 }
1146 
1149 {
1151  "BFRP Trigger frame is not supported");
1153  "GCR-MU-BAR Trigger frame is not supported");
1155  "NFRP Trigger frame is not supported");
1156 
1157  Buffer::Iterator i = start;
1158 
1159  uint32_t userInfo = 0; // User Info except the MSB
1160  userInfo |= (m_aid12 & 0x0fff);
1161  userInfo |= (m_ruAllocation << 12);
1162  userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1163  userInfo |= (m_ulMcs & 0x0f) << 21;
1165  {
1166  userInfo |= (m_ulDcm ? 1 << 25 : 0);
1167  }
1168 
1169  if (m_aid12 != 0 && m_aid12 != 2045)
1170  {
1171  userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1172  userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1173  }
1174  else
1175  {
1176  userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1177  userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1178  }
1179 
1180  i.WriteHtolsbU32(userInfo);
1181  // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and B39, which is
1182  // reserved in the HE variant and the PS160 subfield in the EHT variant.
1183  uint8_t bit32To39 = m_ulTargetRssi;
1185  {
1186  bit32To39 |= (m_ps160 ? 1 << 7 : 0);
1187  }
1188 
1189  i.WriteU8(bit32To39);
1190 
1192  {
1194  }
1196  {
1199  }
1200 
1201  return i;
1202 }
1203 
1206 {
1208  "BFRP Trigger frame is not supported");
1210  "GCR-MU-BAR Trigger frame is not supported");
1212  "NFRP Trigger frame is not supported");
1213 
1214  Buffer::Iterator i = start;
1215 
1216  uint32_t userInfo = i.ReadLsbtohU32();
1217 
1218  m_aid12 = userInfo & 0x0fff;
1219  NS_ABORT_MSG_IF(m_aid12 == 4095, "Cannot deserialize a Padding field");
1220  m_ruAllocation = (userInfo >> 12) & 0xff;
1221  m_ulFecCodingType = (userInfo >> 20) & 0x01;
1222  m_ulMcs = (userInfo >> 21) & 0x0f;
1224  {
1225  m_ulDcm = (userInfo >> 25) & 0x01;
1226  }
1227 
1228  if (m_aid12 != 0 && m_aid12 != 2045)
1229  {
1230  m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1231  m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1232  }
1233  else
1234  {
1235  m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1236  m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1237  }
1238 
1239  uint8_t bit32To39 = i.ReadU8();
1240  m_ulTargetRssi = bit32To39 & 0x7f; // B39 is reserved in HE variant
1242  {
1243  m_ps160 = (bit32To39 >> 7) == 1;
1244  }
1245 
1247  {
1249  }
1251  {
1252  uint32_t len = m_muBarTriggerDependentUserInfo.Deserialize(i);
1253  i.Next(len);
1254  }
1255 
1256  return i;
1257 }
1258 
1261 {
1262  return m_triggerType;
1263 }
1264 
1267 {
1268  switch (m_variant)
1269  {
1271  return WIFI_PREAMBLE_HE_TB;
1273  return WIFI_PREAMBLE_EHT_TB;
1274  default:
1275  NS_ABORT_MSG("Unexpected variant: " << +static_cast<uint8_t>(m_variant));
1276  }
1277  return WIFI_PREAMBLE_LONG; // to silence warning
1278 }
1279 
1280 void
1282 {
1283  m_aid12 = aid & 0x0fff;
1284 }
1285 
1286 uint16_t
1288 {
1289  return m_aid12;
1290 }
1291 
1292 bool
1294 {
1295  return (m_aid12 == 0);
1296 }
1297 
1298 bool
1300 {
1301  return (m_aid12 == 2045);
1302 }
1303 
1304 void
1306 {
1307  NS_ABORT_MSG_IF(ru.GetIndex() == 0, "Valid indices start at 1");
1309  "SetMuRtsRuAllocation() must be used for MU-RTS");
1310 
1311  switch (ru.GetRuType())
1312  {
1313  case HeRu::RU_26_TONE:
1314  m_ruAllocation = ru.GetIndex() - 1;
1315  break;
1316  case HeRu::RU_52_TONE:
1317  m_ruAllocation = ru.GetIndex() + 36;
1318  break;
1319  case HeRu::RU_106_TONE:
1320  m_ruAllocation = ru.GetIndex() + 52;
1321  break;
1322  case HeRu::RU_242_TONE:
1323  m_ruAllocation = ru.GetIndex() + 60;
1324  break;
1325  case HeRu::RU_484_TONE:
1326  m_ruAllocation = ru.GetIndex() + 64;
1327  break;
1328  case HeRu::RU_996_TONE:
1329  m_ruAllocation = 67;
1330  break;
1331  case HeRu::RU_2x996_TONE:
1332  m_ruAllocation = 68;
1333  break;
1334  default:
1335  NS_FATAL_ERROR("RU type unknown.");
1336  break;
1337  }
1338 
1339  NS_ABORT_MSG_IF(m_ruAllocation > 68, "Reserved value.");
1340 
1341  m_ruAllocation <<= 1;
1342  if (!ru.GetPrimary80MHz())
1343  {
1344  m_ruAllocation++;
1345  }
1346 }
1347 
1350 {
1352  "GetMuRtsRuAllocation() must be used for MU-RTS");
1353 
1354  HeRu::RuType ruType;
1355  std::size_t index;
1356 
1357  bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1358 
1359  uint8_t val = m_ruAllocation >> 1;
1360 
1361  if (val < 37)
1362  {
1363  ruType = HeRu::RU_26_TONE;
1364  index = val + 1;
1365  }
1366  else if (val < 53)
1367  {
1368  ruType = HeRu::RU_52_TONE;
1369  index = val - 36;
1370  }
1371  else if (val < 61)
1372  {
1373  ruType = HeRu::RU_106_TONE;
1374  index = val - 52;
1375  }
1376  else if (val < 65)
1377  {
1378  ruType = HeRu::RU_242_TONE;
1379  index = val - 60;
1380  }
1381  else if (val < 67)
1382  {
1383  ruType = HeRu::RU_484_TONE;
1384  index = val - 64;
1385  }
1386  else if (val == 67)
1387  {
1388  ruType = HeRu::RU_996_TONE;
1389  index = 1;
1390  }
1391  else if (val == 68)
1392  {
1393  ruType = HeRu::RU_2x996_TONE;
1394  index = 1;
1395  }
1396  else
1397  {
1398  NS_FATAL_ERROR("Reserved value.");
1399  }
1400 
1401  return HeRu::RuSpec(ruType, index, primary80MHz);
1402 }
1403 
1404 void
1406 {
1408  "SetMuRtsRuAllocation() can only be used for MU-RTS");
1410  value < 61 || value > 68,
1411  "Value "
1412  << +value
1413  << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1414 
1415  m_ruAllocation = (value << 1);
1416  if (value == 68)
1417  {
1418  // set B0 for 160 MHz and 80+80 MHz indication
1419  m_ruAllocation++;
1420  }
1421 }
1422 
1423 uint8_t
1425 {
1427  "GetMuRtsRuAllocation() can only be used for MU-RTS");
1428  uint8_t value = (m_ruAllocation >> 1);
1430  value < 61 || value > 68,
1431  "Value "
1432  << +value
1433  << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1434  return value;
1435 }
1436 
1437 void
1439 {
1440  m_ulFecCodingType = ldpc;
1441 }
1442 
1443 bool
1445 {
1446  return m_ulFecCodingType;
1447 }
1448 
1449 void
1451 {
1452  NS_ABORT_MSG_IF(mcs > 11, "Invalid MCS index");
1453  m_ulMcs = mcs;
1454 }
1455 
1456 uint8_t
1458 {
1459  return m_ulMcs;
1460 }
1461 
1462 void
1464 {
1465  NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1466  m_ulDcm = dcm;
1467 }
1468 
1469 bool
1471 {
1472  NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1473  return m_ulDcm;
1474 }
1475 
1476 void
1477 CtrlTriggerUserInfoField::SetSsAllocation(uint8_t startingSs, uint8_t nSs)
1478 {
1479  NS_ABORT_MSG_IF(m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1480  NS_ABORT_MSG_IF(!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1481  NS_ABORT_MSG_IF(!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1482 
1483  m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1484  m_bits26To31.ssAllocation.nSs = nSs - 1;
1485 }
1486 
1487 uint8_t
1489 {
1490  if (m_aid12 == 0 || m_aid12 == 2045)
1491  {
1492  return 1;
1493  }
1494  return m_bits26To31.ssAllocation.startingSs + 1;
1495 }
1496 
1497 uint8_t
1499 {
1500  if (m_aid12 == 0 || m_aid12 == 2045)
1501  {
1502  return 1;
1503  }
1504  return m_bits26To31.ssAllocation.nSs + 1;
1505 }
1506 
1507 void
1509 {
1510  NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1511  NS_ABORT_MSG_IF(!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1512 
1513  m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1514  m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1515 }
1516 
1517 uint8_t
1519 {
1520  NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1521 
1522  return m_bits26To31.raRuInformation.nRaRu + 1;
1523 }
1524 
1525 bool
1527 {
1528  NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1529 
1530  return m_bits26To31.raRuInformation.moreRaRu;
1531 }
1532 
1533 void
1535 {
1536  m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1537 }
1538 
1539 void
1541 {
1542  NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
1543 
1544  m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
1545 }
1546 
1547 bool
1549 {
1550  return (m_ulTargetRssi == 127);
1551 }
1552 
1553 int8_t
1555 {
1556  NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
1557 
1558  return static_cast<int8_t>(m_ulTargetRssi) - 110;
1559 }
1560 
1561 void
1563  uint8_t tidLimit,
1564  AcIndex prefAc)
1565 {
1566  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1567 
1568  m_basicTriggerDependentUserInfo = (spacingFactor & 0x03) |
1569  (tidLimit & 0x07) << 2
1570  // B5 is reserved
1571  | (prefAc & 0x03) << 6;
1572 }
1573 
1574 uint8_t
1576 {
1577  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1578 
1579  return m_basicTriggerDependentUserInfo & 0x03;
1580 }
1581 
1582 uint8_t
1584 {
1585  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1586 
1587  return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1588 }
1589 
1590 AcIndex
1592 {
1593  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1594 
1595  return AcIndex((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1596 }
1597 
1598 void
1600 {
1602  "Not a MU-BAR Trigger frame");
1605  "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1607 }
1608 
1609 const CtrlBAckRequestHeader&
1611 {
1613  "Not a MU-BAR Trigger frame");
1614 
1616 }
1617 
1618 /***********************************
1619  * Trigger frame
1620  ***********************************/
1621 
1623 
1625  : m_variant(TriggerFrameVariant::HE),
1626  m_triggerType(TriggerFrameType::BASIC_TRIGGER),
1627  m_ulLength(0),
1628  m_moreTF(false),
1629  m_csRequired(false),
1630  m_ulBandwidth(0),
1631  m_giAndLtfType(0),
1632  m_apTxPower(0),
1633  m_ulSpatialReuse(0)
1634 {
1635 }
1636 
1638  : CtrlTriggerHeader()
1639 {
1641  "This constructor cannot be used for MU-RTS");
1642 
1643  switch (txVector.GetPreambleType())
1644  {
1645  case WIFI_PREAMBLE_HE_TB:
1647  break;
1648  case WIFI_PREAMBLE_EHT_TB:
1650  break;
1651  default:
1652  NS_ABORT_MSG("Cannot create a TF out of a TXVECTOR with preamble type: "
1653  << txVector.GetPreambleType());
1654  }
1655 
1656  m_triggerType = type;
1657  SetUlBandwidth(txVector.GetChannelWidth());
1658  SetUlLength(txVector.GetLength());
1659  uint16_t gi = txVector.GetGuardInterval();
1660  if (gi == 800 || gi == 1600)
1661  {
1662  m_giAndLtfType = 1;
1663  }
1664  else
1665  {
1666  m_giAndLtfType = 2;
1667  }
1668  for (auto& userInfo : txVector.GetHeMuUserInfoMap())
1669  {
1671  ui.SetAid12(userInfo.first);
1672  ui.SetRuAllocation(userInfo.second.ru);
1673  ui.SetUlMcs(userInfo.second.mcs);
1674  ui.SetSsAllocation(1, userInfo.second.nss); // MU-MIMO is not supported
1675  }
1676 }
1677 
1679 {
1680 }
1681 
1684 {
1685  // check for self-assignment
1686  if (&trigger == this)
1687  {
1688  return *this;
1689  }
1690 
1691  m_variant = trigger.m_variant;
1692  m_triggerType = trigger.m_triggerType;
1693  m_ulLength = trigger.m_ulLength;
1694  m_moreTF = trigger.m_moreTF;
1695  m_csRequired = trigger.m_csRequired;
1696  m_ulBandwidth = trigger.m_ulBandwidth;
1697  m_giAndLtfType = trigger.m_giAndLtfType;
1698  m_apTxPower = trigger.m_apTxPower;
1700  m_userInfoFields.clear();
1702  return *this;
1703 }
1704 
1705 TypeId
1707 {
1708  static TypeId tid = TypeId("ns3::CtrlTriggerHeader")
1709  .SetParent<Header>()
1710  .SetGroupName("Wifi")
1711  .AddConstructor<CtrlTriggerHeader>();
1712  return tid;
1713 }
1714 
1715 TypeId
1717 {
1718  return GetTypeId();
1719 }
1720 
1721 void
1722 CtrlTriggerHeader::Print(std::ostream& os) const
1723 {
1724  os << "TriggerType=" << GetTypeString() << ", Bandwidth=" << +GetUlBandwidth()
1725  << ", UL Length=" << m_ulLength;
1726 
1727  for (auto& ui : m_userInfoFields)
1728  {
1729  ui.Print(os);
1730  }
1731 }
1732 
1733 void
1735 {
1737  "Cannot change Common Info field variant if User Info fields are present");
1738  m_variant = variant;
1739 }
1740 
1743 {
1744  return m_variant;
1745 }
1746 
1747 uint32_t
1749 {
1750  uint32_t size = 0;
1751  size += 8; // Common Info (excluding Trigger Dependent Common Info)
1752 
1753  // Add the size of the Trigger Dependent Common Info subfield
1755  {
1756  size += 4;
1757  }
1758 
1759  for (auto& ui : m_userInfoFields)
1760  {
1761  size += ui.GetSerializedSize();
1762  }
1763 
1764  size += 2; // Padding field
1765 
1766  return size;
1767 }
1768 
1769 void
1771 {
1773  "BFRP Trigger frame is not supported");
1775  "GCR-MU-BAR Trigger frame is not supported");
1777  "NFRP Trigger frame is not supported");
1778 
1779  Buffer::Iterator i = start;
1780 
1781  uint64_t commonInfo = 0;
1782  commonInfo |= (static_cast<uint8_t>(m_triggerType) & 0x0f);
1783  commonInfo |= (m_ulLength & 0x0fff) << 4;
1784  commonInfo |= (m_moreTF ? 1 << 16 : 0);
1785  commonInfo |= (m_csRequired ? 1 << 17 : 0);
1786  commonInfo |= (m_ulBandwidth & 0x03) << 18;
1787  commonInfo |= (m_giAndLtfType & 0x03) << 20;
1788  commonInfo |= static_cast<uint64_t>(m_apTxPower & 0x3f) << 28;
1789  commonInfo |= static_cast<uint64_t>(m_ulSpatialReuse) << 37;
1791  {
1792  uint64_t ulHeSigA2 = 0x01ff; // nine bits equal to 1
1793  commonInfo |= ulHeSigA2 << 54;
1794  }
1795 
1796  i.WriteHtolsbU64(commonInfo);
1797 
1798  for (auto& ui : m_userInfoFields)
1799  {
1800  i = ui.Serialize(i);
1801  }
1802 
1803  i.WriteHtolsbU16(0xffff); // Padding field, used as delimiter
1804 }
1805 
1806 uint32_t
1808 {
1809  Buffer::Iterator i = start;
1810 
1811  uint64_t commonInfo = i.ReadLsbtohU64();
1812 
1813  m_triggerType = static_cast<TriggerFrameType>(commonInfo & 0x0f);
1814  m_ulLength = (commonInfo >> 4) & 0x0fff;
1815  m_moreTF = (commonInfo >> 16) & 0x01;
1816  m_csRequired = (commonInfo >> 17) & 0x01;
1817  m_ulBandwidth = (commonInfo >> 18) & 0x03;
1818  m_giAndLtfType = (commonInfo >> 20) & 0x03;
1819  m_apTxPower = (commonInfo >> 28) & 0x3f;
1820  m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1821  uint8_t bit54and55 = (commonInfo >> 54) & 0x03;
1823  m_userInfoFields.clear();
1824 
1826  "BFRP Trigger frame is not supported");
1828  "GCR-MU-BAR Trigger frame is not supported");
1830  "NFRP Trigger frame is not supported");
1831 
1832  bool isPadding = false;
1833 
1834  // We always add a Padding field (of two octets of all 1s) as delimiter
1835  while (!isPadding)
1836  {
1837  // read the first 2 bytes to check if we encountered the Padding field
1838  if (i.ReadU16() == 0xffff)
1839  {
1840  isPadding = true;
1841  }
1842  else
1843  {
1844  // go back 2 bytes to deserialize the User Info field from the beginning
1845  i.Prev(2);
1847  i = ui.Deserialize(i);
1848  }
1849  }
1850 
1851  return i.GetDistanceFrom(start);
1852 }
1853 
1854 void
1856 {
1857  m_triggerType = type;
1858 }
1859 
1862 {
1863  return m_triggerType;
1864 }
1865 
1866 const char*
1868 {
1869  return GetTypeString(GetType());
1870 }
1871 
1872 const char*
1874 {
1875 #define FOO(x) \
1876  case TriggerFrameType::x: \
1877  return #x; \
1878  break;
1879 
1880  switch (type)
1881  {
1882  FOO(BASIC_TRIGGER);
1883  FOO(BFRP_TRIGGER);
1886  FOO(BSRP_TRIGGER);
1888  FOO(BQRP_TRIGGER);
1889  FOO(NFRP_TRIGGER);
1890  default:
1891  return "ERROR";
1892  }
1893 #undef FOO
1894 }
1895 
1896 bool
1898 {
1900 }
1901 
1902 bool
1904 {
1906 }
1907 
1908 bool
1910 {
1912 }
1913 
1914 bool
1916 {
1918 }
1919 
1920 bool
1922 {
1924 }
1925 
1926 bool
1928 {
1930 }
1931 
1932 bool
1934 {
1936 }
1937 
1938 bool
1940 {
1942 }
1943 
1944 void
1946 {
1947  m_ulLength = (len & 0x0fff);
1948 }
1949 
1950 uint16_t
1952 {
1953  return m_ulLength;
1954 }
1955 
1958 {
1960  "GetHeTbTxVector() cannot be used for MU-RTS");
1961  auto userInfoIt = FindUserInfoWithAid(staId);
1962  NS_ASSERT(userInfoIt != end());
1963 
1964  WifiTxVector v;
1965  v.SetPreambleType(userInfoIt->GetPreambleType());
1968  v.SetLength(GetUlLength());
1969  v.SetHeMuUserInfo(
1970  staId,
1971  {userInfoIt->GetRuAllocation(), userInfoIt->GetUlMcs(), userInfoIt->GetNss()});
1972  return v;
1973 }
1974 
1975 void
1977 {
1978  m_moreTF = more;
1979 }
1980 
1981 bool
1983 {
1984  return m_moreTF;
1985 }
1986 
1987 void
1989 {
1990  m_csRequired = cs;
1991 }
1992 
1993 bool
1995 {
1996  return m_csRequired;
1997 }
1998 
1999 void
2001 {
2002  switch (bw)
2003  {
2004  case 20:
2005  m_ulBandwidth = 0;
2006  break;
2007  case 40:
2008  m_ulBandwidth = 1;
2009  break;
2010  case 80:
2011  m_ulBandwidth = 2;
2012  break;
2013  case 160:
2014  m_ulBandwidth = 3;
2015  break;
2016  default:
2017  NS_FATAL_ERROR("Bandwidth value not allowed.");
2018  break;
2019  }
2020 }
2021 
2022 uint16_t
2024 {
2025  return (1 << m_ulBandwidth) * 20;
2026 }
2027 
2028 void
2029 CtrlTriggerHeader::SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
2030 {
2031  if (ltfType == 1 && guardInterval == 1600)
2032  {
2033  m_giAndLtfType = 0;
2034  }
2035  else if (ltfType == 2 && guardInterval == 1600)
2036  {
2037  m_giAndLtfType = 1;
2038  }
2039  else if (ltfType == 4 && guardInterval == 3200)
2040  {
2041  m_giAndLtfType = 2;
2042  }
2043  else
2044  {
2045  NS_FATAL_ERROR("Invalid combination of GI and LTF type");
2046  }
2047 }
2048 
2049 uint16_t
2051 {
2052  if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
2053  {
2054  return 1600;
2055  }
2056  else if (m_giAndLtfType == 2)
2057  {
2058  return 3200;
2059  }
2060  else
2061  {
2062  NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2063  }
2064 }
2065 
2066 uint8_t
2068 {
2069  if (m_giAndLtfType == 0)
2070  {
2071  return 1;
2072  }
2073  else if (m_giAndLtfType == 1)
2074  {
2075  return 2;
2076  }
2077  else if (m_giAndLtfType == 2)
2078  {
2079  return 4;
2080  }
2081  else
2082  {
2083  NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2084  }
2085 }
2086 
2087 void
2089 {
2090  // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2091  NS_ABORT_MSG_IF(power < -20 || power > 40, "Out of range power values");
2092 
2093  m_apTxPower = static_cast<uint8_t>(power + 20);
2094 }
2095 
2096 int8_t
2098 {
2099  // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2100  return static_cast<int8_t>(m_apTxPower) - 20;
2101 }
2102 
2103 void
2105 {
2106  m_ulSpatialReuse = sr;
2107 }
2108 
2109 uint16_t
2111 {
2112  return m_ulSpatialReuse;
2113 }
2114 
2117 {
2118  // make a copy of this Trigger Frame and remove the User Info fields from the copy
2119  CtrlTriggerHeader trigger(*this);
2120  trigger.m_userInfoFields.clear();
2121  return trigger;
2122 }
2123 
2126 {
2127  m_userInfoFields.emplace_back(m_triggerType, m_variant);
2128  return m_userInfoFields.back();
2129 }
2130 
2133 {
2135  userInfo.GetType() != m_triggerType,
2136  "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2137  m_userInfoFields.push_back(userInfo);
2138  return m_userInfoFields.back();
2139 }
2140 
2143 {
2144  return m_userInfoFields.begin();
2145 }
2146 
2149 {
2150  return m_userInfoFields.end();
2151 }
2152 
2155 {
2156  return m_userInfoFields.begin();
2157 }
2158 
2161 {
2162  return m_userInfoFields.end();
2163 }
2164 
2165 std::size_t
2167 {
2168  return m_userInfoFields.size();
2169 }
2170 
2173 {
2174  // the lambda function returns true if a User Info field has the AID12 subfield
2175  // equal to the given aid12 value
2176  return std::find_if(start, end(), [aid12](const CtrlTriggerUserInfoField& ui) -> bool {
2177  return (ui.GetAid12() == aid12);
2178  });
2179 }
2180 
2183 {
2184  return FindUserInfoWithAid(m_userInfoFields.begin(), aid12);
2185 }
2186 
2189 {
2190  return FindUserInfoWithAid(start, 0);
2191 }
2192 
2195 {
2196  return FindUserInfoWithAid(0);
2197 }
2198 
2201 {
2202  return FindUserInfoWithAid(start, 2045);
2203 }
2204 
2207 {
2208  return FindUserInfoWithAid(2045);
2209 }
2210 
2211 bool
2213 {
2215  {
2216  return true;
2217  }
2218 
2219  // check that allocated RUs do not overlap
2220  // TODO This is not a problem in case of UL MU-MIMO
2221  std::vector<HeRu::RuSpec> prevRus;
2222 
2223  for (auto& ui : m_userInfoFields)
2224  {
2225  if (HeRu::DoesOverlap(GetUlBandwidth(), ui.GetRuAllocation(), prevRus))
2226  {
2227  return false;
2228  }
2229  prevRus.push_back(ui.GetRuAllocation());
2230  }
2231  return true;
2232 }
2233 
2234 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint32_t GetRemainingSize() const
Definition: buffer.cc:1176
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:905
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:913
uint16_t ReadLsbtohU16()
Definition: buffer.cc:1067
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1097
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:923
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:783
void Prev()
go backward by one byte
Definition: buffer.h:860
uint16_t ReadU16()
Definition: buffer.h:1035
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1079
void Next()
go forward by one byte
Definition: buffer.h:853
Headers for BlockAckRequest.
Definition: ctrl-headers.h:52
uint16_t GetStartingSequence() const
Return the starting sequence number.
uint32_t GetSerializedSize() const override
Definition: ctrl-headers.cc:72
void Serialize(Buffer::Iterator start) const override
Definition: ctrl-headers.cc:94
uint16_t m_startingSeq
starting seq
Definition: ctrl-headers.h:187
bool m_barAckPolicy
The LSB bit of the BAR control field is used only for the HT (High Throughput) delayed block ack conf...
Definition: ctrl-headers.h:184
uint16_t m_tidInfo
TID info.
Definition: ctrl-headers.h:186
uint8_t GetTidInfo() const
Return the Traffic ID (TID).
bool IsExtendedCompressed() const
Check if the current Ack Policy is Extended Compressed Block Ack.
void Print(std::ostream &os) const override
Definition: ctrl-headers.cc:66
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
BlockAckReqType m_barType
BAR type.
Definition: ctrl-headers.h:185
void SetStartingSequenceControl(uint16_t seqControl)
Set the starting sequence control with the given sequence control value.
bool IsMultiTid() const
Check if the current Ack Policy has Multi-TID Block Ack.
BlockAckReqType GetType() const
Return the BlockAckRequest type.
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
uint32_t Deserialize(Buffer::Iterator start) override
bool IsCompressed() const
Check if the current Ack Policy is Compressed Block Ack and not multi-TID.
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
uint16_t GetBarControl() const
Return the Block Ack control.
static TypeId GetTypeId()
Get the type ID.
Definition: ctrl-headers.cc:50
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Definition: ctrl-headers.cc:60
uint16_t GetStartingSequenceControl() const
Return the starting sequence control.
void SetBarControl(uint16_t bar)
Set the Block Ack control.
bool MustSendHtImmediateAck() const
Check if the current Ack Policy is immediate.
bool IsBasic() const
Check if the current Ack Policy is Basic Block Ack (i.e.
Headers for BlockAck response.
Definition: ctrl-headers.h:203
void SetBaControl(uint16_t ba)
Set the Block Ack control.
bool IsExtendedCompressed() const
Check if the current BA policy is Extended Compressed Block Ack.
void SetStartingSequence(uint16_t seq, std::size_t index=0)
For Block Ack variants other than Multi-STA Block Ack, set the starting sequence number to the given ...
uint16_t GetStartingSequenceControl(std::size_t index=0) const
Return the value of the Starting Sequence Control subfield.
BlockAckType m_baType
BA type.
Definition: ctrl-headers.h:530
bool IsFragmentReceived(uint16_t seq, uint8_t frag) const
Check if the packet with the given sequence number and fragment number was acknowledged in this Block...
void Serialize(Buffer::Iterator start) const override
bool IsPacketReceived(uint16_t seq, std::size_t index=0) const
Check if the packet with the given sequence number was acknowledged in this BlockAck response.
void SetStartingSequenceControl(uint16_t seqControl, std::size_t index=0)
Set the Starting Sequence Control subfield with the given sequence control value.
std::vector< uint32_t > FindPerAidTidInfoWithAid(uint16_t aid) const
For Multi-STA Block Acks, get the indices of the Per AID TID Info subfields carrying the given AID in...
Buffer::Iterator SerializeBitmap(Buffer::Iterator start, std::size_t index=0) const
Serialize bitmap to the given buffer.
std::size_t GetNPerAidTidInfoSubfields() const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack.
uint16_t GetStartingSequence(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the starting sequence number.
Mac48Address GetUnassociatedStaAddress(std::size_t index) const
For Multi-STA Block Acks, get the RA subfield of the Per AID TID Info subfield (with AID11 subfield e...
uint8_t GetTidInfo(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the TID_INFO subfield of the BA Control fi...
bool IsBasic() const
Check if the current BA policy is Basic Block Ack.
const std::vector< uint8_t > & GetBitmap(std::size_t index=0) const
Return a const reference to the bitmap from the BlockAck response header.
bool m_baAckPolicy
The LSB bit of the BA control field is used only for the HT (High Throughput) delayed block ack confi...
Definition: ctrl-headers.h:529
bool IsCompressed() const
Check if the current BA policy is Compressed Block Ack.
void SetUnassociatedStaAddress(const Mac48Address &ra, std::size_t index)
For Multi-STA Block Acks, set the RA subfield of the Per AID TID Info subfield (with AID11 subfield e...
bool MustSendHtImmediateAck() const
Check if the current Ack Policy is immediate.
Buffer::Iterator DeserializeBitmap(Buffer::Iterator start, std::size_t index=0)
Deserialize bitmap from the given buffer.
void ResetBitmap(std::size_t index=0)
Reset the bitmap to 0.
void SetAckType(bool type, std::size_t index)
For Multi-STA Block Acks, set the Ack Type subfield of the Per AID TID Info subfield identified by th...
void SetTidInfo(uint8_t tid, std::size_t index=0)
For Block Ack variants other than Multi-STA Block Ack, set the TID_INFO subfield of the BA Control fi...
uint16_t m_tidInfo
TID info (reserved if Multi-STA Block Ack)
Definition: ctrl-headers.h:531
void Print(std::ostream &os) const override
void SetType(BlockAckType type)
Set the block ack type.
uint32_t GetSerializedSize() const override
uint16_t GetBaControl() const
Return the Block Ack control.
BlockAckType GetType() const
Return the block ack type ID.
void SetReceivedFragment(uint16_t seq, uint8_t frag)
Set the bitmap that the packet with the given sequence number and fragment number was received.
static TypeId GetTypeId()
Get the type ID.
void SetReceivedPacket(uint16_t seq, std::size_t index=0)
Record in the bitmap that the packet with the given sequence number was received.
bool IsMultiTid() const
Check if the current BA policy is Multi-TID Block Ack.
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
std::vector< BaInfoInstance > m_baInfo
BA Information field.
Definition: ctrl-headers.h:552
void SetAid11(uint16_t aid, std::size_t index)
For Multi-STA Block Acks, set the AID11 subfield of the Per AID TID Info subfield identified by the g...
bool GetAckType(std::size_t index) const
For Multi-STA Block Acks, get the Ack Type subfield of the Per AID TID Info subfield identified by th...
uint16_t GetAid11(std::size_t index) const
For Multi-STA Block Acks, get the AID11 subfield of the Per AID TID Info subfield identified by the g...
bool IsMultiSta() const
Check if the BlockAck frame variant is Multi-STA Block Ack.
bool IsInBitmap(uint16_t seq, std::size_t index=0) const
Check if sequence number seq can be acknowledged in the bitmap.
uint16_t IndexInBitmap(uint16_t seq, std::size_t index=0) const
This function is used to correctly index in both bitmap and compressed bitmap, one bit or one block o...
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
Headers for Trigger frames.
Definition: ctrl-headers.h:945
CtrlTriggerUserInfoField & AddUserInfoField()
Append a new User Info field to this Trigger frame and return a non-const reference to it.
uint32_t GetSerializedSize() const override
bool IsBasic() const
Check if this is a Basic Trigger frame.
ConstIterator FindUserInfoWithRaRuAssociated() const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
void Print(std::ostream &os) const override
bool IsNfrp() const
Check if this is a NDP Feedback Report Poll Trigger frame.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
ConstIterator end() const
Get a const iterator indicating past-the-last User Info field in the list.
uint16_t GetUlSpatialReuse() const
Get the UL Spatial Reuse subfield of the Common Info field.
uint8_t m_giAndLtfType
GI And LTF Type subfield.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
bool IsMuRts() const
Check if this is a MU-RTS Trigger frame.
TriggerFrameType m_triggerType
Trigger type.
uint16_t GetGuardInterval() const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
bool IsBsrp() const
Check if this is a Buffer Status Report Poll Trigger frame.
TriggerFrameType GetType() const
Get the Trigger Frame type.
bool IsMuBar() const
Check if this is a MU-BAR Trigger frame.
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
ConstIterator FindUserInfoWithRaRuUnassociated() const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
bool IsBfrp() const
Check if this is a Beamforming Report Poll Trigger frame.
ConstIterator begin() const
Get a const iterator pointing to the first User Info field in the list.
std::size_t GetNUserInfoFields() const
Get the number of User Info fields in this Trigger Frame.
uint8_t GetLtfType() const
Get the LTF type of the solicited HE TB PPDU.
bool GetMoreTF() const
Get the More TF subfield of the Common Info field.
std::list< CtrlTriggerUserInfoField >::const_iterator ConstIterator
User Info fields list const iterator.
bool IsBqrp() const
Check if this is a Bandwidth Query Report Poll Trigger frame.
static TypeId GetTypeId()
Get the type ID.
bool IsValid() const
Check the validity of this Trigger frame.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
ConstIterator FindUserInfoWithAid(ConstIterator start, uint16_t aid12) const
Get a const iterator pointing to the first User Info field found (starting from the one pointed to by...
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
const char * GetTypeString() const
Return a string corresponding to the Trigger Frame type.
uint16_t GetUlLength() const
Get the UL Length subfield of the Common Info field.
uint16_t GetUlBandwidth() const
Get the bandwidth of the solicited HE TB PPDU.
TriggerFrameVariant m_variant
Common Info field.
uint16_t m_ulLength
Value for the L-SIG Length field.
bool m_csRequired
Carrier Sense required.
TriggerFrameVariant GetVariant() const
Get the Common Info field variant.
CtrlTriggerHeader GetCommonInfoField() const
Get a copy of the Common Info field of this Trigger frame.
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
std::list< CtrlTriggerUserInfoField > m_userInfoFields
List of User Info fields.
bool m_moreTF
True if a subsequent Trigger frame follows.
void SetVariant(TriggerFrameVariant variant)
Set the Common Info field variant.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
uint8_t m_ulBandwidth
UL BW subfield.
bool GetCsRequired() const
Get the CS Required subfield of the Common Info field.
bool IsGcrMuBar() const
Check if this is a Groupcast with Retries (GCR) MU-BAR Trigger frame.
std::list< CtrlTriggerUserInfoField >::iterator Iterator
User Info fields list iterator.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void Serialize(Buffer::Iterator start) const override
int8_t GetApTxPower() const
Get the power value (dBm) indicated by the AP TX Power subfield of the Common Info field.
uint8_t m_apTxPower
Tx Power used by AP to transmit the Trigger Frame.
CtrlTriggerHeader & operator=(const CtrlTriggerHeader &trigger)
Copy assignment operator.
uint16_t m_ulSpatialReuse
Value for the Spatial Reuse field in HE-SIG-A.
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
User Info field of Trigger frames.
Definition: ctrl-headers.h:590
bool GetUlFecCodingType() const
Get the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
bool GetUlDcm() const
Get the UL DCM subfield, which indicates whether or not DCM is used This method can only be used with...
AcIndex GetPreferredAc() const
Get the Preferred AC subfield.
uint8_t GetMpduMuSpacingFactor() const
Get the MPDU MU spacing factor.
int8_t GetUlTargetRssi() const
Get the expected receive signal power for the solicited HE TB PPDU.
uint8_t startingSs
Starting spatial stream.
Definition: ctrl-headers.h:902
TriggerFrameType m_triggerType
Trigger frame type.
Definition: ctrl-headers.h:914
uint8_t GetUlMcs() const
Get the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
WifiPreamble GetPreambleType() const
uint32_t GetSerializedSize() const
Get the expected size of this User Info field.
void SetMuRtsRuAllocation(uint8_t value)
Set the RU Allocation subfield based on the given value for the B7-B1 bits.
CtrlTriggerUserInfoField(TriggerFrameType triggerType, TriggerFrameVariant variant)
Constructor.
void Print(std::ostream &os) const
Print the content of this User Info field.
uint8_t nRaRu
Number of Random Access RUs.
Definition: ctrl-headers.h:908
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
union ns3::CtrlTriggerUserInfoField::@72 m_bits26To31
Fields occupying bits 26-31 in the User Info field.
bool m_ps160
identifies the location of the RU (EHT variant only)
Definition: ctrl-headers.h:897
const CtrlBAckRequestHeader & GetMuBarTriggerDepUserInfo() const
Get the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
bool HasRaRuForUnassociatedSta() const
Check if this User Info field allocates a Random Access RU for stations not associated with the AP th...
void SetUlTargetRssiMaxTxPower()
Set the UL Target RSSI subfield to indicate to the station to transmit an HE TB PPDU response at its ...
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
uint16_t m_aid12
Association ID of the addressed station.
Definition: ctrl-headers.h:892
uint8_t nSs
Number of spatial streams.
Definition: ctrl-headers.h:903
uint8_t m_basicTriggerDependentUserInfo
Basic Trigger variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:915
TriggerFrameVariant m_variant
User Info field variant.
Definition: ctrl-headers.h:890
uint8_t GetTidAggregationLimit() const
Get the TID Aggregation Limit.
uint8_t m_ulMcs
MCS to be used by the addressed station.
Definition: ctrl-headers.h:895
TriggerFrameType GetType() const
Get the type of the Trigger Frame this User Info field belongs to.
uint8_t m_ruAllocation
RU Allocation.
Definition: ctrl-headers.h:893
HeRu::RuSpec GetRuAllocation() const
Get the RU specified by the RU Allocation subfield.
uint8_t GetNss() const
Get the number of spatial streams.
bool HasRaRuForAssociatedSta() const
Check if this User Info field allocates a Random Access RU for stations associated with the AP that t...
uint8_t GetMuRtsRuAllocation() const
This method can only be called on MU-RTS Trigger Frames.
uint16_t GetAid12() const
Get the value of the AID12 subfield.
Buffer::Iterator Serialize(Buffer::Iterator start) const
Serialize the User Info field to the given buffer.
uint8_t GetNRaRus() const
Get the number of contiguous RUs for Random Access.
bool m_ulDcm
whether or not to use Dual Carrier Modulation (HE variant only)
Definition: ctrl-headers.h:896
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
uint8_t GetStartingSs() const
Get the starting spatial stream.
CtrlTriggerUserInfoField & operator=(const CtrlTriggerUserInfoField &userInfo)
Copy assignment operator.
uint8_t m_ulTargetRssi
Expected receive signal power.
Definition: ctrl-headers.h:913
void SetRaRuInformation(uint8_t nRaRu, bool moreRaRu)
Set the RA-RU Information subfield, which is present when the AID12 subfield is 0 or 2045.
Buffer::Iterator Deserialize(Buffer::Iterator start)
Deserialize the User Info field from the given buffer.
bool IsUlTargetRssiMaxTxPower() const
Return true if the UL Target RSSI subfield indicates to the station to transmit an HE TB PPDU respons...
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
void SetBasicTriggerDepUserInfo(uint8_t spacingFactor, uint8_t tidLimit, AcIndex prefAc)
Set the Trigger Dependent User Info subfield for Basic Trigger frames.
bool moreRaRu
More RA-RU in subsequent Trigger frames.
Definition: ctrl-headers.h:909
bool m_ulFecCodingType
UL FEC Coding Type.
Definition: ctrl-headers.h:894
CtrlBAckRequestHeader m_muBarTriggerDependentUserInfo
MU-BAR variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:918
bool GetMoreRaRu() const
Return true if more RA-RUs are allocated in subsequent Trigger frames that are sent before the end of...
RU Specification.
Definition: he-ru.h:66
std::size_t GetIndex() const
Get the RU index.
Definition: he-ru.cc:442
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:435
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition: he-ru.cc:449
static bool DoesOverlap(uint16_t bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
Definition: he-ru.cc:607
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
@ RU_26_TONE
Definition: he-ru.h:42
@ RU_484_TONE
Definition: he-ru.h:46
@ RU_996_TONE
Definition: he-ru.h:47
@ RU_106_TONE
Definition: he-ru.h:44
@ RU_52_TONE
Definition: he-ru.h:43
@ RU_242_TONE
Definition: he-ru.h:45
@ RU_2x996_TONE
Definition: he-ru.h:48
Protocol header serialization and deserialization.
Definition: header.h:44
virtual uint32_t Deserialize(Buffer::Iterator start)=0
Deserialize the object from a buffer iterator.
an EUI-48 address
Definition: mac48-address.h:46
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint16_t GetGuardInterval() const
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
uint16_t GetLength() const
Get the LENGTH field of the L-SIG.
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
uint16_t GetChannelWidth() const
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#define FOO(x)
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
TriggerFrameVariant
The different variants for Common Info field and User Info field of Trigger Frames.
Definition: ctrl-headers.h:576
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:72
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:560
@ WIFI_PREAMBLE_LONG
@ WIFI_PREAMBLE_EHT_TB
@ WIFI_PREAMBLE_HE_TB
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:133
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.
value
Definition: second.py:41
The different BlockAckRequest variants.
Variant m_variant
Block Ack Request variant.
The different BlockAck variants.
Variant m_variant
Block Ack variant.
std::vector< uint8_t > m_bitmapLen
Length (bytes) of included bitmaps.