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