1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009 CTTC
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, Include., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Authors: Nicola Baldo <nbaldo@cttc.es>
19  *          Sébastien Deronne <sebastien.deronne@gmail.com>
20  */
21 
22 #include <iomanip>
23 #include <cmath>
24 #include "ns3/log.h"
25 #include "radiotap-header.h"
26 
27 namespace ns3 {
28 
29 NS_LOG_COMPONENT_DEFINE ("RadiotapHeader");
30 
31 NS_OBJECT_ENSURE_REGISTERED (RadiotapHeader);
32 
RadiotapHeader()33 RadiotapHeader::RadiotapHeader ()
34   : m_length (8),
35     m_present (0),
36     m_tsft (0),
37     m_flags (FRAME_FLAG_NONE),
38     m_rate (0),
39     m_channelFreq (0),
40     m_channelFlags (CHANNEL_FLAG_NONE),
41     m_antennaSignal (0),
42     m_antennaNoise (0),
43     m_ampduStatusRef (0),
44     m_ampduStatusFlags (0),
45     m_ampduStatusCRC (0),
46     m_vhtPad (0),
47     m_vhtKnown (0),
48     m_vhtFlags (0),
49     m_vhtBandwidth (0),
50     m_vhtCoding (0),
51     m_vhtGroupId (0),
52     m_vhtPartialAid (0),
53     m_hePad (0),
54     m_heData1 (0),
55     m_heData2 (0),
56     m_heData3 (0),
57     m_heData4 (0),
58     m_heData5 (0),
59     m_heData6 (0),
60     m_heMuPad (0),
61     m_heMuFlags1 (0),
62     m_heMuFlags2 (0),
63     m_heMuOtherUserPad (0),
64     m_heMuPerUser1 (0),
65     m_heMuPerUser2 (0),
66     m_heMuPerUserPosition (0),
67     m_heMuPerUserKnown (0)
68 {
69   NS_LOG_FUNCTION (this);
70 }
71 
GetTypeId(void)72 TypeId RadiotapHeader::GetTypeId (void)
73 {
74   static TypeId tid = TypeId ("ns3::RadiotapHeader")
75     .SetParent<Header> ()
76     .SetGroupName ("Network")
77 
78     .AddConstructor<RadiotapHeader> ()
79   ;
80   return tid;
81 }
82 
83 TypeId
GetInstanceTypeId(void) const84 RadiotapHeader::GetInstanceTypeId (void) const
85 {
86   return GetTypeId ();
87 }
88 
89 uint32_t
GetSerializedSize(void) const90 RadiotapHeader::GetSerializedSize (void) const
91 {
92   NS_LOG_FUNCTION (this);
93   return m_length;
94 }
95 
96 void
Serialize(Buffer::Iterator start) const97 RadiotapHeader::Serialize (Buffer::Iterator start) const
98 {
99   NS_LOG_FUNCTION (this << &start);
100 
101   start.WriteU8 (0); // major version of radiotap header
102   start.WriteU8 (0); // pad field
103   start.WriteU16 (m_length); // entire length of radiotap data + header
104   start.WriteU32 (m_present); // bits describing which fields follow header
105 
106   //
107   // Time Synchronization Function Timer (when the first bit of the MPDU
108   // arrived at the MAC)
109   // Reference: https://www.radiotap.org/fields/TSFT.html
110   //
111   if (m_present & RADIOTAP_TSFT) // bit 0
112     {
113       start.WriteU64 (m_tsft);
114     }
115 
116   //
117   // Properties of transmitted and received frames.
118   // Reference: https://www.radiotap.org/fields/Flags.html
119   //
120   if (m_present & RADIOTAP_FLAGS) // bit 1
121     {
122       start.WriteU8 (m_flags);
123     }
124 
125   //
126   // TX/RX data rate in units of 500 kbps
127   // Reference: https://www.radiotap.org/fields/Rate.html
128   //
129   if (m_present & RADIOTAP_RATE) // bit 2
130     {
131       start.WriteU8 (m_rate);
132     }
133 
134   //
135   // Tx/Rx frequency in MHz, followed by flags.
136   // Reference: https://www.radiotap.org/fields/Channel.html
137   //
138   if (m_present & RADIOTAP_CHANNEL) // bit 3
139     {
140       start.WriteU8 (0, m_channelPad);
141       start.WriteU16 (m_channelFreq);
142       start.WriteU16 (m_channelFlags);
143     }
144 
145   //
146   // The hop set and pattern for frequency-hopping radios.  We don't need it but
147   // still need to account for it.
148   // Reference: https://www.radiotap.org/fields/FHSS.html
149   //
150   if (m_present & RADIOTAP_FHSS) // bit 4
151     {
152       start.WriteU8 (0); //not yet implemented
153     }
154 
155   //
156   // RF signal power at the antenna, decibel difference from an arbitrary, fixed
157   // reference.
158   // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
159   //
160   if (m_present & RADIOTAP_DBM_ANTSIGNAL) // bit 5
161     {
162       start.WriteU8 (m_antennaSignal);
163     }
164 
165   //
166   // RF noise power at the antenna, decibel difference from an arbitrary, fixed
167   // reference.
168   // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
169   //
170   if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
171     {
172       start.WriteU8 (m_antennaNoise);
173     }
174 
175   //
176   // Quality of Barker code lock.
177   // Reference: https://www.radiotap.org/fields/Lock%20quality.html
178   //
179   if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
180     {
181       start.WriteU16 (0); //not yet implemented
182     }
183 
184   //
185   // Transmit power expressed as unitless distance from max power
186   // set at factory calibration (0 is max power).
187   // Reference: https://www.radiotap.org/fields/TX%20attenuation.html
188   //
189   if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
190     {
191       start.WriteU16 (0); //not yet implemented
192     }
193 
194   //
195   // Transmit power expressed as decibel distance from max power
196   // set at factory calibration (0 is max power).
197   // Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
198   //
199   if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
200     {
201       start.WriteU16 (0); //not yet implemented
202     }
203 
204   //
205   // Transmit power expressed as dBm (decibels from a 1 milliwatt reference).
206   // This is the absolute power level measured at the antenna port.
207   // Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
208   //
209   if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
210     {
211       start.WriteU8 (0); //not yet implemented
212     }
213 
214   //
215   // Unitless indication of the Rx/Tx antenna for this packet.
216   // The first antenna is antenna 0.
217   // Reference: https://www.radiotap.org/fields/Antenna.html
218   //
219   if (m_present & RADIOTAP_ANTENNA) // bit 11
220     {
221       start.WriteU8 (0); //not yet implemented
222     }
223 
224   //
225   // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
226   // Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
227   //
228   if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
229     {
230       start.WriteU8 (0); //not yet implemented
231     }
232 
233   //
234   // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
235   // Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
236   //
237   if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
238     {
239       start.WriteU8 (0); //not yet implemented
240     }
241 
242   //
243   // Properties of received frames.
244   // Reference: https://www.radiotap.org/fields/RX%20flags.html
245   //
246   if (m_present & RADIOTAP_RX_FLAGS) // bit 14
247     {
248       start.WriteU16 (0); //not yet implemented
249     }
250 
251   //
252   // MCS field.
253   // Reference: https://www.radiotap.org/fields/MCS.html
254   //
255   if (m_present & RADIOTAP_MCS) // bit 19
256     {
257       start.WriteU8 (m_mcsKnown);
258       start.WriteU8 (m_mcsFlags);
259       start.WriteU8 (m_mcsRate);
260     }
261 
262   //
263   // A-MPDU Status, information about the received or transmitted A-MPDU.
264   // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
265   //
266   if (m_present & RADIOTAP_AMPDU_STATUS) // bit 20
267     {
268       start.WriteU8 (0, m_ampduStatusPad);
269       start.WriteU32 (m_ampduStatusRef);
270       start.WriteU16 (m_ampduStatusFlags);
271       start.WriteU8 (m_ampduStatusCRC);
272       start.WriteU8 (0);
273     }
274 
275   //
276   // Information about the received or transmitted VHT frame.
277   // Reference: https://www.radiotap.org/fields/VHT.html
278   //
279   if (m_present & RADIOTAP_VHT) // bit 21
280     {
281       start.WriteU8 (0, m_vhtPad);
282       start.WriteU16 (m_vhtKnown);
283       start.WriteU8 (m_vhtFlags);
284       start.WriteU8 (m_vhtBandwidth);
285       for (uint8_t i = 0; i < 4; i++)
286         {
287           start.WriteU8 (m_vhtMcsNss[i]);
288         }
289       start.WriteU8 (m_vhtCoding);
290       start.WriteU8 (m_vhtGroupId);
291       start.WriteU16 (m_vhtPartialAid);
292     }
293 
294   //
295   // HE field.
296   // Reference: https://www.radiotap.org/fields/HE.html
297   //
298   if (m_present & RADIOTAP_HE) // bit 23
299     {
300       start.WriteU8 (0, m_hePad);
301       start.WriteU16 (m_heData1);
302       start.WriteU16 (m_heData2);
303       start.WriteU16 (m_heData3);
304       start.WriteU16 (m_heData4);
305       start.WriteU16 (m_heData5);
306       start.WriteU16 (m_heData6);
307     }
308 
309   //
310   // HE MU field.
311   // Reference: https://www.radiotap.org/fields/HE-MU.html
312   //
313   if (m_present & RADIOTAP_HE_MU) // bit 24
314     {
315       start.WriteU8 (0, m_heMuPad);
316       start.WriteU16 (m_heMuFlags1);
317       start.WriteU16 (m_heMuFlags2);
318       start.WriteU8 (0);
319       start.WriteU8 (0);
320       start.WriteU8 (0);
321       start.WriteU8 (0);
322       start.WriteU8 (0);
323       start.WriteU8 (0);
324       start.WriteU8 (0);
325       start.WriteU8 (0);
326     }
327 
328   //
329   // HE MU other user field.
330   // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
331   //
332   if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25
333     {
334       start.WriteU8 (0, m_heMuOtherUserPad);
335       start.WriteU16 (m_heMuPerUser1);
336       start.WriteU16 (m_heMuPerUser2);
337       start.WriteU8 (m_heMuPerUserPosition);
338       start.WriteU8 (m_heMuPerUserKnown);
339     }
340 }
341 
342 uint32_t
Deserialize(Buffer::Iterator start)343 RadiotapHeader::Deserialize (Buffer::Iterator start)
344 {
345   NS_LOG_FUNCTION (this << &start);
346 
347   uint8_t tmp = start.ReadU8 (); // major version of radiotap header
348   NS_ASSERT_MSG (tmp == 0x00, "RadiotapHeader::Deserialize(): Unexpected major version");
349   start.ReadU8 (); // pad field
350 
351   m_length = start.ReadU16 (); // entire length of radiotap data + header
352   m_present = start.ReadU32 (); // bits describing which fields follow header
353 
354   uint32_t bytesRead = 8;
355 
356   //
357   // Time Synchronization Function Timer (when the first bit of the MPDU arrived at the MAC)
358   // Reference: https://www.radiotap.org/fields/TSFT.html
359   //
360   if (m_present & RADIOTAP_TSFT) // bit 0
361     {
362       m_tsft = start.ReadU64 ();
363       bytesRead += 8;
364     }
365 
366   //
367   // Properties of transmitted and received frames.
368   // Reference: https://www.radiotap.org/fields/Flags.html
369   //
370   if (m_present & RADIOTAP_FLAGS) // bit 1
371     {
372       m_flags = start.ReadU8 ();
373       ++bytesRead;
374     }
375 
376   //
377   // TX/RX data rate in units of 500 kbps
378   // Reference: https://www.radiotap.org/fields/Rate.html
379   //
380   if (m_present & RADIOTAP_RATE) // bit 2
381     {
382       m_rate = start.ReadU8 ();
383       ++bytesRead;
384     }
385 
386   //
387   // Tx/Rx frequency in MHz, followed by flags.
388   // Reference: https://www.radiotap.org/fields/Channel.html
389   //
390   if (m_present & RADIOTAP_CHANNEL) // bit 3
391     {
392       m_channelPad = ((2 - bytesRead % 2) % 2);
393       start.Next (m_channelPad);
394       m_channelFreq = start.ReadU16 ();
395       m_channelFlags = start.ReadU16 ();
396       bytesRead += (4 + m_channelPad);
397     }
398 
399   //
400   // The hop set and pattern for frequency-hopping radios.  We don't need it but
401   // still need to account for it.
402   // Reference: https://www.radiotap.org/fields/FHSS.html
403   //
404   if (m_present & RADIOTAP_FHSS) // bit 4
405     {
406       //not yet implemented
407       start.ReadU8 ();
408       ++bytesRead;
409     }
410 
411   //
412   // RF signal power at the antenna, decibel difference from an arbitrary, fixed
413   // reference.
414   // Reference: https://www.radiotap.org/fields/Antenna%20signal.html
415   //
416   if (m_present & RADIOTAP_DBM_ANTSIGNAL) // bit 5
417     {
418       m_antennaSignal = start.ReadU8 ();
419       ++bytesRead;
420     }
421 
422   //
423   // RF noise power at the antenna, decibel difference from an arbitrary, fixed
424   // reference.
425   // Reference: https://www.radiotap.org/fields/Antenna%20noise.html
426   //
427   if (m_present & RADIOTAP_DBM_ANTNOISE) // bit 6
428     {
429       m_antennaNoise = start.ReadU8 ();
430       ++bytesRead;
431     }
432 
433   //
434   // Quality of Barker code lock.
435   // Reference: https://www.radiotap.org/fields/Lock%20quality.html
436   //
437   if (m_present & RADIOTAP_LOCK_QUALITY) // bit 7
438     {
439       //not yet implemented
440       start.ReadU16 ();
441       bytesRead += 2;
442     }
443 
444   //
445   // Transmit power expressed as unitless distance from max power
446   // set at factory calibration (0 is max power).
447   // Reference: https://www.radiotap.org/fields/TX%20attenuation.html
448   //
449   if (m_present & RADIOTAP_TX_ATTENUATION) // bit 8
450     {
451       //not yet implemented
452       start.ReadU16 ();
453       bytesRead += 2;
454     }
455 
456   //
457   // Transmit power expressed as decibel distance from max power
458   // set at factory calibration (0 is max power).
459   // Reference: https://www.radiotap.org/fields/dB%20TX%20attenuation.html
460   //
461   if (m_present & RADIOTAP_DB_TX_ATTENUATION) // bit 9
462     {
463       //not yet implemented
464       start.ReadU16 ();
465       bytesRead += 2;
466     }
467 
468   //
469   // Transmit power expressed as dBm (decibels from a 1 milliwatt reference).
470   // This is the absolute power level measured at the antenna port.
471   // Reference: https://www.radiotap.org/fields/dBm%20TX%20power.html
472   //
473   if (m_present & RADIOTAP_DBM_TX_POWER) // bit 10
474     {
475       //not yet implemented
476       start.ReadU8 ();
477       ++bytesRead;
478     }
479 
480   //
481   // Unitless indication of the Rx/Tx antenna for this packet.
482   // The first antenna is antenna 0.
483   // Reference: https://www.radiotap.org/fields/Antenna.html
484   //
485   if (m_present & RADIOTAP_ANTENNA) // bit 11
486     {
487       //not yet implemented
488       start.ReadU8 ();
489       ++bytesRead;
490     }
491 
492   //
493   // RF signal power at the antenna (decibel difference from an arbitrary fixed reference).
494   // Reference: https://www.radiotap.org/fields/dB%20antenna%20signal.html
495   //
496   if (m_present & RADIOTAP_DB_ANTSIGNAL) // bit 12
497     {
498       //not yet implemented
499       start.ReadU8 ();
500       ++bytesRead;
501     }
502 
503   //
504   // RF noise power at the antenna (decibel difference from an arbitrary fixed reference).
505   // Reference: https://www.radiotap.org/fields/dB%20antenna%20noise.html
506   //
507   if (m_present & RADIOTAP_DB_ANTNOISE) // bit 13
508     {
509       //not yet implemented
510       start.ReadU8 ();
511       ++bytesRead;
512     }
513 
514   //
515   // Properties of received frames.
516   // Reference: https://www.radiotap.org/fields/RX%20flags.html
517   //
518   if (m_present & RADIOTAP_RX_FLAGS) // bit 14
519     {
520       //not yet implemented
521       start.ReadU16 ();
522       bytesRead += 2;
523     }
524 
525   //
526   // MCS field.
527   // Reference: https://www.radiotap.org/fields/MCS.html
528   //
529   if (m_present & RADIOTAP_MCS) // bit 19
530     {
531       m_mcsKnown = start.ReadU8 ();
532       m_mcsFlags = start.ReadU8 ();
533       m_mcsRate = start.ReadU8 ();
534       bytesRead += 3;
535     }
536 
537   //
538   // A-MPDU Status, information about the received or transmitted A-MPDU.
539   // Reference: https://www.radiotap.org/fields/A-MPDU%20status.html
540   //
541   if (m_present & RADIOTAP_AMPDU_STATUS) // bit 20
542     {
543       m_ampduStatusPad = ((4 - bytesRead % 4) % 4);
544       start.Next (m_ampduStatusPad);
545       m_ampduStatusRef = start.ReadU32 ();
546       m_ampduStatusFlags = start.ReadU16 ();
547       m_ampduStatusCRC = start.ReadU8 ();
548       start.ReadU8 ();
549       bytesRead += (8 + m_ampduStatusPad);
550     }
551 
552   //
553   // Information about the received or transmitted VHT frame.
554   // Reference: https://www.radiotap.org/fields/VHT.html
555   //
556   if (m_present & RADIOTAP_VHT) // bit 21
557     {
558       m_vhtPad = ((2 - bytesRead % 2) % 2);
559       start.Next (m_vhtPad);
560       m_vhtKnown = start.ReadU16 ();
561       m_vhtFlags = start.ReadU8 ();
562       m_vhtBandwidth = start.ReadU8 ();
563       for (uint8_t i = 0; i < 4; i++)
564         {
565           m_vhtMcsNss[i] = start.ReadU8 ();
566         }
567       m_vhtCoding = start.ReadU8 ();
568       m_vhtGroupId = start.ReadU8 ();
569       m_vhtPartialAid = start.ReadU16 ();
570       bytesRead += (12 + m_vhtPad);
571     }
572 
573   //
574   // HE field.
575   // Reference: https://www.radiotap.org/fields/HE.html
576   //
577   if (m_present & RADIOTAP_HE) // bit 23
578     {
579       m_hePad = ((2 - bytesRead % 2) % 2);
580       start.Next (m_hePad);
581       m_heData1 = start.ReadU16 ();
582       m_heData2 = start.ReadU16 ();
583       m_heData3 = start.ReadU16 ();
584       m_heData4 = start.ReadU16 ();
585       m_heData5 = start.ReadU16 ();
586       m_heData6 = start.ReadU16 ();
587       bytesRead += (12 + m_hePad);
588     }
589 
590   //
591   // HE MU field.
592   // Reference: https://www.radiotap.org/fields/HE-MU.html
593   //
594   if (m_present & RADIOTAP_HE_MU) // bit 24
595     {
596       m_heMuPad = ((2 - bytesRead % 2) % 2);
597       m_heMuFlags1 = start.ReadU16 ();
598       m_heMuFlags2 = start.ReadU16 ();
599       start.ReadU8 ();
600       start.ReadU8 ();
601       start.ReadU8 ();
602       start.ReadU8 ();
603       start.ReadU8 ();
604       start.ReadU8 ();
605       start.ReadU8 ();
606       start.ReadU8 ();
607       bytesRead += (12 + m_heMuPad);
608     }
609 
610   //
611   // HE MU other user field.
612   // Reference: https://www.radiotap.org/fields/HE-MU-other-user.html
613   //
614   if (m_present & RADIOTAP_HE_MU_OTHER_USER) // bit 25
615     {
616       m_heMuOtherUserPad = ((2 - bytesRead % 2) % 2);
617       m_heMuPerUser1 = start.ReadU16 ();
618       m_heMuPerUser2 = start.ReadU16 ();
619       m_heMuPerUserPosition = start.ReadU8 ();
620       m_heMuPerUserKnown = start.ReadU8 ();
621       bytesRead += (6 + m_heMuOtherUserPad);
622     }
623 
624   NS_ASSERT_MSG (m_length == bytesRead, "RadiotapHeader::Deserialize(): expected and actual lengths inconsistent");
625   return bytesRead;
626 }
627 
628 void
Print(std::ostream & os) const629 RadiotapHeader::Print (std::ostream &os) const
630 {
631   NS_LOG_FUNCTION (this << &os);
632   os << " tsft=" << m_tsft
633      << " flags=" << std::hex << m_flags << std::dec
634      << " rate=" << +m_rate
635      << " freq=" << m_channelFreq
636      << " chflags=" << std::hex << +m_channelFlags << std::dec
637      << " signal=" << +m_antennaSignal
638      << " noise=" << +m_antennaNoise
639      << " mcsKnown=" << m_mcsKnown
640      << " mcsFlags=" << m_mcsFlags
641      << " mcsRate=" << m_mcsRate
642      << " ampduStatusFlags=" << +m_ampduStatusFlags
643      << " vhtKnown=" << m_vhtKnown
644      << " vhtFlags=" << m_vhtFlags
645      << " vhtBandwidth=" << m_vhtBandwidth
646      << " vhtMcsNss for user 1=" << m_vhtMcsNss[0]
647      << " vhtMcsNss for user 2=" << m_vhtMcsNss[1]
648      << " vhtMcsNss for user 3=" << m_vhtMcsNss[2]
649      << " vhtMcsNss for user 4=" << m_vhtMcsNss[3]
650      << " vhtCoding=" << m_vhtCoding
651      << " vhtGroupId=" << m_vhtGroupId
652      << " vhtPartialAid=" << m_vhtPartialAid
653      << " heData1=" << m_heData1
654      << " heData2=" << m_heData2
655      << " heData3=" << m_heData3
656      << " heData4=" << m_heData4
657      << " heData5=" << m_heData5
658      << " heData6=" << m_heData6
659      << " heMuFlags1=" << m_heMuFlags1
660      << " heMuFlags2=" << m_heMuFlags2
661      << " heMuPerUser1=" << m_heMuPerUser1
662      << " heMuPerUser2=" << m_heMuPerUser2
663      << " heMuPerUserPosition=" << +m_heMuPerUserPosition
664      << " heMuPerUserKnown=" << +m_heMuPerUserKnown;
665 }
666 
667 void
SetTsft(uint64_t value)668 RadiotapHeader::SetTsft (uint64_t value)
669 {
670   NS_LOG_FUNCTION (this << value);
671   m_tsft = value;
672 
673   if (!(m_present & RADIOTAP_TSFT))
674     {
675       m_present |= RADIOTAP_TSFT;
676       m_length += 8;
677     }
678 
679   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
680 }
681 
682 void
SetFrameFlags(uint8_t flags)683 RadiotapHeader::SetFrameFlags (uint8_t flags)
684 {
685   NS_LOG_FUNCTION (this << +flags);
686   m_flags = flags;
687 
688   if (!(m_present & RADIOTAP_FLAGS))
689     {
690       m_present |= RADIOTAP_FLAGS;
691       m_length += 1;
692     }
693 
694   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
695 }
696 
697 void
SetRate(uint8_t rate)698 RadiotapHeader::SetRate (uint8_t rate)
699 {
700   NS_LOG_FUNCTION (this << +rate);
701   m_rate = rate;
702 
703   if (!(m_present & RADIOTAP_RATE))
704     {
705       m_present |= RADIOTAP_RATE;
706       m_length += 1;
707     }
708 
709   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
710 }
711 
712 void
SetChannelFrequencyAndFlags(uint16_t frequency,uint16_t flags)713 RadiotapHeader::SetChannelFrequencyAndFlags (uint16_t frequency, uint16_t flags)
714 {
715   NS_LOG_FUNCTION (this << frequency << flags);
716   m_channelFreq = frequency;
717   m_channelFlags = flags;
718 
719   if (!(m_present & RADIOTAP_CHANNEL))
720     {
721       m_channelPad = ((2 - m_length % 2) % 2);
722       m_present |= RADIOTAP_CHANNEL;
723       m_length += (4 + m_channelPad);
724     }
725 
726   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
727 }
728 
729 void
SetAntennaSignalPower(double signal)730 RadiotapHeader::SetAntennaSignalPower (double signal)
731 {
732   NS_LOG_FUNCTION (this << signal);
733 
734   if (!(m_present & RADIOTAP_DBM_ANTSIGNAL))
735     {
736       m_present |= RADIOTAP_DBM_ANTSIGNAL;
737       m_length += 1;
738     }
739   if (signal > 127)
740     {
741       m_antennaSignal = 127;
742     }
743   else if (signal < -128)
744     {
745       m_antennaSignal = -128;
746     }
747   else
748     {
749       m_antennaSignal = static_cast<int8_t> (floor (signal + 0.5));
750     }
751 
752   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
753 }
754 
755 void
SetAntennaNoisePower(double noise)756 RadiotapHeader::SetAntennaNoisePower (double noise)
757 {
758   NS_LOG_FUNCTION (this << noise);
759 
760   if (!(m_present & RADIOTAP_DBM_ANTNOISE))
761     {
762       m_present |= RADIOTAP_DBM_ANTNOISE;
763       m_length += 1;
764     }
765   if (noise > 127.0)
766     {
767       m_antennaNoise = 127;
768     }
769   else if (noise < -128.0)
770     {
771       m_antennaNoise = -128;
772     }
773   else
774     {
775       m_antennaNoise = static_cast<int8_t> (floor (noise + 0.5));
776     }
777 
778   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
779 }
780 
781 void
SetMcsFields(uint8_t known,uint8_t flags,uint8_t mcs)782 RadiotapHeader::SetMcsFields (uint8_t known, uint8_t flags, uint8_t mcs)
783 {
784   NS_LOG_FUNCTION (this << known << +flags << +mcs);
785   m_mcsKnown = known;
786   m_mcsFlags = flags;
787   m_mcsRate = mcs;
788   if (!(m_present & RADIOTAP_MCS))
789     {
790       m_present |= RADIOTAP_MCS;
791       m_length += 3;
792     }
793 
794   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
795 }
796 
797 void
SetAmpduStatus(uint32_t referenceNumber,uint16_t flags,uint8_t crc)798 RadiotapHeader::SetAmpduStatus (uint32_t referenceNumber, uint16_t flags, uint8_t crc)
799 {
800   NS_LOG_FUNCTION (this << referenceNumber << flags);
801   m_ampduStatusRef = referenceNumber;
802   m_ampduStatusFlags = flags;
803   m_ampduStatusCRC = crc;
804   if (!(m_present & RADIOTAP_AMPDU_STATUS))
805     {
806       m_ampduStatusPad = ((4 - m_length % 4) % 4);
807       m_present |= RADIOTAP_AMPDU_STATUS;
808       m_length += (8 + m_ampduStatusPad);
809     }
810 
811   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
812 }
813 
814 void
SetVhtFields(uint16_t known,uint8_t flags,uint8_t bandwidth,uint8_t mcs_nss[4],uint8_t coding,uint8_t group_id,uint16_t partial_aid)815 RadiotapHeader::SetVhtFields (uint16_t known, uint8_t flags, uint8_t bandwidth, uint8_t mcs_nss[4], uint8_t coding, uint8_t group_id, uint16_t partial_aid)
816 {
817   NS_LOG_FUNCTION (this << known << flags << +mcs_nss[0] << +mcs_nss[1] << +mcs_nss[2] << +mcs_nss[3] << +coding << +group_id << +partial_aid);
818   m_vhtKnown = known;
819   m_vhtFlags = flags;
820   m_vhtBandwidth = bandwidth;
821   for (uint8_t i = 0; i < 4; i++)
822     {
823       m_vhtMcsNss[i] = mcs_nss[i];
824     }
825   m_vhtCoding = coding;
826   m_vhtGroupId = group_id;
827   m_vhtPartialAid = partial_aid;
828   if (!(m_present & RADIOTAP_VHT))
829     {
830       m_vhtPad = ((2 - m_length % 2) % 2);
831       m_present |= RADIOTAP_VHT;
832       m_length += (12 + m_vhtPad);
833     }
834 
835   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
836 }
837 
838 void
SetHeFields(uint16_t data1,uint16_t data2,uint16_t data3,uint16_t data4,uint16_t data5,uint16_t data6)839 RadiotapHeader::SetHeFields (uint16_t data1, uint16_t data2, uint16_t data3, uint16_t data4, uint16_t data5, uint16_t data6)
840 {
841   NS_LOG_FUNCTION (this << data1 << data2 << data3 << data4 << data5 << data6);
842   m_heData1 = data1;
843   m_heData2 = data2;
844   m_heData3 = data3;
845   m_heData4 = data4;
846   m_heData5 = data5;
847   m_heData6 = data6;
848   if (!(m_present & RADIOTAP_HE))
849     {
850       m_hePad = ((2 - m_length % 2) % 2);
851       m_present |= RADIOTAP_HE;
852       m_length += (12 + m_hePad);
853     }
854 
855   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
856 }
857 
858 void
SetHeMuFields(uint16_t flags1,uint16_t flags2,const std::array<uint8_t,4> &,const std::array<uint8_t,4> &)859 RadiotapHeader::SetHeMuFields (uint16_t flags1, uint16_t flags2, const std::array<uint8_t, 4> &/*ruChannel1*/, const std::array<uint8_t, 4> &/*ruChannel2*/)
860 {
861   NS_LOG_FUNCTION (this << flags1 << flags2);
862   m_heMuFlags1 = flags1;
863   m_heMuFlags2 = flags2;
864   if (!(m_present & RADIOTAP_HE_MU))
865     {
866       m_heMuPad = ((2 - m_length % 2) % 2);
867       m_present |= RADIOTAP_HE_MU;
868       m_length += (12 + m_heMuPad);
869     }
870 
871   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
872 }
873 
874 void
SetHeMuPerUserFields(uint16_t perUser1,uint16_t perUser2,uint8_t perUserPosition,uint8_t perUserKnown)875 RadiotapHeader::SetHeMuPerUserFields (uint16_t perUser1, uint16_t perUser2, uint8_t perUserPosition, uint8_t perUserKnown)
876 {
877   NS_LOG_FUNCTION (this << perUser1 << perUser2 << +perUserPosition << +perUserKnown);
878   m_heMuPerUser1 = perUser1;
879   m_heMuPerUser2 = perUser2;
880   m_heMuPerUserPosition = perUserPosition;
881   m_heMuPerUserKnown = perUserKnown;
882   if (!(m_present & RADIOTAP_HE_MU_OTHER_USER))
883     {
884       m_heMuOtherUserPad = ((2 - m_length % 2) % 2);
885       m_present |= RADIOTAP_HE_MU_OTHER_USER;
886       m_length += (6 + m_heMuOtherUserPad);
887     }
888 
889   NS_LOG_LOGIC (this << " m_length=" << m_length << " m_present=0x" << std::hex << m_present << std::dec);
890 }
891 
892 } // namespace ns3
893