1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 INRIA
4  * Copyright (c) 2009 MIRKO BANCHI
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20  *          Mirko Banchi <mk.banchi@gmail.com>
21  */
22 
23 #include "ns3/wifi-net-device.h"
24 #include "ns3/ap-wifi-mac.h"
25 #include "ns3/ampdu-subframe-header.h"
26 #include "ns3/mobility-model.h"
27 #include "ns3/log.h"
28 #include "ns3/pointer.h"
29 #include "ns3/radiotap-header.h"
30 #include "ns3/config.h"
31 #include "ns3/names.h"
32 #include "ns3/net-device-queue-interface.h"
33 #include "ns3/wifi-mac-queue.h"
34 #include "ns3/qos-utils.h"
35 #include "ns3/ht-configuration.h"
36 #include "ns3/vht-configuration.h"
37 #include "ns3/he-configuration.h"
38 #include "ns3/obss-pd-algorithm.h"
39 #include "wifi-helper.h"
40 
41 namespace ns3 {
42 
43 NS_LOG_COMPONENT_DEFINE ("WifiHelper");
44 
45 /**
46  * ASCII trace PHY transmit sink with context
47  * \param stream the output stream
48  * \param context the context name
49  * \param p the packet
50  * \param mode the wifi mode
51  * \param preamble the wifi preamble
52  * \param txLevel the transmit power level
53  */
54 static void
AsciiPhyTransmitSinkWithContext(Ptr<OutputStreamWrapper> stream,std::string context,Ptr<const Packet> p,WifiMode mode,WifiPreamble preamble,uint8_t txLevel)55 AsciiPhyTransmitSinkWithContext (
56   Ptr<OutputStreamWrapper> stream,
57   std::string context,
58   Ptr<const Packet> p,
59   WifiMode mode,
60   WifiPreamble preamble,
61   uint8_t txLevel)
62 {
63   NS_LOG_FUNCTION (stream << context << p << mode << preamble << txLevel);
64   *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << " " << mode << " " << *p << std::endl;
65 }
66 
67 /**
68  * ASCII trace PHY transmit sink without context
69  * \param stream the output stream
70  * \param p the packet
71  * \param mode the wifi mode
72  * \param preamble the wifi preamble
73  * \param txLevel the transmit power level
74  */
75 static void
AsciiPhyTransmitSinkWithoutContext(Ptr<OutputStreamWrapper> stream,Ptr<const Packet> p,WifiMode mode,WifiPreamble preamble,uint8_t txLevel)76 AsciiPhyTransmitSinkWithoutContext (
77   Ptr<OutputStreamWrapper> stream,
78   Ptr<const Packet> p,
79   WifiMode mode,
80   WifiPreamble preamble,
81   uint8_t txLevel)
82 {
83   NS_LOG_FUNCTION (stream << p << mode << preamble << txLevel);
84   *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << mode << " " << *p << std::endl;
85 }
86 
87 /**
88  * ASCII trace PHY receive sink with context
89  * \param stream the output stream
90  * \param context the context name
91  * \param p the packet
92  * \param snr the SNR
93  * \param mode the wifi mode
94  * \param preamble the wifi preamble
95  */
96 static void
AsciiPhyReceiveSinkWithContext(Ptr<OutputStreamWrapper> stream,std::string context,Ptr<const Packet> p,double snr,WifiMode mode,WifiPreamble preamble)97 AsciiPhyReceiveSinkWithContext (
98   Ptr<OutputStreamWrapper> stream,
99   std::string context,
100   Ptr<const Packet> p,
101   double snr,
102   WifiMode mode,
103   WifiPreamble preamble)
104 {
105   NS_LOG_FUNCTION (stream << context << p << snr << mode << preamble);
106   *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << mode << "" << context << " " << *p << std::endl;
107 }
108 
109 /**
110  * ASCII trace PHY receive sink without context
111  * \param stream the output stream
112  * \param p the packet
113  * \param snr the SNR
114  * \param mode the wifi mode
115  * \param preamble the wifi preamble
116  */
117 static void
AsciiPhyReceiveSinkWithoutContext(Ptr<OutputStreamWrapper> stream,Ptr<const Packet> p,double snr,WifiMode mode,WifiPreamble preamble)118 AsciiPhyReceiveSinkWithoutContext (
119   Ptr<OutputStreamWrapper> stream,
120   Ptr<const Packet> p,
121   double snr,
122   WifiMode mode,
123   WifiPreamble preamble)
124 {
125   NS_LOG_FUNCTION (stream << p << snr << mode << preamble);
126   *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << mode << " " << *p << std::endl;
127 }
128 
WifiPhyHelper()129 WifiPhyHelper::WifiPhyHelper ()
130   : m_pcapDlt (PcapHelper::DLT_IEEE802_11)
131 {
132   SetPreambleDetectionModel ("ns3::ThresholdPreambleDetectionModel");
133 }
134 
~WifiPhyHelper()135 WifiPhyHelper::~WifiPhyHelper ()
136 {
137 }
138 
139 void
Set(std::string name,const AttributeValue & v)140 WifiPhyHelper::Set (std::string name, const AttributeValue &v)
141 {
142   m_phy.Set (name, v);
143 }
144 
145 void
SetErrorRateModel(std::string name,std::string n0,const AttributeValue & v0,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7)146 WifiPhyHelper::SetErrorRateModel (std::string name,
147                                   std::string n0, const AttributeValue &v0,
148                                   std::string n1, const AttributeValue &v1,
149                                   std::string n2, const AttributeValue &v2,
150                                   std::string n3, const AttributeValue &v3,
151                                   std::string n4, const AttributeValue &v4,
152                                   std::string n5, const AttributeValue &v5,
153                                   std::string n6, const AttributeValue &v6,
154                                   std::string n7, const AttributeValue &v7)
155 {
156   m_errorRateModel = ObjectFactory ();
157   m_errorRateModel.SetTypeId (name);
158   m_errorRateModel.Set (n0, v0);
159   m_errorRateModel.Set (n1, v1);
160   m_errorRateModel.Set (n2, v2);
161   m_errorRateModel.Set (n3, v3);
162   m_errorRateModel.Set (n4, v4);
163   m_errorRateModel.Set (n5, v5);
164   m_errorRateModel.Set (n6, v6);
165   m_errorRateModel.Set (n7, v7);
166 }
167 
168 void
SetFrameCaptureModel(std::string name,std::string n0,const AttributeValue & v0,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7)169 WifiPhyHelper::SetFrameCaptureModel (std::string name,
170                                      std::string n0, const AttributeValue &v0,
171                                      std::string n1, const AttributeValue &v1,
172                                      std::string n2, const AttributeValue &v2,
173                                      std::string n3, const AttributeValue &v3,
174                                      std::string n4, const AttributeValue &v4,
175                                      std::string n5, const AttributeValue &v5,
176                                      std::string n6, const AttributeValue &v6,
177                                      std::string n7, const AttributeValue &v7)
178 {
179   m_frameCaptureModel = ObjectFactory ();
180   m_frameCaptureModel.SetTypeId (name);
181   m_frameCaptureModel.Set (n0, v0);
182   m_frameCaptureModel.Set (n1, v1);
183   m_frameCaptureModel.Set (n2, v2);
184   m_frameCaptureModel.Set (n3, v3);
185   m_frameCaptureModel.Set (n4, v4);
186   m_frameCaptureModel.Set (n5, v5);
187   m_frameCaptureModel.Set (n6, v6);
188   m_frameCaptureModel.Set (n7, v7);
189 }
190 
191 void
SetPreambleDetectionModel(std::string name,std::string n0,const AttributeValue & v0,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7)192 WifiPhyHelper::SetPreambleDetectionModel (std::string name,
193                                           std::string n0, const AttributeValue &v0,
194                                           std::string n1, const AttributeValue &v1,
195                                           std::string n2, const AttributeValue &v2,
196                                           std::string n3, const AttributeValue &v3,
197                                           std::string n4, const AttributeValue &v4,
198                                           std::string n5, const AttributeValue &v5,
199                                           std::string n6, const AttributeValue &v6,
200                                           std::string n7, const AttributeValue &v7)
201 {
202   m_preambleDetectionModel = ObjectFactory ();
203   m_preambleDetectionModel.SetTypeId (name);
204   m_preambleDetectionModel.Set (n0, v0);
205   m_preambleDetectionModel.Set (n1, v1);
206   m_preambleDetectionModel.Set (n2, v2);
207   m_preambleDetectionModel.Set (n3, v3);
208   m_preambleDetectionModel.Set (n4, v4);
209   m_preambleDetectionModel.Set (n5, v5);
210   m_preambleDetectionModel.Set (n6, v6);
211   m_preambleDetectionModel.Set (n7, v7);
212 }
213 
214 void
DisablePreambleDetectionModel()215 WifiPhyHelper::DisablePreambleDetectionModel ()
216 {
217     m_preambleDetectionModel.SetTypeId (TypeId ());
218 }
219 
220 void
PcapSniffTxEvent(Ptr<PcapFileWrapper> file,Ptr<const Packet> packet,uint16_t channelFreqMhz,WifiTxVector txVector,MpduInfo aMpdu,uint16_t staId)221 WifiPhyHelper::PcapSniffTxEvent (
222   Ptr<PcapFileWrapper> file,
223   Ptr<const Packet>    packet,
224   uint16_t             channelFreqMhz,
225   WifiTxVector         txVector,
226   MpduInfo             aMpdu,
227   uint16_t             staId)
228 {
229   uint32_t dlt = file->GetDataLinkType ();
230   switch (dlt)
231     {
232     case PcapHelper::DLT_IEEE802_11:
233       file->Write (Simulator::Now (), packet);
234       return;
235     case PcapHelper::DLT_PRISM_HEADER:
236       {
237         NS_FATAL_ERROR ("PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented");
238         return;
239       }
240     case PcapHelper::DLT_IEEE802_11_RADIO:
241       {
242         Ptr<Packet> p = packet->Copy ();
243         RadiotapHeader header;
244         GetRadiotapHeader (header, p, channelFreqMhz, txVector, aMpdu, staId);
245         p->AddHeader (header);
246         file->Write (Simulator::Now (), p);
247         return;
248       }
249     default:
250       NS_ABORT_MSG ("PcapSniffTxEvent(): Unexpected data link type " << dlt);
251     }
252 }
253 
254 void
PcapSniffRxEvent(Ptr<PcapFileWrapper> file,Ptr<const Packet> packet,uint16_t channelFreqMhz,WifiTxVector txVector,MpduInfo aMpdu,SignalNoiseDbm signalNoise,uint16_t staId)255 WifiPhyHelper::PcapSniffRxEvent (
256   Ptr<PcapFileWrapper>  file,
257   Ptr<const Packet>     packet,
258   uint16_t              channelFreqMhz,
259   WifiTxVector          txVector,
260   MpduInfo              aMpdu,
261   SignalNoiseDbm        signalNoise,
262   uint16_t              staId)
263 {
264   uint32_t dlt = file->GetDataLinkType ();
265   switch (dlt)
266     {
267     case PcapHelper::DLT_IEEE802_11:
268       file->Write (Simulator::Now (), packet);
269       return;
270     case PcapHelper::DLT_PRISM_HEADER:
271       {
272         NS_FATAL_ERROR ("PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented");
273         return;
274       }
275     case PcapHelper::DLT_IEEE802_11_RADIO:
276       {
277         Ptr<Packet> p = packet->Copy ();
278         RadiotapHeader header;
279         GetRadiotapHeader (header, p, channelFreqMhz, txVector, aMpdu, staId, signalNoise);
280         p->AddHeader (header);
281         file->Write (Simulator::Now (), p);
282         return;
283       }
284     default:
285       NS_ABORT_MSG ("PcapSniffRxEvent(): Unexpected data link type " << dlt);
286     }
287 }
288 
289 void
GetRadiotapHeader(RadiotapHeader & header,Ptr<Packet> packet,uint16_t channelFreqMhz,WifiTxVector txVector,MpduInfo aMpdu,uint16_t staId,SignalNoiseDbm signalNoise)290 WifiPhyHelper::GetRadiotapHeader (
291   RadiotapHeader       &header,
292   Ptr<Packet>          packet,
293   uint16_t             channelFreqMhz,
294   WifiTxVector         txVector,
295   MpduInfo             aMpdu,
296   uint16_t             staId,
297   SignalNoiseDbm       signalNoise)
298 {
299   header.SetAntennaSignalPower (signalNoise.signal);
300   header.SetAntennaNoisePower (signalNoise.noise);
301   GetRadiotapHeader (header, packet, channelFreqMhz, txVector, aMpdu, staId);
302 }
303 
304 void
GetRadiotapHeader(RadiotapHeader & header,Ptr<Packet> packet,uint16_t channelFreqMhz,WifiTxVector txVector,MpduInfo aMpdu,uint16_t staId)305 WifiPhyHelper::GetRadiotapHeader (
306   RadiotapHeader       &header,
307   Ptr<Packet>          packet,
308   uint16_t             channelFreqMhz,
309   WifiTxVector         txVector,
310   MpduInfo             aMpdu,
311   uint16_t             staId)
312 {
313   WifiPreamble preamble = txVector.GetPreambleType ();
314 
315   uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
316   header.SetTsft (Simulator::Now ().GetMicroSeconds ());
317 
318   //Our capture includes the FCS, so we set the flag to say so.
319   frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
320 
321   if (preamble == WIFI_PREAMBLE_SHORT)
322     {
323       frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
324     }
325 
326   if (txVector.GetGuardInterval () == 400)
327     {
328       frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_GUARD;
329     }
330 
331   header.SetFrameFlags (frameFlags);
332 
333   uint64_t rate = 0;
334   if (txVector.GetMode (staId).GetModulationClass () != WIFI_MOD_CLASS_HT
335       && txVector.GetMode (staId).GetModulationClass () != WIFI_MOD_CLASS_VHT
336       && txVector.GetMode (staId).GetModulationClass () != WIFI_MOD_CLASS_HE)
337     {
338       rate = txVector.GetMode (staId).GetDataRate (txVector.GetChannelWidth (), txVector.GetGuardInterval (), 1) * txVector.GetNss (staId) / 500000;
339       header.SetRate (static_cast<uint8_t> (rate));
340     }
341 
342   uint16_t channelFlags = 0;
343   switch (rate)
344     {
345     case 2:  //1Mbps
346     case 4:  //2Mbps
347     case 10: //5Mbps
348     case 22: //11Mbps
349       channelFlags |= RadiotapHeader::CHANNEL_FLAG_CCK;
350       break;
351     default:
352       channelFlags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
353       break;
354     }
355 
356   if (channelFreqMhz < 2500)
357     {
358       channelFlags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
359     }
360   else
361     {
362       channelFlags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
363     }
364 
365   header.SetChannelFrequencyAndFlags (channelFreqMhz, channelFlags);
366 
367   if (txVector.GetMode (staId).GetModulationClass () == WIFI_MOD_CLASS_HT)
368     {
369       uint8_t mcsKnown = RadiotapHeader::MCS_KNOWN_NONE;
370       uint8_t mcsFlags = RadiotapHeader::MCS_FLAGS_NONE;
371 
372       mcsKnown |= RadiotapHeader::MCS_KNOWN_INDEX;
373 
374       mcsKnown |= RadiotapHeader::MCS_KNOWN_BANDWIDTH;
375       if (txVector.GetChannelWidth () == 40)
376         {
377           mcsFlags |= RadiotapHeader::MCS_FLAGS_BANDWIDTH_40;
378         }
379 
380       mcsKnown |= RadiotapHeader::MCS_KNOWN_GUARD_INTERVAL;
381       if (txVector.GetGuardInterval () == 400)
382         {
383           mcsFlags |= RadiotapHeader::MCS_FLAGS_GUARD_INTERVAL;
384         }
385 
386       mcsKnown |= RadiotapHeader::MCS_KNOWN_HT_FORMAT;
387 
388       mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS;
389       if (txVector.GetNess () & 0x01) //bit 1
390         {
391           mcsFlags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
392         }
393       if (txVector.GetNess () & 0x02) //bit 2
394         {
395           mcsKnown |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
396         }
397 
398       mcsKnown |= RadiotapHeader::MCS_KNOWN_FEC_TYPE; //only BCC is currently supported
399 
400       mcsKnown |= RadiotapHeader::MCS_KNOWN_STBC;
401       if (txVector.IsStbc ())
402         {
403           mcsFlags |= RadiotapHeader::MCS_FLAGS_STBC_STREAMS;
404         }
405 
406       header.SetMcsFields (mcsKnown, mcsFlags, txVector.GetMode (staId).GetMcsValue ());
407     }
408 
409   if (txVector.IsAggregation ())
410     {
411       uint16_t ampduStatusFlags = RadiotapHeader::A_MPDU_STATUS_NONE;
412       ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
413       /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
414       AmpduSubframeHeader hdr;
415       uint32_t extractedLength;
416       packet->RemoveHeader (hdr);
417       extractedLength = hdr.GetLength ();
418       packet = packet->CreateFragment (0, static_cast<uint32_t> (extractedLength));
419       if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof () == true && hdr.GetLength () > 0))
420         {
421           ampduStatusFlags |= RadiotapHeader::A_MPDU_STATUS_LAST;
422         }
423       header.SetAmpduStatus (aMpdu.mpduRefNumber, ampduStatusFlags, 1 /*CRC*/);
424     }
425 
426   if (txVector.GetMode (staId).GetModulationClass () == WIFI_MOD_CLASS_VHT)
427     {
428       uint16_t vhtKnown = RadiotapHeader::VHT_KNOWN_NONE;
429       uint8_t vhtFlags = RadiotapHeader::VHT_FLAGS_NONE;
430       uint8_t vhtBandwidth = 0;
431       uint8_t vhtMcsNss[4] = {0,0,0,0};
432       uint8_t vhtCoding = 0;
433       uint8_t vhtGroupId = 0;
434       uint16_t vhtPartialAid = 0;
435 
436       vhtKnown |= RadiotapHeader::VHT_KNOWN_STBC;
437       if (txVector.IsStbc ())
438         {
439           vhtFlags |= RadiotapHeader::VHT_FLAGS_STBC;
440         }
441 
442       vhtKnown |= RadiotapHeader::VHT_KNOWN_GUARD_INTERVAL;
443       if (txVector.GetGuardInterval () == 400)
444         {
445           vhtFlags |= RadiotapHeader::VHT_FLAGS_GUARD_INTERVAL;
446         }
447 
448       vhtKnown |= RadiotapHeader::VHT_KNOWN_BEAMFORMED; //Beamforming is currently not supported
449 
450       vhtKnown |= RadiotapHeader::VHT_KNOWN_BANDWIDTH;
451       //not all bandwidth values are currently supported
452       if (txVector.GetChannelWidth () == 40)
453         {
454           vhtBandwidth = 1;
455         }
456       else if (txVector.GetChannelWidth () == 80)
457         {
458           vhtBandwidth = 4;
459         }
460       else if (txVector.GetChannelWidth () == 160)
461         {
462           vhtBandwidth = 11;
463         }
464 
465       //only SU PPDUs are currently supported
466       vhtMcsNss[0] |= (txVector.GetNss (staId) & 0x0f);
467       vhtMcsNss[0] |= ((txVector.GetMode (staId).GetMcsValue () << 4) & 0xf0);
468 
469       header.SetVhtFields (vhtKnown, vhtFlags, vhtBandwidth, vhtMcsNss, vhtCoding, vhtGroupId, vhtPartialAid);
470     }
471 
472   if (txVector.GetMode (staId).GetModulationClass () == WIFI_MOD_CLASS_HE)
473     {
474       uint16_t data1 = RadiotapHeader::HE_DATA1_BSS_COLOR_KNOWN | RadiotapHeader::HE_DATA1_DATA_MCS_KNOWN | RadiotapHeader::HE_DATA1_BW_RU_ALLOC_KNOWN;
475       if (preamble == WIFI_PREAMBLE_HE_ER_SU)
476         {
477           data1 |= RadiotapHeader::HE_DATA1_FORMAT_EXT_SU;
478         }
479       else if (preamble == WIFI_PREAMBLE_HE_MU)
480         {
481           data1 |= RadiotapHeader::HE_DATA1_FORMAT_MU;
482           data1 |= RadiotapHeader::HE_DATA1_SPTL_REUSE2_KNOWN;
483         }
484       else if (preamble == WIFI_PREAMBLE_HE_TB)
485         {
486           data1 |= RadiotapHeader::HE_DATA1_FORMAT_TRIG;
487         }
488 
489       uint16_t data2 = RadiotapHeader::HE_DATA2_GI_KNOWN;
490       if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
491         {
492           data2 |= RadiotapHeader::HE_DATA2_RU_OFFSET_KNOWN;
493           //HeRu indices start at 1 whereas RadioTap starts at 0
494           data2 |= (((txVector.GetHeMuUserInfo (staId).ru.GetIndex () - 1) << 8) & 0x3f00);
495           data2 |= (((!txVector.GetHeMuUserInfo (staId).ru.GetPrimary80MHz ()) << 15) & 0x8000);
496         }
497 
498       uint16_t data3 = 0;
499       data3 |= (txVector.GetBssColor () & 0x003f);
500       data3 |= ((txVector.GetMode (staId).GetMcsValue () << 8) & 0x0f00);
501 
502       uint16_t data4 = 0;
503       if (preamble == WIFI_PREAMBLE_HE_MU)
504         {
505           data4 |= ((staId << 4) & 0x7ff0);
506         }
507 
508       uint16_t data5 = 0;
509       if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
510         {
511           HeRu::RuType ruType = txVector.GetHeMuUserInfo (staId).ru.GetRuType ();
512           switch (ruType)
513             {
514             case HeRu::RU_26_TONE:
515               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_26T;
516               break;
517             case HeRu::RU_52_TONE:
518               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_52T;
519               break;
520             case HeRu::RU_106_TONE:
521               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_106T;
522               break;
523             case HeRu::RU_242_TONE:
524               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_242T;
525               break;
526             case HeRu::RU_484_TONE:
527               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_484T;
528               break;
529             case HeRu::RU_996_TONE:
530               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_996T;
531               break;
532             case HeRu::RU_2x996_TONE:
533               data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_2x996T;
534               break;
535             default:
536               NS_ABORT_MSG ("Unexpected RU type");
537             }
538         }
539       else if (txVector.GetChannelWidth () == 40)
540         {
541           data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_40MHZ;
542         }
543       else if (txVector.GetChannelWidth () == 80)
544         {
545           data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_80MHZ;
546         }
547       else if (txVector.GetChannelWidth () == 160)
548         {
549           data5 |= RadiotapHeader::HE_DATA5_DATA_BW_RU_ALLOC_160MHZ;
550         }
551       if (txVector.GetGuardInterval () == 1600)
552         {
553           data5 |= RadiotapHeader::HE_DATA5_GI_1_6;
554         }
555       else if (txVector.GetGuardInterval () == 3200)
556         {
557           data5 |= RadiotapHeader::HE_DATA5_GI_3_2;
558         }
559 
560       header.SetHeFields (data1, data2, data3, data4, data5, 0);
561     }
562 
563   if (preamble == WIFI_PREAMBLE_HE_MU)
564     {
565       //TODO: fill in fields (everything is set to 0 so far)
566       std::array<uint8_t, 4> ruChannel1, ruChannel2;
567       header.SetHeMuFields (0, 0, ruChannel1, ruChannel2);
568       header.SetHeMuPerUserFields (0, 0, 0, 0);
569     }
570 }
571 
572 void
SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)573 WifiPhyHelper::SetPcapDataLinkType (SupportedPcapDataLinkTypes dlt)
574 {
575   switch (dlt)
576     {
577     case DLT_IEEE802_11:
578       m_pcapDlt = PcapHelper::DLT_IEEE802_11;
579       return;
580     case DLT_PRISM_HEADER:
581       m_pcapDlt = PcapHelper::DLT_PRISM_HEADER;
582       return;
583     case DLT_IEEE802_11_RADIO:
584       m_pcapDlt = PcapHelper::DLT_IEEE802_11_RADIO;
585       return;
586     default:
587       NS_ABORT_MSG ("WifiPhyHelper::SetPcapFormat(): Unexpected format");
588     }
589 }
590 
591 PcapHelper::DataLinkType
GetPcapDataLinkType(void) const592 WifiPhyHelper::GetPcapDataLinkType (void) const
593 {
594   return m_pcapDlt;
595 }
596 
597 void
EnablePcapInternal(std::string prefix,Ptr<NetDevice> nd,bool promiscuous,bool explicitFilename)598 WifiPhyHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
599 {
600   NS_LOG_FUNCTION (this << prefix << nd << promiscuous << explicitFilename);
601 
602   //All of the Pcap enable functions vector through here including the ones
603   //that are wandering through all of devices on perhaps all of the nodes in
604   //the system. We can only deal with devices of type WifiNetDevice.
605   Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice> ();
606   if (device == 0)
607     {
608       NS_LOG_INFO ("WifiHelper::EnablePcapInternal(): Device " << &device << " not of type ns3::WifiNetDevice");
609       return;
610     }
611 
612   Ptr<WifiPhy> phy = device->GetPhy ();
613   NS_ABORT_MSG_IF (phy == 0, "WifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
614 
615   PcapHelper pcapHelper;
616 
617   std::string filename;
618   if (explicitFilename)
619     {
620       filename = prefix;
621     }
622   else
623     {
624       filename = pcapHelper.GetFilenameFromDevice (prefix, device);
625     }
626 
627   Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, m_pcapDlt);
628 
629   phy->TraceConnectWithoutContext ("MonitorSnifferTx", MakeBoundCallback (&WifiPhyHelper::PcapSniffTxEvent, file));
630   phy->TraceConnectWithoutContext ("MonitorSnifferRx", MakeBoundCallback (&WifiPhyHelper::PcapSniffRxEvent, file));
631 }
632 
633 void
EnableAsciiInternal(Ptr<OutputStreamWrapper> stream,std::string prefix,Ptr<NetDevice> nd,bool explicitFilename)634 WifiPhyHelper::EnableAsciiInternal (
635   Ptr<OutputStreamWrapper> stream,
636   std::string prefix,
637   Ptr<NetDevice> nd,
638   bool explicitFilename)
639 {
640   //All of the ASCII enable functions vector through here including the ones
641   //that are wandering through all of devices on perhaps all of the nodes in
642   //the system. We can only deal with devices of type WifiNetDevice.
643   Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice> ();
644   if (device == 0)
645     {
646       NS_LOG_INFO ("WifiHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::WifiNetDevice");
647       return;
648     }
649 
650   //Our trace sinks are going to use packet printing, so we have to make sure
651   //that is turned on.
652   Packet::EnablePrinting ();
653 
654   uint32_t nodeid = nd->GetNode ()->GetId ();
655   uint32_t deviceid = nd->GetIfIndex ();
656   std::ostringstream oss;
657 
658   //If we are not provided an OutputStreamWrapper, we are expected to create
659   //one using the usual trace filename conventions and write our traces
660   //without a context since there will be one file per context and therefore
661   //the context would be redundant.
662   if (stream == 0)
663     {
664       //Set up an output stream object to deal with private ofstream copy
665       //constructor and lifetime issues. Let the helper decide the actual
666       //name of the file given the prefix.
667       AsciiTraceHelper asciiTraceHelper;
668 
669       std::string filename;
670       if (explicitFilename)
671         {
672           filename = prefix;
673         }
674       else
675         {
676           filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
677         }
678 
679       Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
680       //We could go poking through the PHY and the state looking for the
681       //correct trace source, but we can let Config deal with that with
682       //some search cost.  Since this is presumably happening at topology
683       //creation time, it doesn't seem much of a price to pay.
684       oss.str ("");
685       oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk";
686       Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithoutContext, theStream));
687 
688       oss.str ("");
689       oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx";
690       Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithoutContext, theStream));
691 
692       return;
693     }
694 
695   //If we are provided an OutputStreamWrapper, we are expected to use it, and
696   //to provide a context. We are free to come up with our own context if we
697   //want, and use the AsciiTraceHelper Hook*WithContext functions, but for
698   //compatibility and simplicity, we just use Config::Connect and let it deal
699   //with coming up with a context.
700   oss.str ("");
701   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk";
702   Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithContext, stream));
703 
704   oss.str ("");
705   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx";
706   Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithContext, stream));
707 }
708 
~WifiHelper()709 WifiHelper::~WifiHelper ()
710 {
711 }
712 
WifiHelper()713 WifiHelper::WifiHelper ()
714   : m_standard (WIFI_STANDARD_80211a),
715     m_selectQueueCallback (&SelectQueueByDSField)
716 {
717   SetRemoteStationManager ("ns3::ArfWifiManager");
718 }
719 
720 void
SetRemoteStationManager(std::string type,std::string n0,const AttributeValue & v0,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7)721 WifiHelper::SetRemoteStationManager (std::string type,
722                                      std::string n0, const AttributeValue &v0,
723                                      std::string n1, const AttributeValue &v1,
724                                      std::string n2, const AttributeValue &v2,
725                                      std::string n3, const AttributeValue &v3,
726                                      std::string n4, const AttributeValue &v4,
727                                      std::string n5, const AttributeValue &v5,
728                                      std::string n6, const AttributeValue &v6,
729                                      std::string n7, const AttributeValue &v7)
730 {
731   m_stationManager = ObjectFactory ();
732   m_stationManager.SetTypeId (type);
733   m_stationManager.Set (n0, v0);
734   m_stationManager.Set (n1, v1);
735   m_stationManager.Set (n2, v2);
736   m_stationManager.Set (n3, v3);
737   m_stationManager.Set (n4, v4);
738   m_stationManager.Set (n5, v5);
739   m_stationManager.Set (n6, v6);
740   m_stationManager.Set (n7, v7);
741 }
742 
743 void
SetObssPdAlgorithm(std::string type,std::string n0,const AttributeValue & v0,std::string n1,const AttributeValue & v1,std::string n2,const AttributeValue & v2,std::string n3,const AttributeValue & v3,std::string n4,const AttributeValue & v4,std::string n5,const AttributeValue & v5,std::string n6,const AttributeValue & v6,std::string n7,const AttributeValue & v7)744 WifiHelper::SetObssPdAlgorithm (std::string type,
745                                 std::string n0, const AttributeValue &v0,
746                                 std::string n1, const AttributeValue &v1,
747                                 std::string n2, const AttributeValue &v2,
748                                 std::string n3, const AttributeValue &v3,
749                                 std::string n4, const AttributeValue &v4,
750                                 std::string n5, const AttributeValue &v5,
751                                 std::string n6, const AttributeValue &v6,
752                                 std::string n7, const AttributeValue &v7)
753 {
754   m_obssPdAlgorithm = ObjectFactory ();
755   m_obssPdAlgorithm.SetTypeId (type);
756   m_obssPdAlgorithm.Set (n0, v0);
757   m_obssPdAlgorithm.Set (n1, v1);
758   m_obssPdAlgorithm.Set (n2, v2);
759   m_obssPdAlgorithm.Set (n3, v3);
760   m_obssPdAlgorithm.Set (n4, v4);
761   m_obssPdAlgorithm.Set (n5, v5);
762   m_obssPdAlgorithm.Set (n6, v6);
763   m_obssPdAlgorithm.Set (n7, v7);
764 }
765 
766 void
SetStandard(WifiStandard standard)767 WifiHelper::SetStandard (WifiStandard standard)
768 {
769   m_standard = standard;
770 }
771 
772 void
SetSelectQueueCallback(SelectQueueCallback f)773 WifiHelper::SetSelectQueueCallback (SelectQueueCallback f)
774 {
775   m_selectQueueCallback = f;
776 }
777 
778 NetDeviceContainer
Install(const WifiPhyHelper & phyHelper,const WifiMacHelper & macHelper,NodeContainer::Iterator first,NodeContainer::Iterator last) const779 WifiHelper::Install (const WifiPhyHelper &phyHelper,
780                      const WifiMacHelper &macHelper,
781                      NodeContainer::Iterator first,
782                      NodeContainer::Iterator last) const
783 {
784   NetDeviceContainer devices;
785   for (NodeContainer::Iterator i = first; i != last; ++i)
786     {
787       Ptr<Node> node = *i;
788       Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
789       auto it = wifiStandards.find (m_standard);
790       if (it == wifiStandards.end ())
791         {
792           NS_FATAL_ERROR ("Selected standard is not defined!");
793           return devices;
794         }
795       if (it->second.phyStandard >= WIFI_PHY_STANDARD_80211n)
796         {
797           Ptr<HtConfiguration> htConfiguration = CreateObject<HtConfiguration> ();
798           device->SetHtConfiguration (htConfiguration);
799         }
800       if ((it->second.phyStandard >= WIFI_PHY_STANDARD_80211ac) && (it->second.phyBand != WIFI_PHY_BAND_2_4GHZ))
801         {
802           Ptr<VhtConfiguration> vhtConfiguration = CreateObject<VhtConfiguration> ();
803           device->SetVhtConfiguration (vhtConfiguration);
804         }
805       if (it->second.phyStandard >= WIFI_PHY_STANDARD_80211ax)
806         {
807           Ptr<HeConfiguration> heConfiguration = CreateObject<HeConfiguration> ();
808           device->SetHeConfiguration (heConfiguration);
809         }
810       Ptr<WifiRemoteStationManager> manager = m_stationManager.Create<WifiRemoteStationManager> ();
811       Ptr<WifiPhy> phy = phyHelper.Create (node, device);
812       phy->ConfigureStandardAndBand (it->second.phyStandard, it->second.phyBand);
813       device->SetPhy (phy);
814       Ptr<WifiMac> mac = macHelper.Create (device, m_standard);
815       device->SetMac (mac);
816       device->SetRemoteStationManager (manager);
817       node->AddDevice (device);
818       if ((it->second.phyStandard >= WIFI_PHY_STANDARD_80211ax) && (m_obssPdAlgorithm.IsTypeIdSet ()))
819         {
820           Ptr<ObssPdAlgorithm> obssPdAlgorithm = m_obssPdAlgorithm.Create<ObssPdAlgorithm> ();
821           device->AggregateObject (obssPdAlgorithm);
822           obssPdAlgorithm->ConnectWifiNetDevice (device);
823         }
824       devices.Add (device);
825       NS_LOG_DEBUG ("node=" << node << ", mob=" << node->GetObject<MobilityModel> ());
826       // Aggregate a NetDeviceQueueInterface object if a RegularWifiMac is installed
827       Ptr<RegularWifiMac> rmac = DynamicCast<RegularWifiMac> (mac);
828       if (rmac)
829         {
830           Ptr<NetDeviceQueueInterface> ndqi;
831           BooleanValue qosSupported;
832           Ptr<WifiMacQueue> wmq;
833 
834           rmac->GetAttributeFailSafe ("QosSupported", qosSupported);
835           if (qosSupported.Get ())
836             {
837               ndqi = CreateObjectWithAttributes<NetDeviceQueueInterface> ("NTxQueues",
838                                                                           UintegerValue (4));
839               for (auto& ac : {AC_BE, AC_BK, AC_VI, AC_VO})
840                 {
841                   Ptr<QosTxop> qosTxop = rmac->GetQosTxop (ac);
842                   wmq = qosTxop->GetWifiMacQueue ();
843                   ndqi->GetTxQueue (static_cast<std::size_t> (ac))->ConnectQueueTraces (wmq);
844                 }
845               ndqi->SetSelectQueueCallback (m_selectQueueCallback);
846             }
847           else
848             {
849               ndqi = CreateObject<NetDeviceQueueInterface> ();
850 
851               wmq = rmac->GetTxop ()->GetWifiMacQueue ();
852               ndqi->GetTxQueue (0)->ConnectQueueTraces (wmq);
853             }
854           device->AggregateObject (ndqi);
855         }
856     }
857   return devices;
858 }
859 
860 NetDeviceContainer
Install(const WifiPhyHelper & phyHelper,const WifiMacHelper & macHelper,NodeContainer c) const861 WifiHelper::Install (const WifiPhyHelper &phyHelper,
862                      const WifiMacHelper &macHelper, NodeContainer c) const
863 {
864   return Install (phyHelper, macHelper, c.Begin (), c.End ());
865 }
866 
867 NetDeviceContainer
Install(const WifiPhyHelper & phy,const WifiMacHelper & mac,Ptr<Node> node) const868 WifiHelper::Install (const WifiPhyHelper &phy,
869                      const WifiMacHelper &mac, Ptr<Node> node) const
870 {
871   return Install (phy, mac, NodeContainer (node));
872 }
873 
874 NetDeviceContainer
Install(const WifiPhyHelper & phy,const WifiMacHelper & mac,std::string nodeName) const875 WifiHelper::Install (const WifiPhyHelper &phy,
876                      const WifiMacHelper &mac, std::string nodeName) const
877 {
878   Ptr<Node> node = Names::Find<Node> (nodeName);
879   return Install (phy, mac, NodeContainer (node));
880 }
881 
882 void
EnableLogComponents(void)883 WifiHelper::EnableLogComponents (void)
884 {
885   LogComponentEnableAll (LOG_PREFIX_TIME);
886   LogComponentEnableAll (LOG_PREFIX_NODE);
887 
888   LogComponentEnable ("AarfWifiManager", LOG_LEVEL_ALL);
889   LogComponentEnable ("AarfcdWifiManager", LOG_LEVEL_ALL);
890   LogComponentEnable ("AdhocWifiMac", LOG_LEVEL_ALL);
891   LogComponentEnable ("AmrrWifiManager", LOG_LEVEL_ALL);
892   LogComponentEnable ("ApWifiMac", LOG_LEVEL_ALL);
893   LogComponentEnable ("AparfWifiManager", LOG_LEVEL_ALL);
894   LogComponentEnable ("ArfWifiManager", LOG_LEVEL_ALL);
895   LogComponentEnable ("BlockAckAgreement", LOG_LEVEL_ALL);
896   LogComponentEnable ("RecipientBlockAckAgreement", LOG_LEVEL_ALL);
897   LogComponentEnable ("BlockAckManager", LOG_LEVEL_ALL);
898   LogComponentEnable ("CaraWifiManager", LOG_LEVEL_ALL);
899   LogComponentEnable ("ChannelAccessManager", LOG_LEVEL_ALL);
900   LogComponentEnable ("ConstantObssPdAlgorithm", LOG_LEVEL_ALL);
901   LogComponentEnable ("ConstantRateWifiManager", LOG_LEVEL_ALL);
902   LogComponentEnable ("ChannelAccessManager", LOG_LEVEL_ALL);
903   LogComponentEnable ("DsssErrorRateModel", LOG_LEVEL_ALL);
904   LogComponentEnable ("DsssPhy", LOG_LEVEL_ALL);
905   LogComponentEnable ("DsssPpdu", LOG_LEVEL_ALL);
906   LogComponentEnable ("ErpOfdmPhy", LOG_LEVEL_ALL);
907   LogComponentEnable ("ErpOfdmPpdu", LOG_LEVEL_ALL);
908   LogComponentEnable ("FrameExchangeManager", LOG_LEVEL_ALL);
909   LogComponentEnable ("HeConfiguration", LOG_LEVEL_ALL);
910   LogComponentEnable ("HeFrameExchangeManager", LOG_LEVEL_ALL);
911   LogComponentEnable ("HePhy", LOG_LEVEL_ALL);
912   LogComponentEnable ("HePpdu", LOG_LEVEL_ALL);
913   LogComponentEnable ("HtConfiguration", LOG_LEVEL_ALL);
914   LogComponentEnable ("HtFrameExchangeManager", LOG_LEVEL_ALL);
915   LogComponentEnable ("HtPhy", LOG_LEVEL_ALL);
916   LogComponentEnable ("HtPpdu", LOG_LEVEL_ALL);
917   LogComponentEnable ("IdealWifiManager", LOG_LEVEL_ALL);
918   LogComponentEnable ("InterferenceHelper", LOG_LEVEL_ALL);
919   LogComponentEnable ("MacRxMiddle", LOG_LEVEL_ALL);
920   LogComponentEnable ("MacTxMiddle", LOG_LEVEL_ALL);
921   LogComponentEnable ("MinstrelHtWifiManager", LOG_LEVEL_ALL);
922   LogComponentEnable ("MinstrelWifiManager", LOG_LEVEL_ALL);
923   LogComponentEnable ("MpduAggregator", LOG_LEVEL_ALL);
924   LogComponentEnable ("MsduAggregator", LOG_LEVEL_ALL);
925   LogComponentEnable ("MultiUserScheduler", LOG_LEVEL_ALL);
926   LogComponentEnable ("NistErrorRateModel", LOG_LEVEL_ALL);
927   LogComponentEnable ("ObssPdAlgorithm", LOG_LEVEL_ALL);
928   LogComponentEnable ("OfdmPhy", LOG_LEVEL_ALL);
929   LogComponentEnable ("OnoeWifiManager", LOG_LEVEL_ALL);
930   LogComponentEnable ("OriginatorBlockAckAgreement", LOG_LEVEL_ALL);
931   LogComponentEnable ("OfdmPpdu", LOG_LEVEL_ALL);
932   LogComponentEnable ("ParfWifiManager", LOG_LEVEL_ALL);
933   LogComponentEnable ("PhyEntity", LOG_LEVEL_ALL);
934   LogComponentEnable ("QosFrameExchangeManager", LOG_LEVEL_ALL);
935   LogComponentEnable ("QosTxop", LOG_LEVEL_ALL);
936   LogComponentEnable ("RegularWifiMac", LOG_LEVEL_ALL);
937   LogComponentEnable ("RraaWifiManager", LOG_LEVEL_ALL);
938   LogComponentEnable ("RrMultiUserScheduler", LOG_LEVEL_ALL);
939   LogComponentEnable ("RrpaaWifiManager", LOG_LEVEL_ALL);
940   LogComponentEnable ("SimpleFrameCaptureModel", LOG_LEVEL_ALL);
941   LogComponentEnable ("SpectrumWifiPhy", LOG_LEVEL_ALL);
942   LogComponentEnable ("StaWifiMac", LOG_LEVEL_ALL);
943   LogComponentEnable ("SupportedRates", LOG_LEVEL_ALL);
944   LogComponentEnable ("TableBasedErrorRateModel", LOG_LEVEL_ALL);
945   LogComponentEnable ("ThompsonSamplingWifiManager", LOG_LEVEL_ALL);
946   LogComponentEnable ("ThresholdPreambleDetectionModel", LOG_LEVEL_ALL);
947   LogComponentEnable ("Txop", LOG_LEVEL_ALL);
948   LogComponentEnable ("VhtConfiguration", LOG_LEVEL_ALL);
949   LogComponentEnable ("VhtFrameExchangeManager", LOG_LEVEL_ALL);
950   LogComponentEnable ("VhtPhy", LOG_LEVEL_ALL);
951   LogComponentEnable ("VhtPpdu", LOG_LEVEL_ALL);
952   LogComponentEnable ("WifiAckManager", LOG_LEVEL_ALL);
953   LogComponentEnable ("WifiDefaultAckManager", LOG_LEVEL_ALL);
954   LogComponentEnable ("WifiDefaultProtectionManager", LOG_LEVEL_ALL);
955   LogComponentEnable ("WifiMac", LOG_LEVEL_ALL);
956   LogComponentEnable ("WifiMacQueue", LOG_LEVEL_ALL);
957   LogComponentEnable ("WifiMacQueueItem", LOG_LEVEL_ALL);
958   LogComponentEnable ("WifiNetDevice", LOG_LEVEL_ALL);
959   LogComponentEnable ("WifiPhyStateHelper", LOG_LEVEL_ALL);
960   LogComponentEnable ("WifiPhy", LOG_LEVEL_ALL);
961   LogComponentEnable ("WifiPhyOperatingChannel", LOG_LEVEL_ALL);
962   LogComponentEnable ("WifiPpdu", LOG_LEVEL_ALL);
963   LogComponentEnable ("WifiProtectionManager", LOG_LEVEL_ALL);
964   LogComponentEnable ("WifiPsdu", LOG_LEVEL_ALL);
965   LogComponentEnable ("WifiRadioEnergyModel", LOG_LEVEL_ALL);
966   LogComponentEnable ("WifiRemoteStationManager", LOG_LEVEL_ALL);
967   LogComponentEnable ("WifiSpectrumPhyInterface", LOG_LEVEL_ALL);
968   LogComponentEnable ("WifiSpectrumSignalParameters", LOG_LEVEL_ALL);
969   LogComponentEnable ("WifiTxCurrentModel", LOG_LEVEL_ALL);
970   LogComponentEnable ("WifiTxParameters", LOG_LEVEL_ALL);
971   LogComponentEnable ("WifiTxTimer", LOG_LEVEL_ALL);
972   LogComponentEnable ("YansErrorRateModel", LOG_LEVEL_ALL);
973   LogComponentEnable ("YansWifiChannel", LOG_LEVEL_ALL);
974   LogComponentEnable ("YansWifiPhy", LOG_LEVEL_ALL);
975 
976   //From Spectrum
977   LogComponentEnable ("WifiSpectrumValueHelper", LOG_LEVEL_ALL);
978 }
979 
980 int64_t
AssignStreams(NetDeviceContainer c,int64_t stream)981 WifiHelper::AssignStreams (NetDeviceContainer c, int64_t stream)
982 {
983   int64_t currentStream = stream;
984   Ptr<NetDevice> netDevice;
985   for (NetDeviceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
986     {
987       netDevice = (*i);
988       Ptr<WifiNetDevice> wifi = DynamicCast<WifiNetDevice> (netDevice);
989       if (wifi)
990         {
991           //Handle any random numbers in the PHY objects.
992           currentStream += wifi->GetPhy ()->AssignStreams (currentStream);
993 
994           //Handle any random numbers in the station managers.
995           currentStream += wifi->GetRemoteStationManager ()->AssignStreams (currentStream);
996 
997           //Handle any random numbers in the MAC objects.
998           Ptr<WifiMac> mac = wifi->GetMac ();
999           Ptr<RegularWifiMac> rmac = DynamicCast<RegularWifiMac> (mac);
1000           if (rmac)
1001             {
1002               PointerValue ptr;
1003               rmac->GetAttribute ("Txop", ptr);
1004               Ptr<Txop> txop = ptr.Get<Txop> ();
1005               currentStream += txop->AssignStreams (currentStream);
1006 
1007               rmac->GetAttribute ("VO_Txop", ptr);
1008               Ptr<QosTxop> vo_txop = ptr.Get<QosTxop> ();
1009               currentStream += vo_txop->AssignStreams (currentStream);
1010 
1011               rmac->GetAttribute ("VI_Txop", ptr);
1012               Ptr<QosTxop> vi_txop = ptr.Get<QosTxop> ();
1013               currentStream += vi_txop->AssignStreams (currentStream);
1014 
1015               rmac->GetAttribute ("BE_Txop", ptr);
1016               Ptr<QosTxop> be_txop = ptr.Get<QosTxop> ();
1017               currentStream += be_txop->AssignStreams (currentStream);
1018 
1019               rmac->GetAttribute ("BK_Txop", ptr);
1020               Ptr<QosTxop> bk_txop = ptr.Get<QosTxop> ();
1021               currentStream += bk_txop->AssignStreams (currentStream);
1022 
1023               //if an AP, handle any beacon jitter
1024               Ptr<ApWifiMac> apmac = DynamicCast<ApWifiMac> (rmac);
1025               if (apmac)
1026                 {
1027                   currentStream += apmac->AssignStreams (currentStream);
1028                 }
1029             }
1030         }
1031     }
1032   return (currentStream - stream);
1033 }
1034 
1035 } //namespace ns3
1036