A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
radiotap-header.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 CTTC
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Authors: Nicola Baldo <nbaldo@cttc.es>
7 * Sébastien Deronne <sebastien.deronne@gmail.com>
8 */
9
10#include "radiotap-header.h"
11
12#include "ns3/log.h"
13
14#include <bit>
15#include <cmath>
16#include <iomanip>
17
18namespace ns3
19{
20
21NS_LOG_COMPONENT_DEFINE("RadiotapHeader");
22
23NS_OBJECT_ENSURE_REGISTERED(RadiotapHeader);
24
29
32{
33 static TypeId tid = TypeId("ns3::RadiotapHeader")
35 .SetGroupName("Network")
36
37 .AddConstructor<RadiotapHeader>();
38 return tid;
39}
40
43{
44 return GetTypeId();
45}
46
49{
50 NS_LOG_FUNCTION(this);
51 return m_length;
52}
53
54void
56{
57 NS_LOG_FUNCTION(this << &start);
58
59 start.WriteU8(0); // major version of radiotap header
60 start.WriteU8(0); // pad field
61 start.WriteU16(m_length); // entire length of radiotap data + header
62 NS_ASSERT(!m_present.empty());
63 for (const auto present : m_present)
64 {
65 start.WriteU32(present); // bits describing which fields follow header
66 }
67
68 //
69 // Time Synchronization Function Timer (when the first bit of the MPDU
70 // arrived at the MAC)
71 // Reference: https://www.radiotap.org/fields/TSFT.html
72 //
73 if (m_present.at(0) & RADIOTAP_TSFT) // bit 0
74 {
75 SerializeTsft(start);
76 }
77
78 //
79 // Properties of transmitted and received frames.
80 // Reference: https://www.radiotap.org/fields/Flags.html
81 //
82 if (m_present.at(0) & RADIOTAP_FLAGS) // bit 1
83 {
84 start.WriteU8(m_flags);
85 }
86
87 //
88 // TX/RX data rate in units of 500 kbps
89 // Reference: https://www.radiotap.org/fields/Rate.html
90 //
91 if (m_present.at(0) & RADIOTAP_RATE) // bit 2
92 {
93 start.WriteU8(m_rate);
94 }
95
96 //
97 // Tx/Rx frequency in MHz, followed by flags.
98 // Reference: https://www.radiotap.org/fields/Channel.html
99 //
100 if (m_present.at(0) & RADIOTAP_CHANNEL) // bit 3
101 {
102 SerializeChannel(start);
103 }
104
105 //
106 // The hop set and pattern for frequency-hopping radios. We don't need it but
107 // still need to account for it.
108 // Reference: https://www.radiotap.org/fields/FHSS.html
109 //
110 if (m_present.at(0) & RADIOTAP_FHSS) // bit 4
111 {
112 NS_ASSERT(false); // not yet implemented
113 }
114
115 //
116 // RF signal power at the antenna, decibel difference from an arbitrary, fixed
117 // reference.
118 // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
119 //
120 if (m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL) // bit 5
121 {
122 start.WriteU8(m_antennaSignal);
123 }
124
125 //
126 // RF noise power at the antenna, decibel difference from an arbitrary, fixed
127 // reference.
128 // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
129 //
130 if (m_present.at(0) & RADIOTAP_DBM_ANTNOISE) // bit 6
131 {
132 start.WriteU8(m_antennaNoise);
133 }
134
135 //
136 // Quality of Barker code lock.
137 // Reference: https://www.radiotap.org/fields/Lock%20quality.html
138 //
139 if (m_present.at(0) & RADIOTAP_LOCK_QUALITY) // bit 7
140 {
141 NS_ASSERT(false); // not yet implemented
142 }
143
144 //
145 // Transmit power expressed as unitless distance from max power
146 // set at factory calibration (0 is max power).
147 // Reference: https://www.radiotap.org/fields/TX%20attenuation.html
148 //
149 if (m_present.at(0) & RADIOTAP_TX_ATTENUATION) // bit 8
150 {
151 NS_ASSERT(false); // not yet implemented
152 }
153
154 //
155 // Transmit power expressed as decibel distance from max power
156 // set at factory calibration (0 is max power).
157 // Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
158 //
159 if (m_present.at(0) & RADIOTAP_DB_TX_ATTENUATION) // bit 9
160 {
161 NS_ASSERT(false); // not yet implemented
162 }
163
164 //
165 // Transmit power expressed as dBm (decibels from a 1 milliwatt reference).
166 // This is the absolute power level measured at the antenna port.
167 // Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
168 //
169 if (m_present.at(0) & RADIOTAP_DBM_TX_POWER) // bit 10
170 {
171 NS_ASSERT(false); // not yet implemented
172 }
173
174 //
175 // Unitless indication of the Rx/Tx antenna for this packet.
176 // The first antenna is antenna 0.
177 // Reference: https://www.radiotap.org/fields/Antenna.html
178 //
179 if (m_present.at(0) & RADIOTAP_ANTENNA) // bit 11
180 {
181 NS_ASSERT(false); // not yet implemented
182 }
183
184 //
185 // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
186 // Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
187 //
188 if (m_present.at(0) & RADIOTAP_DB_ANTSIGNAL) // bit 12
189 {
190 NS_ASSERT(false); // not yet implemented
191 }
192
193 //
194 // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
195 // Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
196 //
197 if (m_present.at(0) & RADIOTAP_DB_ANTNOISE) // bit 13
198 {
199 NS_ASSERT(false); // not yet implemented
200 }
201
202 //
203 // Properties of received frames.
204 // Reference: https://www.radiotap.org/fields/RX%20flags.html
205 //
206 if (m_present.at(0) & RADIOTAP_RX_FLAGS) // bit 14
207 {
208 NS_ASSERT(false); // not yet implemented
209 }
210
211 //
212 // MCS field.
213 // Reference: https://www.radiotap.org/fields/MCS.html
214 //
215 if (m_present.at(0) & RADIOTAP_MCS) // bit 19
216 {
217 SerializeMcs(start);
218 }
219
220 //
221 // A-MPDU Status, information about the received or transmitted A-MPDU.
222 // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
223 //
224 if (m_present.at(0) & RADIOTAP_AMPDU_STATUS) // bit 20
225 {
227 }
228
229 //
230 // Information about the received or transmitted VHT frame.
231 // Reference: https://www.radiotap.org/fields/VHT.html
232 //
233 if (m_present.at(0) & RADIOTAP_VHT) // bit 21
234 {
235 SerializeVht(start);
236 }
237
238 //
239 // HE field.
240 // Reference: https://www.radiotap.org/fields/HE.html
241 //
242 if (m_present.at(0) & RADIOTAP_HE) // bit 23
243 {
244 SerializeHe(start);
245 }
246
247 //
248 // HE MU field.
249 // Reference: https://www.radiotap.org/fields/HE-MU.html
250 //
251 if (m_present.at(0) & RADIOTAP_HE_MU) // bit 24
252 {
253 SerializeHeMu(start);
254 }
255
256 //
257 // HE MU other user field.
258 // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
259 //
260 if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER) // bit 25
261 {
263 }
264
265 //
266 // U-SIG field.
267 // Reference: https://www.radiotap.org/fields/U-SIG.html
268 //
269 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG) // bit 33
270 {
271 SerializeUsig(start);
272 }
273
274 //
275 // EHT field.
276 // Reference: https://www.radiotap.org/fields/EHT.html
277 //
278 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG) // bit 34
279 {
280 SerializeEht(start);
281 }
282}
283
286{
287 NS_LOG_FUNCTION(this << &start);
288
289 uint8_t tmp = start.ReadU8(); // major version of radiotap header
290 NS_ASSERT_MSG(tmp == 0x00, "RadiotapHeader::Deserialize(): Unexpected major version");
291 start.ReadU8(); // pad field
292
293 m_length = start.ReadU16(); // entire length of radiotap data + header
294 m_present.emplace_back(start.ReadU32()); // bits describing which fields follow header
295 uint32_t bytesRead = MIN_HEADER_SIZE;
296
297 std::size_t index{0};
298 while (m_present.at(index++) & RADIOTAP_EXT)
299 {
300 // If bit 31 of the it_present field is set, another it_present bitmask is present.
301 m_present.emplace_back(start.ReadU32());
302 bytesRead += 4;
303 }
304
305 //
306 // Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
307 // Reference: https://www.radiotap.org/fields/TSFT.html
308 //
309 if (m_present.at(0) & RADIOTAP_TSFT) // bit 0
310 {
311 bytesRead += DeserializeTsft(start, bytesRead);
312 }
313
314 //
315 // Properties of transmitted and received frames.
316 // Reference: https://www.radiotap.org/fields/Flags.html
317 //
318 if (m_present.at(0) & RADIOTAP_FLAGS) // bit 1
319 {
320 m_flags = start.ReadU8();
321 ++bytesRead;
322 }
323
324 //
325 // TX/RX data rate in units of 500 kbps
326 // Reference: https://www.radiotap.org/fields/Rate.html
327 //
328 if (m_present.at(0) & RADIOTAP_RATE) // bit 2
329 {
330 m_rate = start.ReadU8();
331 ++bytesRead;
332 }
333
334 //
335 // Tx/Rx frequency in MHz, followed by flags.
336 // Reference: https://www.radiotap.org/fields/Channel.html
337 //
338 if (m_present.at(0) & RADIOTAP_CHANNEL) // bit 3
339 {
340 bytesRead += DeserializeChannel(start, bytesRead);
341 }
342
343 //
344 // The hop set and pattern for frequency-hopping radios. We don't need it but
345 // still need to account for it.
346 // Reference: https://www.radiotap.org/fields/FHSS.html
347 //
348 if (m_present.at(0) & RADIOTAP_FHSS) // bit 4
349 {
350 NS_ASSERT(false); // not yet implemented
351 }
352
353 //
354 // RF signal power at the antenna, decibel difference from an arbitrary, fixed
355 // reference.
356 // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
357 //
358 if (m_present.at(0) & RADIOTAP_DBM_ANTSIGNAL) // bit 5
359 {
360 m_antennaSignal = start.ReadU8();
361 ++bytesRead;
362 }
363
364 //
365 // RF noise power at the antenna, decibel difference from an arbitrary, fixed
366 // reference.
367 // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
368 //
369 if (m_present.at(0) & RADIOTAP_DBM_ANTNOISE) // bit 6
370 {
371 m_antennaNoise = start.ReadU8();
372 ++bytesRead;
373 }
374
375 //
376 // Quality of Barker code lock.
377 // Reference: https://www.radiotap.org/fields/Lock%20quality.html
378 //
379 if (m_present.at(0) & RADIOTAP_LOCK_QUALITY) // bit 7
380 {
381 NS_ASSERT(false); // not yet implemented
382 }
383
384 //
385 // Transmit power expressed as unitless distance from max power
386 // set at factory calibration (0 is max power).
387 // Reference: https://www.radiotap.org/fields/TX%20attenuation.html
388 //
389 if (m_present.at(0) & RADIOTAP_TX_ATTENUATION) // bit 8
390 {
391 NS_ASSERT(false); // not yet implemented
392 }
393
394 //
395 // Transmit power expressed as decibel distance from max power
396 // set at factory calibration (0 is max power).
397 // Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
398 //
399 if (m_present.at(0) & RADIOTAP_DB_TX_ATTENUATION) // bit 9
400 {
401 NS_ASSERT(false); // not yet implemented
402 }
403
404 //
405 // Transmit power expressed as dBm (decibels from a 1 milliwatt reference).
406 // This is the absolute power level measured at the antenna port.
407 // Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
408 //
409 if (m_present.at(0) & RADIOTAP_DBM_TX_POWER) // bit 10
410 {
411 NS_ASSERT(false); // not yet implemented
412 }
413
414 //
415 // Unitless indication of the Rx/Tx antenna for this packet.
416 // The first antenna is antenna 0.
417 // Reference: https://www.radiotap.org/fields/Antenna.html
418 //
419 if (m_present.at(0) & RADIOTAP_ANTENNA) // bit 11
420 {
421 NS_ASSERT(false); // not yet implemented
422 }
423
424 //
425 // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
426 // Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
427 //
428 if (m_present.at(0) & RADIOTAP_DB_ANTSIGNAL) // bit 12
429 {
430 NS_ASSERT(false); // not yet implemented
431 }
432
433 //
434 // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
435 // Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
436 //
437 if (m_present.at(0) & RADIOTAP_DB_ANTNOISE) // bit 13
438 {
439 NS_ASSERT(false); // not yet implemented
440 }
441
442 //
443 // Properties of received frames.
444 // Reference: https://www.radiotap.org/fields/RX%20flags.html
445 //
446 if (m_present.at(0) & RADIOTAP_RX_FLAGS) // bit 14
447 {
448 NS_ASSERT(false); // not yet implemented
449 }
450
451 //
452 // MCS field.
453 // Reference: https://www.radiotap.org/fields/MCS.html
454 //
455 if (m_present.at(0) & RADIOTAP_MCS) // bit 19
456 {
457 bytesRead += DeserializeMcs(start, bytesRead);
458 }
459
460 //
461 // A-MPDU Status, information about the received or transmitted A-MPDU.
462 // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
463 //
465 {
466 bytesRead += DeserializeAmpduStatus(start, bytesRead);
467 }
468
469 //
470 // Information about the received or transmitted VHT frame.
471 // Reference: https://www.radiotap.org/fields/VHT.html
472 //
473 if (m_present.at(0) & RADIOTAP_VHT) // bit 21
474 {
475 bytesRead += DeserializeVht(start, bytesRead);
476 }
477
478 //
479 // HE field.
480 // Reference: https://www.radiotap.org/fields/HE.html
481 //
482 if (m_present.at(0) & RADIOTAP_HE) // bit 23
483 {
484 bytesRead += DeserializeHe(start, bytesRead);
485 }
486
487 //
488 // HE MU field.
489 // Reference: https://www.radiotap.org/fields/HE-MU.html
490 //
491 if (m_present.at(0) & RADIOTAP_HE_MU) // bit 24
492 {
493 bytesRead += DeserializeHeMu(start, bytesRead);
494 }
495
496 //
497 // HE MU other user field.
498 // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
499 //
500 if (m_present.at(0) & RADIOTAP_HE_MU_OTHER_USER) // bit 25
501 {
502 bytesRead += DeserializeHeMuOtherUser(start, bytesRead);
503 }
504
505 //
506 // U-SIG field.
507 // Reference: https://www.radiotap.org/fields/U-SIG.html
508 //
509 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG) // bit 33
510 {
511 bytesRead += DeserializeUsig(start, bytesRead);
512 }
513
514 //
515 // EHT field.
516 // Reference: https://www.radiotap.org/fields/EHT.html
517 //
518 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG) // bit 34
519 {
520 bytesRead += DeserializeEht(start, bytesRead);
521 }
522
523 NS_ASSERT_MSG(m_length == bytesRead,
524 "RadiotapHeader::Deserialize(): expected and actual lengths inconsistent");
525 return bytesRead;
526}
527
528void
529RadiotapHeader::Print(std::ostream& os) const
530{
531 NS_LOG_FUNCTION(this << &os);
532 os << " tsft=" << m_tsft << " flags=" << std::hex << m_flags << std::dec << " rate=" << +m_rate;
533 if (m_present.at(0) & RADIOTAP_CHANNEL)
534 {
535 PrintChannel(os);
536 }
537 os << std::dec << " signal=" << +m_antennaSignal << " noise=" << +m_antennaNoise;
538 if (m_present.at(0) & RADIOTAP_MCS)
539 {
540 PrintMcs(os);
541 }
543 {
545 }
546 if (m_present.at(0) & RADIOTAP_VHT)
547 {
548 PrintVht(os);
549 }
550 if (m_present.at(0) & RADIOTAP_HE)
551 {
552 PrintHe(os);
553 }
554 if (m_present.at(0) & RADIOTAP_HE_MU)
555 {
556 PrintHeMu(os);
557 }
559 {
561 }
562 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG)
563 {
564 PrintUsig(os);
565 }
566 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT_SIG)
567 {
568 PrintEht(os);
569 }
570}
571
572void
573RadiotapHeader::SetWifiHeader(std::size_t numPresentWords)
574{
575 NS_LOG_FUNCTION(this << numPresentWords);
576 NS_ASSERT_MSG(numPresentWords > 0,
577 "RadiotapHeader::SetWifiHeader() requires at least one it_present word");
579 "RadiotapHeader::SetWifiHeader() should be called before any other Set* method");
580 NS_ASSERT_MSG(m_present.size() == 1, "RadiotapHeader::SetWifiHeader() should be called once");
581 for (std::size_t i = 0; i < (numPresentWords - 1); ++i)
582 {
583 m_present.at(i) |= RADIOTAP_EXT;
584 m_present.emplace_back(0);
585 m_length += sizeof(RadiotapExtFlags);
586 }
587}
588
589void
591{
592 NS_LOG_FUNCTION(this << value);
593
594 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_TSFT), "TSFT radiotap field already present");
595 m_tsftPad = ((8 - m_length % 8) % 8);
596 m_present.at(0) |= RADIOTAP_TSFT;
597 m_length += 8 + m_tsftPad;
598 m_tsft = value;
599
600 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
601 << std::dec);
602}
603
604void
606{
607 start.WriteU8(0, m_tsftPad);
608 start.WriteU64(m_tsft);
609}
610
613{
614 m_tsftPad = ((8 - bytesRead % 8) % 8);
615 start.Next(m_tsftPad);
616 m_tsft = start.ReadU64();
617 return sizeof(m_tsft) + m_tsftPad;
618}
619
620void
622{
623 NS_LOG_FUNCTION(this << +flags);
624
625 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_FLAGS), "Flags radiotap field already present");
626 m_present.at(0) |= RADIOTAP_FLAGS;
627 m_length += 1;
628 m_flags = flags;
629
630 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
631 << std::dec);
632}
633
634void
636{
637 NS_LOG_FUNCTION(this << +rate);
638
639 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_RATE), "Rate radiotap field already present");
640 m_present.at(0) |= RADIOTAP_RATE;
641 m_length += 1;
642 m_rate = rate;
643
644 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
645 << std::dec);
646}
647
648void
650{
651 NS_LOG_FUNCTION(this << channelFields.frequency << channelFields.flags);
652
653 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_CHANNEL), "Channel radiotap field already present");
654 m_channelPad = ((2 - m_length % 2) % 2);
656 m_length += (sizeof(ChannelFields) + m_channelPad);
657 m_channelFields = channelFields;
658
659 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
660 << std::dec);
661}
662
663void
665{
666 start.WriteU8(0, m_channelPad);
667 start.WriteU16(m_channelFields.frequency);
668 start.WriteU16(m_channelFields.flags);
669}
670
673{
674 m_channelPad = ((2 - bytesRead % 2) % 2);
675 start.Next(m_channelPad);
676 m_channelFields.frequency = start.ReadU16();
677 m_channelFields.flags = start.ReadU16();
678 return sizeof(ChannelFields) + m_channelPad;
679}
680
681void
682RadiotapHeader::PrintChannel(std::ostream& os) const
683{
684 os << " channel.frequency=" << m_channelFields.frequency << " channel.flags=0x" << std::hex
685 << m_channelFields.flags << std::dec;
686}
687
688void
690{
691 NS_LOG_FUNCTION(this << signal);
692
694 "Antenna signal radiotap field already present");
696 m_length += 1;
697
698 if (signal > 127)
699 {
700 m_antennaSignal = 127;
701 }
702 else if (signal < -128)
703 {
704 m_antennaSignal = -128;
705 }
706 else
707 {
708 m_antennaSignal = static_cast<int8_t>(floor(signal + 0.5));
709 }
710
711 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
712 << std::dec);
713}
714
715void
717{
718 NS_LOG_FUNCTION(this << noise);
719
721 "Antenna noise radiotap field already present");
723 m_length += 1;
724
725 if (noise > 127.0)
726 {
727 m_antennaNoise = 127;
728 }
729 else if (noise < -128.0)
730 {
731 m_antennaNoise = -128;
732 }
733 else
734 {
735 m_antennaNoise = static_cast<int8_t>(floor(noise + 0.5));
736 }
737
738 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
739 << std::dec);
740}
741
742void
744{
745 NS_LOG_FUNCTION(this << +mcsFields.known << +mcsFields.flags << +mcsFields.mcs);
746
747 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_MCS), "MCS radiotap field already present");
748 m_present.at(0) |= RADIOTAP_MCS;
749 m_length += sizeof(McsFields);
750 m_mcsFields = mcsFields;
751
752 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
753 << std::dec);
754}
755
756void
758{
759 start.WriteU8(m_mcsFields.known);
760 start.WriteU8(m_mcsFields.flags);
761 start.WriteU8(m_mcsFields.mcs);
762}
763
766{
767 m_mcsFields.known = start.ReadU8();
768 m_mcsFields.flags = start.ReadU8();
769 m_mcsFields.mcs = start.ReadU8();
770 return sizeof(McsFields);
771}
772
773void
774RadiotapHeader::PrintMcs(std::ostream& os) const
775{
776 os << " mcs.known=0x" << std::hex << +m_mcsFields.known << " mcs.flags0x=" << +m_mcsFields.flags
777 << " mcsRate=" << std::dec << +m_mcsFields.mcs;
778}
779
780void
782{
783 NS_LOG_FUNCTION(this << ampduStatusFields.referenceNumber << ampduStatusFields.flags);
784
786 "A-MPDU status radiotap field already present");
787 m_ampduStatusPad = ((4 - m_length % 4) % 4);
789 m_length += (sizeof(ampduStatusFields) + m_ampduStatusPad);
790 m_ampduStatusFields = ampduStatusFields;
791
792 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
793 << std::dec);
794}
795
796void
798{
799 start.WriteU8(0, m_ampduStatusPad);
800 start.WriteU32(m_ampduStatusFields.referenceNumber);
801 start.WriteU16(m_ampduStatusFields.flags);
802 start.WriteU8(m_ampduStatusFields.crc);
803 start.WriteU8(m_ampduStatusFields.reserved);
804}
805
808{
809 m_ampduStatusPad = ((4 - bytesRead % 4) % 4);
810 start.Next(m_ampduStatusPad);
811 m_ampduStatusFields.referenceNumber = start.ReadU32();
812 m_ampduStatusFields.flags = start.ReadU16();
813 m_ampduStatusFields.crc = start.ReadU8();
814 m_ampduStatusFields.reserved = start.ReadU8();
815 return sizeof(AmpduStatusFields) + m_ampduStatusPad;
816}
817
818void
819RadiotapHeader::PrintAmpduStatus(std::ostream& os) const
820{
821 os << " ampduStatus.flags=0x" << std::hex << m_ampduStatusFields.flags << std::dec;
822}
823
824void
826{
827 NS_LOG_FUNCTION(this << vhtFields.known << vhtFields.flags << +vhtFields.mcsNss.at(0)
828 << +vhtFields.mcsNss.at(1) << +vhtFields.mcsNss.at(2)
829 << +vhtFields.mcsNss.at(3) << +vhtFields.coding << +vhtFields.groupId
830 << +vhtFields.partialAid);
831
832 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_VHT), "VHT radiotap field already present");
833 m_vhtPad = ((2 - m_length % 2) % 2);
834 m_present.at(0) |= RADIOTAP_VHT;
835 m_length += (sizeof(VhtFields) + m_vhtPad);
836 m_vhtFields = vhtFields;
837
838 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
839 << std::dec);
840}
841
842void
844{
845 start.WriteU8(0, m_vhtPad);
846 start.WriteU16(m_vhtFields.known);
847 start.WriteU8(m_vhtFields.flags);
848 start.WriteU8(m_vhtFields.bandwidth);
849 for (const auto mcsNss : m_vhtFields.mcsNss)
850 {
851 start.WriteU8(mcsNss);
852 }
853 start.WriteU8(m_vhtFields.coding);
854 start.WriteU8(m_vhtFields.groupId);
855 start.WriteU16(m_vhtFields.partialAid);
856}
857
860{
861 m_vhtPad = ((2 - bytesRead % 2) % 2);
862 start.Next(m_vhtPad);
863 m_vhtFields.known = start.ReadU16();
864 m_vhtFields.flags = start.ReadU8();
865 m_vhtFields.bandwidth = start.ReadU8();
866 for (auto& mcsNss : m_vhtFields.mcsNss)
867 {
868 mcsNss = start.ReadU8();
869 }
870 m_vhtFields.coding = start.ReadU8();
871 m_vhtFields.groupId = start.ReadU8();
872 m_vhtFields.partialAid = start.ReadU16();
873 return sizeof(VhtFields) + m_vhtPad;
874}
875
876void
877RadiotapHeader::PrintVht(std::ostream& os) const
878{
879 os << " vht.known=0x" << m_vhtFields.known << " vht.flags=0x" << m_vhtFields.flags
880 << " vht.bandwidth=" << std::dec << m_vhtFields.bandwidth
881 << " vht.mcsNss[0]=" << +m_vhtFields.mcsNss.at(0)
882 << " vht.mcsNss[1]=" << +m_vhtFields.mcsNss.at(1)
883 << " vht.mcsNss[2]=" << +m_vhtFields.mcsNss.at(2)
884 << " vht.mcsNss[3]=" << +m_vhtFields.mcsNss.at(3) << " vht.coding=" << m_vhtFields.coding
885 << " vht.groupId=" << m_vhtFields.groupId << " vht.partialAid=" << m_vhtFields.partialAid;
886}
887
888void
890{
891 NS_LOG_FUNCTION(this << heFields.data1 << heFields.data2 << heFields.data3 << heFields.data4
892 << heFields.data5 << heFields.data6);
893
894 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE), "HE radiotap field already present");
895 m_hePad = ((2 - m_length % 2) % 2);
896 m_present.at(0) |= RADIOTAP_HE;
897 m_length += (sizeof(heFields) + m_hePad);
898 m_heFields = heFields;
899
900 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
901 << std::dec);
902}
903
904void
906{
907 start.WriteU8(0, m_hePad);
908 start.WriteU16(m_heFields.data1);
909 start.WriteU16(m_heFields.data2);
910 start.WriteU16(m_heFields.data3);
911 start.WriteU16(m_heFields.data4);
912 start.WriteU16(m_heFields.data5);
913 start.WriteU16(m_heFields.data6);
914}
915
918{
919 m_hePad = ((2 - bytesRead % 2) % 2);
920 start.Next(m_hePad);
921 m_heFields.data1 = start.ReadU16();
922 m_heFields.data2 = start.ReadU16();
923 m_heFields.data3 = start.ReadU16();
924 m_heFields.data4 = start.ReadU16();
925 m_heFields.data5 = start.ReadU16();
926 m_heFields.data6 = start.ReadU16();
927 return sizeof(HeFields) + m_hePad;
928}
929
930void
931RadiotapHeader::PrintHe(std::ostream& os) const
932{
933 os << " he.data1=0x" << std::hex << m_heFields.data1 << " he.data2=0x" << std::hex
934 << m_heFields.data2 << " he.data3=0x" << std::hex << m_heFields.data3 << " he.data4=0x"
935 << std::hex << m_heFields.data4 << " he.data5=0x" << std::hex << m_heFields.data5
936 << " he.data6=0x" << std::hex << m_heFields.data6 << std::dec;
937}
938
939void
941{
942 NS_LOG_FUNCTION(this << heMuFields.flags1 << heMuFields.flags2);
943
944 NS_ASSERT_MSG(!(m_present.at(0) & RADIOTAP_HE_MU), "HE-MU radiotap field already present");
945 m_heMuPad = ((2 - m_length % 2) % 2);
946 m_present.at(0) |= RADIOTAP_HE_MU;
947 m_length += (sizeof(heMuFields) + m_heMuPad);
948 m_heMuFields = heMuFields;
949
950 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
951 << std::dec);
952}
953
954void
956{
957 start.WriteU8(0, m_heMuPad);
958 start.WriteU16(m_heMuFields.flags1);
959 start.WriteU16(m_heMuFields.flags2);
960 for (const auto ruChannel : m_heMuFields.ruChannel1)
961 {
962 start.WriteU8(ruChannel);
963 }
964 for (const auto ruChannel : m_heMuFields.ruChannel2)
965 {
966 start.WriteU8(ruChannel);
967 }
968}
969
972{
973 m_heMuPad = ((2 - bytesRead % 2) % 2);
974 start.Next(m_heMuPad);
975 m_heMuFields.flags1 = start.ReadU16();
976 m_heMuFields.flags2 = start.ReadU16();
977 for (auto& ruChannel : m_heMuFields.ruChannel1)
978 {
979 ruChannel = start.ReadU8();
980 }
981 for (auto& ruChannel : m_heMuFields.ruChannel2)
982 {
983 ruChannel = start.ReadU8();
984 }
985 return sizeof(HeMuFields) + m_heMuPad;
986}
987
988void
989RadiotapHeader::PrintHeMu(std::ostream& os) const
990{
991 os << " heMu.flags1=0x" << std::hex << m_heMuFields.flags1 << " heMu.flags2=0x"
992 << m_heMuFields.flags2 << std::dec;
993}
994
995void
997{
998 NS_LOG_FUNCTION(this << heMuOtherUserFields.perUser1 << heMuOtherUserFields.perUser2
999 << +heMuOtherUserFields.perUserPosition
1000 << +heMuOtherUserFields.perUserKnown);
1001
1003 "HE-MU-other-user radiotap field already present");
1004 m_heMuOtherUserPad = ((2 - m_length % 2) % 2);
1007 m_heMuOtherUserFields = heMuOtherUserFields;
1008
1009 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
1010 << std::dec);
1011}
1012
1013void
1015{
1016 start.WriteU8(0, m_heMuOtherUserPad);
1017 start.WriteU16(m_heMuOtherUserFields.perUser1);
1018 start.WriteU16(m_heMuOtherUserFields.perUser2);
1020 start.WriteU8(m_heMuOtherUserFields.perUserKnown);
1021}
1022
1025{
1026 m_heMuOtherUserPad = ((2 - bytesRead % 2) % 2);
1027 start.Next(m_heMuOtherUserPad);
1028 m_heMuOtherUserFields.perUser1 = start.ReadU16();
1029 m_heMuOtherUserFields.perUser2 = start.ReadU16();
1030 m_heMuOtherUserFields.perUserPosition = start.ReadU8();
1031 m_heMuOtherUserFields.perUserKnown = start.ReadU8();
1032 return sizeof(HeMuOtherUserFields) + m_heMuOtherUserPad;
1033}
1034
1035void
1037{
1038 os << " heMuOtherUser.perUser1=" << m_heMuOtherUserFields.perUser1
1039 << " heMuOtherUser.perUser2=" << m_heMuOtherUserFields.perUser2
1040 << " heMuOtherUser.perUserPosition=" << m_heMuOtherUserFields.perUserPosition
1041 << " heMuOtherUser.perUserKnown=0x" << std::hex << m_heMuOtherUserFields.perUserKnown
1042 << std::dec;
1043}
1044
1045void
1047{
1048 NS_LOG_FUNCTION(this << usigFields.common << usigFields.mask << usigFields.value);
1049 NS_ASSERT_MSG(m_present.size() >= 2,
1050 "Number of it_present words (" << m_present.size() << ") is incorrect");
1051 m_present.at(0) |= RADIOTAP_TLV;
1052
1053 NS_ASSERT_MSG(!(m_present.at(1) & RADIOTAP_USIG), "U-SIG radiotap field already present");
1054 m_present.at(1) |= RADIOTAP_USIG;
1055
1056 m_usigTlvPad = ((8 - m_length % 8) % 8);
1057 m_usigTlv.type = 32 + std::countr_zero<uint16_t>(RADIOTAP_USIG);
1058 m_usigTlv.length = sizeof(UsigFields);
1059 m_length += sizeof(TlvFields) + m_usigTlvPad;
1060
1061 m_usigPad = ((4 - m_length % 4) % 4);
1062 m_usigFields = usigFields;
1064
1065 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present[0]=0x" << std::hex
1066 << m_present.at(0) << " m_present[1]=0x" << m_present.at(1) << std::dec);
1067}
1068
1069void
1071{
1072 start.WriteU8(0, m_usigTlvPad);
1073 start.WriteU16(m_usigTlv.type);
1074 start.WriteU16(m_usigTlv.length);
1075 start.WriteU8(0, m_usigPad);
1076 start.WriteU32(m_usigFields.common);
1077 start.WriteU32(m_usigFields.value);
1078 start.WriteU32(m_usigFields.mask);
1079}
1080
1083{
1084 const auto startBytesRead = bytesRead;
1085 m_usigTlvPad = ((8 - bytesRead % 8) % 8);
1086 start.Next(m_usigTlvPad);
1087 bytesRead += m_usigTlvPad;
1088 m_usigTlv.type = start.ReadU16();
1089 m_usigTlv.length = start.ReadU16();
1090 bytesRead += sizeof(TlvFields);
1091 m_usigPad = ((4 - bytesRead % 4) % 4);
1092 start.Next(m_usigPad);
1093 bytesRead += m_usigPad;
1094 m_usigFields.common = start.ReadU32();
1095 m_usigFields.value = start.ReadU32();
1096 m_usigFields.mask = start.ReadU32();
1097 bytesRead += sizeof(UsigFields);
1098 return bytesRead - startBytesRead;
1099}
1100
1101void
1102RadiotapHeader::PrintUsig(std::ostream& os) const
1103{
1104 os << " usig.common=0x" << std::hex << m_usigFields.common << " usig.value=0x"
1105 << m_usigFields.value << " usig.mask=0x" << m_usigFields.mask << std::dec;
1106}
1107
1108void
1110{
1111 NS_LOG_FUNCTION(this << ehtFields.known);
1112 NS_ASSERT_MSG(m_present.size() >= 2,
1113 "Number of it_present words (" << m_present.size() << ") is incorrect");
1114 m_present.at(0) |= RADIOTAP_TLV;
1115
1116 NS_ASSERT_MSG(!(m_present.at(1) & RADIOTAP_EHT_SIG), "EHT radiotap field already present");
1117 m_present.at(1) |= RADIOTAP_EHT_SIG;
1118
1119 m_ehtTlvPad = ((8 - m_length % 8) % 8);
1120 m_ehtTlv.type = 32 + std::countr_zero<uint16_t>(RADIOTAP_EHT_SIG);
1121 m_ehtTlv.length = (40 + ehtFields.userInfo.size() * 4);
1122 m_length += sizeof(TlvFields) + m_ehtTlvPad;
1123
1124 m_ehtPad = ((4 - m_length % 4) % 4);
1125 m_ehtFields = ehtFields;
1127
1128 NS_LOG_LOGIC(this << " m_length=" << m_length << " m_present[0]=0x" << std::hex
1129 << m_present.at(0) << " m_present[1]=0x" << m_present.at(1) << std::dec);
1130}
1131
1132void
1134{
1135 start.WriteU8(0, m_ehtTlvPad);
1136 start.WriteU16(m_ehtTlv.type);
1137 start.WriteU16(m_ehtTlv.length);
1138 start.WriteU8(0, m_ehtPad);
1139 start.WriteU32(m_ehtFields.known);
1140 for (const auto dataField : m_ehtFields.data)
1141 {
1142 start.WriteU32(dataField);
1143 }
1144 for (const auto userInfoField : m_ehtFields.userInfo)
1145 {
1146 start.WriteU32(userInfoField);
1147 }
1148}
1149
1152{
1153 const auto startBytesRead = bytesRead;
1154
1155 m_ehtTlvPad = ((8 - bytesRead % 8) % 8);
1156 start.Next(m_ehtTlvPad);
1157 bytesRead += m_ehtTlvPad;
1158 m_ehtTlv.type = start.ReadU16();
1159 m_ehtTlv.length = start.ReadU16();
1160 bytesRead += sizeof(TlvFields);
1161
1162 m_ehtPad = ((4 - bytesRead % 4) % 4);
1163 start.Next(m_ehtPad);
1164 bytesRead += m_ehtPad;
1165 m_ehtFields.known = start.ReadU32();
1166 bytesRead += 4;
1167 for (auto& dataField : m_ehtFields.data)
1168 {
1169 dataField = start.ReadU32();
1170 bytesRead += 4;
1171 }
1172 const auto userInfosBytes = m_ehtTlv.length - bytesRead - m_ehtTlvPad;
1173 NS_ASSERT(userInfosBytes % 4 == 0);
1174 const std::size_t numUsers = userInfosBytes / 4;
1175 for (std::size_t i = 0; i < numUsers; ++i)
1176 {
1177 m_ehtFields.userInfo.push_back(start.ReadU32());
1178 bytesRead += 4;
1179 }
1180
1181 return bytesRead - startBytesRead;
1182}
1183
1184void
1185RadiotapHeader::PrintEht(std::ostream& os) const
1186{
1187 os << " eht.known=0x" << std::hex << m_ehtFields.known;
1188 std::size_t index = 0;
1189 for (const auto dataField : m_ehtFields.data)
1190 {
1191 os << " eht.data" << index++ << "=0x" << dataField;
1192 }
1193 index = 0;
1194 for (const auto userInfoField : m_ehtFields.userInfo)
1195 {
1196 os << " eht.userInfo" << index++ << "=0x" << userInfoField;
1197 }
1198 os << std::dec;
1199}
1200
1201} // namespace ns3
iterator in a Buffer instance
Definition buffer.h:89
Protocol header serialization and deserialization.
Definition header.h:33
Radiotap header implementation.
void SerializeMcs(Buffer::Iterator &start) const
Serialize the MCS radiotap header.
HeMuFields m_heMuFields
HE MU fields.
uint32_t DeserializeHe(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the HE radiotap header.
void PrintHeMu(std::ostream &os) const
Add HE-MU subfield/value pairs to the output stream.
void SerializeHe(Buffer::Iterator &start) const
Serialize the HE radiotap header.
uint8_t m_rate
TX/RX data rate in units of 500 kbps.
void PrintMcs(std::ostream &os) const
Add MCS subfield/value pairs to the output stream.
void SetAmpduStatus(const AmpduStatusFields &ampduStatusFields)
Set the subfields of the A-MPDU status field.
uint32_t DeserializeUsig(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the U-SIG radiotap header.
void PrintEht(std::ostream &os) const
Add EHT subfield/value pairs to the output stream.
static TypeId GetTypeId()
Get the type ID.
uint8_t m_ampduStatusPad
A-MPDU Status Flags, padding before A-MPDU Status Field.
void PrintHeMuOtherUser(std::ostream &os) const
Add HE-MU-other-user subfield/value pairs to the output stream.
void SetHeMuOtherUserFields(const HeMuOtherUserFields &heMuOtherUserFields)
Set the subfields of the HE-MU-other-user field.
uint8_t m_ehtPad
EHT padding.
HeFields m_heFields
HE fields.
uint8_t m_heMuPad
HE MU padding.
void Print(std::ostream &os) const override
This method is used by Packet::Print to print the content of the header as ascii data to a C++ output...
uint8_t m_usigPad
U-SIG padding.
uint8_t m_heMuOtherUserPad
HE MU other user padding.
void SetHeFields(const HeFields &heFields)
Set the subfields of the HE field.
uint8_t m_hePad
HE padding.
void SerializeHeMuOtherUser(Buffer::Iterator &start) const
Serialize the HE-MU-other-user radiotap header.
EhtFields m_ehtFields
EHT fields.
void SetMcsFields(const McsFields &mcsFields)
Set the subfields of the MCS field.
uint8_t m_tsftPad
TSFT padding.
void SetRate(uint8_t rate)
Set the transmit/receive channel frequency in units of megahertz.
uint8_t m_ehtTlvPad
EHT TLV padding.
int8_t m_antennaSignal
RF signal power at the antenna, dB difference from an arbitrary, fixed reference.
void SetAntennaSignalPower(double signal)
Set the RF signal power at the antenna as a decibel difference from an arbitrary, fixed reference.
uint32_t DeserializeAmpduStatus(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the A-MPDU Status radiotap header.
uint32_t DeserializeVht(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the VHT radiotap header.
uint32_t DeserializeHeMuOtherUser(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the HE-MU-other-user radiotap header.
void SetTsft(uint64_t tsft)
Set the Time Synchronization Function Timer (TSFT) value.
void PrintHe(std::ostream &os) const
Add HE subfield/value pairs to the output stream.
TlvFields m_usigTlv
U-SIG TLV fields.
uint16_t m_length
entire length of radiotap data + header
void Serialize(Buffer::Iterator start) const override
This method is used by Packet::AddHeader to store the header into the byte buffer of a packet.
void SerializeTsft(Buffer::Iterator &start) const
Serialize the TSFT radiotap header.
void SetUsigFields(const UsigFields &usigFields)
Set the subfields of the U-SIG field.
static constexpr int MIN_HEADER_SIZE
the minimum size of the radiotap header
void SerializeUsig(Buffer::Iterator &start) const
Serialize the U-SIG radiotap header.
uint32_t Deserialize(Buffer::Iterator start) override
This method is used by Packet::RemoveHeader to re-create a header from the byte buffer of a packet.
void PrintUsig(std::ostream &os) const
Add U-SIG subfield/value pairs to the output stream.
void PrintChannel(std::ostream &os) const
Add Channel subfield/value pairs to the output stream.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint32_t DeserializeMcs(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the MCS radiotap header.
void SerializeHeMu(Buffer::Iterator &start) const
Serialize the HE-MU radiotap header.
McsFields m_mcsFields
MCS fields.
void SerializeAmpduStatus(Buffer::Iterator &start) const
Serialize the A-MPDU Status radiotap header.
void SetVhtFields(const VhtFields &vhtFields)
Set the subfields of the VHT field.
void SerializeEht(Buffer::Iterator &start) const
Serialize the EHT radiotap header.
uint32_t DeserializeChannel(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the Channel radiotap header.
UsigFields m_usigFields
U-SIG fields.
RadiotapExtFlags
Radiotap extended flags.
void SerializeChannel(Buffer::Iterator &start) const
Serialize the Channel radiotap header.
void SetAntennaNoisePower(double noise)
Set the RF noise power at the antenna as a decibel difference from an arbitrary, fixed reference.
std::vector< uint32_t > m_present
bits describing which fields follow header
void PrintVht(std::ostream &os) const
Add VHT subfield/value pairs to the output stream.
uint32_t GetSerializedSize() const override
This method is used by Packet::AddHeader to store the header into the byte buffer of a packet.
TlvFields m_ehtTlv
EHT TLV fields.
void SetEhtFields(const EhtFields &ehtFields)
Set the subfields of the EHT-SIG field.
ChannelFields m_channelFields
Channel fields.
uint8_t m_usigTlvPad
U-SIG TLV padding.
uint8_t m_channelPad
Channel padding.
uint32_t DeserializeHeMu(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the HE-MU radiotap header.
uint8_t m_vhtPad
VHT padding.
AmpduStatusFields m_ampduStatusFields
A-MPDU Status fields.
void SerializeVht(Buffer::Iterator &start) const
Serialize the VHT radiotap header.
void PrintAmpduStatus(std::ostream &os) const
Add A-MPDU Status subfield/value pairs to the output stream.
void SetWifiHeader(std::size_t numPresentWords)
Set the ieee80211_radiotap_header.
uint32_t DeserializeTsft(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the TSFT radiotap header.
uint8_t m_flags
Properties of transmitted and received frames.
void SetHeMuFields(const HeMuFields &heMuFields)
Set the subfields of the HE-MU field.
void SetChannelFields(const ChannelFields &channelFields)
Set the subfields of the Channel field.
HeMuOtherUserFields m_heMuOtherUserFields
HE MU other user fields.
void SetFrameFlags(uint8_t flags)
Set the frame flags of the transmitted or received frame.
VhtFields m_vhtFields
VHT fields.
uint64_t m_tsft
Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
uint32_t DeserializeEht(Buffer::Iterator start, uint32_t bytesRead)
Deserialize the EHT radiotap header.
int8_t m_antennaNoise
RF noise power at the antenna, dB difference from an arbitrary, fixed reference.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Every class exported by the ns3 library is enclosed in the ns3 namespace.
structure that contains the subfields of the A-MPDU status field.
uint32_t referenceNumber
A-MPDU reference number to identify all subframes belonging to the same A-MPDU.
structure that contains the subfields of the Channel field.
uint16_t frequency
Tx/Rx frequency in MHz.
structure that contains the subfields of the EHT field.
std::vector< uint32_t > userInfo
user info fields.
std::array< uint32_t, 9 > data
data fields.
structure that contains the subfields of the HE field.
structure that contains the subfields of the HE-MU field.
std::array< uint8_t, 4 > ruChannel2
RU_channel2 field.
std::array< uint8_t, 4 > ruChannel1
RU_channel1 field.
structure that contains the subfields of the HE-MU-other-user field.
uint8_t perUserKnown
per_user_known field
uint8_t perUserPosition
per_user_position field
structure that contains the subfields of the MCS field.
uint8_t mcs
MCS index value.
structure that contains the subfields of the TLV fields.
structure that contains the subfields of the U-SIG field.
structure that contains the subfields of the VHT field.
uint8_t groupId
group_id field
uint8_t bandwidth
bandwidth field
std::array< uint8_t, 4 > mcsNss
mcs_nss field
uint16_t partialAid
partial_aid field
uint16_t known
known flags field