A Discrete-Event Network Simulator
API
ctrl-headers.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 MIRKO BANCHI
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mirko Banchi <mk.banchi@gmail.com>
19  */
20 
21 #include "ctrl-headers.h"
22 #include "wifi-tx-vector.h"
23 #include "ns3/he-phy.h"
24 #include "wifi-utils.h"
25 #include "ns3/address-utils.h"
26 #include <algorithm>
27 
28 namespace ns3 {
29 
30 
31 /***********************************
32  * Block ack request
33  ***********************************/
34 
35 NS_OBJECT_ENSURE_REGISTERED (CtrlBAckRequestHeader);
36 
38  : m_barAckPolicy (false),
39  m_barType (BlockAckReqType::BASIC)
40 {
41 }
42 
44 {
45 }
46 
47 TypeId
49 {
50  static TypeId tid = TypeId ("ns3::CtrlBAckRequestHeader")
51  .SetParent<Header> ()
52  .SetGroupName ("Wifi")
53  .AddConstructor<CtrlBAckRequestHeader> ()
54  ;
55  return tid;
56 }
57 
58 TypeId
60 {
61  return GetTypeId ();
62 }
63 
64 void
65 CtrlBAckRequestHeader::Print (std::ostream &os) const
66 {
67  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=" << std::hex << m_startingSeq << std::dec;
68 }
69 
70 uint32_t
72 {
73  uint32_t size = 0;
74  size += 2; //Bar control
75  switch (m_barType.m_variant)
76  {
80  size += 2;
81  break;
83  size += (2 + 2) * (m_tidInfo + 1);
84  break;
85  default:
86  NS_FATAL_ERROR ("Invalid BA type");
87  break;
88  }
89  return size;
90 }
91 
92 void
94 {
97  switch (m_barType.m_variant)
98  {
103  break;
105  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
106  break;
107  default:
108  NS_FATAL_ERROR ("Invalid BA type");
109  break;
110  }
111 }
112 
113 uint32_t
115 {
118  switch (m_barType.m_variant)
119  {
124  break;
126  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
127  break;
128  default:
129  NS_FATAL_ERROR ("Invalid BA type");
130  break;
131  }
132  return i.GetDistanceFrom (start);
133 }
134 
135 uint16_t
137 {
138  uint16_t res = 0;
139  switch (m_barType.m_variant)
140  {
142  break;
144  res |= (0x02 << 1);
145  break;
147  res |= (0x01 << 1);
148  break;
150  res |= (0x03 << 1);
151  break;
152  default:
153  NS_FATAL_ERROR ("Invalid BA type");
154  break;
155  }
156  res |= (m_tidInfo << 12) & (0xf << 12);
157  return res;
158 }
159 
160 void
162 {
163  m_barAckPolicy = ((bar & 0x01) == 1) ? true : false;
164  if (((bar >> 1) & 0x0f) == 0x03)
165  {
167  }
168  else if (((bar >> 1) & 0x0f) == 0x01)
169  {
171  }
172  else if (((bar >> 1) & 0x0f) == 0x02)
173  {
175  }
176  else
177  {
179  }
180  m_tidInfo = (bar >> 12) & 0x0f;
181 }
182 
183 uint16_t
185 {
186  return (m_startingSeq << 4) & 0xfff0;
187 }
188 
189 void
191 {
192  m_startingSeq = (seqControl >> 4) & 0x0fff;
193 }
194 
195 void
197 {
198  m_barAckPolicy = immediateAck;
199 }
200 
201 void
203 {
204  m_barType = type;
205 }
206 
209 {
210  return m_barType;
211 }
212 
213 void
215 {
216  m_tidInfo = static_cast<uint16_t> (tid);
217 }
218 
219 void
221 {
222  m_startingSeq = seq;
223 }
224 
225 bool
227 {
228  return m_barAckPolicy;
229 }
230 
231 uint8_t
233 {
234  uint8_t tid = static_cast<uint8_t> (m_tidInfo);
235  return tid;
236 }
237 
238 uint16_t
240 {
241  return m_startingSeq;
242 }
243 
244 bool
246 {
247  return (m_barType.m_variant == BlockAckReqType::BASIC) ? true : false;
248 }
249 
250 bool
252 {
253  return (m_barType.m_variant == BlockAckReqType::COMPRESSED) ? true : false;
254 }
255 
256 bool
258 {
259  return (m_barType.m_variant == BlockAckReqType::EXTENDED_COMPRESSED) ? true : false;
260 }
261 
262 bool
264 {
265  return (m_barType.m_variant == BlockAckReqType::MULTI_TID) ? true : false;
266 }
267 
268 
269 /***********************************
270  * Block ack response
271  ***********************************/
272 
274 
276  : m_baAckPolicy (false),
277  m_tidInfo (0)
278 {
280 }
281 
283 {
284 }
285 
286 TypeId
288 {
289  static TypeId tid = TypeId ("ns3::CtrlBAckResponseHeader")
290  .SetParent<Header> ()
291  .SetGroupName ("Wifi")
292  .AddConstructor<CtrlBAckResponseHeader> ()
293  ;
294  return tid;
295 }
296 
297 TypeId
299 {
300  return GetTypeId ();
301 }
302 
303 void
304 CtrlBAckResponseHeader::Print (std::ostream &os) const
305 {
307  {
308  os << "TID_INFO=" << m_tidInfo << ", StartingSeq=0x" << std::hex << m_baInfo[0].m_startingSeq << std::dec;
309  }
310  else
311  {
312  for (std::size_t i = 0; i < m_baInfo.size (); i++)
313  {
314  os << "{AID=" << GetAid11 (i)
315  << ", TID=" << GetTidInfo (i)
316  << ", StartingSeq=0x" << std::hex << m_baInfo[i].m_startingSeq << std::dec << "}";
317  }
318  }
319 }
320 
321 uint32_t
323 {
324  // This method only makes use of the configured BA type, so that functions like
325  // GetBlockAckSize () can easily return the size of a Block Ack of a given type
326  uint32_t size = 0;
327  size += 2; //BA control
328  switch (m_baType.m_variant)
329  {
330  case BlockAckType::BASIC:
333  size += (2 + m_baType.m_bitmapLen[0]);
334  break;
336  size += (2 + 2 + 8) * (m_tidInfo + 1); //Multi-TID block ack
337  break;
339  for (auto& bitmapLen : m_baType.m_bitmapLen)
340  {
341  size += 2 /* AID TID Info */ + (bitmapLen > 0 ? 2 : 0) /* BA SSC */ + bitmapLen;
342  }
343  break;
344  default:
345  NS_FATAL_ERROR ("Invalid BA type");
346  break;
347  }
348  return size;
349 }
350 
351 void
353 {
356  switch (m_baType.m_variant)
357  {
358  case BlockAckType::BASIC:
362  i = SerializeBitmap (i);
363  break;
365  for (std::size_t index = 0; index < m_baInfo.size (); index++)
366  {
367  i.WriteHtolsbU16 (m_baInfo[index].m_aidTidInfo);
368  if (GetAid11 (index) != 2045)
369  {
370  if (m_baInfo[index].m_bitmap.size () > 0)
371  {
373  i = SerializeBitmap (i, index);
374  }
375  }
376  else
377  {
378  uint32_t reserved = 0;
379  i.WriteHtolsbU32 (reserved);
380  WriteTo (i, m_baInfo[index].m_ra);
381  }
382  }
383  break;
385  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
386  break;
387  default:
388  NS_FATAL_ERROR ("Invalid BA type");
389  break;
390  }
391 }
392 
393 uint32_t
395 {
398  switch (m_baType.m_variant)
399  {
400  case BlockAckType::BASIC:
404  i = DeserializeBitmap (i);
405  break;
407  {
408  std::size_t index = 0;
409  while (i.GetRemainingSize () > 0)
410  {
411  m_baInfo.push_back (BaInfoInstance ());
412  m_baType.m_bitmapLen.push_back (0); // updated by next call to SetStartingSequenceControl
413 
414  m_baInfo.back ().m_aidTidInfo = i.ReadLsbtohU16 ();
415 
416  if (GetAid11 (index) != 2045)
417  {
418  // the Block Ack Starting Sequence Control and Block Ack Bitmap subfields
419  // are only present in Block acknowledgement context, i.e., if the Ack Type
420  // subfield is set to 0 and the TID subfield is set to a value from 0 to 7.
421  if (!GetAckType (index) && GetTidInfo (index) < 8)
422  {
423  SetStartingSequenceControl (i.ReadLsbtohU16 (), index);
424  i = DeserializeBitmap (i, index);
425  }
426  }
427  else
428  {
429  i.ReadLsbtohU32 (); // next 4 bytes are reserved
430  ReadFrom (i, m_baInfo.back ().m_ra);
431  // the length of this Per AID TID Info subfield is 12, so set
432  // the bitmap length to 8 to simulate the correct size
433  m_baType.m_bitmapLen.back () = 8;
434  }
435  index++;
436  }
437  }
438  break;
440  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
441  break;
442  default:
443  NS_FATAL_ERROR ("Invalid BA type");
444  break;
445  }
446  return i.GetDistanceFrom (start);
447 }
448 
449 void
451 {
452  m_baAckPolicy = immediateAck;
453 }
454 
455 void
457 {
458  m_baType = type;
459  m_baInfo.clear ();
460 
461  for (auto& bitmapLen : m_baType.m_bitmapLen)
462  {
463  m_baInfo.push_back ({.m_aidTidInfo = 0,
464  .m_startingSeq = 0,
465  .m_bitmap = std::vector<uint8_t> (bitmapLen, 0),
466  .m_ra = Mac48Address ()});
467  }
468 }
469 
472 {
473  return m_baType;
474 }
475 
476 void
477 CtrlBAckResponseHeader::SetTidInfo (uint8_t tid, std::size_t index)
478 {
480  "index can only be non null for Multi-STA Block Ack");
481  NS_ASSERT (index < m_baInfo.size ());
482 
484  {
485  m_tidInfo = static_cast<uint16_t> (tid);
486  }
487  else
488  {
489  m_baInfo[index].m_aidTidInfo |= ((static_cast<uint16_t> (tid) & 0x000f) << 12);
490  }
491 }
492 
493 void
494 CtrlBAckResponseHeader::SetStartingSequence (uint16_t seq, std::size_t index)
495 {
497  "index can only be non null for Multi-STA Block Ack");
498  NS_ASSERT (index < m_baInfo.size ());
499 
500  m_baInfo[index].m_startingSeq = seq;
501 }
502 
503 bool
505 {
506  return (m_baAckPolicy) ? true : false;
507 }
508 
509 uint8_t
510 CtrlBAckResponseHeader::GetTidInfo (std::size_t index) const
511 {
513  "index can only be non null for Multi-STA Block Ack");
514  NS_ASSERT (index < m_baInfo.size ());
515 
516  uint8_t tid = 0;
517 
519  {
520  tid = static_cast<uint8_t> (m_tidInfo);
521  }
522  else
523  {
524  tid = static_cast<uint8_t> ((m_baInfo[index].m_aidTidInfo >> 12) & 0x000f);
525  }
526  return tid;
527 }
528 
529 uint16_t
531 {
533  "index can only be non null for Multi-STA Block Ack");
534  NS_ASSERT (index < m_baInfo.size ());
535 
536  return m_baInfo[index].m_startingSeq;
537 }
538 
539 bool
541 {
542  return (m_baType.m_variant == BlockAckType::BASIC) ? true : false;
543 }
544 
545 bool
547 {
548  return (m_baType.m_variant == BlockAckType::COMPRESSED) ? true : false;
549 }
550 
551 bool
553 {
554  return (m_baType.m_variant == BlockAckType::EXTENDED_COMPRESSED) ? true : false;
555 }
556 
557 bool
559 {
560  return (m_baType.m_variant == BlockAckType::MULTI_TID) ? true : false;
561 }
562 
563 bool
565 {
566  return (m_baType.m_variant == BlockAckType::MULTI_STA) ? true : false;
567 }
568 
569 void
570 CtrlBAckResponseHeader::SetAid11 (uint16_t aid, std::size_t index)
571 {
573 
574  m_baInfo[index].m_aidTidInfo |= (aid & 0x07ff);
575 }
576 
577 uint16_t
578 CtrlBAckResponseHeader::GetAid11 (std::size_t index) const
579 {
581 
582  return m_baInfo[index].m_aidTidInfo & 0x07ff;
583 }
584 
585 void
586 CtrlBAckResponseHeader::SetAckType (bool type, std::size_t index)
587 {
589 
590  if (type)
591  {
592  m_baInfo[index].m_aidTidInfo |= (1 << 11);
593  }
594 }
595 
596 bool
597 CtrlBAckResponseHeader::GetAckType (std::size_t index) const
598 {
600 
601  return ((m_baInfo[index].m_aidTidInfo >> 11) & 0x0001) != 0;
602 }
603 
604 void
606 {
607  NS_ASSERT (GetAid11 (index) == 2045);
608 
609  m_baInfo[index].m_ra = ra;
610 }
611 
614 {
615  NS_ASSERT (GetAid11 (index) == 2045);
616 
617  return m_baInfo[index].m_ra;
618 }
619 
620 std::size_t
622 {
624  return m_baInfo.size ();
625 }
626 
627 std::vector<uint32_t>
629 {
631 
632  std::vector<uint32_t> ret;
633  ret.reserve (m_baInfo.size ());
634  for (uint32_t i = 0; i < m_baInfo.size (); i++)
635  {
636  if (GetAid11 (i) == aid)
637  {
638  ret.push_back (i);
639  }
640  }
641  return ret;
642 }
643 
644 uint16_t
646 {
647  uint16_t res = 0;
648  if (m_baAckPolicy)
649  {
650  res |= 0x1;
651  }
652  switch (m_baType.m_variant)
653  {
654  case BlockAckType::BASIC:
655  break;
657  res |= (0x02 << 1);
658  break;
660  res |= (0x01 << 1);
661  break;
663  res |= (0x03 << 1);
664  break;
666  res |= (0x0b << 1);
667  break;
668  default:
669  NS_FATAL_ERROR ("Invalid BA type");
670  break;
671  }
673  {
674  res |= (m_tidInfo << 12) & (0xf << 12);
675  }
676  return res;
677 }
678 
679 void
681 {
682  m_baAckPolicy = ((ba & 0x01) == 1) ? true : false;
683  if (((ba >> 1) & 0x0f) == 0x03)
684  {
686  }
687  else if (((ba >> 1) & 0x0f) == 0x01)
688  {
690  }
691  else if (((ba >> 1) & 0x0f) == 0x02)
692  {
694  }
695  else if (((ba >> 1) & 0x0f) == 0)
696  {
698  }
699  else if (((ba >> 1) & 0x0f) == 0x0b)
700  {
702  }
703  else
704  {
705  NS_FATAL_ERROR ("Invalid BA type");
706  }
708  {
709  m_tidInfo = (ba >> 12) & 0x0f;
710  }
711 }
712 
713 uint16_t
715 {
717  "index can only be non null for Multi-STA Block Ack");
718  NS_ASSERT (index < m_baInfo.size ());
719 
720  uint16_t ret = (m_baInfo[index].m_startingSeq << 4) & 0xfff0;
721 
722  // The Fragment Number subfield encodes the length of the bitmap for
723  // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
724  // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
726  {
727  if (m_baType.m_bitmapLen[0] == 32)
728  {
729  ret |= 0x0004;
730  }
731  }
733  {
734  NS_ASSERT (m_baInfo.size () == m_baType.m_bitmapLen.size ());
735  NS_ASSERT_MSG (m_baInfo[index].m_bitmap.size () > 0,
736  "This Per AID TID Info subfield has no Starting Sequence Control subfield");
737 
738  if (m_baType.m_bitmapLen[index] == 16)
739  {
740  ret |= 0x0002;
741  }
742  else if (m_baType.m_bitmapLen[index] == 32)
743  {
744  ret |= 0x0004;
745  }
746  else if (m_baType.m_bitmapLen[index] == 4)
747  {
748  ret |= 0x0006;
749  }
750  }
751  return ret;
752 }
753 
754 void
755 CtrlBAckResponseHeader::SetStartingSequenceControl (uint16_t seqControl, std::size_t index)
756 {
758  "index can only be non null for Multi-STA Block Ack");
759  NS_ASSERT (index < m_baInfo.size ());
760 
761  // The Fragment Number subfield encodes the length of the bitmap for
762  // Compressed and Multi-STA variants (see sections 9.3.1.9.3 and 9.3.1.9.7
763  // of 802.11ax Draft 3.0). Note that Fragmentation Level 3 is not supported.
765  {
766  if ((seqControl & 0x0001) == 1)
767  {
768  NS_FATAL_ERROR ("Fragmentation Level 3 unsupported");
769  }
770  if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 0)
771  {
773  }
774  else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
775  {
777  }
778  else
779  {
780  NS_FATAL_ERROR ("Reserved configurations");
781  }
782  }
784  {
785  if ((seqControl & 0x0001) == 1)
786  {
787  NS_FATAL_ERROR ("Fragmentation Level 3 unsupported");
788  }
789  uint8_t bitmapLen = 0;
790  if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 0)
791  {
792  bitmapLen = 8;
793  }
794  else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 1)
795  {
796  bitmapLen = 16;
797  }
798  else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
799  {
800  bitmapLen = 32;
801  }
802  else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 3)
803  {
804  bitmapLen = 4;
805  }
806  else
807  {
808  NS_FATAL_ERROR ("Reserved configurations");
809  }
810  m_baType.m_bitmapLen[index] = bitmapLen;
811  m_baInfo[index].m_bitmap.assign (bitmapLen, 0);
812  }
813 
814  m_baInfo[index].m_startingSeq = (seqControl >> 4) & 0x0fff;
815 }
816 
819 {
821  "index can only be non null for Multi-STA Block Ack");
822  NS_ASSERT (index < m_baInfo.size ());
823 
825  switch (m_baType.m_variant)
826  {
827  case BlockAckType::BASIC:
831  for (const auto& byte : m_baInfo[index].m_bitmap)
832  {
833  i.WriteU8 (byte);
834  }
835  break;
837  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
838  break;
839  default:
840  NS_FATAL_ERROR ("Invalid BA type");
841  break;
842  }
843  return i;
844 }
845 
848 {
850  "index can only be non null for Multi-STA Block Ack");
851  NS_ASSERT (index < m_baInfo.size ());
852 
854  switch (m_baType.m_variant)
855  {
856  case BlockAckType::BASIC:
860  for (uint8_t j = 0; j < m_baType.m_bitmapLen[index]; j++)
861  {
862  m_baInfo[index].m_bitmap[j] = i.ReadU8 ();
863  }
864  break;
866  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
867  break;
868  default:
869  NS_FATAL_ERROR ("Invalid BA type");
870  break;
871  }
872  return i;
873 }
874 
875 void
876 CtrlBAckResponseHeader::SetReceivedPacket (uint16_t seq, std::size_t index)
877 {
879  "index can only be non null for Multi-STA Block Ack");
880  NS_ASSERT (index < m_baInfo.size ());
881 
882  if (!IsInBitmap (seq, index))
883  {
884  return;
885  }
886  switch (m_baType.m_variant)
887  {
888  case BlockAckType::BASIC:
889  /* To set correctly basic block ack bitmap we need fragment number too.
890  So if it's not specified, we consider packet not fragmented. */
891  m_baInfo[index].m_bitmap[IndexInBitmap (seq) * 2] |= 0x01;
892  break;
896  {
897  uint16_t i = IndexInBitmap (seq, index);
898  m_baInfo[index].m_bitmap[i / 8] |= (uint8_t (0x01) << (i % 8));
899  break;
900  }
902  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
903  break;
904  default:
905  NS_FATAL_ERROR ("Invalid BA type");
906  break;
907  }
908 }
909 
910 void
912 {
913  NS_ASSERT (frag < 16);
914  if (!IsInBitmap (seq))
915  {
916  return;
917  }
918  switch (m_baType.m_variant)
919  {
920  case BlockAckType::BASIC:
921  m_baInfo[0].m_bitmap[IndexInBitmap (seq) * 2 + frag / 8] |= (0x01 << (frag % 8));
922  break;
926  /* We can ignore this...compressed block ack doesn't support
927  acknowledgment of single fragments */
928  break;
930  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
931  break;
932  default:
933  NS_FATAL_ERROR ("Invalid BA type");
934  break;
935  }
936 }
937 
938 bool
939 CtrlBAckResponseHeader::IsPacketReceived (uint16_t seq, std::size_t index) const
940 {
942  "index can only be non null for Multi-STA Block Ack");
943  NS_ASSERT (index < m_baInfo.size ());
944 
946  && GetAckType (index) && GetTidInfo (index) == 14)
947  {
948  // All-ack context
949  return true;
950  }
951  if (!IsInBitmap (seq, index))
952  {
953  return false;
954  }
955  switch (m_baType.m_variant)
956  {
957  case BlockAckType::BASIC:
958  /*It's impossible to say if an entire packet was correctly received. */
959  return false;
963  {
964  uint16_t i = IndexInBitmap (seq, index);
965  uint8_t mask = uint8_t (0x01) << (i % 8);
966  return ((m_baInfo[index].m_bitmap[i / 8] & mask) != 0) ? true : false;
967  }
969  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
970  break;
971  default:
972  NS_FATAL_ERROR ("Invalid BA type");
973  break;
974  }
975  return false;
976 }
977 
978 bool
979 CtrlBAckResponseHeader::IsFragmentReceived (uint16_t seq, uint8_t frag) const
980 {
981  NS_ASSERT (frag < 16);
982  if (!IsInBitmap (seq))
983  {
984  return false;
985  }
986  switch (m_baType.m_variant)
987  {
988  case BlockAckType::BASIC:
989  return ((m_baInfo[0].m_bitmap[IndexInBitmap (seq) * 2 + frag / 8] & (0x01 << (frag % 8))) != 0) ? true : false;
993  /* We can ignore this...compressed block ack doesn't support
994  acknowledgement of single fragments */
995  return false;
997  {
998  NS_FATAL_ERROR ("Multi-tid block ack is not supported.");
999  break;
1000  }
1001  default:
1002  {
1003  NS_FATAL_ERROR ("Invalid BA type");
1004  break;
1005  }
1006  }
1007  return false;
1008 }
1009 
1010 uint16_t
1011 CtrlBAckResponseHeader::IndexInBitmap (uint16_t seq, std::size_t index) const
1012 {
1013  uint16_t i;
1014  if (seq >= m_baInfo[index].m_startingSeq)
1015  {
1016  i = seq - m_baInfo[index].m_startingSeq;
1017  }
1018  else
1019  {
1020  i = SEQNO_SPACE_SIZE - m_baInfo[index].m_startingSeq + seq;
1021  }
1022 
1023  uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1024 
1026  {
1027  nAckedMpdus = nAckedMpdus / 16;
1028  }
1029 
1030  NS_ASSERT (i < nAckedMpdus);
1031  return i;
1032 }
1033 
1034 bool
1035 CtrlBAckResponseHeader::IsInBitmap (uint16_t seq, std::size_t index) const
1036 {
1038  "index can only be non null for Multi-STA Block Ack");
1039  NS_ASSERT (index < m_baType.m_bitmapLen.size ());
1040 
1041  uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1042 
1044  {
1045  nAckedMpdus = nAckedMpdus / 16;
1046  }
1047 
1048  return (seq - m_baInfo[index].m_startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE < nAckedMpdus;
1049 }
1050 
1051 const std::vector<uint8_t>&
1052 CtrlBAckResponseHeader::GetBitmap (std::size_t index) const
1053 {
1055  "index can only be non null for Multi-STA Block Ack");
1056  NS_ASSERT (index < m_baInfo.size ());
1057 
1058  return m_baInfo[index].m_bitmap;
1059 }
1060 
1061 void
1063 {
1065  "index can only be non null for Multi-STA Block Ack");
1066  NS_ASSERT (index < m_baInfo.size ());
1067 
1068  m_baInfo[index].m_bitmap.assign (m_baType.m_bitmapLen[index], 0);
1069 }
1070 
1071 
1072 /***********************************
1073  * Trigger frame - User Info field
1074  ***********************************/
1075 
1077  : m_aid12 (0),
1078  m_ruAllocation (0),
1079  m_ulFecCodingType (false),
1080  m_ulMcs (0),
1081  m_ulDcm (false),
1082  m_ulTargetRssi (0),
1083  m_triggerType (triggerType),
1084  m_basicTriggerDependentUserInfo (0)
1085 {
1086  memset (&m_bits26To31, 0, sizeof (m_bits26To31));
1087 }
1088 
1090 {
1091 }
1092 
1095 {
1096  NS_ABORT_MSG_IF (m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1097 
1098  // check for self-assignment
1099  if (&userInfo == this)
1100  {
1101  return *this;
1102  }
1103 
1104  m_aid12 = userInfo.m_aid12;
1105  m_ruAllocation = userInfo.m_ruAllocation;
1107  m_ulMcs = userInfo.m_ulMcs;
1108  m_ulDcm = userInfo.m_ulDcm;
1109  m_bits26To31 = userInfo.m_bits26To31;
1110  m_ulTargetRssi = userInfo.m_ulTargetRssi;
1113  return *this;
1114 }
1115 
1116 void
1117 CtrlTriggerUserInfoField::Print (std::ostream &os) const
1118 {
1119  os << ", USER_INFO AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation << ", MCS=" << +m_ulMcs;
1120 }
1121 
1122 uint32_t
1124 {
1125  uint32_t size = 0;
1126  size += 5; // User Info (excluding Trigger Dependent User Info)
1127 
1128  switch (m_triggerType)
1129  {
1130  case BASIC_TRIGGER:
1131  case BFRP_TRIGGER:
1132  size += 1;
1133  break;
1134  case MU_BAR_TRIGGER:
1135  size += m_muBarTriggerDependentUserInfo.GetSerializedSize (); // BAR Control and BAR Information
1136  break;
1137  // The Trigger Dependent User Info subfield is not present in the other variants
1138  }
1139 
1140  return size;
1141 }
1142 
1145 {
1146  NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1147  NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1148  NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1149 
1150  Buffer::Iterator i = start;
1151 
1152  uint32_t userInfo = 0; // User Info except the MSB
1153  userInfo |= (m_aid12 & 0x0fff);
1154  userInfo |= (m_ruAllocation << 12);
1155  userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1156  userInfo |= (m_ulMcs & 0x0f) << 21;
1157  userInfo |= (m_ulDcm ? 1 << 25 : 0);
1158 
1159  if (m_aid12 != 0 && m_aid12 != 2045)
1160  {
1161  userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1162  userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1163  }
1164  else
1165  {
1166  userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1167  userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1168  }
1169 
1170  i.WriteHtolsbU32 (userInfo);
1171  // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and the
1172  // Reserved bit. Given how m_ulTargetRssi is set, writing m_ulTargetRssi
1173  // leads to setting the Reserved bit to zero
1174  i.WriteU8 (m_ulTargetRssi);
1175 
1177  {
1179  }
1180  else if (m_triggerType == MU_BAR_TRIGGER)
1181  {
1184  }
1185 
1186  return i;
1187 }
1188 
1191 {
1192  NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1193  NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1194  NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1195 
1196  Buffer::Iterator i = start;
1197 
1198  uint32_t userInfo = i.ReadLsbtohU32 ();
1199 
1200  m_aid12 = userInfo & 0x0fff;
1201  NS_ABORT_MSG_IF (m_aid12 == 4095, "Cannot deserialize a Padding field");
1202  m_ruAllocation = (userInfo >> 12) & 0xff;
1203  m_ulFecCodingType = (userInfo >> 20) & 0x01;
1204  m_ulMcs = (userInfo >> 21) & 0x0f;
1205  m_ulDcm = (userInfo >> 25) & 0x01;
1206 
1207  if (m_aid12 != 0 && m_aid12 != 2045)
1208  {
1209  m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1210  m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1211  }
1212  else
1213  {
1214  m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1215  m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1216  }
1217 
1218  m_ulTargetRssi = i.ReadU8 () & 0x7f; // B39 is reserved
1219 
1221  {
1223  }
1224  else if (m_triggerType == MU_BAR_TRIGGER)
1225  {
1226  uint32_t len = m_muBarTriggerDependentUserInfo.Deserialize (i);
1227  i.Next (len);
1228  }
1229 
1230  return i;
1231 }
1232 
1235 {
1236  return static_cast<TriggerFrameType> (m_triggerType);
1237 }
1238 
1239 void
1241 {
1242  m_aid12 = aid & 0x0fff;
1243 }
1244 
1245 uint16_t
1247 {
1248  return m_aid12;
1249 }
1250 
1251 bool
1253 {
1254  return (m_aid12 == 0);
1255 }
1256 
1257 bool
1259 {
1260  return (m_aid12 == 2045);
1261 }
1262 
1263 void
1265 {
1266  NS_ABORT_MSG_IF (ru.GetIndex () == 0, "Valid indices start at 1");
1267 
1268  switch (ru.GetRuType ())
1269  {
1270  case HeRu::RU_26_TONE:
1271  m_ruAllocation = ru.GetIndex () - 1;
1272  break;
1273  case HeRu::RU_52_TONE:
1274  m_ruAllocation = ru.GetIndex () + 36;
1275  break;
1276  case HeRu::RU_106_TONE:
1277  m_ruAllocation = ru.GetIndex () + 52;
1278  break;
1279  case HeRu::RU_242_TONE:
1280  m_ruAllocation = ru.GetIndex () + 60;
1281  break;
1282  case HeRu::RU_484_TONE:
1283  m_ruAllocation = ru.GetIndex () + 64;
1284  break;
1285  case HeRu::RU_996_TONE:
1286  m_ruAllocation = 67;
1287  break;
1288  case HeRu::RU_2x996_TONE:
1289  m_ruAllocation = 68;
1290  break;
1291  default:
1292  NS_FATAL_ERROR ("RU type unknown.");
1293  break;
1294  }
1295 
1296  NS_ABORT_MSG_IF (m_ruAllocation > 68, "Reserved value.");
1297 
1298  m_ruAllocation <<= 1;
1299  if (!ru.GetPrimary80MHz ())
1300  {
1301  m_ruAllocation++;
1302  }
1303 }
1304 
1307 {
1308  HeRu::RuType ruType;
1309  std::size_t index;
1310 
1311  bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1312 
1313  uint8_t val = m_ruAllocation >> 1;
1314 
1315  if (val < 37)
1316  {
1317  ruType = HeRu::RU_26_TONE;
1318  index = val + 1;
1319  }
1320  else if (val < 53)
1321  {
1322  ruType = HeRu::RU_52_TONE;
1323  index = val - 36;
1324  }
1325  else if (val < 61)
1326  {
1327  ruType = HeRu::RU_106_TONE;
1328  index = val - 52;
1329  }
1330  else if (val < 65)
1331  {
1332  ruType = HeRu::RU_242_TONE;
1333  index = val - 60;
1334  }
1335  else if (val < 67)
1336  {
1337  ruType = HeRu::RU_484_TONE;
1338  index = val - 64;
1339  }
1340  else if (val == 67)
1341  {
1342  ruType = HeRu::RU_996_TONE;
1343  index = 1;
1344  }
1345  else if (val == 68)
1346  {
1347  ruType = HeRu::RU_2x996_TONE;
1348  index = 1;
1349  }
1350  else
1351  {
1352  NS_FATAL_ERROR ("Reserved value.");
1353  }
1354 
1355  return HeRu::RuSpec (ruType, index, primary80MHz);
1356 }
1357 
1358 void
1360 {
1361  m_ulFecCodingType = ldpc;
1362 }
1363 
1364 bool
1366 {
1367  return m_ulFecCodingType;
1368 }
1369 
1370 void
1372 {
1373  NS_ABORT_MSG_IF (mcs > 11, "Invalid MCS index");
1374  m_ulMcs = mcs;
1375 }
1376 
1377 uint8_t
1379 {
1380  return m_ulMcs;
1381 }
1382 
1383 void
1385 {
1386  m_ulDcm = dcm;
1387 }
1388 
1389 bool
1391 {
1392  return m_ulDcm;
1393 }
1394 
1395 void
1396 CtrlTriggerUserInfoField::SetSsAllocation (uint8_t startingSs, uint8_t nSs)
1397 {
1398  NS_ABORT_MSG_IF (m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1399  NS_ABORT_MSG_IF (!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1400  NS_ABORT_MSG_IF (!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1401 
1402  m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1403  m_bits26To31.ssAllocation.nSs = nSs - 1;
1404 }
1405 
1406 uint8_t
1408 {
1409  if (m_aid12 == 0 || m_aid12 == 2045)
1410  {
1411  return 1;
1412  }
1413  return m_bits26To31.ssAllocation.startingSs + 1;
1414 }
1415 
1416 uint8_t
1418 {
1419  if (m_aid12 == 0 || m_aid12 == 2045)
1420  {
1421  return 1;
1422  }
1423  return m_bits26To31.ssAllocation.nSs + 1;
1424 }
1425 
1426 void
1427 CtrlTriggerUserInfoField::SetRaRuInformation (uint8_t nRaRu, bool moreRaRu)
1428 {
1429  NS_ABORT_MSG_IF (m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1430  NS_ABORT_MSG_IF (!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1431 
1432  m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1433  m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1434 }
1435 
1436 uint8_t
1438 {
1439  NS_ABORT_MSG_IF (m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1440 
1441  return m_bits26To31.raRuInformation.nRaRu + 1;
1442 }
1443 
1444 bool
1446 {
1447  NS_ABORT_MSG_IF (m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1448 
1449  return m_bits26To31.raRuInformation.moreRaRu;
1450 }
1451 
1452 void
1454 {
1455  m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1456 }
1457 
1458 void
1460 {
1461  NS_ABORT_MSG_IF (dBm < -110 || dBm > -20, "Invalid values for signal power");
1462 
1463  m_ulTargetRssi = static_cast<uint8_t> (110 + dBm);
1464 }
1465 
1466 bool
1468 {
1469  return (m_ulTargetRssi == 127);
1470 }
1471 
1472 int8_t
1474 {
1475  NS_ABORT_MSG_IF (m_ulTargetRssi == 127, "STA must use its max TX power");
1476 
1477  return static_cast<int8_t> (m_ulTargetRssi) - 110;
1478 }
1479 
1480 void
1481 CtrlTriggerUserInfoField::SetBasicTriggerDepUserInfo (uint8_t spacingFactor, uint8_t tidLimit, AcIndex prefAc)
1482 {
1483  NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1484 
1485  m_basicTriggerDependentUserInfo = (spacingFactor & 0x03)
1486  | (tidLimit & 0x07) << 2
1487  // B5 is reserved
1488  | (prefAc & 0x03) << 6;
1489 }
1490 
1491 uint8_t
1493 {
1494  NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1495 
1496  return m_basicTriggerDependentUserInfo & 0x03;
1497 }
1498 
1499 uint8_t
1501 {
1502  NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1503 
1504  return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1505 }
1506 
1507 AcIndex
1509 {
1510  NS_ABORT_MSG_IF (m_triggerType != BASIC_TRIGGER, "Not a Basic Trigger Frame");
1511 
1512  return AcIndex ((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1513 }
1514 
1515 void
1517 {
1518  NS_ABORT_MSG_IF (m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1521  "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1523 }
1524 
1525 const CtrlBAckRequestHeader&
1527 {
1528  NS_ABORT_MSG_IF (m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1529 
1531 }
1532 
1533 /***********************************
1534  * Trigger frame
1535  ***********************************/
1536 
1538 
1540  : m_triggerType (0),
1541  m_ulLength (0),
1542  m_moreTF (false),
1543  m_csRequired (false),
1544  m_ulBandwidth (0),
1545  m_giAndLtfType (0),
1546  m_apTxPower (0),
1547  m_ulSpatialReuse (0)
1548 {
1549 }
1550 
1552  : CtrlTriggerHeader ()
1553 {
1554  m_triggerType = type;
1555  SetUlBandwidth (txVector.GetChannelWidth ());
1556  SetUlLength (txVector.GetLength ());
1557  uint16_t gi = txVector.GetGuardInterval ();
1558  if (gi == 800 || gi == 1600)
1559  {
1560  m_giAndLtfType = 1;
1561  }
1562  else
1563  {
1564  m_giAndLtfType = 2;
1565  }
1566  for (auto& userInfo : txVector.GetHeMuUserInfoMap ())
1567  {
1569  ui.SetAid12 (userInfo.first);
1570  ui.SetRuAllocation (userInfo.second.ru);
1571  ui.SetUlMcs (userInfo.second.mcs.GetMcsValue ());
1572  ui.SetSsAllocation (1, userInfo.second.nss); // MU-MIMO is not supported
1573  }
1574 }
1575 
1577 {
1578 }
1579 
1582 {
1583  // check for self-assignment
1584  if (&trigger == this)
1585  {
1586  return *this;
1587  }
1588 
1589  m_triggerType = trigger.m_triggerType;
1590  m_ulLength = trigger.m_ulLength;
1591  m_moreTF = trigger.m_moreTF;
1592  m_csRequired = trigger.m_csRequired;
1593  m_ulBandwidth = trigger.m_ulBandwidth;
1594  m_giAndLtfType = trigger.m_giAndLtfType;
1595  m_apTxPower = trigger.m_apTxPower;
1597  m_userInfoFields.clear ();
1599  return *this;
1600 }
1601 
1602 TypeId
1604 {
1605  static TypeId tid = TypeId ("ns3::CtrlTriggerHeader")
1606  .SetParent<Header> ()
1607  .SetGroupName ("Wifi")
1608  .AddConstructor<CtrlTriggerHeader> ()
1609  ;
1610  return tid;
1611 }
1612 
1613 TypeId
1615 {
1616  return GetTypeId ();
1617 }
1618 
1619 void
1620 CtrlTriggerHeader::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 
1631 uint32_t
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 
1653 void
1655 {
1656  NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1657  NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1658  NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1659 
1660  Buffer::Iterator i = start;
1661 
1662  uint64_t commonInfo = 0;
1663  commonInfo |= (m_triggerType & 0x0f);
1664  commonInfo |= (m_ulLength & 0x0fff) << 4;
1665  commonInfo |= (m_moreTF ? 1 << 16 : 0);
1666  commonInfo |= (m_csRequired ? 1 << 17 : 0);
1667  commonInfo |= (m_ulBandwidth & 0x03) << 18;
1668  commonInfo |= (m_giAndLtfType & 0x03) << 20;
1669  commonInfo |= static_cast<uint64_t> (m_apTxPower & 0x3f) << 28;
1670  commonInfo |= static_cast<uint64_t> (m_ulSpatialReuse) << 37;
1671 
1672  i.WriteHtolsbU64 (commonInfo);
1673 
1674  for (auto& ui : m_userInfoFields)
1675  {
1676  i = ui.Serialize (i);
1677  }
1678 
1679  i.WriteHtolsbU16 (0xffff); // Padding field, used as delimiter
1680 }
1681 
1682 uint32_t
1684 {
1685  Buffer::Iterator i = start;
1686 
1687  uint64_t commonInfo = i.ReadLsbtohU64 ();
1688 
1689  m_triggerType = (commonInfo & 0x0f);
1690  m_ulLength = (commonInfo >> 4) & 0x0fff;
1691  m_moreTF = (commonInfo >> 16) & 0x01;
1692  m_csRequired = (commonInfo >> 17) & 0x01;
1693  m_ulBandwidth = (commonInfo >> 18) & 0x03;
1694  m_giAndLtfType = (commonInfo >> 20) & 0x03;
1695  m_apTxPower = (commonInfo >> 28) & 0x3f;
1696  m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1697  m_userInfoFields.clear ();
1698 
1699  NS_ABORT_MSG_IF (m_triggerType == BFRP_TRIGGER, "BFRP Trigger frame is not supported");
1700  NS_ABORT_MSG_IF (m_triggerType == GCR_MU_BAR_TRIGGER, "GCR-MU-BAR Trigger frame is not supported");
1701  NS_ABORT_MSG_IF (m_triggerType == NFRP_TRIGGER, "NFRP Trigger frame is not supported");
1702 
1703  bool isPadding = false;
1704 
1705  // We always add a Padding field (of two octets of all 1s) as delimiter
1706  while (!isPadding)
1707  {
1708  // read the first 2 bytes to check if we encountered the Padding field
1709  if (i.ReadU16 () == 0xffff)
1710  {
1711  isPadding = true;
1712  }
1713  else
1714  {
1715  // go back 2 bytes to deserialize the User Info field from the beginning
1716  i.Prev (2);
1718  i = ui.Deserialize (i);
1719  }
1720  }
1721 
1722  return i.GetDistanceFrom (start);
1723 }
1724 
1725 void
1727 {
1728  m_triggerType = type;
1729 }
1730 
1733 {
1734  return static_cast<TriggerFrameType> (m_triggerType);
1735 }
1736 
1737 const char *
1739 {
1740  return GetTypeString (GetType ());
1741 }
1742 
1743 const char *
1745 {
1746 #define FOO(x) \
1747 case x: \
1748  return # x; \
1749  break;
1750 
1751  switch (type)
1752  {
1753  FOO (BASIC_TRIGGER);
1754  FOO (BFRP_TRIGGER);
1755  FOO (MU_BAR_TRIGGER);
1756  FOO (MU_RTS_TRIGGER);
1757  FOO (BSRP_TRIGGER);
1759  FOO (BQRP_TRIGGER);
1760  FOO (NFRP_TRIGGER);
1761  default:
1762  return "ERROR";
1763  }
1764 #undef FOO
1765 }
1766 
1767 bool
1769 {
1770  return (m_triggerType == BASIC_TRIGGER);
1771 }
1772 
1773 bool
1775 {
1776  return (m_triggerType == BFRP_TRIGGER);
1777 }
1778 
1779 bool
1781 {
1782  return (m_triggerType == MU_BAR_TRIGGER);
1783 }
1784 
1785 bool
1787 {
1788  return (m_triggerType == MU_RTS_TRIGGER);
1789 }
1790 
1791 bool
1793 {
1794  return (m_triggerType == BSRP_TRIGGER);
1795 }
1796 
1797 bool
1799 {
1800  return (m_triggerType == GCR_MU_BAR_TRIGGER);
1801 }
1802 
1803 bool
1805 {
1806  return (m_triggerType == BQRP_TRIGGER);
1807 }
1808 
1809 bool
1811 {
1812  return (m_triggerType == NFRP_TRIGGER);
1813 }
1814 
1815 void
1817 {
1818  m_ulLength = (len & 0x0fff);
1819 }
1820 
1821 uint16_t
1823 {
1824  return m_ulLength;
1825 }
1826 
1829 {
1830  auto userInfoIt = FindUserInfoWithAid (staId);
1831  NS_ASSERT (userInfoIt != end ());
1832 
1833  WifiTxVector v;
1837  v.SetLength (GetUlLength ());
1838  v.SetHeMuUserInfo (staId, {userInfoIt->GetRuAllocation (),
1839  HePhy::GetHeMcs (userInfoIt->GetUlMcs ()),
1840  userInfoIt->GetNss ()});
1841  return v;
1842 }
1843 
1844 void
1846 {
1847  m_moreTF = more;
1848 }
1849 
1850 bool
1852 {
1853  return m_moreTF;
1854 }
1855 
1856 void
1858 {
1859  m_csRequired = cs;
1860 }
1861 
1862 bool
1864 {
1865  return m_csRequired;
1866 }
1867 
1868 void
1870 {
1871  switch (bw)
1872  {
1873  case 20:
1874  m_ulBandwidth = 0;
1875  break;
1876  case 40:
1877  m_ulBandwidth = 1;
1878  break;
1879  case 80:
1880  m_ulBandwidth = 2;
1881  break;
1882  case 160:
1883  m_ulBandwidth = 3;
1884  break;
1885  default:
1886  NS_FATAL_ERROR ("Bandwidth value not allowed.");
1887  break;
1888  }
1889 }
1890 
1891 uint16_t
1893 {
1894  return (1 << m_ulBandwidth) * 20;
1895 }
1896 
1897 void
1898 CtrlTriggerHeader::SetGiAndLtfType (uint16_t guardInterval, uint8_t ltfType)
1899 {
1900  if (ltfType == 1 && guardInterval == 1600)
1901  {
1902  m_giAndLtfType = 0;
1903  }
1904  else if (ltfType == 2 && guardInterval == 1600)
1905  {
1906  m_giAndLtfType = 1;
1907  }
1908  else if (ltfType == 4 && guardInterval == 3200)
1909  {
1910  m_giAndLtfType = 2;
1911  }
1912  else
1913  {
1914  NS_FATAL_ERROR ("Invalid combination of GI and LTF type");
1915  }
1916 }
1917 
1918 uint16_t
1920 {
1921  if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
1922  {
1923  return 1600;
1924  }
1925  else if (m_giAndLtfType == 2)
1926  {
1927  return 3200;
1928  }
1929  else
1930  {
1931  NS_FATAL_ERROR ("Invalid value for GI And LTF Type subfield");
1932  }
1933 }
1934 
1935 uint8_t
1937 {
1938  if (m_giAndLtfType == 0)
1939  {
1940  return 1;
1941  }
1942  else if (m_giAndLtfType == 1)
1943  {
1944  return 2;
1945  }
1946  else if (m_giAndLtfType == 2)
1947  {
1948  return 4;
1949  }
1950  else
1951  {
1952  NS_FATAL_ERROR ("Invalid value for GI And LTF Type subfield");
1953  }
1954 }
1955 
1956 void
1958 {
1959  // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
1960  NS_ABORT_MSG_IF (power < -20 || power > 40, "Out of range power values");
1961 
1962  m_apTxPower = static_cast<uint8_t> (power + 20);
1963 }
1964 
1965 int8_t
1967 {
1968  // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
1969  return static_cast<int8_t> (m_apTxPower) - 20;
1970 }
1971 
1972 void
1974 {
1975  m_ulSpatialReuse = sr;
1976 }
1977 
1978 uint16_t
1980 {
1981  return m_ulSpatialReuse;
1982 }
1983 
1986 {
1987  // make a copy of this Trigger Frame and remove the User Info fields from the copy
1988  CtrlTriggerHeader trigger (*this);
1989  trigger.m_userInfoFields.clear ();
1990  return trigger;
1991 }
1992 
1995 {
1996  m_userInfoFields.emplace_back (m_triggerType);
1997  return m_userInfoFields.back ();
1998 }
1999 
2002 {
2003  NS_ABORT_MSG_IF (userInfo.GetType () != m_triggerType,
2004  "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2005  m_userInfoFields.push_back (userInfo);
2006  return m_userInfoFields.back ();
2007 }
2008 
2011 {
2012  return m_userInfoFields.begin ();
2013 }
2014 
2017 {
2018  return m_userInfoFields.end ();
2019 }
2020 
2023 {
2024  return m_userInfoFields.begin ();
2025 }
2026 
2029 {
2030  return m_userInfoFields.end ();
2031 }
2032 
2033 std::size_t
2035 {
2036  return m_userInfoFields.size ();
2037 }
2038 
2041 {
2042  // the lambda function returns true if a User Info field has the AID12 subfield
2043  // equal to the given aid12 value
2044  return std::find_if (start, end (), [aid12] (const CtrlTriggerUserInfoField& ui) -> bool
2045  { return (ui.GetAid12 () == aid12); });
2046 }
2047 
2050 {
2051  return FindUserInfoWithAid (m_userInfoFields.begin (), aid12);
2052 }
2053 
2056 {
2057  return FindUserInfoWithAid (start, 0);
2058 }
2059 
2062 {
2063  return FindUserInfoWithAid (0);
2064 }
2065 
2068 {
2069  return FindUserInfoWithAid (start, 2045);
2070 }
2071 
2074 {
2075  return FindUserInfoWithAid (2045);
2076 }
2077 
2078 bool
2080 {
2081  // check that allocated RUs do not overlap
2082  // TODO This is not a problem in case of UL MU-MIMO
2083  std::vector<HeRu::RuSpec> prevRus;
2084 
2085  for (auto& ui : m_userInfoFields)
2086  {
2087  if (HeRu::DoesOverlap (GetUlBandwidth (), ui.GetRuAllocation (), prevRus))
2088  {
2089  return false;
2090  }
2091  prevRus.push_back (ui.GetRuAllocation ());
2092  }
2093  return true;
2094 }
2095 
2096 } //namespace ns3
uint16_t ReadU16(void)
Definition: buffer.h:1029
Protocol header serialization and deserialization.
Definition: header.h:42
CtrlTriggerUserInfoField(uint8_t triggerType)
Constructor.
ConstIterator FindUserInfoWithRaRuUnassociated(void) const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
uint8_t m_ulBandwidth
UL BW subfield.
bool GetCsRequired(void) const
Get the CS Required subfield of the Common Info field.
#define FOO(x)
bool IsUlTargetRssiMaxTxPower(void) const
Return true if the UL Target RSSI subfield indicates to the station to transmit an HE TB PPDU respons...
const std::vector< uint8_t > & GetBitmap(std::size_t index=0) const
Return a const reference to the bitmap from the BlockAck response header.
TypeId GetInstanceTypeId(void) const override
Get the most derived TypeId for this Object.
Definition: ctrl-headers.cc:59
RU Specification.
Definition: he-ru.h:67
void SetType(TriggerFrameType type)
Set the Trigger frame type.
uint8_t nRaRu
Number of Random Access RUs.
Definition: ctrl-headers.h:851
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...
const char * GetTypeString(void) const
Return a string corresponding to the Trigger Frame type.
enum Variant m_variant
Block Ack Request variant.
uint16_t GetBaControl(void) const
Return the Block Ack control.
Headers for Trigger frames.
Definition: ctrl-headers.h:885
uint8_t m_ulTargetRssi
Expected receive signal power.
Definition: ctrl-headers.h:855
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetMoreTF(bool more)
Set the More TF subfield of the Common Info field.
uint8_t m_ulMcs
MCS to be used by the addressed station.
Definition: ctrl-headers.h:840
uint8_t GetNRaRus(void) const
Get the number of contiguous RUs for Random Access.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
uint8_t m_triggerType
Common Info field.
uint16_t m_aid12
Association ID of the addressed station.
Definition: ctrl-headers.h:837
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:70
bool IsInBitmap(uint16_t seq, std::size_t index=0) const
Check if sequence number seq can be acknowledged in the bitmap.
uint32_t GetSerializedSize(void) const override
Definition: ctrl-headers.cc:71
CtrlBAckRequestHeader m_muBarTriggerDependentUserInfo
MU-BAR variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:858
bool IsMuRts(void) const
Check if this is a MU-RTS Trigger frame.
uint8_t startingSs
Starting spatial stream.
Definition: ctrl-headers.h:846
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.
def start()
Definition: core.py:1855
uint32_t GetSerializedSize(void) const
void SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
Set the GI And LTF Type subfield of the Common Info field.
uint8_t GetUlMcs(void) const
Get the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
bool GetUlFecCodingType(void) const
Get the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used. ...
uint8_t m_apTxPower
Tx Power used by AP to transmit the Trigger Frame.
void Print(std::ostream &os) const
Print the content of this User Info field.
void SetReceivedPacket(uint16_t seq, std::size_t index=0)
Record in the bitmap that the packet with the given sequence number was received. ...
void SetBarControl(uint16_t bar)
Set the Block Ack control.
bool HasRaRuForUnassociatedSta(void) const
Check if this User Info field allocates a Random Access RU for stations not associated with the AP th...
uint16_t GetAid12(void) const
Get the value of the AID12 subfield.
bool IsValid(void) const
Check the validity of this Trigger frame.
std::list< CtrlTriggerUserInfoField > m_userInfoFields
List of User Info fields.
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...
uint32_t GetSerializedSize(void) const
Get the expected size of this User Info field.
void SetRaRuInformation(uint8_t nRaRu, bool moreRaRu)
Set the RA-RU Information subfield, which is present when the AID12 subfield is 0 or 2045...
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
std::vector< BaInfoInstance > m_baInfo
BA Information field.
Definition: ctrl-headers.h:552
uint32_t Deserialize(Buffer::Iterator start) override
uint16_t GetGuardInterval(void) const
uint8_t m_basicTriggerDependentUserInfo
Basic Trigger variant of Trigger Dependent User Info subfield.
Definition: ctrl-headers.h:857
std::list< CtrlTriggerUserInfoField >::const_iterator ConstIterator
User Info fields list const iterator.
std::size_t GetNPerAidTidInfoSubfields(void) const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack...
bool IsGcrMuBar(void) const
Check if this is a Groupcast with Retries (GCR) MU-BAR Trigger frame.
bool GetPrimary80MHz(void) const
Get the primary 80 MHz flag.
Definition: he-ru.cc:181
bool GetMoreTF(void) const
Get the More TF subfield of the Common Info field.
void SetCsRequired(bool cs)
Set the CS Required subfield of the Common Info field.
The different BlockAckRequest variants.
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...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used. ...
bool m_baAckPolicy
The LSB bit of the BA control field is used only for the HT (High Throughput) delayed block ack confi...
Definition: ctrl-headers.h:529
void Serialize(Buffer::Iterator start) const
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...
static WifiMode GetHeMcs(uint8_t index)
Return the HE MCS corresponding to the provided index.
Definition: he-phy.cc:957
bool IsExtendedCompressed(void) const
Check if the current BA policy is Extended Compressed Block Ack.
uint8_t m_triggerType
Trigger frame type.
Definition: ctrl-headers.h:856
static bool DoesOverlap(uint16_t bw, RuSpec ru, const std::vector< RuSpec > &v)
Check whether the given RU overlaps with the given set of RUs.
Definition: he-ru.cc:352
uint16_t GetStartingSequenceControl(std::size_t index=0) const
Return the value of the Starting Sequence Control subfield.
CtrlTriggerUserInfoField & operator=(const CtrlTriggerUserInfoField &userInfo)
Copy assignment operator.
enum Variant m_variant
Block Ack variant.
uint8_t GetStartingSs(void) const
Get the starting spatial stream.
bool IsBasic(void) const
Check if the current BA policy is Basic Block Ack.
iterator in a Buffer instance
Definition: buffer.h:98
uint8_t GetTidInfo(void) const
Return the Traffic ID (TID).
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames, which includes a BAR Control subfield and a BAR Information subfield.
void SetBasicTriggerDepUserInfo(uint8_t spacingFactor, uint8_t tidLimit, AcIndex prefAc)
Set the Trigger Dependent User Info subfield for Basic Trigger frames.
uint32_t GetDistanceFrom(Iterator const &o) const
Definition: buffer.cc:783
uint32_t GetSerializedSize(void) const
static TypeId GetTypeId(void)
Get the type ID.
bool m_csRequired
Carrier Sense required.
TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
bool IsCompressed(void) const
Check if the current BA policy is Compressed Block Ack.
bool MustSendHtImmediateAck(void) const
Check if the current Ack Policy is immediate.
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:560
bool GetMoreRaRu(void) const
Return true if more RA-RUs are allocated in subsequent Trigger frames that are sent before the end of...
uint8_t GetMpduMuSpacingFactor(void) const
Get the MPDU MU spacing factor.
void SetUlTargetRssiMaxTxPower(void)
Set the UL Target RSSI subfield to indicate to the station to transmit an HE TB PPDU response at its ...
uint16_t GetGuardInterval(void) const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
void Prev(void)
go backward by one byte
Definition: buffer.h:851
bool m_ulDcm
whether or not to use Dual Carrier Modulation
Definition: ctrl-headers.h:841
bool m_moreTF
True if a subsequent Trigger frame follows.
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetType(BlockAckReqType type)
Set the BlockAckRequest type.
bool m_barAckPolicy
The LSB bit of the BAR control field is used only for the HT (High Throughput) delayed block ack conf...
Definition: ctrl-headers.h:182
uint16_t GetStartingSequence(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the starting sequence number.
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...
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 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...
uint16_t m_startingSeq
starting seq
Definition: ctrl-headers.h:185
uint8_t GetLtfType(void) const
Get the LTF type of the solicited HE TB PPDU.
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 ...
void Print(std::ostream &os) const
void Next(void)
go forward by one byte
Definition: buffer.h:845
bool HasRaRuForAssociatedSta(void) const
Check if this User Info field allocates a Random Access RU for stations associated with the AP that t...
CtrlTriggerHeader & operator=(const CtrlTriggerHeader &trigger)
Copy assignment operator.
BlockAckReqType m_barType
BAR type.
Definition: ctrl-headers.h:183
const CtrlBAckRequestHeader & GetMuBarTriggerDepUserInfo(void) const
Get the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames, which includes a BAR Control subfield and a BAR Information subfield.
bool IsMultiSta(void) const
Check if the BlockAck frame variant is Multi-STA Block Ack.
Headers for BlockAck response.
Definition: ctrl-headers.h:201
static TypeId GetTypeId(void)
Get the type ID.
Definition: ctrl-headers.cc:48
uint32_t Deserialize(Buffer::Iterator start)
uint16_t m_tidInfo
TID info (reserved if Multi-STA Block Ack)
Definition: ctrl-headers.h:531
bool IsCompressed(void) const
Check if the current Ack Policy is Compressed Block Ack and not multi-TID.
bool IsExtendedCompressed(void) const
Check if the current Ack Policy is Extended Compressed Block Ack.
Buffer::Iterator Deserialize(Buffer::Iterator start)
Deserialize the User Info field from the given buffer.
TriggerFrameType GetType(void) const
Get the Trigger Frame type.
BlockAckReqType GetType(void) const
Return the BlockAckRequest type.
void SetStartingSequenceControl(uint16_t seqControl, std::size_t index=0)
Set the Starting Sequence Control subfield with the given sequence control value. ...
void Print(std::ostream &os) const override
Definition: ctrl-headers.cc:65
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
uint16_t GetUlBandwidth(void) const
Get the bandwidth of the solicited HE TB PPDU.
void ResetBitmap(std::size_t index=0)
Reset the bitmap to 0.
bool IsNfrp(void) const
Check if this is a NDP Feedback Report Poll Trigger frame.
void SetTidInfo(uint8_t tid)
Set Traffic ID (TID).
ConstIterator begin(void) const
Get a const iterator pointing to the first User Info field in the list.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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...
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
bool moreRaRu
More RA-RU in subsequent Trigger frames.
Definition: ctrl-headers.h:852
static TypeId GetTypeId(void)
Get the type ID.
void SetType(BlockAckType type)
Set the block ack type.
RuType GetRuType(void) const
Get the RU type.
Definition: he-ru.cc:167
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...
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
bool IsMultiTid(void) const
Check if the current Ack Policy has Multi-TID Block Ack.
an EUI-48 address
Definition: mac48-address.h:43
bool IsBasic(void) const
Check if the current Ack Policy is Basic Block Ack (i.e.
uint16_t GetStartingSequence(void) const
Return the starting sequence number.
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
uint8_t m_ruAllocation
RU Allocation.
Definition: ctrl-headers.h:838
BlockAckType m_baType
BA type.
Definition: ctrl-headers.h:530
uint8_t nSs
Number of spatial streams.
Definition: ctrl-headers.h:847
The following structure can hold the BA Information field for the Basic and Compressed variants...
Definition: ctrl-headers.h:541
uint8_t GetTidAggregationLimit(void) const
Get the TID Aggregation Limit.
bool IsBqrp(void) const
Check if this is a Bandwidth Query Report Poll Trigger frame.
ConstIterator FindUserInfoWithRaRuAssociated(void) const
Get a const iterator pointing to the first User Info field found which allocates a Random Access RU f...
User Info field of Trigger frames.
Definition: ctrl-headers.h:581
uint8_t GetNss(void) const
Get the number of spatial streams.
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 WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:910
std::size_t GetNUserInfoFields(void) const
Get the number of User Info fields in this Trigger Frame.
void SetUlSpatialReuse(uint16_t sr)
Set the UL Spatial Reuse subfield of the Common Info field.
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
void SetReceivedFragment(uint16_t seq, uint8_t frag)
Set the bitmap that the packet with the given sequence number and fragment number was received...
TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
bool IsMuBar(void) const
Check if this is a MU-BAR Trigger frame.
bool IsBsrp(void) const
Check if this is a Buffer Status Report Poll Trigger frame.
std::vector< uint8_t > m_bitmapLen
Length (bytes) of included bitmaps.
TriggerFrameType GetType(void) const
Get the type of the Trigger Frame this User Info field belongs to.
void SetApTxPower(int8_t power)
Set the AP TX Power subfield of the Common Info field.
void SetRuAllocation(HeRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
void SetStartingSequenceControl(uint16_t seqControl)
Set the starting sequence control with the given sequence control value.
uint16_t GetLength(void) const
Get the LENGTH field of the L-SIG.
uint16_t GetBarControl(void) const
Return the Block Ack control.
The different BlockAck variants.
void WriteU8(uint8_t data)
Definition: buffer.h:869
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
void Serialize(Buffer::Iterator start) const override
Definition: ctrl-headers.cc:93
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...
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:926
bool GetUlDcm(void) const
Get the UL DCM subfield, which indicates whether or not DCM is used.
CtrlTriggerHeader GetCommonInfoField(void) const
Get a copy of the Common Info field of this Trigger frame.
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...
CtrlTriggerUserInfoField & AddUserInfoField(void)
Append a new User Info field to this Trigger frame and return a non-const reference to it...
uint32_t Deserialize(Buffer::Iterator start)
Buffer::Iterator SerializeBitmap(Buffer::Iterator start, std::size_t index=0) const
Serialize bitmap to the given buffer.
uint16_t m_tidInfo
TID info.
Definition: ctrl-headers.h:184
std::list< CtrlTriggerUserInfoField >::iterator Iterator
User Info fields list iterator.
bool IsMultiTid(void) const
Check if the current BA policy is Multi-TID Block Ack.
Buffer::Iterator DeserializeBitmap(Buffer::Iterator start, std::size_t index=0)
Deserialize bitmap from the given buffer.
void SetHtImmediateAck(bool immediateAck)
Enable or disable HT immediate Ack.
const uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:222
uint8_t ReadU8(void)
Definition: buffer.h:1021
void Print(std::ostream &os) const
Buffer::Iterator Serialize(Buffer::Iterator start) const
Serialize the User Info field to the given buffer.
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...
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...
BlockAckType GetType(void) const
Return the block ack type ID.
bool IsBfrp(void) const
Check if this is a Beamforming Report Poll Trigger frame.
uint8_t m_giAndLtfType
GI And LTF Type subfield.
uint16_t ReadLsbtohU16(void)
Definition: buffer.cc:1065
uint16_t GetUlSpatialReuse(void) const
Get the UL Spatial Reuse subfield of the Common Info field.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
uint16_t GetChannelWidth(void) const
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
int8_t GetApTxPower(void) const
Get the power value (dBm) indicated by the AP TX Power subfield of the Common Info field...
ConstIterator end(void) const
Get a const iterator indicating past-the-last User Info field in the list.
uint64_t ReadLsbtohU64(void)
Definition: buffer.cc:1093
uint16_t GetUlLength(void) const
Get the UL Length subfield of the Common Info field.
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...
Headers for BlockAckRequest.
Definition: ctrl-headers.h:48
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID...
std::size_t GetIndex(void) const
Get the RU index.
Definition: he-ru.cc:174
a unique identifier for an interface.
Definition: type-id.h:58
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
union ns3::CtrlTriggerUserInfoField::@72 m_bits26To31
Fields occupying bits 26-31 in the User Info field.
uint16_t GetStartingSequenceControl(void) const
Return the starting sequence control.
bool MustSendHtImmediateAck(void) const
Check if the current Ack Policy is immediate.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
HeRu::RuSpec GetRuAllocation(void) const
Get the RU specified by the RU Allocation subfield.
uint32_t ReadLsbtohU32(void)
Definition: buffer.cc:1076
bool IsBasic(void) const
Check if this is a Basic Trigger frame.
~CtrlTriggerUserInfoField()
Destructor.
uint16_t m_ulLength
Value for the L-SIG Length field.
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_ulSpatialReuse
Value for the Spatial Reuse field in HE-SIG-A.
AcIndex GetPreferredAc(void) const
Get the Preferred AC subfield.
bool m_ulFecCodingType
UL FEC Coding Type.
Definition: ctrl-headers.h:839
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetBaControl(uint16_t ba)
Set the Block Ack control.
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:917
void Serialize(Buffer::Iterator start) const
int8_t GetUlTargetRssi(void) const
Get the expected receive signal power for the solicited HE TB PPDU.