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  auto 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  BaInfoInstance baInfoInstance{.m_aidTidInfo = 0,
462  .m_startingSeq = 0,
463  .m_bitmap = std::vector<uint8_t>(bitmapLen, 0),
464  .m_ra = Mac48Address()};
465 
466  m_baInfo.emplace_back(baInfoInstance);
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;
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 {
543 }
544 
545 bool
547 {
549 }
550 
551 bool
553 {
555 }
556 
557 bool
559 {
561 }
562 
563 bool
565 {
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);
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 Compressed and Multi-STA
723  // variants (see sections 9.3.1.8.2 and 9.3.1.8.7 of 802.11ax-2021 and 802.11be Draft 4.0).
724  // Note that Fragmentation Level 3 is not supported.
726  {
727  switch (m_baType.m_bitmapLen[0])
728  {
729  case 8:
730  // do nothing
731  break;
732  case 32:
733  ret |= 0x0004;
734  break;
735  case 64:
736  ret |= 0x0008;
737  break;
738  case 128:
739  ret |= 0x000a;
740  break;
741  default:
742  NS_ABORT_MSG("Unsupported bitmap length: " << +m_baType.m_bitmapLen[0] << " bytes");
743  }
744  }
746  {
747  NS_ASSERT(m_baInfo.size() == m_baType.m_bitmapLen.size());
748  NS_ASSERT_MSG(!m_baInfo[index].m_bitmap.empty(),
749  "This Per AID TID Info subfield has no Starting Sequence Control subfield");
750 
751  switch (m_baType.m_bitmapLen[index])
752  {
753  case 8:
754  // do nothing
755  break;
756  case 16:
757  ret |= 0x0002;
758  break;
759  case 32:
760  ret |= 0x0004;
761  break;
762  case 4:
763  ret |= 0x0006;
764  break;
765  case 64:
766  ret |= 0x0008;
767  break;
768  case 128:
769  ret |= 0x000a;
770  break;
771  default:
772  NS_ABORT_MSG("Unsupported bitmap length: " << +m_baType.m_bitmapLen[index] << " bytes");
773  }
774  }
775  return ret;
776 }
777 
778 void
779 CtrlBAckResponseHeader::SetStartingSequenceControl(uint16_t seqControl, std::size_t index)
780 {
782  "index can only be non null for Multi-STA Block Ack");
783  NS_ASSERT(index < m_baInfo.size());
784 
785  // The Fragment Number subfield encodes the length of the bitmap for Compressed and Multi-STA
786  // variants (see sections 9.3.1.8.2 and 9.3.1.8.7 of 802.11ax-2021 and 802.11be Draft 4.0).
787  // Note that Fragmentation Level 3 is not supported.
789  {
790  uint16_t fragNumber = seqControl & 0x000f;
791 
792  if ((fragNumber & 0x0001) == 1)
793  {
794  NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
795  }
796  switch (fragNumber)
797  {
798  case 0:
800  break;
801  case 4:
803  break;
804  case 8:
806  break;
807  case 10:
809  break;
810  default:
811  NS_ABORT_MSG("Unsupported fragment number: " << fragNumber);
812  }
813  }
815  {
816  uint16_t fragNumber = seqControl & 0x000f;
817 
818  if ((fragNumber & 0x0001) == 1)
819  {
820  NS_FATAL_ERROR("Fragmentation Level 3 unsupported");
821  }
822  uint8_t bitmapLen = 0;
823  switch (fragNumber)
824  {
825  case 0:
826  bitmapLen = 8;
827  break;
828  case 2:
829  bitmapLen = 16;
830  break;
831  case 4:
832  bitmapLen = 32;
833  break;
834  case 6:
835  bitmapLen = 4;
836  break;
837  case 8:
838  bitmapLen = 64;
839  break;
840  case 10:
841  bitmapLen = 128;
842  break;
843  default:
844  NS_ABORT_MSG("Unsupported fragment number: " << fragNumber);
845  }
846  m_baType.m_bitmapLen[index] = bitmapLen;
847  m_baInfo[index].m_bitmap.assign(bitmapLen, 0);
848  }
849 
850  m_baInfo[index].m_startingSeq = (seqControl >> 4) & 0x0fff;
851 }
852 
855 {
857  "index can only be non null for Multi-STA Block Ack");
858  NS_ASSERT(index < m_baInfo.size());
859 
861  switch (m_baType.m_variant)
862  {
863  case BlockAckType::BASIC:
867  for (const auto& byte : m_baInfo[index].m_bitmap)
868  {
869  i.WriteU8(byte);
870  }
871  break;
873  NS_FATAL_ERROR("Multi-tid block ack is not supported.");
874  break;
875  default:
876  NS_FATAL_ERROR("Invalid BA type");
877  break;
878  }
879  return i;
880 }
881 
884 {
886  "index can only be non null for Multi-STA Block Ack");
887  NS_ASSERT(index < m_baInfo.size());
888 
890  switch (m_baType.m_variant)
891  {
892  case BlockAckType::BASIC:
896  for (uint8_t j = 0; j < m_baType.m_bitmapLen[index]; j++)
897  {
898  m_baInfo[index].m_bitmap[j] = i.ReadU8();
899  }
900  break;
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  return i;
909 }
910 
911 void
912 CtrlBAckResponseHeader::SetReceivedPacket(uint16_t seq, std::size_t index)
913 {
915  "index can only be non null for Multi-STA Block Ack");
916  NS_ASSERT(index < m_baInfo.size());
917 
918  if (!IsInBitmap(seq, index))
919  {
920  return;
921  }
922  switch (m_baType.m_variant)
923  {
924  case BlockAckType::BASIC:
925  /* To set correctly basic block ack bitmap we need fragment number too.
926  So if it's not specified, we consider packet not fragmented. */
927  m_baInfo[index].m_bitmap[IndexInBitmap(seq) * 2] |= 0x01;
928  break;
932  uint16_t i = IndexInBitmap(seq, index);
933  m_baInfo[index].m_bitmap[i / 8] |= (uint8_t(0x01) << (i % 8));
934  break;
935  }
937  NS_FATAL_ERROR("Multi-tid block ack is not supported.");
938  break;
939  default:
940  NS_FATAL_ERROR("Invalid BA type");
941  break;
942  }
943 }
944 
945 void
947 {
948  NS_ASSERT(frag < 16);
949  if (!IsInBitmap(seq))
950  {
951  return;
952  }
953  switch (m_baType.m_variant)
954  {
955  case BlockAckType::BASIC:
956  m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] |= (0x01 << (frag % 8));
957  break;
961  /* We can ignore this...compressed block ack doesn't support
962  acknowledgment of single fragments */
963  break;
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 }
972 
973 bool
974 CtrlBAckResponseHeader::IsPacketReceived(uint16_t seq, std::size_t index) const
975 {
977  "index can only be non null for Multi-STA Block Ack");
978  NS_ASSERT(index < m_baInfo.size());
979 
981  GetTidInfo(index) == 14)
982  {
983  // All-ack context
984  return true;
985  }
986  if (!IsInBitmap(seq, index))
987  {
988  return false;
989  }
990  switch (m_baType.m_variant)
991  {
992  case BlockAckType::BASIC:
993  /*It's impossible to say if an entire packet was correctly received. */
994  return false;
998  uint16_t i = IndexInBitmap(seq, index);
999  uint8_t mask = uint8_t(0x01) << (i % 8);
1000  return (m_baInfo[index].m_bitmap[i / 8] & mask) != 0;
1001  }
1003  NS_FATAL_ERROR("Multi-tid block ack is not supported.");
1004  break;
1005  default:
1006  NS_FATAL_ERROR("Invalid BA type");
1007  break;
1008  }
1009  return false;
1010 }
1011 
1012 bool
1013 CtrlBAckResponseHeader::IsFragmentReceived(uint16_t seq, uint8_t frag) const
1014 {
1015  NS_ASSERT(frag < 16);
1016  if (!IsInBitmap(seq))
1017  {
1018  return false;
1019  }
1020  switch (m_baType.m_variant)
1021  {
1022  case BlockAckType::BASIC:
1023  return (m_baInfo[0].m_bitmap[IndexInBitmap(seq) * 2 + frag / 8] & (0x01 << (frag % 8))) !=
1024  0;
1028  /* We can ignore this...compressed block ack doesn't support
1029  acknowledgement of single fragments */
1030  return false;
1031  case BlockAckType::MULTI_TID: {
1032  NS_FATAL_ERROR("Multi-tid block ack is not supported.");
1033  break;
1034  }
1035  default: {
1036  NS_FATAL_ERROR("Invalid BA type");
1037  break;
1038  }
1039  }
1040  return false;
1041 }
1042 
1043 uint16_t
1044 CtrlBAckResponseHeader::IndexInBitmap(uint16_t seq, std::size_t index) const
1045 {
1046  uint16_t i;
1047  if (seq >= m_baInfo[index].m_startingSeq)
1048  {
1049  i = seq - m_baInfo[index].m_startingSeq;
1050  }
1051  else
1052  {
1053  i = SEQNO_SPACE_SIZE - m_baInfo[index].m_startingSeq + seq;
1054  }
1055 
1056  uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1057 
1059  {
1060  nAckedMpdus = nAckedMpdus / 16;
1061  }
1062 
1063  NS_ASSERT(i < nAckedMpdus);
1064  return i;
1065 }
1066 
1067 bool
1068 CtrlBAckResponseHeader::IsInBitmap(uint16_t seq, std::size_t index) const
1069 {
1071  "index can only be non null for Multi-STA Block Ack");
1072  NS_ASSERT(index < m_baType.m_bitmapLen.size());
1073 
1074  uint16_t nAckedMpdus = m_baType.m_bitmapLen[index] * 8;
1075 
1077  {
1078  nAckedMpdus = nAckedMpdus / 16;
1079  }
1080 
1081  return (seq - m_baInfo[index].m_startingSeq + SEQNO_SPACE_SIZE) % SEQNO_SPACE_SIZE <
1082  nAckedMpdus;
1083 }
1084 
1085 const std::vector<uint8_t>&
1086 CtrlBAckResponseHeader::GetBitmap(std::size_t index) const
1087 {
1089  "index can only be non null for Multi-STA Block Ack");
1090  NS_ASSERT(index < m_baInfo.size());
1091 
1092  return m_baInfo[index].m_bitmap;
1093 }
1094 
1095 void
1097 {
1099  "index can only be non null for Multi-STA Block Ack");
1100  NS_ASSERT(index < m_baInfo.size());
1101 
1102  m_baInfo[index].m_bitmap.assign(m_baType.m_bitmapLen[index], 0);
1103 }
1104 
1105 /***********************************
1106  * Trigger frame - User Info field
1107  ***********************************/
1108 
1110  TriggerFrameVariant variant)
1111  : m_variant(variant),
1112  m_aid12(0),
1113  m_ruAllocation(0),
1114  m_ulFecCodingType(false),
1115  m_ulMcs(0),
1116  m_ulDcm(false),
1117  m_ps160(true),
1118  m_ulTargetRssi(0),
1119  m_triggerType(triggerType),
1120  m_basicTriggerDependentUserInfo(0)
1121 {
1122  memset(&m_bits26To31, 0, sizeof(m_bits26To31));
1123 }
1124 
1126 {
1127 }
1128 
1131 {
1132  NS_ABORT_MSG_IF(m_triggerType != userInfo.m_triggerType, "Trigger Frame type mismatch");
1133 
1134  // check for self-assignment
1135  if (&userInfo == this)
1136  {
1137  return *this;
1138  }
1139 
1140  m_variant = userInfo.m_variant;
1141  m_aid12 = userInfo.m_aid12;
1142  m_ruAllocation = userInfo.m_ruAllocation;
1144  m_ulMcs = userInfo.m_ulMcs;
1145  m_ulDcm = userInfo.m_ulDcm;
1146  m_ps160 = userInfo.m_ps160;
1147  m_bits26To31 = userInfo.m_bits26To31;
1148  m_ulTargetRssi = userInfo.m_ulTargetRssi;
1151  return *this;
1152 }
1153 
1154 void
1155 CtrlTriggerUserInfoField::Print(std::ostream& os) const
1156 {
1157  os << ", USER_INFO " << (m_variant == TriggerFrameVariant::HE ? "HE" : "EHT")
1158  << " variant AID=" << m_aid12 << ", RU_Allocation=" << +m_ruAllocation
1159  << ", MCS=" << +m_ulMcs;
1160 }
1161 
1162 uint32_t
1164 {
1165  uint32_t size = 0;
1166  size += 5; // User Info (excluding Trigger Dependent User Info)
1167 
1168  switch (m_triggerType)
1169  {
1172  size += 1;
1173  break;
1175  size +=
1176  m_muBarTriggerDependentUserInfo.GetSerializedSize(); // BAR Control and BAR Information
1177  break;
1178  default:;
1179  // The Trigger Dependent User Info subfield is not present in the other variants
1180  }
1181 
1182  return size;
1183 }
1184 
1187 {
1189  "BFRP Trigger frame is not supported");
1191  "GCR-MU-BAR Trigger frame is not supported");
1193  "NFRP Trigger frame is not supported");
1194 
1195  Buffer::Iterator i = start;
1196 
1197  uint32_t userInfo = 0; // User Info except the MSB
1198  userInfo |= (m_aid12 & 0x0fff);
1199  userInfo |= (m_ruAllocation << 12);
1200  userInfo |= (m_ulFecCodingType ? 1 << 20 : 0);
1201  userInfo |= (m_ulMcs & 0x0f) << 21;
1203  {
1204  userInfo |= (m_ulDcm ? 1 << 25 : 0);
1205  }
1206 
1207  if (m_aid12 != 0 && m_aid12 != 2045)
1208  {
1209  userInfo |= (m_bits26To31.ssAllocation.startingSs & 0x07) << 26;
1210  userInfo |= (m_bits26To31.ssAllocation.nSs & 0x07) << 29;
1211  }
1212  else
1213  {
1214  userInfo |= (m_bits26To31.raRuInformation.nRaRu & 0x1f) << 26;
1215  userInfo |= (m_bits26To31.raRuInformation.moreRaRu ? 1 << 31 : 0);
1216  }
1217 
1218  i.WriteHtolsbU32(userInfo);
1219  // Here we need to write 8 bits covering the UL Target RSSI (7 bits) and B39, which is
1220  // reserved in the HE variant and the PS160 subfield in the EHT variant.
1221  uint8_t bit32To39 = m_ulTargetRssi;
1223  {
1224  bit32To39 |= (m_ps160 ? 1 << 7 : 0);
1225  }
1226 
1227  i.WriteU8(bit32To39);
1228 
1230  {
1232  }
1234  {
1237  }
1238 
1239  return i;
1240 }
1241 
1244 {
1246  "BFRP Trigger frame is not supported");
1248  "GCR-MU-BAR Trigger frame is not supported");
1250  "NFRP Trigger frame is not supported");
1251 
1252  Buffer::Iterator i = start;
1253 
1254  uint32_t userInfo = i.ReadLsbtohU32();
1255 
1256  m_aid12 = userInfo & 0x0fff;
1257  NS_ABORT_MSG_IF(m_aid12 == 4095, "Cannot deserialize a Padding field");
1258  m_ruAllocation = (userInfo >> 12) & 0xff;
1259  m_ulFecCodingType = (userInfo >> 20) & 0x01;
1260  m_ulMcs = (userInfo >> 21) & 0x0f;
1262  {
1263  m_ulDcm = (userInfo >> 25) & 0x01;
1264  }
1265 
1266  if (m_aid12 != 0 && m_aid12 != 2045)
1267  {
1268  m_bits26To31.ssAllocation.startingSs = (userInfo >> 26) & 0x07;
1269  m_bits26To31.ssAllocation.nSs = (userInfo >> 29) & 0x07;
1270  }
1271  else
1272  {
1273  m_bits26To31.raRuInformation.nRaRu = (userInfo >> 26) & 0x1f;
1274  m_bits26To31.raRuInformation.moreRaRu = (userInfo >> 31) & 0x01;
1275  }
1276 
1277  uint8_t bit32To39 = i.ReadU8();
1278  m_ulTargetRssi = bit32To39 & 0x7f; // B39 is reserved in HE variant
1280  {
1281  m_ps160 = (bit32To39 >> 7) == 1;
1282  }
1283 
1285  {
1287  }
1289  {
1290  uint32_t len = m_muBarTriggerDependentUserInfo.Deserialize(i);
1291  i.Next(len);
1292  }
1293 
1294  return i;
1295 }
1296 
1299 {
1300  return m_triggerType;
1301 }
1302 
1305 {
1306  switch (m_variant)
1307  {
1309  return WIFI_PREAMBLE_HE_TB;
1311  return WIFI_PREAMBLE_EHT_TB;
1312  default:
1313  NS_ABORT_MSG("Unexpected variant: " << +static_cast<uint8_t>(m_variant));
1314  }
1315  return WIFI_PREAMBLE_LONG; // to silence warning
1316 }
1317 
1318 void
1320 {
1321  m_aid12 = aid & 0x0fff;
1322 }
1323 
1324 uint16_t
1326 {
1327  return m_aid12;
1328 }
1329 
1330 bool
1332 {
1333  return (m_aid12 == 0);
1334 }
1335 
1336 bool
1338 {
1339  return (m_aid12 == 2045);
1340 }
1341 
1342 void
1344 {
1345  NS_ABORT_MSG_IF(ru.GetIndex() == 0, "Valid indices start at 1");
1347  "SetMuRtsRuAllocation() must be used for MU-RTS");
1348 
1349  switch (ru.GetRuType())
1350  {
1351  case HeRu::RU_26_TONE:
1352  m_ruAllocation = ru.GetIndex() - 1;
1353  break;
1354  case HeRu::RU_52_TONE:
1355  m_ruAllocation = ru.GetIndex() + 36;
1356  break;
1357  case HeRu::RU_106_TONE:
1358  m_ruAllocation = ru.GetIndex() + 52;
1359  break;
1360  case HeRu::RU_242_TONE:
1361  m_ruAllocation = ru.GetIndex() + 60;
1362  break;
1363  case HeRu::RU_484_TONE:
1364  m_ruAllocation = ru.GetIndex() + 64;
1365  break;
1366  case HeRu::RU_996_TONE:
1367  m_ruAllocation = 67;
1368  break;
1369  case HeRu::RU_2x996_TONE:
1370  m_ruAllocation = 68;
1371  break;
1372  default:
1373  NS_FATAL_ERROR("RU type unknown.");
1374  break;
1375  }
1376 
1377  NS_ABORT_MSG_IF(m_ruAllocation > 68, "Reserved value.");
1378 
1379  m_ruAllocation <<= 1;
1380  if (!ru.GetPrimary80MHz())
1381  {
1382  m_ruAllocation++;
1383  }
1384 }
1385 
1388 {
1390  "GetMuRtsRuAllocation() must be used for MU-RTS");
1391 
1392  HeRu::RuType ruType;
1393  std::size_t index;
1394 
1395  bool primary80MHz = ((m_ruAllocation & 0x01) == 0);
1396 
1397  uint8_t val = m_ruAllocation >> 1;
1398 
1399  if (val < 37)
1400  {
1401  ruType = HeRu::RU_26_TONE;
1402  index = val + 1;
1403  }
1404  else if (val < 53)
1405  {
1406  ruType = HeRu::RU_52_TONE;
1407  index = val - 36;
1408  }
1409  else if (val < 61)
1410  {
1411  ruType = HeRu::RU_106_TONE;
1412  index = val - 52;
1413  }
1414  else if (val < 65)
1415  {
1416  ruType = HeRu::RU_242_TONE;
1417  index = val - 60;
1418  }
1419  else if (val < 67)
1420  {
1421  ruType = HeRu::RU_484_TONE;
1422  index = val - 64;
1423  }
1424  else if (val == 67)
1425  {
1426  ruType = HeRu::RU_996_TONE;
1427  index = 1;
1428  }
1429  else if (val == 68)
1430  {
1431  ruType = HeRu::RU_2x996_TONE;
1432  index = 1;
1433  }
1434  else
1435  {
1436  NS_FATAL_ERROR("Reserved value.");
1437  }
1438 
1439  return HeRu::RuSpec(ruType, index, primary80MHz);
1440 }
1441 
1442 void
1444 {
1446  "SetMuRtsRuAllocation() can only be used for MU-RTS");
1448  value < 61 || value > 68,
1449  "Value "
1450  << +value
1451  << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1452 
1453  m_ruAllocation = (value << 1);
1454  if (value == 68)
1455  {
1456  // set B0 for 160 MHz and 80+80 MHz indication
1457  m_ruAllocation++;
1458  }
1459 }
1460 
1461 uint8_t
1463 {
1465  "GetMuRtsRuAllocation() can only be used for MU-RTS");
1466  uint8_t value = (m_ruAllocation >> 1);
1468  value < 61 || value > 68,
1469  "Value "
1470  << +value
1471  << " is not admitted for B7-B1 of the RU Allocation subfield of MU-RTS Trigger Frames");
1472  return value;
1473 }
1474 
1475 void
1477 {
1478  m_ulFecCodingType = ldpc;
1479 }
1480 
1481 bool
1483 {
1484  return m_ulFecCodingType;
1485 }
1486 
1487 void
1489 {
1490  uint8_t maxMcs = m_variant == TriggerFrameVariant::EHT ? 13 : 11;
1491  NS_ABORT_MSG_IF(mcs > maxMcs, "Invalid MCS index");
1492  m_ulMcs = mcs;
1493 }
1494 
1495 uint8_t
1497 {
1498  return m_ulMcs;
1499 }
1500 
1501 void
1503 {
1504  NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1505  m_ulDcm = dcm;
1506 }
1507 
1508 bool
1510 {
1511  NS_ASSERT_MSG(m_variant == TriggerFrameVariant::HE, "UL DCM flag only present in HE variant");
1512  return m_ulDcm;
1513 }
1514 
1515 void
1516 CtrlTriggerUserInfoField::SetSsAllocation(uint8_t startingSs, uint8_t nSs)
1517 {
1518  NS_ABORT_MSG_IF(m_aid12 == 0 || m_aid12 == 2045, "SS Allocation subfield not present");
1519  NS_ABORT_MSG_IF(!startingSs || startingSs > 8, "Starting SS must be from 1 to 8");
1520  NS_ABORT_MSG_IF(!nSs || nSs > 8, "Number of SS must be from 1 to 8");
1521 
1522  m_bits26To31.ssAllocation.startingSs = startingSs - 1;
1523  m_bits26To31.ssAllocation.nSs = nSs - 1;
1524 }
1525 
1526 uint8_t
1528 {
1529  if (m_aid12 == 0 || m_aid12 == 2045)
1530  {
1531  return 1;
1532  }
1533  return m_bits26To31.ssAllocation.startingSs + 1;
1534 }
1535 
1536 uint8_t
1538 {
1539  if (m_aid12 == 0 || m_aid12 == 2045)
1540  {
1541  return 1;
1542  }
1543  return m_bits26To31.ssAllocation.nSs + 1;
1544 }
1545 
1546 void
1548 {
1549  NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1550  NS_ABORT_MSG_IF(!nRaRu || nRaRu > 32, "Number of contiguous RA-RUs must be from 1 to 32");
1551 
1552  m_bits26To31.raRuInformation.nRaRu = nRaRu - 1;
1553  m_bits26To31.raRuInformation.moreRaRu = moreRaRu;
1554 }
1555 
1556 uint8_t
1558 {
1559  NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1560 
1561  return m_bits26To31.raRuInformation.nRaRu + 1;
1562 }
1563 
1564 bool
1566 {
1567  NS_ABORT_MSG_IF(m_aid12 != 0 && m_aid12 != 2045, "RA-RU Information subfield not present");
1568 
1569  return m_bits26To31.raRuInformation.moreRaRu;
1570 }
1571 
1572 void
1574 {
1575  m_ulTargetRssi = 127; // see Table 9-25i of 802.11ax amendment D3.0
1576 }
1577 
1578 void
1580 {
1581  NS_ABORT_MSG_IF(dBm < -110 || dBm > -20, "Invalid values for signal power");
1582 
1583  m_ulTargetRssi = static_cast<uint8_t>(110 + dBm);
1584 }
1585 
1586 bool
1588 {
1589  return (m_ulTargetRssi == 127);
1590 }
1591 
1592 int8_t
1594 {
1595  NS_ABORT_MSG_IF(m_ulTargetRssi == 127, "STA must use its max TX power");
1596 
1597  return static_cast<int8_t>(m_ulTargetRssi) - 110;
1598 }
1599 
1600 void
1602  uint8_t tidLimit,
1603  AcIndex prefAc)
1604 {
1605  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1606 
1607  m_basicTriggerDependentUserInfo = (spacingFactor & 0x03) |
1608  (tidLimit & 0x07) << 2
1609  // B5 is reserved
1610  | (prefAc & 0x03) << 6;
1611 }
1612 
1613 uint8_t
1615 {
1616  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1617 
1618  return m_basicTriggerDependentUserInfo & 0x03;
1619 }
1620 
1621 uint8_t
1623 {
1624  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1625 
1626  return (m_basicTriggerDependentUserInfo & 0x1c) >> 2;
1627 }
1628 
1629 AcIndex
1631 {
1632  NS_ABORT_MSG_IF(m_triggerType != TriggerFrameType::BASIC_TRIGGER, "Not a Basic Trigger Frame");
1633 
1634  return AcIndex((m_basicTriggerDependentUserInfo & 0xc0) >> 6);
1635 }
1636 
1637 void
1639 {
1641  "Not a MU-BAR Trigger frame");
1644  "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1646 }
1647 
1648 const CtrlBAckRequestHeader&
1650 {
1652  "Not a MU-BAR Trigger frame");
1653 
1655 }
1656 
1657 /***********************************
1658  * Trigger frame
1659  ***********************************/
1660 
1662 
1664  : m_variant(TriggerFrameVariant::HE),
1665  m_triggerType(TriggerFrameType::BASIC_TRIGGER),
1666  m_ulLength(0),
1667  m_moreTF(false),
1668  m_csRequired(false),
1669  m_ulBandwidth(0),
1670  m_giAndLtfType(0),
1671  m_apTxPower(0),
1672  m_ulSpatialReuse(0),
1673  m_padding(0)
1674 {
1675 }
1676 
1678  : CtrlTriggerHeader()
1679 {
1681  "This constructor cannot be used for MU-RTS");
1682 
1683  switch (txVector.GetPreambleType())
1684  {
1685  case WIFI_PREAMBLE_HE_TB:
1687  break;
1688  case WIFI_PREAMBLE_EHT_TB:
1690  break;
1691  default:
1692  NS_ABORT_MSG("Cannot create a TF out of a TXVECTOR with preamble type: "
1693  << txVector.GetPreambleType());
1694  }
1695 
1696  m_triggerType = type;
1697  SetUlBandwidth(txVector.GetChannelWidth());
1698  SetUlLength(txVector.GetLength());
1699  uint16_t gi = txVector.GetGuardInterval();
1700  if (gi == 800 || gi == 1600)
1701  {
1702  m_giAndLtfType = 1;
1703  }
1704  else
1705  {
1706  m_giAndLtfType = 2;
1707  }
1708  for (auto& userInfo : txVector.GetHeMuUserInfoMap())
1709  {
1711  ui.SetAid12(userInfo.first);
1712  ui.SetRuAllocation(userInfo.second.ru);
1713  ui.SetUlMcs(userInfo.second.mcs);
1714  ui.SetSsAllocation(1, userInfo.second.nss); // MU-MIMO is not supported
1715  }
1716 }
1717 
1719 {
1720 }
1721 
1724 {
1725  // check for self-assignment
1726  if (&trigger == this)
1727  {
1728  return *this;
1729  }
1730 
1731  m_variant = trigger.m_variant;
1732  m_triggerType = trigger.m_triggerType;
1733  m_ulLength = trigger.m_ulLength;
1734  m_moreTF = trigger.m_moreTF;
1735  m_csRequired = trigger.m_csRequired;
1736  m_ulBandwidth = trigger.m_ulBandwidth;
1737  m_giAndLtfType = trigger.m_giAndLtfType;
1738  m_apTxPower = trigger.m_apTxPower;
1740  m_padding = trigger.m_padding;
1741  m_userInfoFields.clear();
1743  return *this;
1744 }
1745 
1746 TypeId
1748 {
1749  static TypeId tid = TypeId("ns3::CtrlTriggerHeader")
1750  .SetParent<Header>()
1751  .SetGroupName("Wifi")
1752  .AddConstructor<CtrlTriggerHeader>();
1753  return tid;
1754 }
1755 
1756 TypeId
1758 {
1759  return GetTypeId();
1760 }
1761 
1762 void
1763 CtrlTriggerHeader::Print(std::ostream& os) const
1764 {
1765  os << "TriggerType=" << GetTypeString() << ", Bandwidth=" << +GetUlBandwidth()
1766  << ", UL Length=" << m_ulLength;
1767 
1768  for (auto& ui : m_userInfoFields)
1769  {
1770  ui.Print(os);
1771  }
1772 }
1773 
1774 void
1776 {
1778  "Cannot change Common Info field variant if User Info fields are present");
1779  m_variant = variant;
1780 }
1781 
1784 {
1785  return m_variant;
1786 }
1787 
1788 uint32_t
1790 {
1791  uint32_t size = 0;
1792  size += 8; // Common Info (excluding Trigger Dependent Common Info)
1793 
1794  // Add the size of the Trigger Dependent Common Info subfield
1796  {
1797  size += 4;
1798  }
1799 
1800  for (auto& ui : m_userInfoFields)
1801  {
1802  size += ui.GetSerializedSize();
1803  }
1804 
1805  size += m_padding;
1806 
1807  return size;
1808 }
1809 
1810 void
1812 {
1814  "BFRP Trigger frame is not supported");
1816  "GCR-MU-BAR Trigger frame is not supported");
1818  "NFRP Trigger frame is not supported");
1819 
1820  Buffer::Iterator i = start;
1821 
1822  uint64_t commonInfo = 0;
1823  commonInfo |= (static_cast<uint8_t>(m_triggerType) & 0x0f);
1824  commonInfo |= (m_ulLength & 0x0fff) << 4;
1825  commonInfo |= (m_moreTF ? 1 << 16 : 0);
1826  commonInfo |= (m_csRequired ? 1 << 17 : 0);
1827  commonInfo |= (m_ulBandwidth & 0x03) << 18;
1828  commonInfo |= (m_giAndLtfType & 0x03) << 20;
1829  commonInfo |= static_cast<uint64_t>(m_apTxPower & 0x3f) << 28;
1830  commonInfo |= static_cast<uint64_t>(m_ulSpatialReuse) << 37;
1832  {
1833  uint64_t ulHeSigA2 = 0x01ff; // nine bits equal to 1
1834  commonInfo |= ulHeSigA2 << 54;
1835  }
1836 
1837  i.WriteHtolsbU64(commonInfo);
1838 
1839  for (auto& ui : m_userInfoFields)
1840  {
1841  i = ui.Serialize(i);
1842  }
1843 
1844  for (std::size_t count = 0; count < m_padding; count++)
1845  {
1846  i.WriteU8(0xff); // Padding field
1847  }
1848 }
1849 
1850 uint32_t
1852 {
1853  Buffer::Iterator i = start;
1854 
1855  uint64_t commonInfo = i.ReadLsbtohU64();
1856 
1857  m_triggerType = static_cast<TriggerFrameType>(commonInfo & 0x0f);
1858  m_ulLength = (commonInfo >> 4) & 0x0fff;
1859  m_moreTF = (commonInfo >> 16) & 0x01;
1860  m_csRequired = (commonInfo >> 17) & 0x01;
1861  m_ulBandwidth = (commonInfo >> 18) & 0x03;
1862  m_giAndLtfType = (commonInfo >> 20) & 0x03;
1863  m_apTxPower = (commonInfo >> 28) & 0x3f;
1864  m_ulSpatialReuse = (commonInfo >> 37) & 0xffff;
1865  uint8_t bit54and55 = (commonInfo >> 54) & 0x03;
1867  m_userInfoFields.clear();
1868  m_padding = 0;
1869 
1871  "BFRP Trigger frame is not supported");
1873  "GCR-MU-BAR Trigger frame is not supported");
1875  "NFRP Trigger frame is not supported");
1876 
1877  while (i.GetRemainingSize() >= 2)
1878  {
1879  // read the first 2 bytes to check if we encountered the Padding field
1880  if (i.ReadU16() == 0xffff)
1881  {
1882  m_padding = i.GetRemainingSize() + 2;
1883  }
1884  else
1885  {
1886  // go back 2 bytes to deserialize the User Info field from the beginning
1887  i.Prev(2);
1889  i = ui.Deserialize(i);
1890  }
1891  }
1892 
1893  return i.GetDistanceFrom(start);
1894 }
1895 
1896 void
1898 {
1899  m_triggerType = type;
1900 }
1901 
1904 {
1905  return m_triggerType;
1906 }
1907 
1908 const char*
1910 {
1911  return GetTypeString(GetType());
1912 }
1913 
1914 const char*
1916 {
1917 #define FOO(x) \
1918  case TriggerFrameType::x: \
1919  return #x;
1920 
1921  switch (type)
1922  {
1923  FOO(BASIC_TRIGGER);
1924  FOO(BFRP_TRIGGER);
1927  FOO(BSRP_TRIGGER);
1929  FOO(BQRP_TRIGGER);
1930  FOO(NFRP_TRIGGER);
1931  default:
1932  return "ERROR";
1933  }
1934 #undef FOO
1935 }
1936 
1937 bool
1939 {
1941 }
1942 
1943 bool
1945 {
1947 }
1948 
1949 bool
1951 {
1953 }
1954 
1955 bool
1957 {
1959 }
1960 
1961 bool
1963 {
1965 }
1966 
1967 bool
1969 {
1971 }
1972 
1973 bool
1975 {
1977 }
1978 
1979 bool
1981 {
1983 }
1984 
1985 void
1987 {
1988  m_ulLength = (len & 0x0fff);
1989 }
1990 
1991 uint16_t
1993 {
1994  return m_ulLength;
1995 }
1996 
1999 {
2001  "GetHeTbTxVector() cannot be used for MU-RTS");
2002  auto userInfoIt = FindUserInfoWithAid(staId);
2003  NS_ASSERT(userInfoIt != end());
2004 
2005  WifiTxVector v;
2006  v.SetPreambleType(userInfoIt->GetPreambleType());
2009  v.SetLength(GetUlLength());
2010  v.SetHeMuUserInfo(
2011  staId,
2012  {userInfoIt->GetRuAllocation(), userInfoIt->GetUlMcs(), userInfoIt->GetNss()});
2013  return v;
2014 }
2015 
2016 void
2018 {
2019  m_moreTF = more;
2020 }
2021 
2022 bool
2024 {
2025  return m_moreTF;
2026 }
2027 
2028 void
2030 {
2031  m_csRequired = cs;
2032 }
2033 
2034 bool
2036 {
2037  return m_csRequired;
2038 }
2039 
2040 void
2042 {
2043  switch (bw)
2044  {
2045  case 20:
2046  m_ulBandwidth = 0;
2047  break;
2048  case 40:
2049  m_ulBandwidth = 1;
2050  break;
2051  case 80:
2052  m_ulBandwidth = 2;
2053  break;
2054  case 160:
2055  m_ulBandwidth = 3;
2056  break;
2057  default:
2058  NS_FATAL_ERROR("Bandwidth value not allowed.");
2059  break;
2060  }
2061 }
2062 
2063 uint16_t
2065 {
2066  return (1 << m_ulBandwidth) * 20;
2067 }
2068 
2069 void
2070 CtrlTriggerHeader::SetGiAndLtfType(uint16_t guardInterval, uint8_t ltfType)
2071 {
2072  if (ltfType == 1 && guardInterval == 1600)
2073  {
2074  m_giAndLtfType = 0;
2075  }
2076  else if (ltfType == 2 && guardInterval == 1600)
2077  {
2078  m_giAndLtfType = 1;
2079  }
2080  else if (ltfType == 4 && guardInterval == 3200)
2081  {
2082  m_giAndLtfType = 2;
2083  }
2084  else
2085  {
2086  NS_FATAL_ERROR("Invalid combination of GI and LTF type");
2087  }
2088 }
2089 
2090 uint16_t
2092 {
2093  if (m_giAndLtfType == 0 || m_giAndLtfType == 1)
2094  {
2095  return 1600;
2096  }
2097  else if (m_giAndLtfType == 2)
2098  {
2099  return 3200;
2100  }
2101  else
2102  {
2103  NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2104  }
2105 }
2106 
2107 uint8_t
2109 {
2110  if (m_giAndLtfType == 0)
2111  {
2112  return 1;
2113  }
2114  else if (m_giAndLtfType == 1)
2115  {
2116  return 2;
2117  }
2118  else if (m_giAndLtfType == 2)
2119  {
2120  return 4;
2121  }
2122  else
2123  {
2124  NS_FATAL_ERROR("Invalid value for GI And LTF Type subfield");
2125  }
2126 }
2127 
2128 void
2130 {
2131  // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2132  NS_ABORT_MSG_IF(power < -20 || power > 40, "Out of range power values");
2133 
2134  m_apTxPower = static_cast<uint8_t>(power + 20);
2135 }
2136 
2137 int8_t
2139 {
2140  // see Table 9-25f "AP Tx Power subfield encoding" of 802.11ax amendment D3.0
2141  return static_cast<int8_t>(m_apTxPower) - 20;
2142 }
2143 
2144 void
2146 {
2147  m_ulSpatialReuse = sr;
2148 }
2149 
2150 uint16_t
2152 {
2153  return m_ulSpatialReuse;
2154 }
2155 
2156 void
2158 {
2159  NS_ABORT_MSG_IF(size == 1, "The Padding field, if present, shall be at least two octets");
2160  m_padding = size;
2161 }
2162 
2163 std::size_t
2165 {
2166  return m_padding;
2167 }
2168 
2171 {
2172  // make a copy of this Trigger Frame and remove the User Info fields from the copy
2173  CtrlTriggerHeader trigger(*this);
2174  trigger.m_userInfoFields.clear();
2175  return trigger;
2176 }
2177 
2180 {
2181  m_userInfoFields.emplace_back(m_triggerType, m_variant);
2182  return m_userInfoFields.back();
2183 }
2184 
2187 {
2189  userInfo.GetType() != m_triggerType,
2190  "Trying to add a User Info field of a type other than the type of the Trigger Frame");
2191  m_userInfoFields.push_back(userInfo);
2192  return m_userInfoFields.back();
2193 }
2194 
2197 {
2198  return m_userInfoFields.begin();
2199 }
2200 
2203 {
2204  return m_userInfoFields.end();
2205 }
2206 
2209 {
2210  return m_userInfoFields.begin();
2211 }
2212 
2215 {
2216  return m_userInfoFields.end();
2217 }
2218 
2219 std::size_t
2221 {
2222  return m_userInfoFields.size();
2223 }
2224 
2227 {
2228  // the lambda function returns true if a User Info field has the AID12 subfield
2229  // equal to the given aid12 value
2230  return std::find_if(start, end(), [aid12](const CtrlTriggerUserInfoField& ui) -> bool {
2231  return (ui.GetAid12() == aid12);
2232  });
2233 }
2234 
2237 {
2238  return FindUserInfoWithAid(m_userInfoFields.begin(), aid12);
2239 }
2240 
2243 {
2244  return FindUserInfoWithAid(start, 0);
2245 }
2246 
2249 {
2250  return FindUserInfoWithAid(0);
2251 }
2252 
2255 {
2256  return FindUserInfoWithAid(start, 2045);
2257 }
2258 
2261 {
2262  return FindUserInfoWithAid(2045);
2263 }
2264 
2265 bool
2267 {
2269  {
2270  return true;
2271  }
2272 
2273  // check that allocated RUs do not overlap
2274  // TODO This is not a problem in case of UL MU-MIMO
2275  std::vector<HeRu::RuSpec> prevRus;
2276 
2277  for (auto& ui : m_userInfoFields)
2278  {
2279  if (HeRu::DoesOverlap(GetUlBandwidth(), ui.GetRuAllocation(), prevRus))
2280  {
2281  return false;
2282  }
2283  prevRus.push_back(ui.GetRuAllocation());
2284  }
2285  return true;
2286 }
2287 
2288 } // namespace ns3
iterator in a Buffer instance
Definition: buffer.h:100
uint32_t GetRemainingSize() const
Definition: buffer.cc:1173
void WriteHtolsbU16(uint16_t data)
Definition: buffer.cc:902
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void WriteHtolsbU32(uint32_t data)
Definition: buffer.cc:910
uint16_t ReadLsbtohU16()
Definition: buffer.cc:1064
uint64_t ReadLsbtohU64()
Definition: buffer.cc:1094
void WriteHtolsbU64(uint64_t data)
Definition: buffer.cc:920
uint32_t GetDistanceFrom(const Iterator &o) const
Definition: buffer.cc:780
void Prev()
go backward by one byte
Definition: buffer.h:860
uint16_t ReadU16()
Definition: buffer.h:1035
uint32_t ReadLsbtohU32()
Definition: buffer.cc:1076
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:942
std::size_t GetPaddingSize() const
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.
std::size_t m_padding
the size in bytes of the Padding 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.
void SetPaddingSize(std::size_t size)
Set the size in bytes of the Padding field.
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::@71 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:461
RuType GetRuType() const
Get the RU type.
Definition: he-ru.cc:454
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition: he-ru.cc:468
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:626
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:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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:73
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:185
void WriteTo(Buffer::Iterator &i, Ipv4Address ad)
Write an Ipv4Address to a Buffer.
void ReadFrom(Buffer::Iterator &i, Ipv4Address &ad)
Read an Ipv4Address from a Buffer.
The different BlockAckRequest variants.
Variant m_variant
Block Ack Request variant.
The different BlockAck variants.
Variant m_variant
Block Ack variant.
std::vector< uint8_t > m_bitmapLen
Length (bytes) of included bitmaps.
The following structure can hold the BA Information field for the Basic and Compressed variants,...
Definition: ctrl-headers.h:542
uint16_t m_aidTidInfo
Reserved for Basic and Compressed Per TID Info subfield for Multi-TID AID TID Info subfield for Multi...
Definition: ctrl-headers.h:543