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