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 <algorithm>
15#include <bitset>
16#include <cmath>
17#include <iomanip>
18
19namespace ns3
20{
21
22namespace
23{
24/// Number of bits per "present" field in the radiotap header
25constexpr std::size_t RADIOTAP_BITS_PER_PRESENT_FIELD{32};
26/// Size in bytes of the TSFT field in the radiotap header
27constexpr uint16_t RADIOTAP_TSFT_SIZE_B = 8;
28/// Alignment in bytes of the TSFT field in the radiotap header
29constexpr uint16_t RADIOTAP_TSFT_ALIGNMENT_B = 8;
30/// Size in bytes of the Flags field in the radiotap header
31constexpr uint16_t RADIOTAP_FLAGS_SIZE_B = 1;
32/// Size in bytes of the Rate field in the radiotap header
33constexpr uint16_t RADIOTAP_RATE_SIZE_B = 1;
34/// Size in bytes of the Channel field in the radiotap header
35constexpr uint16_t RADIOTAP_CHANNEL_SIZE_B = 4;
36/// Alignment in bytes of the Channel field in the radiotap header
37constexpr uint16_t RADIOTAP_CHANNEL_ALIGNMENT_B = 2;
38/// Size in bytes of the Antenna Signal field in the radiotap header
39constexpr uint16_t RADIOTAP_ANTENNA_SIGNAL_SIZE_B = 1;
40/// Size in bytes of the Antenna Noise field in the radiotap header
41constexpr uint16_t RADIOTAP_ANTENNA_NOISE_SIZE_B = 1;
42/// Size in bytes of the MCS field in the radiotap header
43constexpr uint16_t RADIOTAP_MCS_SIZE_B = 3;
44/// Alignment in bytes of the MCS field in the radiotap header
45constexpr uint16_t RADIOTAP_MCS_ALIGNMENT_B = 1;
46/// Size in bytes of the A-MPDU status field in the radiotap header
47constexpr uint16_t RADIOTAP_AMPDU_STATUS_SIZE_B = 8;
48/// Alignment in bytes of the A-MPDU status field in the radiotap header
49constexpr uint16_t RADIOTAP_AMPDU_STATUS_ALIGNMENT_B = 4;
50/// Size in bytes of the VHT field in the radiotap header
51constexpr uint16_t RADIOTAP_VHT_SIZE_B = 12;
52/// Alignment in bytes of the VHT field in the radiotap header
53constexpr uint16_t RADIOTAP_VHT_ALIGNMENT_B = 2;
54/// Size in bytes of the HE field in the radiotap header
55constexpr uint16_t RADIOTAP_HE_SIZE_B = 12;
56/// Alignment in bytes of the HE field in the radiotap header
57constexpr uint16_t RADIOTAP_HE_ALIGNMENT_B = 2;
58/// Size in bytes of the HE MU field in the radiotap header
59constexpr uint16_t RADIOTAP_HE_MU_SIZE_B = 12;
60/// Alignment in bytes of the HE MU field in the radiotap header
61constexpr uint16_t RADIOTAP_HE_MU_ALIGNMENT_B = 2;
62/// Size in bytes of the HE MU Other User field in the radiotap header
63constexpr uint16_t RADIOTAP_HE_MU_OTHER_USER_SIZE_B = 6;
64/// Alignment in bytes of the HE MU Other User field in the radiotap header
66/// Size in bytes of the TLV fields (without data) in the radiotap header
67constexpr uint16_t RADIOTAP_TLV_HEADER_SIZE_B = 4;
68/// Alignment in bytes of the TLV fields in the radiotap header
69constexpr uint16_t RADIOTAP_TLV_ALIGNMENT_B = 4;
70/// Size in bytes of the U-SIG field in the radiotap header
71constexpr uint16_t RADIOTAP_USIG_SIZE_B = 12;
72/// Alignment in bytes of the U-SIG field in the radiotap header
73constexpr uint16_t RADIOTAP_USIG_ALIGNMENT_B = 4;
74/// Size in bytes of the known subfield of the EHT field in the radiotap header
75constexpr uint16_t RADIOTAP_EHT_KNOWN_SIZE_B = 4;
76/// Size in bytes of a data subfield of the EHT field in the radiotap header
77constexpr uint16_t RADIOTAP_EHT_DATA_SIZE_B = 4;
78/// Size in bytes of a user info subfield of the EHT field in the radiotap header
79constexpr uint16_t RADIOTAP_EHT_USER_INFO_SIZE_B = 4;
80/// Alignment in bytes of the EHT field in the radiotap header
81constexpr uint16_t RADIOTAP_EHT_ALIGNMENT_B = 4;
82
83/**
84 * @brief Calculate the padding needed to align a field
85 * @param offset Current offset in bytes
86 * @param alignment Alignment requirement in bytes
87 * @return Number of padding bytes needed
88 */
89uint8_t
90GetPadding(uint32_t offset, uint32_t alignment)
91{
92 uint8_t padding = (alignment - (offset % alignment)) % alignment;
93 return padding;
94}
95
96/**
97 * @brief Check if a specific field is present in the radiotap header
98 * @param presentBits Vector of bitsets representing the present fields
99 * @param field Field to check
100 * @return true if the field is present, false otherwise
101 */
102bool
103IsPresent(const std::vector<std::bitset<RADIOTAP_BITS_PER_PRESENT_FIELD>>& presentBits,
104 uint32_t field)
105{
106 const std::size_t bitmaskIdx = field / RADIOTAP_BITS_PER_PRESENT_FIELD;
107 const std::size_t bitIdx = field % RADIOTAP_BITS_PER_PRESENT_FIELD;
108 return (presentBits.size() > bitmaskIdx) && presentBits.at(bitmaskIdx).test(bitIdx);
109}
110
111} // namespace
112
113NS_LOG_COMPONENT_DEFINE("RadiotapHeader");
114
115NS_OBJECT_ENSURE_REGISTERED(RadiotapHeader);
116
117TypeId
119{
120 static TypeId tid = TypeId("ns3::RadiotapHeader")
121 .SetParent<Header>()
122 .SetGroupName("Network")
123
124 .AddConstructor<RadiotapHeader>();
125 return tid;
126}
127
128TypeId
130{
131 return GetTypeId();
132}
133
136{
137 return m_length;
138}
139
140void
142{
143 NS_LOG_FUNCTION(this << &start);
144
145 start.WriteU8(0); // major version of radiotap header
146 start.WriteU8(0); // pad field
147 start.WriteU16(m_length); // entire length of radiotap data + header
148 NS_ASSERT(!m_present.empty());
149 std::vector<std::bitset<RADIOTAP_BITS_PER_PRESENT_FIELD>> presentBits;
150 for (const auto present : m_present)
151 {
152 start.WriteU32(present); // bits describing which fields follow header
153 presentBits.emplace_back(present);
154 }
155
156 //
157 // Time Synchronization Function Timer (when the first bit of the MPDU
158 // arrived at the MAC)
159 // Reference: https://www.radiotap.org/fields/TSFT.html
160 //
161 if (IsPresent(presentBits, RADIOTAP_TSFT))
162 {
163 SerializeTsft(start);
164 }
165
166 //
167 // Properties of transmitted and received frames.
168 // Reference: https://www.radiotap.org/fields/Flags.html
169 //
170 if (IsPresent(presentBits, RADIOTAP_FLAGS))
171 {
172 start.WriteU8(m_flags);
173 }
174
175 //
176 // TX/RX data rate in units of 500 kbps
177 // Reference: https://www.radiotap.org/fields/Rate.html
178 //
179 if (IsPresent(presentBits, RADIOTAP_RATE))
180 {
181 start.WriteU8(m_rate);
182 }
183
184 //
185 // Tx/Rx frequency in MHz, followed by flags.
186 // Reference: https://www.radiotap.org/fields/Channel.html
187 //
188 if (IsPresent(presentBits, RADIOTAP_CHANNEL))
189 {
190 SerializeChannel(start);
191 }
192
193 //
194 // RF signal power at the antenna, decibel difference from an arbitrary, fixed
195 // reference.
196 // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
197 //
198 if (IsPresent(presentBits, RADIOTAP_DBM_ANTSIGNAL))
199 {
200 start.WriteU8(m_antennaSignal);
201 }
202
203 //
204 // RF noise power at the antenna, decibel difference from an arbitrary, fixed
205 // reference.
206 // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
207 //
208 if (IsPresent(presentBits, RADIOTAP_DBM_ANTNOISE))
209 {
210 start.WriteU8(m_antennaNoise);
211 }
212
213 //
214 // MCS field.
215 // Reference: https://www.radiotap.org/fields/MCS.html
216 //
217 if (IsPresent(presentBits, RADIOTAP_MCS))
218 {
219 SerializeMcs(start);
220 }
221
222 //
223 // A-MPDU Status, information about the received or transmitted A-MPDU.
224 // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
225 //
226 if (IsPresent(presentBits, RADIOTAP_AMPDU_STATUS))
227 {
229 }
230
231 //
232 // Information about the received or transmitted VHT frame.
233 // Reference: https://www.radiotap.org/fields/VHT.html
234 //
235 if (IsPresent(presentBits, RADIOTAP_VHT))
236 {
237 SerializeVht(start);
238 }
239
240 //
241 // HE field.
242 // Reference: https://www.radiotap.org/fields/HE.html
243 //
244 if (IsPresent(presentBits, RADIOTAP_HE))
245 {
246 SerializeHe(start);
247 }
248
249 //
250 // HE MU field.
251 // Reference: https://www.radiotap.org/fields/HE-MU.html
252 //
253 if (IsPresent(presentBits, RADIOTAP_HE_MU))
254 {
255 SerializeHeMu(start);
256 }
257
258 //
259 // HE MU other user field.
260 // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
261 //
262 if (IsPresent(presentBits, RADIOTAP_HE_MU_OTHER_USER))
263 {
265 }
266
267 //
268 // U-SIG field.
269 // Reference: https://www.radiotap.org/fields/U-SIG.html
270 //
271 if (IsPresent(presentBits, RADIOTAP_USIG))
272 {
273 SerializeUsig(start);
274 }
275
276 //
277 // EHT field.
278 // Reference: https://www.radiotap.org/fields/EHT.html
279 //
280 if (IsPresent(presentBits, RADIOTAP_EHT))
281 {
282 SerializeEht(start);
283 }
284}
285
288{
289 NS_LOG_FUNCTION(this << &start);
290 m_present.clear();
291
292 auto tmp = start.ReadU8(); // major version of radiotap header
293 NS_ASSERT_MSG(tmp == 0x00, "RadiotapHeader::Deserialize(): Unexpected major version");
294 start.ReadU8(); // pad field
295
296 m_length = start.ReadU16(); // entire length of radiotap data + header
297 m_present.emplace_back(start.ReadU32()); // bits describing which fields follow header
298 uint32_t bytesRead = MIN_HEADER_SIZE;
299
300 std::size_t index{0};
301 std::vector<std::bitset<RADIOTAP_BITS_PER_PRESENT_FIELD>> presentBits;
302 presentBits.emplace_back(m_present.at(0));
303 while (presentBits.at(index++).test(RADIOTAP_MORE_PRESENT))
304 {
305 // If bit 31 of the it_present field is set, another it_present bitmask is present.
306 m_present.emplace_back(start.ReadU32());
307 bytesRead += (RADIOTAP_BITS_PER_PRESENT_FIELD / 8);
308 presentBits.emplace_back(m_present.at(index));
309 }
310
311 //
312 // Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
313 // Reference: https://www.radiotap.org/fields/TSFT.html
314 //
315 if (IsPresent(presentBits, RADIOTAP_TSFT))
316 {
317 const auto size = DeserializeTsft(start, bytesRead);
318 start.Next(size);
319 bytesRead += size;
320 }
321
322 //
323 // Properties of transmitted and received frames.
324 // Reference: https://www.radiotap.org/fields/Flags.html
325 //
326 if (IsPresent(presentBits, RADIOTAP_FLAGS))
327 {
328 m_flags = start.ReadU8();
329 ++bytesRead;
330 }
331
332 //
333 // TX/RX data rate in units of 500 kbps
334 // Reference: https://www.radiotap.org/fields/Rate.html
335 //
336 if (IsPresent(presentBits, RADIOTAP_RATE))
337 {
338 m_rate = start.ReadU8();
339 ++bytesRead;
340 }
341
342 //
343 // Tx/Rx frequency in MHz, followed by flags.
344 // Reference: https://www.radiotap.org/fields/Channel.html
345 //
346 if (IsPresent(presentBits, RADIOTAP_CHANNEL))
347 {
348 const auto size = DeserializeChannel(start, bytesRead);
349 start.Next(size);
350 bytesRead += size;
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 (IsPresent(presentBits, RADIOTAP_DBM_ANTSIGNAL))
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 (IsPresent(presentBits, RADIOTAP_DBM_ANTNOISE))
370 {
371 m_antennaNoise = start.ReadU8();
372 ++bytesRead;
373 }
374
375 //
376 // MCS field.
377 // Reference: https://www.radiotap.org/fields/MCS.html
378 //
379 if (IsPresent(presentBits, RADIOTAP_MCS))
380 {
381 const auto size = DeserializeMcs(start, bytesRead);
382 start.Next(size);
383 bytesRead += size;
384 }
385
386 //
387 // A-MPDU Status, information about the received or transmitted A-MPDU.
388 // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
389 //
390 if (IsPresent(presentBits, RADIOTAP_AMPDU_STATUS))
391 {
392 const auto size = DeserializeAmpduStatus(start, bytesRead);
393 start.Next(size);
394 bytesRead += size;
395 }
396
397 //
398 // Information about the received or transmitted VHT frame.
399 // Reference: https://www.radiotap.org/fields/VHT.html
400 //
401 if (IsPresent(presentBits, RADIOTAP_VHT))
402 {
403 const auto size = DeserializeVht(start, bytesRead);
404 start.Next(size);
405 bytesRead += size;
406 }
407
408 //
409 // HE field.
410 // Reference: https://www.radiotap.org/fields/HE.html
411 //
412 if (IsPresent(presentBits, RADIOTAP_HE))
413 {
414 const auto size = DeserializeHe(start, bytesRead);
415 start.Next(size);
416 bytesRead += size;
417 }
418
419 //
420 // HE MU field.
421 // Reference: https://www.radiotap.org/fields/HE-MU.html
422 //
423 if (IsPresent(presentBits, RADIOTAP_HE_MU))
424 {
425 const auto size = DeserializeHeMu(start, bytesRead);
426 start.Next(size);
427 bytesRead += size;
428 }
429
430 //
431 // HE MU other user field.
432 // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
433 if (IsPresent(presentBits, RADIOTAP_HE_MU_OTHER_USER))
434 {
435 const auto size = DeserializeHeMuOtherUser(start, bytesRead);
436 start.Next(size);
437 bytesRead += size;
438 }
439
440 //
441 // U-SIG field.
442 // Reference: https://www.radiotap.org/fields/U-SIG.html
443 //
444 if (IsPresent(presentBits, RADIOTAP_USIG))
445 {
446 const auto size = DeserializeUsig(start, bytesRead);
447 start.Next(size);
448 bytesRead += size;
449 }
450
451 //
452 // EHT field.
453 // Reference: https://www.radiotap.org/fields/EHT.html
454 //
455 if (IsPresent(presentBits, RADIOTAP_EHT))
456 {
457 const auto size = DeserializeEht(start, bytesRead);
458 start.Next(size);
459 bytesRead += size;
460 }
461
462 NS_ASSERT_MSG(m_length == bytesRead,
463 "RadiotapHeader::Deserialize(): expected and actual lengths inconsistent ("
464 << m_length << " != " << bytesRead << ")");
465 return bytesRead;
466}
467
468void
469RadiotapHeader::Print(std::ostream& os) const
470{
471 os << " tsft=" << m_tsft << " flags=" << std::hex << m_flags << std::dec << " rate=" << +m_rate;
472 if (m_present.at(0) & RADIOTAP_CHANNEL)
473 {
474 PrintChannel(os);
475 }
476 os << std::dec << " signal=" << +m_antennaSignal << " noise=" << +m_antennaNoise;
477 if (m_present.at(0) & RADIOTAP_MCS)
478 {
479 PrintMcs(os);
480 }
482 {
484 }
485 if (m_present.at(0) & RADIOTAP_VHT)
486 {
487 PrintVht(os);
488 }
489 if (m_present.at(0) & RADIOTAP_HE)
490 {
491 PrintHe(os);
492 }
493 if (m_present.at(0) & RADIOTAP_HE_MU)
494 {
495 PrintHeMu(os);
496 }
498 {
500 }
501 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_USIG)
502 {
503 PrintUsig(os);
504 }
505 if ((m_present.size() > 1) && m_present.at(1) & RADIOTAP_EHT)
506 {
507 PrintEht(os);
508 }
509}
510
511void
513{
514 NS_LOG_FUNCTION(this << field);
515 const std::size_t bitmaskIdx = field / RADIOTAP_BITS_PER_PRESENT_FIELD;
516 NS_ASSERT_MSG(bitmaskIdx < m_present.size(),
517 "Number of it_present words (" << m_present.size()
518 << ") less than expected index " << bitmaskIdx);
519 const std::size_t fieldIdx = field % RADIOTAP_BITS_PER_PRESENT_FIELD;
520 const uint32_t flag = (1 << fieldIdx);
521 if (field != RADIOTAP_TLV)
522 {
523 NS_ASSERT_MSG(!(m_present.at(bitmaskIdx) & flag),
524 "Radiotap field " << field << " already set in present field at index "
525 << bitmaskIdx);
526 NS_ASSERT_MSG((m_present.at(bitmaskIdx) < flag) &&
527 ((m_present.size() == (bitmaskIdx + 1)) ||
528 std::all_of(m_present.begin() + bitmaskIdx + 1,
529 m_present.end(),
530 [](uint32_t present) { return present == 0; })),
531 "Radiotap fields not set in correct order");
532 }
533 if (const uint32_t morePresentWordFlag = (1 << RADIOTAP_MORE_PRESENT); bitmaskIdx > 0)
534 {
535 // Ensure that the bit indicating more present words is set in the previous word
536 m_present.at(bitmaskIdx - 1) |= morePresentWordFlag;
537 }
538 m_present.at(bitmaskIdx) |= flag;
539}
540
541void
542RadiotapHeader::SetWifiHeader(std::size_t numPresentWords)
543{
544 NS_LOG_FUNCTION(this << numPresentWords);
545 NS_ASSERT_MSG(numPresentWords > 0,
546 "RadiotapHeader::SetWifiHeader() requires at least one it_present word");
548 "RadiotapHeader::SetWifiHeader() should be called before any other Set* method");
549 NS_ASSERT_MSG(m_present.size() == 1, "RadiotapHeader::SetWifiHeader() should be called once");
550 for (std::size_t i = 0; i < (numPresentWords - 1); ++i)
551 {
552 m_present.emplace_back(0);
553 m_length += (RADIOTAP_BITS_PER_PRESENT_FIELD / 8);
554 }
555}
556
557void
559{
560 NS_LOG_FUNCTION(this << value);
561
563 m_tsftPad = GetPadding(m_length, RADIOTAP_TSFT_ALIGNMENT_B);
564 m_length += RADIOTAP_TSFT_SIZE_B + m_tsftPad;
565 m_tsft = value;
566
567 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
568 << std::dec);
569}
570
571void
573{
574 NS_LOG_FUNCTION(this << &start);
575 start.WriteU8(0, m_tsftPad);
576 start.WriteU64(m_tsft);
577}
578
581{
582 NS_LOG_FUNCTION(this << &start << bytesRead);
583 m_tsftPad = GetPadding(bytesRead, RADIOTAP_TSFT_ALIGNMENT_B);
584 start.Next(m_tsftPad);
585 m_tsft = start.ReadU64();
586 return RADIOTAP_TSFT_SIZE_B + m_tsftPad;
587}
588
589void
591{
592 NS_LOG_FUNCTION(this << flags);
593
595 m_length += RADIOTAP_FLAGS_SIZE_B;
596 m_flags = flags;
597
598 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
599 << std::dec);
600}
601
602void
604{
605 NS_LOG_FUNCTION(this << rate);
606
608 m_length += RADIOTAP_RATE_SIZE_B;
609 m_rate = rate;
610
611 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
612 << std::dec);
613}
614
615void
617{
618 NS_LOG_FUNCTION(this << channelFields.frequency << channelFields.flags);
619
621 m_channelPad = GetPadding(m_length, RADIOTAP_CHANNEL_ALIGNMENT_B);
622 m_length += RADIOTAP_CHANNEL_SIZE_B + m_channelPad;
623 m_channelFields = channelFields;
624
625 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
626 << std::dec);
627}
628
629void
631{
632 NS_LOG_FUNCTION(this << &start);
633 start.WriteU8(0, m_channelPad);
634 start.WriteU16(m_channelFields.frequency);
635 start.WriteU16(m_channelFields.flags);
636}
637
640{
641 NS_LOG_FUNCTION(this << &start << bytesRead);
642 m_channelPad = GetPadding(bytesRead, RADIOTAP_CHANNEL_ALIGNMENT_B);
643 start.Next(m_channelPad);
644 m_channelFields.frequency = start.ReadU16();
645 m_channelFields.flags = start.ReadU16();
646 return RADIOTAP_CHANNEL_SIZE_B + m_channelPad;
647}
648
649void
650RadiotapHeader::PrintChannel(std::ostream& os) const
651{
652 os << " channel.frequency=" << m_channelFields.frequency << " channel.flags=0x" << std::hex
653 << m_channelFields.flags << std::dec;
654}
655
656void
658{
659 NS_LOG_FUNCTION(this << signal);
660
662 m_length += RADIOTAP_ANTENNA_SIGNAL_SIZE_B;
663
664 if (signal > 127)
665 {
666 m_antennaSignal = 127;
667 }
668 else if (signal < -128)
669 {
670 m_antennaSignal = -128;
671 }
672 else
673 {
674 m_antennaSignal = static_cast<int8_t>(floor(signal + 0.5));
675 }
676
677 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
678 << std::dec);
679}
680
681void
683{
684 NS_LOG_FUNCTION(this << noise);
685
687 m_length += RADIOTAP_ANTENNA_NOISE_SIZE_B;
688
689 if (noise > 127.0)
690 {
691 m_antennaNoise = 127;
692 }
693 else if (noise < -128.0)
694 {
695 m_antennaNoise = -128;
696 }
697 else
698 {
699 m_antennaNoise = static_cast<int8_t>(floor(noise + 0.5));
700 }
701
702 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
703 << std::dec);
704}
705
706void
708{
709 NS_LOG_FUNCTION(this << mcsFields.known << mcsFields.flags << mcsFields.mcs);
710
712 m_mcsPad = GetPadding(m_length, RADIOTAP_MCS_ALIGNMENT_B);
713 m_length += RADIOTAP_MCS_SIZE_B + m_mcsPad;
714 m_mcsFields = mcsFields;
715
716 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
717 << std::dec);
718}
719
720void
722{
723 NS_LOG_FUNCTION(this << &start);
724 start.WriteU8(0, m_mcsPad);
725 start.WriteU8(m_mcsFields.known);
726 start.WriteU8(m_mcsFields.flags);
727 start.WriteU8(m_mcsFields.mcs);
728}
729
732{
733 NS_LOG_FUNCTION(this << &start << bytesRead);
734 m_mcsPad = GetPadding(bytesRead, RADIOTAP_MCS_ALIGNMENT_B);
735 start.Next(m_mcsPad);
736 m_mcsFields.known = start.ReadU8();
737 m_mcsFields.flags = start.ReadU8();
738 m_mcsFields.mcs = start.ReadU8();
739 return RADIOTAP_MCS_SIZE_B + m_mcsPad;
740}
741
742void
743RadiotapHeader::PrintMcs(std::ostream& os) const
744{
745 os << " mcs.known=0x" << std::hex << +m_mcsFields.known << " mcs.flags0x=" << +m_mcsFields.flags
746 << " mcsRate=" << std::dec << +m_mcsFields.mcs;
747}
748
749void
751{
752 NS_LOG_FUNCTION(this << ampduStatusFields.referenceNumber << ampduStatusFields.flags);
753
755 m_ampduStatusPad = GetPadding(m_length, RADIOTAP_AMPDU_STATUS_ALIGNMENT_B);
756 m_length += RADIOTAP_AMPDU_STATUS_SIZE_B + m_ampduStatusPad;
757 m_ampduStatusFields = ampduStatusFields;
758
759 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
760 << std::dec);
761}
762
763void
765{
766 NS_LOG_FUNCTION(this << &start);
767 start.WriteU8(0, m_ampduStatusPad);
768 start.WriteU32(m_ampduStatusFields.referenceNumber);
769 start.WriteU16(m_ampduStatusFields.flags);
770 start.WriteU8(m_ampduStatusFields.crc);
771 start.WriteU8(m_ampduStatusFields.reserved);
772}
773
776{
777 NS_LOG_FUNCTION(this << &start << bytesRead);
778 m_ampduStatusPad = GetPadding(bytesRead, RADIOTAP_AMPDU_STATUS_ALIGNMENT_B);
779 start.Next(m_ampduStatusPad);
780 m_ampduStatusFields.referenceNumber = start.ReadU32();
781 m_ampduStatusFields.flags = start.ReadU16();
782 m_ampduStatusFields.crc = start.ReadU8();
783 m_ampduStatusFields.reserved = start.ReadU8();
784 return RADIOTAP_AMPDU_STATUS_SIZE_B + m_ampduStatusPad;
785}
786
787void
788RadiotapHeader::PrintAmpduStatus(std::ostream& os) const
789{
790 os << " ampduStatus.flags=0x" << std::hex << m_ampduStatusFields.flags << std::dec;
791}
792
793void
795{
796 NS_LOG_FUNCTION(this << vhtFields.known << vhtFields.flags << vhtFields.mcsNss.at(0)
797 << vhtFields.mcsNss.at(1) << vhtFields.mcsNss.at(2)
798 << vhtFields.mcsNss.at(3) << vhtFields.coding << vhtFields.groupId
799 << vhtFields.partialAid);
800
802 m_vhtPad = GetPadding(m_length, RADIOTAP_VHT_ALIGNMENT_B);
803 m_length += RADIOTAP_VHT_SIZE_B + m_vhtPad;
804 m_vhtFields = vhtFields;
805
806 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
807 << std::dec);
808}
809
810void
812{
813 NS_LOG_FUNCTION(this << &start);
814 start.WriteU8(0, m_vhtPad);
815 start.WriteU16(m_vhtFields.known);
816 start.WriteU8(m_vhtFields.flags);
817 start.WriteU8(m_vhtFields.bandwidth);
818 for (const auto mcsNss : m_vhtFields.mcsNss)
819 {
820 start.WriteU8(mcsNss);
821 }
822 start.WriteU8(m_vhtFields.coding);
823 start.WriteU8(m_vhtFields.groupId);
824 start.WriteU16(m_vhtFields.partialAid);
825}
826
829{
830 NS_LOG_FUNCTION(this << &start << bytesRead);
831 m_vhtPad = GetPadding(bytesRead, RADIOTAP_VHT_ALIGNMENT_B);
832 start.Next(m_vhtPad);
833 m_vhtFields.known = start.ReadU16();
834 m_vhtFields.flags = start.ReadU8();
835 m_vhtFields.bandwidth = start.ReadU8();
836 for (auto& mcsNss : m_vhtFields.mcsNss)
837 {
838 mcsNss = start.ReadU8();
839 }
840 m_vhtFields.coding = start.ReadU8();
841 m_vhtFields.groupId = start.ReadU8();
842 m_vhtFields.partialAid = start.ReadU16();
843 return RADIOTAP_VHT_SIZE_B + m_vhtPad;
844}
845
846void
847RadiotapHeader::PrintVht(std::ostream& os) const
848{
849 os << " vht.known=0x" << m_vhtFields.known << " vht.flags=0x" << m_vhtFields.flags
850 << " vht.bandwidth=" << std::dec << m_vhtFields.bandwidth;
851 for (std::size_t i = 0; i < m_vhtFields.mcsNss.size(); ++i)
852 {
853 os << " vht.mcsNss[" << i << "]=" << +m_vhtFields.mcsNss.at(i);
854 }
855 os << " vht.coding=" << m_vhtFields.coding << " vht.groupId=" << m_vhtFields.groupId
856 << " vht.partialAid=" << m_vhtFields.partialAid;
857}
858
859void
861{
862 NS_LOG_FUNCTION(this << heFields.data1 << heFields.data2 << heFields.data3 << heFields.data4
863 << heFields.data5 << heFields.data6);
864
866 m_hePad = GetPadding(m_length, RADIOTAP_HE_ALIGNMENT_B);
867 m_length += RADIOTAP_HE_SIZE_B + m_hePad;
868 m_heFields = heFields;
869
870 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
871 << std::dec);
872}
873
874void
876{
877 NS_LOG_FUNCTION(this << &start);
878 start.WriteU8(0, m_hePad);
879 start.WriteU16(m_heFields.data1);
880 start.WriteU16(m_heFields.data2);
881 start.WriteU16(m_heFields.data3);
882 start.WriteU16(m_heFields.data4);
883 start.WriteU16(m_heFields.data5);
884 start.WriteU16(m_heFields.data6);
885}
886
889{
890 NS_LOG_FUNCTION(this << &start << bytesRead);
891 m_hePad = GetPadding(bytesRead, RADIOTAP_HE_ALIGNMENT_B);
892 start.Next(m_hePad);
893 m_heFields.data1 = start.ReadU16();
894 m_heFields.data2 = start.ReadU16();
895 m_heFields.data3 = start.ReadU16();
896 m_heFields.data4 = start.ReadU16();
897 m_heFields.data5 = start.ReadU16();
898 m_heFields.data6 = start.ReadU16();
899 return RADIOTAP_HE_SIZE_B + m_hePad;
900}
901
902void
903RadiotapHeader::PrintHe(std::ostream& os) const
904{
905 os << " he.data1=0x" << std::hex << m_heFields.data1 << " he.data2=0x" << std::hex
906 << m_heFields.data2 << " he.data3=0x" << std::hex << m_heFields.data3 << " he.data4=0x"
907 << std::hex << m_heFields.data4 << " he.data5=0x" << std::hex << m_heFields.data5
908 << " he.data6=0x" << std::hex << m_heFields.data6 << std::dec;
909}
910
911void
913{
914 NS_LOG_FUNCTION(this << heMuFields.flags1 << heMuFields.flags2);
915
917 m_heMuPad = GetPadding(m_length, RADIOTAP_HE_MU_ALIGNMENT_B);
918 m_length += RADIOTAP_HE_MU_SIZE_B + m_heMuPad;
919 m_heMuFields = heMuFields;
920
921 NS_LOG_LOGIC("m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
922 << std::dec);
923}
924
925void
927{
928 NS_LOG_FUNCTION(this << &start);
929 start.WriteU8(0, m_heMuPad);
930 start.WriteU16(m_heMuFields.flags1);
931 start.WriteU16(m_heMuFields.flags2);
932 for (const auto ruChannel : m_heMuFields.ruChannel1)
933 {
934 start.WriteU8(ruChannel);
935 }
936 for (const auto ruChannel : m_heMuFields.ruChannel2)
937 {
938 start.WriteU8(ruChannel);
939 }
940}
941
944{
945 NS_LOG_FUNCTION(this << &start << bytesRead);
946 m_heMuPad = GetPadding(bytesRead, RADIOTAP_HE_MU_ALIGNMENT_B);
947 start.Next(m_heMuPad);
948 m_heMuFields.flags1 = start.ReadU16();
949 m_heMuFields.flags2 = start.ReadU16();
950 for (auto& ruChannel : m_heMuFields.ruChannel1)
951 {
952 ruChannel = start.ReadU8();
953 }
954 for (auto& ruChannel : m_heMuFields.ruChannel2)
955 {
956 ruChannel = start.ReadU8();
957 }
958 return RADIOTAP_HE_MU_SIZE_B + m_heMuPad;
959}
960
961void
962RadiotapHeader::PrintHeMu(std::ostream& os) const
963{
964 os << " heMu.flags1=0x" << std::hex << m_heMuFields.flags1 << " heMu.flags2=0x"
965 << m_heMuFields.flags2 << std::dec;
966}
967
968void
970{
971 NS_LOG_FUNCTION(this << heMuOtherUserFields.perUser1 << heMuOtherUserFields.perUser2
972 << heMuOtherUserFields.perUserPosition
973 << heMuOtherUserFields.perUserKnown);
974
976 m_heMuOtherUserPad = GetPadding(m_length, RADIOTAP_HE_MU_OTHER_USER_ALIGNMENT_B);
977 m_length += RADIOTAP_HE_MU_OTHER_USER_SIZE_B + m_heMuOtherUserPad;
978 m_heMuOtherUserFields = heMuOtherUserFields;
979
980 NS_LOG_LOGIC(" m_length=" << m_length << " m_present=0x" << std::hex << m_present.at(0)
981 << std::dec);
982}
983
984void
986{
987 NS_LOG_FUNCTION(this << &start);
988 start.WriteU8(0, m_heMuOtherUserPad);
989 start.WriteU16(m_heMuOtherUserFields.perUser1);
990 start.WriteU16(m_heMuOtherUserFields.perUser2);
991 start.WriteU8(m_heMuOtherUserFields.perUserPosition);
992 start.WriteU8(m_heMuOtherUserFields.perUserKnown);
993}
994
997{
998 NS_LOG_FUNCTION(this << &start << bytesRead);
999 m_heMuOtherUserPad = GetPadding(bytesRead, RADIOTAP_HE_MU_OTHER_USER_ALIGNMENT_B);
1000 start.Next(m_heMuOtherUserPad);
1001 m_heMuOtherUserFields.perUser1 = start.ReadU16();
1002 m_heMuOtherUserFields.perUser2 = start.ReadU16();
1003 m_heMuOtherUserFields.perUserPosition = start.ReadU8();
1004 m_heMuOtherUserFields.perUserKnown = start.ReadU8();
1005 return RADIOTAP_HE_MU_OTHER_USER_SIZE_B + m_heMuOtherUserPad;
1006}
1007
1008void
1010{
1011 os << " heMuOtherUser.perUser1=" << m_heMuOtherUserFields.perUser1
1012 << " heMuOtherUser.perUser2=" << m_heMuOtherUserFields.perUser2
1013 << " heMuOtherUser.perUserPosition=" << m_heMuOtherUserFields.perUserPosition
1014 << " heMuOtherUser.perUserKnown=0x" << std::hex << m_heMuOtherUserFields.perUserKnown
1015 << std::dec;
1016}
1017
1018void
1020{
1021 NS_LOG_FUNCTION(this << usigFields.common << usigFields.mask << usigFields.value);
1022
1024 m_usigTlvPad = GetPadding(m_length, RADIOTAP_TLV_ALIGNMENT_B);
1025 m_usigTlv.type = RADIOTAP_USIG;
1026 m_usigTlv.length = RADIOTAP_USIG_SIZE_B;
1027 m_length += RADIOTAP_TLV_HEADER_SIZE_B + m_usigTlvPad;
1028
1030 m_usigPad = GetPadding(m_length, RADIOTAP_USIG_ALIGNMENT_B);
1031 m_usigFields = usigFields;
1032 m_length += m_usigTlv.length + m_usigPad;
1033
1034 NS_LOG_LOGIC(" m_length=" << m_length << " m_present[0]=0x" << std::hex << m_present.at(0)
1035 << " m_present[1]=0x" << m_present.at(1) << std::dec);
1036}
1037
1038void
1040{
1041 NS_LOG_FUNCTION(this << &start);
1042 start.WriteU8(0, m_usigTlvPad);
1043 start.WriteU16(m_usigTlv.type);
1044 start.WriteU16(m_usigTlv.length);
1045 start.WriteU8(0, m_usigPad);
1046 start.WriteU32(m_usigFields.common);
1047 start.WriteU32(m_usigFields.value);
1048 start.WriteU32(m_usigFields.mask);
1049}
1050
1053{
1054 NS_LOG_FUNCTION(this << &start << bytesRead);
1055 const auto startBytesRead = bytesRead;
1056 m_usigTlvPad = GetPadding(bytesRead, RADIOTAP_TLV_ALIGNMENT_B);
1057 start.Next(m_usigTlvPad);
1058 bytesRead += m_usigTlvPad;
1059 m_usigTlv.type = start.ReadU16();
1060 m_usigTlv.length = start.ReadU16();
1061 bytesRead += RADIOTAP_TLV_HEADER_SIZE_B;
1062 m_usigPad = GetPadding(bytesRead, RADIOTAP_USIG_ALIGNMENT_B);
1063 start.Next(m_usigPad);
1064 bytesRead += m_usigPad;
1065 m_usigFields.common = start.ReadU32();
1066 m_usigFields.value = start.ReadU32();
1067 m_usigFields.mask = start.ReadU32();
1068 bytesRead += RADIOTAP_USIG_SIZE_B;
1069 return bytesRead - startBytesRead;
1070}
1071
1072void
1073RadiotapHeader::PrintUsig(std::ostream& os) const
1074{
1075 os << " usig.common=0x" << std::hex << m_usigFields.common << " usig.value=0x"
1076 << m_usigFields.value << " usig.mask=0x" << m_usigFields.mask << std::dec;
1077}
1078
1079void
1081{
1082 NS_LOG_FUNCTION(this << ehtFields.known);
1083
1085 m_ehtTlvPad = GetPadding(m_length, RADIOTAP_TLV_ALIGNMENT_B);
1086 m_ehtTlv.type = RADIOTAP_EHT;
1087 m_ehtTlv.length = RADIOTAP_EHT_KNOWN_SIZE_B +
1088 (RADIOTAP_EHT_DATA_SIZE_B * ehtFields.data.size()) +
1089 (ehtFields.userInfo.size() * RADIOTAP_EHT_USER_INFO_SIZE_B);
1090 m_length += RADIOTAP_TLV_HEADER_SIZE_B + m_ehtTlvPad;
1091
1093 m_ehtPad = GetPadding(m_length, RADIOTAP_EHT_ALIGNMENT_B);
1094 m_ehtFields = ehtFields;
1095 m_length += m_ehtTlv.length + m_ehtPad;
1096
1097 NS_LOG_LOGIC("m_length=" << m_length << " m_present[0]=0x" << std::hex << m_present.at(0)
1098 << " m_present[1]=0x" << m_present.at(1) << std::dec);
1099}
1100
1101void
1103{
1104 NS_LOG_FUNCTION(this << &start);
1105 start.WriteU8(0, m_ehtTlvPad);
1106 start.WriteU16(m_ehtTlv.type);
1107 start.WriteU16(m_ehtTlv.length);
1108 start.WriteU8(0, m_ehtPad);
1109 start.WriteU32(m_ehtFields.known);
1110 for (const auto dataField : m_ehtFields.data)
1111 {
1112 start.WriteU32(dataField);
1113 }
1114 for (const auto userInfoField : m_ehtFields.userInfo)
1115 {
1116 start.WriteU32(userInfoField);
1117 }
1118}
1119
1122{
1123 NS_LOG_FUNCTION(this << &start << bytesRead);
1124
1125 const auto startBytesRead = bytesRead;
1126
1127 m_ehtTlvPad = GetPadding(bytesRead, RADIOTAP_TLV_ALIGNMENT_B);
1128 start.Next(m_ehtTlvPad);
1129 bytesRead += m_ehtTlvPad;
1130 m_ehtTlv.type = start.ReadU16();
1131 m_ehtTlv.length = start.ReadU16();
1132 bytesRead += RADIOTAP_TLV_HEADER_SIZE_B;
1133
1134 m_ehtPad = GetPadding(bytesRead, RADIOTAP_EHT_ALIGNMENT_B);
1135 start.Next(m_ehtPad);
1136 bytesRead += m_ehtPad;
1137 m_ehtFields.known = start.ReadU32();
1138 bytesRead += RADIOTAP_EHT_KNOWN_SIZE_B;
1139 for (auto& dataField : m_ehtFields.data)
1140 {
1141 dataField = start.ReadU32();
1142 bytesRead += RADIOTAP_EHT_DATA_SIZE_B;
1143 }
1144 const auto userInfosBytes = m_ehtTlv.length - bytesRead - m_ehtTlvPad;
1145 NS_ASSERT(userInfosBytes % RADIOTAP_EHT_USER_INFO_SIZE_B == 0);
1146 const std::size_t numUsers = userInfosBytes / RADIOTAP_EHT_USER_INFO_SIZE_B;
1147 for (std::size_t i = 0; i < numUsers; ++i)
1148 {
1149 m_ehtFields.userInfo.push_back(start.ReadU32());
1150 bytesRead += RADIOTAP_EHT_USER_INFO_SIZE_B;
1151 }
1152
1153 return bytesRead - startBytesRead;
1154}
1155
1156void
1157RadiotapHeader::PrintEht(std::ostream& os) const
1158{
1159 os << " eht.known=0x" << std::hex << m_ehtFields.known;
1160 std::size_t index = 0;
1161 for (const auto dataField : m_ehtFields.data)
1162 {
1163 os << " eht.data" << index++ << "=0x" << dataField;
1164 }
1165 index = 0;
1166 for (const auto userInfoField : m_ehtFields.userInfo)
1167 {
1168 os << " eht.userInfo" << index++ << "=0x" << userInfoField;
1169 }
1170 os << std::dec;
1171}
1172
1173} // namespace ns3
iterator in a Buffer instance
Definition buffer.h:89
Protocol header serialization and deserialization.
Definition header.h:36
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.
uint8_t m_mcsPad
MCS padding.
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.
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.
void UpdatePresentField(uint32_t field)
Update a present field.
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:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
#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:194
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:274
#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
constexpr uint16_t RADIOTAP_HE_MU_SIZE_B
Size in bytes of the HE MU field in the radiotap header.
constexpr uint16_t RADIOTAP_USIG_ALIGNMENT_B
Alignment in bytes of the U-SIG field in the radiotap header.
constexpr uint16_t RADIOTAP_ANTENNA_SIGNAL_SIZE_B
Size in bytes of the Antenna Signal field in the radiotap header.
constexpr uint16_t RADIOTAP_HE_ALIGNMENT_B
Alignment in bytes of the HE field in the radiotap header.
constexpr uint16_t RADIOTAP_HE_MU_OTHER_USER_ALIGNMENT_B
Alignment in bytes of the HE MU Other User field in the radiotap header.
constexpr uint16_t RADIOTAP_EHT_DATA_SIZE_B
Size in bytes of a data subfield of the EHT field in the radiotap header.
constexpr uint16_t RADIOTAP_CHANNEL_ALIGNMENT_B
Alignment in bytes of the Channel field in the radiotap header.
constexpr uint16_t RADIOTAP_TSFT_ALIGNMENT_B
Alignment in bytes of the TSFT field in the radiotap header.
constexpr uint16_t RADIOTAP_AMPDU_STATUS_SIZE_B
Size in bytes of the A-MPDU status field in the radiotap header.
constexpr uint16_t RADIOTAP_VHT_SIZE_B
Size in bytes of the VHT field in the radiotap header.
constexpr uint16_t RADIOTAP_EHT_USER_INFO_SIZE_B
Size in bytes of a user info subfield of the EHT field in the radiotap header.
constexpr uint16_t RADIOTAP_EHT_ALIGNMENT_B
Alignment in bytes of the EHT field in the radiotap header.
constexpr uint16_t RADIOTAP_TLV_HEADER_SIZE_B
Size in bytes of the TLV fields (without data) in the radiotap header.
constexpr std::size_t RADIOTAP_BITS_PER_PRESENT_FIELD
Number of bits per "present" field in the radiotap header.
constexpr uint16_t RADIOTAP_HE_SIZE_B
Size in bytes of the HE field in the radiotap header.
constexpr uint16_t RADIOTAP_MCS_ALIGNMENT_B
Alignment in bytes of the MCS field in the radiotap header.
constexpr uint16_t RADIOTAP_TSFT_SIZE_B
Size in bytes of the TSFT field in the radiotap header.
constexpr uint16_t RADIOTAP_HE_MU_ALIGNMENT_B
Alignment in bytes of the HE MU field in the radiotap header.
constexpr uint16_t RADIOTAP_CHANNEL_SIZE_B
Size in bytes of the Channel field in the radiotap header.
constexpr uint16_t RADIOTAP_RATE_SIZE_B
Size in bytes of the Rate field in the radiotap header.
constexpr uint16_t RADIOTAP_FLAGS_SIZE_B
Size in bytes of the Flags field in the radiotap header.
constexpr uint16_t RADIOTAP_HE_MU_OTHER_USER_SIZE_B
Size in bytes of the HE MU Other User field in the radiotap header.
constexpr uint16_t RADIOTAP_VHT_ALIGNMENT_B
Alignment in bytes of the VHT field in the radiotap header.
constexpr uint16_t RADIOTAP_AMPDU_STATUS_ALIGNMENT_B
Alignment in bytes of the A-MPDU status field in the radiotap header.
constexpr uint16_t RADIOTAP_ANTENNA_NOISE_SIZE_B
Size in bytes of the Antenna Noise field in the radiotap header.
bool IsPresent(const std::vector< std::bitset< RADIOTAP_BITS_PER_PRESENT_FIELD > > &presentBits, uint32_t field)
Check if a specific field is present in the radiotap header.
constexpr uint16_t RADIOTAP_TLV_ALIGNMENT_B
Alignment in bytes of the TLV fields in the radiotap header.
constexpr uint16_t RADIOTAP_EHT_KNOWN_SIZE_B
Size in bytes of the known subfield of the EHT field in the radiotap header.
uint8_t GetPadding(uint32_t offset, uint32_t alignment)
Calculate the padding needed to align a field.
constexpr uint16_t RADIOTAP_MCS_SIZE_B
Size in bytes of the MCS field in the radiotap header.
constexpr uint16_t RADIOTAP_USIG_SIZE_B
Size in bytes of the U-SIG field in the radiotap header.
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.
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 U-SIG field.
structure that contains the subfields of the VHT field.
uint8_t groupId
group_id field
std::array< uint8_t, 4 > mcsNss
mcs_nss field
uint16_t partialAid
partial_aid field
uint16_t known
known flags field