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 
CtrlBAckRequestHeader()37 CtrlBAckRequestHeader::CtrlBAckRequestHeader ()
38   : m_barAckPolicy (false),
39     m_barType (BlockAckReqType::BASIC)
40 {
41 }
42 
~CtrlBAckRequestHeader()43 CtrlBAckRequestHeader::~CtrlBAckRequestHeader ()
44 {
45 }
46 
47 TypeId
GetTypeId(void)48 CtrlBAckRequestHeader::GetTypeId (void)
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
GetInstanceTypeId(void) const59 CtrlBAckRequestHeader::GetInstanceTypeId (void) const
60 {
61   return GetTypeId ();
62 }
63 
64 void
Print(std::ostream & os) const65 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
GetSerializedSize() const71 CtrlBAckRequestHeader::GetSerializedSize () const
72 {
73   uint32_t size = 0;
74   size += 2; //Bar control
75   switch (m_barType.m_variant)
76     {
77       case BlockAckReqType::BASIC:
78       case BlockAckReqType::COMPRESSED:
79       case BlockAckReqType::EXTENDED_COMPRESSED:
80         size += 2;
81         break;
82       case BlockAckReqType::MULTI_TID:
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
Serialize(Buffer::Iterator start) const93 CtrlBAckRequestHeader::Serialize (Buffer::Iterator start) const
94 {
95   Buffer::Iterator i = start;
96   i.WriteHtolsbU16 (GetBarControl ());
97   switch (m_barType.m_variant)
98     {
99       case BlockAckReqType::BASIC:
100       case BlockAckReqType::COMPRESSED:
101       case BlockAckReqType::EXTENDED_COMPRESSED:
102         i.WriteHtolsbU16 (GetStartingSequenceControl ());
103         break;
104       case BlockAckReqType::MULTI_TID:
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
Deserialize(Buffer::Iterator start)114 CtrlBAckRequestHeader::Deserialize (Buffer::Iterator start)
115 {
116   Buffer::Iterator i = start;
117   SetBarControl (i.ReadLsbtohU16 ());
118   switch (m_barType.m_variant)
119     {
120       case BlockAckReqType::BASIC:
121       case BlockAckReqType::COMPRESSED:
122       case BlockAckReqType::EXTENDED_COMPRESSED:
123         SetStartingSequenceControl (i.ReadLsbtohU16 ());
124         break;
125       case BlockAckReqType::MULTI_TID:
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
GetBarControl(void) const136 CtrlBAckRequestHeader::GetBarControl (void) const
137 {
138   uint16_t res = 0;
139   switch (m_barType.m_variant)
140     {
141       case BlockAckReqType::BASIC:
142         break;
143       case BlockAckReqType::COMPRESSED:
144         res |= (0x02 << 1);
145         break;
146       case BlockAckReqType::EXTENDED_COMPRESSED:
147         res |= (0x01 << 1);
148         break;
149       case BlockAckReqType::MULTI_TID:
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
SetBarControl(uint16_t bar)161 CtrlBAckRequestHeader::SetBarControl (uint16_t bar)
162 {
163   m_barAckPolicy = ((bar & 0x01) == 1) ? true : false;
164   if (((bar >> 1) & 0x0f) == 0x03)
165     {
166       m_barType.m_variant = BlockAckReqType::MULTI_TID;
167     }
168   else if (((bar >> 1) & 0x0f) == 0x01)
169     {
170       m_barType.m_variant = BlockAckReqType::EXTENDED_COMPRESSED;
171     }
172   else if (((bar >> 1) & 0x0f) == 0x02)
173     {
174       m_barType.m_variant = BlockAckReqType::COMPRESSED;
175     }
176   else
177     {
178       m_barType.m_variant = BlockAckReqType::BASIC;
179     }
180   m_tidInfo = (bar >> 12) & 0x0f;
181 }
182 
183 uint16_t
GetStartingSequenceControl(void) const184 CtrlBAckRequestHeader::GetStartingSequenceControl (void) const
185 {
186   return (m_startingSeq << 4) & 0xfff0;
187 }
188 
189 void
SetStartingSequenceControl(uint16_t seqControl)190 CtrlBAckRequestHeader::SetStartingSequenceControl (uint16_t seqControl)
191 {
192   m_startingSeq = (seqControl >> 4) & 0x0fff;
193 }
194 
195 void
SetHtImmediateAck(bool immediateAck)196 CtrlBAckRequestHeader::SetHtImmediateAck (bool immediateAck)
197 {
198   m_barAckPolicy = immediateAck;
199 }
200 
201 void
SetType(BlockAckReqType type)202 CtrlBAckRequestHeader::SetType (BlockAckReqType type)
203 {
204   m_barType = type;
205 }
206 
207 BlockAckReqType
GetType(void) const208 CtrlBAckRequestHeader::GetType (void) const
209 {
210   return m_barType;
211 }
212 
213 void
SetTidInfo(uint8_t tid)214 CtrlBAckRequestHeader::SetTidInfo (uint8_t tid)
215 {
216   m_tidInfo = static_cast<uint16_t> (tid);
217 }
218 
219 void
SetStartingSequence(uint16_t seq)220 CtrlBAckRequestHeader::SetStartingSequence (uint16_t seq)
221 {
222   m_startingSeq = seq;
223 }
224 
225 bool
MustSendHtImmediateAck(void) const226 CtrlBAckRequestHeader::MustSendHtImmediateAck (void) const
227 {
228   return m_barAckPolicy;
229 }
230 
231 uint8_t
GetTidInfo(void) const232 CtrlBAckRequestHeader::GetTidInfo (void) const
233 {
234   uint8_t tid = static_cast<uint8_t> (m_tidInfo);
235   return tid;
236 }
237 
238 uint16_t
GetStartingSequence(void) const239 CtrlBAckRequestHeader::GetStartingSequence (void) const
240 {
241   return m_startingSeq;
242 }
243 
244 bool
IsBasic(void) const245 CtrlBAckRequestHeader::IsBasic (void) const
246 {
247   return (m_barType.m_variant == BlockAckReqType::BASIC) ? true : false;
248 }
249 
250 bool
IsCompressed(void) const251 CtrlBAckRequestHeader::IsCompressed (void) const
252 {
253   return (m_barType.m_variant == BlockAckReqType::COMPRESSED) ? true : false;
254 }
255 
256 bool
IsExtendedCompressed(void) const257 CtrlBAckRequestHeader::IsExtendedCompressed (void) const
258 {
259   return (m_barType.m_variant == BlockAckReqType::EXTENDED_COMPRESSED) ? true : false;
260 }
261 
262 bool
IsMultiTid(void) const263 CtrlBAckRequestHeader::IsMultiTid (void) const
264 {
265   return (m_barType.m_variant == BlockAckReqType::MULTI_TID) ? true : false;
266 }
267 
268 
269 /***********************************
270  *       Block ack response
271  ***********************************/
272 
273 NS_OBJECT_ENSURE_REGISTERED (CtrlBAckResponseHeader);
274 
CtrlBAckResponseHeader()275 CtrlBAckResponseHeader::CtrlBAckResponseHeader ()
276   : m_baAckPolicy (false),
277     m_tidInfo (0)
278 {
279   SetType (BlockAckType::BASIC);
280 }
281 
~CtrlBAckResponseHeader()282 CtrlBAckResponseHeader::~CtrlBAckResponseHeader ()
283 {
284 }
285 
286 TypeId
GetTypeId(void)287 CtrlBAckResponseHeader::GetTypeId (void)
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
GetInstanceTypeId(void) const298 CtrlBAckResponseHeader::GetInstanceTypeId (void) const
299 {
300   return GetTypeId ();
301 }
302 
303 void
Print(std::ostream & os) const304 CtrlBAckResponseHeader::Print (std::ostream &os) const
305 {
306   if (m_baType.m_variant != BlockAckType::MULTI_STA)
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
GetSerializedSize(void) const322 CtrlBAckResponseHeader::GetSerializedSize (void) const
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:
331       case BlockAckType::COMPRESSED:
332       case BlockAckType::EXTENDED_COMPRESSED:
333         size += (2 + m_baType.m_bitmapLen[0]);
334         break;
335       case BlockAckType::MULTI_TID:
336         size += (2 + 2 + 8) * (m_tidInfo + 1); //Multi-TID block ack
337         break;
338       case BlockAckType::MULTI_STA:
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
Serialize(Buffer::Iterator start) const352 CtrlBAckResponseHeader::Serialize (Buffer::Iterator start) const
353 {
354   Buffer::Iterator i = start;
355   i.WriteHtolsbU16 (GetBaControl ());
356   switch (m_baType.m_variant)
357     {
358       case BlockAckType::BASIC:
359       case BlockAckType::COMPRESSED:
360       case BlockAckType::EXTENDED_COMPRESSED:
361         i.WriteHtolsbU16 (GetStartingSequenceControl ());
362         i = SerializeBitmap (i);
363         break;
364       case BlockAckType::MULTI_STA:
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                   {
372                     i.WriteHtolsbU16 (GetStartingSequenceControl (index));
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;
384       case BlockAckType::MULTI_TID:
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
Deserialize(Buffer::Iterator start)394 CtrlBAckResponseHeader::Deserialize (Buffer::Iterator start)
395 {
396   Buffer::Iterator i = start;
397   SetBaControl (i.ReadLsbtohU16 ());
398   switch (m_baType.m_variant)
399     {
400       case BlockAckType::BASIC:
401       case BlockAckType::COMPRESSED:
402       case BlockAckType::EXTENDED_COMPRESSED:
403         SetStartingSequenceControl (i.ReadLsbtohU16 ());
404         i = DeserializeBitmap (i);
405         break;
406       case BlockAckType::MULTI_STA:
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;
439       case BlockAckType::MULTI_TID:
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
SetHtImmediateAck(bool immediateAck)450 CtrlBAckResponseHeader::SetHtImmediateAck (bool immediateAck)
451 {
452   m_baAckPolicy = immediateAck;
453 }
454 
455 void
SetType(BlockAckType type)456 CtrlBAckResponseHeader::SetType (BlockAckType type)
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 
470 BlockAckType
GetType(void) const471 CtrlBAckResponseHeader::GetType (void) const
472 {
473   return m_baType;
474 }
475 
476 void
SetTidInfo(uint8_t tid,std::size_t index)477 CtrlBAckResponseHeader::SetTidInfo (uint8_t tid, std::size_t index)
478 {
479   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
480                  "index can only be non null for Multi-STA Block Ack");
481   NS_ASSERT (index < m_baInfo.size ());
482 
483   if (m_baType.m_variant != BlockAckType::MULTI_STA)
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
SetStartingSequence(uint16_t seq,std::size_t index)494 CtrlBAckResponseHeader::SetStartingSequence (uint16_t seq, std::size_t index)
495 {
496   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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
MustSendHtImmediateAck(void) const504 CtrlBAckResponseHeader::MustSendHtImmediateAck (void) const
505 {
506   return (m_baAckPolicy) ? true : false;
507 }
508 
509 uint8_t
GetTidInfo(std::size_t index) const510 CtrlBAckResponseHeader::GetTidInfo (std::size_t index) const
511 {
512   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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 
518   if (m_baType.m_variant != BlockAckType::MULTI_STA)
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
GetStartingSequence(std::size_t index) const530 CtrlBAckResponseHeader::GetStartingSequence (std::size_t index) const
531 {
532   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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
IsBasic(void) const540 CtrlBAckResponseHeader::IsBasic (void) const
541 {
542   return (m_baType.m_variant == BlockAckType::BASIC) ? true : false;
543 }
544 
545 bool
IsCompressed(void) const546 CtrlBAckResponseHeader::IsCompressed (void) const
547 {
548   return (m_baType.m_variant == BlockAckType::COMPRESSED) ? true : false;
549 }
550 
551 bool
IsExtendedCompressed(void) const552 CtrlBAckResponseHeader::IsExtendedCompressed (void) const
553 {
554   return (m_baType.m_variant == BlockAckType::EXTENDED_COMPRESSED) ? true : false;
555 }
556 
557 bool
IsMultiTid(void) const558 CtrlBAckResponseHeader::IsMultiTid (void) const
559 {
560   return (m_baType.m_variant == BlockAckType::MULTI_TID) ? true : false;
561 }
562 
563 bool
IsMultiSta(void) const564 CtrlBAckResponseHeader::IsMultiSta (void) const
565 {
566   return (m_baType.m_variant == BlockAckType::MULTI_STA) ? true : false;
567 }
568 
569 void
SetAid11(uint16_t aid,std::size_t index)570 CtrlBAckResponseHeader::SetAid11 (uint16_t aid, std::size_t index)
571 {
572   NS_ASSERT (m_baType.m_variant == BlockAckType::MULTI_STA && index < m_baInfo.size ());
573 
574   m_baInfo[index].m_aidTidInfo |= (aid & 0x07ff);
575 }
576 
577 uint16_t
GetAid11(std::size_t index) const578 CtrlBAckResponseHeader::GetAid11 (std::size_t index) const
579 {
580   NS_ASSERT (m_baType.m_variant == BlockAckType::MULTI_STA && index < m_baInfo.size ());
581 
582   return m_baInfo[index].m_aidTidInfo & 0x07ff;
583 }
584 
585 void
SetAckType(bool type,std::size_t index)586 CtrlBAckResponseHeader::SetAckType (bool type, std::size_t index)
587 {
588   NS_ASSERT (m_baType.m_variant == BlockAckType::MULTI_STA && index < m_baInfo.size ());
589 
590   if (type)
591     {
592       m_baInfo[index].m_aidTidInfo |= (1 << 11);
593     }
594 }
595 
596 bool
GetAckType(std::size_t index) const597 CtrlBAckResponseHeader::GetAckType (std::size_t index) const
598 {
599   NS_ASSERT (m_baType.m_variant == BlockAckType::MULTI_STA && index < m_baInfo.size ());
600 
601   return ((m_baInfo[index].m_aidTidInfo >> 11) & 0x0001) != 0;
602 }
603 
604 void
SetUnassociatedStaAddress(const Mac48Address & ra,std::size_t index)605 CtrlBAckResponseHeader::SetUnassociatedStaAddress (const Mac48Address& ra, std::size_t index)
606 {
607   NS_ASSERT (GetAid11 (index) == 2045);
608 
609   m_baInfo[index].m_ra = ra;
610 }
611 
612 Mac48Address
GetUnassociatedStaAddress(std::size_t index) const613 CtrlBAckResponseHeader::GetUnassociatedStaAddress (std::size_t index) const
614 {
615   NS_ASSERT (GetAid11 (index) == 2045);
616 
617   return m_baInfo[index].m_ra;
618 }
619 
620 std::size_t
GetNPerAidTidInfoSubfields(void) const621 CtrlBAckResponseHeader::GetNPerAidTidInfoSubfields (void) const
622 {
623   NS_ASSERT (m_baType.m_variant == BlockAckType::MULTI_STA);
624   return m_baInfo.size ();
625 }
626 
627 std::vector<uint32_t>
FindPerAidTidInfoWithAid(uint16_t aid) const628 CtrlBAckResponseHeader::FindPerAidTidInfoWithAid (uint16_t aid) const
629 {
630   NS_ASSERT (m_baType.m_variant == BlockAckType::MULTI_STA);
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
GetBaControl(void) const645 CtrlBAckResponseHeader::GetBaControl (void) const
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;
656       case BlockAckType::COMPRESSED:
657         res |= (0x02 << 1);
658         break;
659       case BlockAckType::EXTENDED_COMPRESSED:
660         res |= (0x01 << 1);
661         break;
662       case BlockAckType::MULTI_TID:
663         res |= (0x03 << 1);
664         break;
665       case BlockAckType::MULTI_STA:
666         res |= (0x0b << 1);
667         break;
668       default:
669         NS_FATAL_ERROR ("Invalid BA type");
670         break;
671     }
672   if (m_baType.m_variant != BlockAckType::MULTI_STA)
673     {
674       res |= (m_tidInfo << 12) & (0xf << 12);
675     }
676   return res;
677 }
678 
679 void
SetBaControl(uint16_t ba)680 CtrlBAckResponseHeader::SetBaControl (uint16_t ba)
681 {
682   m_baAckPolicy = ((ba & 0x01) == 1) ? true : false;
683   if (((ba >> 1) & 0x0f) == 0x03)
684     {
685       SetType (BlockAckType::MULTI_TID);
686     }
687   else if (((ba >> 1) & 0x0f) == 0x01)
688     {
689       SetType (BlockAckType::EXTENDED_COMPRESSED);
690     }
691   else if (((ba >> 1) & 0x0f) == 0x02)
692     {
693       SetType (BlockAckType::COMPRESSED);
694     }
695   else if (((ba >> 1) & 0x0f) == 0)
696     {
697       SetType (BlockAckType::BASIC);
698     }
699   else if (((ba >> 1) & 0x0f) == 0x0b)
700     {
701       SetType (BlockAckType::MULTI_STA);
702     }
703   else
704     {
705       NS_FATAL_ERROR ("Invalid BA type");
706     }
707   if (m_baType.m_variant != BlockAckType::MULTI_STA)
708     {
709       m_tidInfo = (ba >> 12) & 0x0f;
710     }
711 }
712 
713 uint16_t
GetStartingSequenceControl(std::size_t index) const714 CtrlBAckResponseHeader::GetStartingSequenceControl (std::size_t index) const
715 {
716   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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.
725   if (m_baType.m_variant == BlockAckType::COMPRESSED)
726     {
727       if (m_baType.m_bitmapLen[0] == 32)
728         {
729           ret |= 0x0004;
730         }
731     }
732   else if (m_baType.m_variant == BlockAckType::MULTI_STA)
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
SetStartingSequenceControl(uint16_t seqControl,std::size_t index)755 CtrlBAckResponseHeader::SetStartingSequenceControl (uint16_t seqControl, std::size_t index)
756 {
757   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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.
764   if (m_baType.m_variant == BlockAckType::COMPRESSED)
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         {
772           SetType ({BlockAckType::COMPRESSED, {8}});
773         }
774       else if (((seqControl >> 3) & 0x0001) == 0 && ((seqControl >> 1) & 0x0003) == 2)
775         {
776           SetType ({BlockAckType::COMPRESSED, {32}});
777         }
778       else
779         {
780           NS_FATAL_ERROR ("Reserved configurations");
781         }
782     }
783   else if (m_baType.m_variant == BlockAckType::MULTI_STA)
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 
817 Buffer::Iterator
SerializeBitmap(Buffer::Iterator start,std::size_t index) const818 CtrlBAckResponseHeader::SerializeBitmap (Buffer::Iterator start, std::size_t index) const
819 {
820   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
821                  "index can only be non null for Multi-STA Block Ack");
822   NS_ASSERT (index < m_baInfo.size ());
823 
824   Buffer::Iterator i = start;
825   switch (m_baType.m_variant)
826     {
827       case BlockAckType::BASIC:
828       case BlockAckType::COMPRESSED:
829       case BlockAckType::EXTENDED_COMPRESSED:
830       case BlockAckType::MULTI_STA:
831           for (const auto& byte : m_baInfo[index].m_bitmap)
832             {
833               i.WriteU8 (byte);
834             }
835           break;
836       case BlockAckType::MULTI_TID:
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 
846 Buffer::Iterator
DeserializeBitmap(Buffer::Iterator start,std::size_t index)847 CtrlBAckResponseHeader::DeserializeBitmap (Buffer::Iterator start, std::size_t index)
848 {
849   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
850                  "index can only be non null for Multi-STA Block Ack");
851   NS_ASSERT (index < m_baInfo.size ());
852 
853   Buffer::Iterator i = start;
854   switch (m_baType.m_variant)
855     {
856       case BlockAckType::BASIC:
857       case BlockAckType::COMPRESSED:
858       case BlockAckType::EXTENDED_COMPRESSED:
859       case BlockAckType::MULTI_STA:
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;
865       case BlockAckType::MULTI_TID:
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
SetReceivedPacket(uint16_t seq,std::size_t index)876 CtrlBAckResponseHeader::SetReceivedPacket (uint16_t seq, std::size_t index)
877 {
878   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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;
893       case BlockAckType::COMPRESSED:
894       case BlockAckType::EXTENDED_COMPRESSED:
895       case BlockAckType::MULTI_STA:
896         {
897           uint16_t i = IndexInBitmap (seq, index);
898           m_baInfo[index].m_bitmap[i / 8] |= (uint8_t (0x01) << (i % 8));
899           break;
900         }
901       case BlockAckType::MULTI_TID:
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
SetReceivedFragment(uint16_t seq,uint8_t frag)911 CtrlBAckResponseHeader::SetReceivedFragment (uint16_t seq, uint8_t frag)
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;
923       case BlockAckType::COMPRESSED:
924       case BlockAckType::EXTENDED_COMPRESSED:
925       case BlockAckType::MULTI_STA:
926         /* We can ignore this...compressed block ack doesn't support
927            acknowledgment of single fragments */
928         break;
929       case BlockAckType::MULTI_TID:
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
IsPacketReceived(uint16_t seq,std::size_t index) const939 CtrlBAckResponseHeader::IsPacketReceived (uint16_t seq, std::size_t index) const
940 {
941   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
942                  "index can only be non null for Multi-STA Block Ack");
943   NS_ASSERT (index < m_baInfo.size ());
944 
945   if (m_baType.m_variant == BlockAckType::MULTI_STA
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;
960       case BlockAckType::COMPRESSED:
961       case BlockAckType::EXTENDED_COMPRESSED:
962       case BlockAckType::MULTI_STA:
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         }
968       case BlockAckType::MULTI_TID:
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
IsFragmentReceived(uint16_t seq,uint8_t frag) const979 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;
990       case BlockAckType::COMPRESSED:
991       case BlockAckType::EXTENDED_COMPRESSED:
992       case BlockAckType::MULTI_STA:
993         /* We can ignore this...compressed block ack doesn't support
994            acknowledgement of single fragments */
995         return false;
996       case BlockAckType::MULTI_TID:
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
IndexInBitmap(uint16_t seq,std::size_t index) const1011 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 
1025   if (m_baType.m_variant == BlockAckType::BASIC)
1026     {
1027       nAckedMpdus = nAckedMpdus / 16;
1028     }
1029 
1030   NS_ASSERT (i < nAckedMpdus);
1031   return i;
1032 }
1033 
1034 bool
IsInBitmap(uint16_t seq,std::size_t index) const1035 CtrlBAckResponseHeader::IsInBitmap (uint16_t seq, std::size_t index) const
1036 {
1037   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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 
1043   if (m_baType.m_variant == BlockAckType::BASIC)
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>&
GetBitmap(std::size_t index) const1052 CtrlBAckResponseHeader::GetBitmap (std::size_t index) const
1053 {
1054   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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
ResetBitmap(std::size_t index)1062 CtrlBAckResponseHeader::ResetBitmap (std::size_t index)
1063 {
1064   NS_ASSERT_MSG (m_baType.m_variant == BlockAckType::MULTI_STA || index == 0,
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 
CtrlTriggerUserInfoField(uint8_t triggerType)1076 CtrlTriggerUserInfoField::CtrlTriggerUserInfoField (uint8_t triggerType)
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 
~CtrlTriggerUserInfoField()1089 CtrlTriggerUserInfoField::~CtrlTriggerUserInfoField ()
1090 {
1091 }
1092 
1093 CtrlTriggerUserInfoField&
operator =(const CtrlTriggerUserInfoField & userInfo)1094 CtrlTriggerUserInfoField::operator= (const CtrlTriggerUserInfoField& userInfo)
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;
1106   m_ulFecCodingType = userInfo.m_ulFecCodingType;
1107   m_ulMcs = userInfo.m_ulMcs;
1108   m_ulDcm = userInfo.m_ulDcm;
1109   m_bits26To31 = userInfo.m_bits26To31;
1110   m_ulTargetRssi = userInfo.m_ulTargetRssi;
1111   m_basicTriggerDependentUserInfo = userInfo.m_basicTriggerDependentUserInfo;
1112   m_muBarTriggerDependentUserInfo = userInfo.m_muBarTriggerDependentUserInfo;
1113   return *this;
1114 }
1115 
1116 void
Print(std::ostream & os) const1117 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
GetSerializedSize(void) const1123 CtrlTriggerUserInfoField::GetSerializedSize (void) const
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 
1143 Buffer::Iterator
Serialize(Buffer::Iterator start) const1144 CtrlTriggerUserInfoField::Serialize (Buffer::Iterator start) const
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 
1176   if (m_triggerType == BASIC_TRIGGER)
1177     {
1178       i.WriteU8 (m_basicTriggerDependentUserInfo);
1179     }
1180   else if (m_triggerType == MU_BAR_TRIGGER)
1181     {
1182       m_muBarTriggerDependentUserInfo.Serialize (i);
1183       i.Next (m_muBarTriggerDependentUserInfo.GetSerializedSize ());
1184     }
1185 
1186   return i;
1187 }
1188 
1189 Buffer::Iterator
Deserialize(Buffer::Iterator start)1190 CtrlTriggerUserInfoField::Deserialize (Buffer::Iterator start)
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 
1220   if (m_triggerType == BASIC_TRIGGER)
1221     {
1222       m_basicTriggerDependentUserInfo= i.ReadU8 ();
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 
1233 TriggerFrameType
GetType(void) const1234 CtrlTriggerUserInfoField::GetType (void) const
1235 {
1236   return static_cast<TriggerFrameType> (m_triggerType);
1237 }
1238 
1239 void
SetAid12(uint16_t aid)1240 CtrlTriggerUserInfoField::SetAid12 (uint16_t aid)
1241 {
1242   m_aid12 = aid & 0x0fff;
1243 }
1244 
1245 uint16_t
GetAid12(void) const1246 CtrlTriggerUserInfoField::GetAid12 (void) const
1247 {
1248   return m_aid12;
1249 }
1250 
1251 bool
HasRaRuForAssociatedSta(void) const1252 CtrlTriggerUserInfoField::HasRaRuForAssociatedSta (void) const
1253 {
1254   return (m_aid12 == 0);
1255 }
1256 
1257 bool
HasRaRuForUnassociatedSta(void) const1258 CtrlTriggerUserInfoField::HasRaRuForUnassociatedSta (void) const
1259 {
1260   return (m_aid12 == 2045);
1261 }
1262 
1263 void
SetRuAllocation(HeRu::RuSpec ru)1264 CtrlTriggerUserInfoField::SetRuAllocation (HeRu::RuSpec ru)
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 
1305 HeRu::RuSpec
GetRuAllocation(void) const1306 CtrlTriggerUserInfoField::GetRuAllocation (void) const
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
SetUlFecCodingType(bool ldpc)1359 CtrlTriggerUserInfoField::SetUlFecCodingType (bool ldpc)
1360 {
1361   m_ulFecCodingType = ldpc;
1362 }
1363 
1364 bool
GetUlFecCodingType(void) const1365 CtrlTriggerUserInfoField::GetUlFecCodingType (void) const
1366 {
1367   return m_ulFecCodingType;
1368 }
1369 
1370 void
SetUlMcs(uint8_t mcs)1371 CtrlTriggerUserInfoField::SetUlMcs (uint8_t mcs)
1372 {
1373   NS_ABORT_MSG_IF (mcs > 11, "Invalid MCS index");
1374   m_ulMcs = mcs;
1375 }
1376 
1377 uint8_t
GetUlMcs(void) const1378 CtrlTriggerUserInfoField::GetUlMcs (void) const
1379 {
1380   return m_ulMcs;
1381 }
1382 
1383 void
SetUlDcm(bool dcm)1384 CtrlTriggerUserInfoField::SetUlDcm (bool dcm)
1385 {
1386   m_ulDcm = dcm;
1387 }
1388 
1389 bool
GetUlDcm(void) const1390 CtrlTriggerUserInfoField::GetUlDcm (void) const
1391 {
1392   return m_ulDcm;
1393 }
1394 
1395 void
SetSsAllocation(uint8_t startingSs,uint8_t nSs)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
GetStartingSs(void) const1407 CtrlTriggerUserInfoField::GetStartingSs (void) const
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
GetNss(void) const1417 CtrlTriggerUserInfoField::GetNss (void) const
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
SetRaRuInformation(uint8_t nRaRu,bool moreRaRu)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
GetNRaRus(void) const1437 CtrlTriggerUserInfoField::GetNRaRus (void) const
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
GetMoreRaRu(void) const1445 CtrlTriggerUserInfoField::GetMoreRaRu (void) const
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
SetUlTargetRssiMaxTxPower(void)1453 CtrlTriggerUserInfoField::SetUlTargetRssiMaxTxPower (void)
1454 {
1455   m_ulTargetRssi = 127;  // see Table 9-25i of 802.11ax amendment D3.0
1456 }
1457 
1458 void
SetUlTargetRssi(int8_t dBm)1459 CtrlTriggerUserInfoField::SetUlTargetRssi (int8_t dBm)
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
IsUlTargetRssiMaxTxPower(void) const1467 CtrlTriggerUserInfoField::IsUlTargetRssiMaxTxPower (void) const
1468 {
1469   return (m_ulTargetRssi == 127);
1470 }
1471 
1472 int8_t
GetUlTargetRssi(void) const1473 CtrlTriggerUserInfoField::GetUlTargetRssi (void) const
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
SetBasicTriggerDepUserInfo(uint8_t spacingFactor,uint8_t tidLimit,AcIndex prefAc)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
GetMpduMuSpacingFactor(void) const1492 CtrlTriggerUserInfoField::GetMpduMuSpacingFactor (void) const
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
GetTidAggregationLimit(void) const1500 CtrlTriggerUserInfoField::GetTidAggregationLimit (void) const
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
GetPreferredAc(void) const1508 CtrlTriggerUserInfoField::GetPreferredAc (void) const
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
SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader & bar)1516 CtrlTriggerUserInfoField::SetMuBarTriggerDepUserInfo (const CtrlBAckRequestHeader& bar)
1517 {
1518   NS_ABORT_MSG_IF (m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1519   NS_ABORT_MSG_IF (bar.GetType ().m_variant != BlockAckReqType::COMPRESSED
1520                    && bar.GetType ().m_variant != BlockAckReqType::MULTI_TID,
1521                    "BAR Control indicates it is neither the Compressed nor the Multi-TID variant");
1522   m_muBarTriggerDependentUserInfo = bar;
1523 }
1524 
1525 const CtrlBAckRequestHeader&
GetMuBarTriggerDepUserInfo(void) const1526 CtrlTriggerUserInfoField::GetMuBarTriggerDepUserInfo (void) const
1527 {
1528   NS_ABORT_MSG_IF (m_triggerType != MU_BAR_TRIGGER, "Not a MU-BAR Trigger frame");
1529 
1530   return m_muBarTriggerDependentUserInfo;
1531 }
1532 
1533 /***********************************
1534  *       Trigger frame
1535  ***********************************/
1536 
1537 NS_OBJECT_ENSURE_REGISTERED (CtrlTriggerHeader);
1538 
CtrlTriggerHeader()1539 CtrlTriggerHeader::CtrlTriggerHeader ()
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 
CtrlTriggerHeader(TriggerFrameType type,const WifiTxVector & txVector)1551 CtrlTriggerHeader::CtrlTriggerHeader (TriggerFrameType type, const WifiTxVector& txVector)
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     {
1568       CtrlTriggerUserInfoField& ui = AddUserInfoField ();
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 
~CtrlTriggerHeader()1576 CtrlTriggerHeader::~CtrlTriggerHeader ()
1577 {
1578 }
1579 
1580 CtrlTriggerHeader&
operator =(const CtrlTriggerHeader & trigger)1581 CtrlTriggerHeader::operator= (const CtrlTriggerHeader& trigger)
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;
1596   m_ulSpatialReuse = trigger.m_ulSpatialReuse;
1597   m_userInfoFields.clear ();
1598   m_userInfoFields = trigger.m_userInfoFields;
1599   return *this;
1600 }
1601 
1602 TypeId
GetTypeId(void)1603 CtrlTriggerHeader::GetTypeId (void)
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
GetInstanceTypeId(void) const1614 CtrlTriggerHeader::GetInstanceTypeId (void) const
1615 {
1616   return GetTypeId ();
1617 }
1618 
1619 void
Print(std::ostream & os) const1620 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
GetSerializedSize(void) const1632 CtrlTriggerHeader::GetSerializedSize (void) const
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
1638   if (m_triggerType == GCR_MU_BAR_TRIGGER)
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
Serialize(Buffer::Iterator start) const1654 CtrlTriggerHeader::Serialize (Buffer::Iterator start) const
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
Deserialize(Buffer::Iterator start)1683 CtrlTriggerHeader::Deserialize (Buffer::Iterator start)
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);
1717           CtrlTriggerUserInfoField& ui = AddUserInfoField ();
1718           i = ui.Deserialize (i);
1719         }
1720     }
1721 
1722   return i.GetDistanceFrom (start);
1723 }
1724 
1725 void
SetType(TriggerFrameType type)1726 CtrlTriggerHeader::SetType (TriggerFrameType type)
1727 {
1728   m_triggerType = type;
1729 }
1730 
1731 TriggerFrameType
GetType(void) const1732 CtrlTriggerHeader::GetType (void) const
1733 {
1734   return static_cast<TriggerFrameType> (m_triggerType);
1735 }
1736 
1737 const char *
GetTypeString(void) const1738 CtrlTriggerHeader::GetTypeString (void) const
1739 {
1740   return GetTypeString (GetType ());
1741 }
1742 
1743 const char *
GetTypeString(TriggerFrameType type)1744 CtrlTriggerHeader::GetTypeString (TriggerFrameType type)
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);
1758       FOO (GCR_MU_BAR_TRIGGER);
1759       FOO (BQRP_TRIGGER);
1760       FOO (NFRP_TRIGGER);
1761     default:
1762       return "ERROR";
1763     }
1764 #undef FOO
1765 }
1766 
1767 bool
IsBasic(void) const1768 CtrlTriggerHeader::IsBasic (void) const
1769 {
1770   return (m_triggerType == BASIC_TRIGGER);
1771 }
1772 
1773 bool
IsBfrp(void) const1774 CtrlTriggerHeader::IsBfrp (void) const
1775 {
1776   return (m_triggerType == BFRP_TRIGGER);
1777 }
1778 
1779 bool
IsMuBar(void) const1780 CtrlTriggerHeader::IsMuBar (void) const
1781 {
1782   return (m_triggerType == MU_BAR_TRIGGER);
1783 }
1784 
1785 bool
IsMuRts(void) const1786 CtrlTriggerHeader::IsMuRts (void) const
1787 {
1788   return (m_triggerType == MU_RTS_TRIGGER);
1789 }
1790 
1791 bool
IsBsrp(void) const1792 CtrlTriggerHeader::IsBsrp (void) const
1793 {
1794   return (m_triggerType == BSRP_TRIGGER);
1795 }
1796 
1797 bool
IsGcrMuBar(void) const1798 CtrlTriggerHeader::IsGcrMuBar (void) const
1799 {
1800   return (m_triggerType == GCR_MU_BAR_TRIGGER);
1801 }
1802 
1803 bool
IsBqrp(void) const1804 CtrlTriggerHeader::IsBqrp (void) const
1805 {
1806   return (m_triggerType == BQRP_TRIGGER);
1807 }
1808 
1809 bool
IsNfrp(void) const1810 CtrlTriggerHeader::IsNfrp (void) const
1811 {
1812   return (m_triggerType == NFRP_TRIGGER);
1813 }
1814 
1815 void
SetUlLength(uint16_t len)1816 CtrlTriggerHeader::SetUlLength (uint16_t len)
1817 {
1818   m_ulLength = (len & 0x0fff);
1819 }
1820 
1821 uint16_t
GetUlLength(void) const1822 CtrlTriggerHeader::GetUlLength (void) const
1823 {
1824   return m_ulLength;
1825 }
1826 
1827 WifiTxVector
GetHeTbTxVector(uint16_t staId) const1828 CtrlTriggerHeader::GetHeTbTxVector (uint16_t staId) const
1829 {
1830   auto userInfoIt = FindUserInfoWithAid (staId);
1831   NS_ASSERT (userInfoIt != end ());
1832 
1833   WifiTxVector v;
1834   v.SetPreambleType (WifiPreamble::WIFI_PREAMBLE_HE_TB);
1835   v.SetChannelWidth (GetUlBandwidth ());
1836   v.SetGuardInterval (GetGuardInterval ());
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
SetMoreTF(bool more)1845 CtrlTriggerHeader::SetMoreTF (bool more)
1846 {
1847   m_moreTF = more;
1848 }
1849 
1850 bool
GetMoreTF(void) const1851 CtrlTriggerHeader::GetMoreTF (void) const
1852 {
1853   return m_moreTF;
1854 }
1855 
1856 void
SetCsRequired(bool cs)1857 CtrlTriggerHeader::SetCsRequired (bool cs)
1858 {
1859   m_csRequired = cs;
1860 }
1861 
1862 bool
GetCsRequired(void) const1863 CtrlTriggerHeader::GetCsRequired (void) const
1864 {
1865   return m_csRequired;
1866 }
1867 
1868 void
SetUlBandwidth(uint16_t bw)1869 CtrlTriggerHeader::SetUlBandwidth (uint16_t bw)
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
GetUlBandwidth(void) const1892 CtrlTriggerHeader::GetUlBandwidth (void) const
1893 {
1894   return (1 << m_ulBandwidth) * 20;
1895 }
1896 
1897 void
SetGiAndLtfType(uint16_t guardInterval,uint8_t ltfType)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
GetGuardInterval(void) const1919 CtrlTriggerHeader::GetGuardInterval (void) const
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
GetLtfType(void) const1936 CtrlTriggerHeader::GetLtfType (void) const
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
SetApTxPower(int8_t power)1957 CtrlTriggerHeader::SetApTxPower (int8_t power)
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
GetApTxPower(void) const1966 CtrlTriggerHeader::GetApTxPower (void) const
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
SetUlSpatialReuse(uint16_t sr)1973 CtrlTriggerHeader::SetUlSpatialReuse (uint16_t sr)
1974 {
1975   m_ulSpatialReuse = sr;
1976 }
1977 
1978 uint16_t
GetUlSpatialReuse(void) const1979 CtrlTriggerHeader::GetUlSpatialReuse (void) const
1980 {
1981   return m_ulSpatialReuse;
1982 }
1983 
1984 CtrlTriggerHeader
GetCommonInfoField(void) const1985 CtrlTriggerHeader::GetCommonInfoField (void) const
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 
1993 CtrlTriggerUserInfoField&
AddUserInfoField(void)1994 CtrlTriggerHeader::AddUserInfoField (void)
1995 {
1996   m_userInfoFields.emplace_back (m_triggerType);
1997   return m_userInfoFields.back ();
1998 }
1999 
2000 CtrlTriggerUserInfoField&
AddUserInfoField(const CtrlTriggerUserInfoField & userInfo)2001 CtrlTriggerHeader::AddUserInfoField (const CtrlTriggerUserInfoField& userInfo)
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 
2009 CtrlTriggerHeader::ConstIterator
begin(void) const2010 CtrlTriggerHeader::begin (void) const
2011 {
2012   return m_userInfoFields.begin ();
2013 }
2014 
2015 CtrlTriggerHeader::ConstIterator
end(void) const2016 CtrlTriggerHeader::end (void) const
2017 {
2018   return m_userInfoFields.end ();
2019 }
2020 
2021 CtrlTriggerHeader::Iterator
begin(void)2022 CtrlTriggerHeader::begin (void)
2023 {
2024   return m_userInfoFields.begin ();
2025 }
2026 
2027 CtrlTriggerHeader::Iterator
end(void)2028 CtrlTriggerHeader::end (void)
2029 {
2030   return m_userInfoFields.end ();
2031 }
2032 
2033 std::size_t
GetNUserInfoFields(void) const2034 CtrlTriggerHeader::GetNUserInfoFields (void) const
2035 {
2036   return m_userInfoFields.size ();
2037 }
2038 
2039 CtrlTriggerHeader::ConstIterator
FindUserInfoWithAid(ConstIterator start,uint16_t aid12) const2040 CtrlTriggerHeader::FindUserInfoWithAid (ConstIterator start, uint16_t aid12) const
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 
2048 CtrlTriggerHeader::ConstIterator
FindUserInfoWithAid(uint16_t aid12) const2049 CtrlTriggerHeader::FindUserInfoWithAid (uint16_t aid12) const
2050 {
2051   return FindUserInfoWithAid (m_userInfoFields.begin (), aid12);
2052 }
2053 
2054 CtrlTriggerHeader::ConstIterator
FindUserInfoWithRaRuAssociated(ConstIterator start) const2055 CtrlTriggerHeader::FindUserInfoWithRaRuAssociated (ConstIterator start) const
2056 {
2057   return FindUserInfoWithAid (start, 0);
2058 }
2059 
2060 CtrlTriggerHeader::ConstIterator
FindUserInfoWithRaRuAssociated(void) const2061 CtrlTriggerHeader::FindUserInfoWithRaRuAssociated (void) const
2062 {
2063   return FindUserInfoWithAid (0);
2064 }
2065 
2066 CtrlTriggerHeader::ConstIterator
FindUserInfoWithRaRuUnassociated(ConstIterator start) const2067 CtrlTriggerHeader::FindUserInfoWithRaRuUnassociated (ConstIterator start) const
2068 {
2069   return FindUserInfoWithAid (start, 2045);
2070 }
2071 
2072 CtrlTriggerHeader::ConstIterator
FindUserInfoWithRaRuUnassociated(void) const2073 CtrlTriggerHeader::FindUserInfoWithRaRuUnassociated (void) const
2074 {
2075   return FindUserInfoWithAid (2045);
2076 }
2077 
2078 bool
IsValid(void) const2079 CtrlTriggerHeader::IsValid (void) const
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
2097