A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 INRIA
3 * Copyright (c) 2009 MIRKO BANCHI
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
8 * Mirko Banchi <mk.banchi@gmail.com>
9 */
10
11#include "wifi-helper.h"
12
13#include "ns3/ampdu-subframe-header.h"
14#include "ns3/ap-wifi-mac.h"
15#include "ns3/config.h"
16#include "ns3/eht-configuration.h"
17#include "ns3/eht-ppdu.h"
18#include "ns3/frame-capture-model.h"
19#include "ns3/he-configuration.h"
20#include "ns3/ht-configuration.h"
21#include "ns3/interference-helper.h"
22#include "ns3/log.h"
23#include "ns3/mobility-model.h"
24#include "ns3/names.h"
25#include "ns3/net-device-queue-interface.h"
26#include "ns3/obss-pd-algorithm.h"
27#include "ns3/pointer.h"
28#include "ns3/preamble-detection-model.h"
29#include "ns3/qos-txop.h"
30#include "ns3/qos-utils.h"
31#include "ns3/radiotap-header.h"
32#include "ns3/sta-wifi-mac.h"
33#include "ns3/vht-configuration.h"
34#include "ns3/wifi-mac-queue.h"
35#include "ns3/wifi-mac-trailer.h"
36#include "ns3/wifi-radio-energy-model.h"
37
38#include <bit>
39#include <memory>
40
41namespace ns3
42{
43
44namespace
45{
46/**
47 * Helper function to place the value to set in the correct bit(s) of a radiotap subfield.
48 *
49 * @param mask the mask of the corresponding subfield
50 * @param val the value the subfield should be set to
51 * @return the value placed at the correct position based on the mask
52 */
55{
56 const auto shift = std::countr_zero(mask);
57 return (val << shift) & mask;
58}
59
60/// 320 MHz channelization map
69} // namespace
70
71NS_LOG_COMPONENT_DEFINE("WifiHelper");
72
73/**
74 * ASCII trace PHY transmit sink with context
75 * @param stream the output stream
76 * @param context the context name
77 * @param p the packet
78 * @param mode the wifi mode
79 * @param preamble the wifi preamble
80 * @param txLevel the transmit power level
81 */
82static void
84 std::string context,
86 WifiMode mode,
87 WifiPreamble preamble,
88 uint8_t txLevel)
89{
90 NS_LOG_FUNCTION(stream << context << p << mode << preamble << txLevel);
91 auto pCopy = p->Copy();
93 pCopy->RemoveTrailer(fcs);
94 *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << context << " " << mode
95 << " " << *pCopy << " " << fcs << std::endl;
96}
97
98/**
99 * ASCII trace PHY transmit sink without context
100 * @param stream the output stream
101 * @param p the packet
102 * @param mode the wifi mode
103 * @param preamble the wifi preamble
104 * @param txLevel the transmit power level
105 */
106static void
109 WifiMode mode,
110 WifiPreamble preamble,
111 uint8_t txLevel)
112{
113 NS_LOG_FUNCTION(stream << p << mode << preamble << txLevel);
114 auto pCopy = p->Copy();
115 WifiMacTrailer fcs;
116 pCopy->RemoveTrailer(fcs);
117 *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << mode << " " << *pCopy
118 << " " << fcs << std::endl;
119}
120
121/**
122 * ASCII trace PHY receive sink with context
123 * @param stream the output stream
124 * @param context the context name
125 * @param p the packet
126 * @param snr the SNR
127 * @param mode the wifi mode
128 * @param preamble the wifi preamble
129 */
130static void
132 std::string context,
134 double snr,
135 WifiMode mode,
136 WifiPreamble preamble)
137{
138 NS_LOG_FUNCTION(stream << context << p << snr << mode << preamble);
139 auto pCopy = p->Copy();
140 WifiMacTrailer fcs;
141 pCopy->RemoveTrailer(fcs);
142 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << mode << " " << context
143 << " " << *pCopy << " " << fcs << std::endl;
144}
145
146/**
147 * ASCII trace PHY receive sink without context
148 * @param stream the output stream
149 * @param p the packet
150 * @param snr the SNR
151 * @param mode the wifi mode
152 * @param preamble the wifi preamble
153 */
154static void
157 double snr,
158 WifiMode mode,
159 WifiPreamble preamble)
160{
161 NS_LOG_FUNCTION(stream << p << snr << mode << preamble);
162 auto pCopy = p->Copy();
163 WifiMacTrailer fcs;
164 pCopy->RemoveTrailer(fcs);
165 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << mode << " " << *pCopy
166 << " " << fcs << std::endl;
167}
168
172{
173 NS_ABORT_IF(nLinks == 0);
174 m_phys.resize(nLinks);
175 m_errorRateModel.resize(nLinks);
176 m_frameCaptureModel.resize(nLinks);
177 m_preambleDetectionModel.resize(nLinks);
178
179 SetPreambleDetectionModel("ns3::ThresholdPreambleDetectionModel");
180}
181
185
186void
187WifiPhyHelper::Set(std::string name, const AttributeValue& v)
188{
189 for (auto& phy : m_phys)
190 {
191 phy.Set(name, v);
192 }
193}
194
195void
196WifiPhyHelper::Set(uint8_t linkId, std::string name, const AttributeValue& v)
197{
198 m_phys.at(linkId).Set(name, v);
199}
200
201void
207
209WifiPhyHelper::GetOrCreatePcapFile(const std::shared_ptr<PcapFilesInfo>& info, uint8_t phyId)
210{
211 uint8_t fileIdx;
212 switch (info->pcapType)
213 {
215 fileIdx = 0;
216 break;
218 fileIdx = phyId;
219 break;
221 if (const auto linkId = info->device->GetMac()->GetLinkForPhy(phyId))
222 {
223 fileIdx = *linkId;
224 break;
225 }
226 return nullptr;
227 default:
228 NS_ABORT_MSG("Unexpected PCAP capture type");
229 return nullptr;
230 }
231
232 if (!info->files.contains(fileIdx))
233 {
234 // file does not exist yet, create it
235 auto tmp = info->commonFilename;
236
237 // find the last point in the filename
238 auto pos = info->commonFilename.find_last_of('.');
239 // if not found, set pos to filename size
240 pos = (pos == std::string::npos) ? info->commonFilename.size() : pos;
241
242 // insert PHY/link ID only for multi-link devices, unless a single PCAP is generated for the
243 // device
244 if ((info->device->GetNPhys() > 1) && (info->pcapType != PcapCaptureType::PCAP_PER_DEVICE))
245 {
246 tmp.insert(pos, "-" + std::to_string(fileIdx));
247 }
248
249 PcapHelper pcapHelper;
250 auto file = pcapHelper.CreateFile(tmp, std::ios::out, info->pcapDlt);
251 info->files.emplace(fileIdx, file);
252 }
253
254 return info->files.at(fileIdx);
255}
256
257void
258WifiPhyHelper::PcapSniffTxEvent(const std::shared_ptr<PcapFilesInfo>& info,
259 uint8_t phyId,
260 Ptr<const Packet> packet,
261 uint16_t channelFreqMhz,
262 WifiTxVector txVector,
263 MpduInfo aMpdu,
264 uint16_t staId)
265{
266 auto file = GetOrCreatePcapFile(info, phyId);
267 if (!file)
268 {
269 return;
270 }
271 switch (info->pcapDlt)
272 {
274 file->Write(Simulator::Now(), packet);
275 return;
277 NS_FATAL_ERROR("PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented");
278 return;
279 }
281 Ptr<Packet> p = packet->Copy();
282 const auto header = GetRadiotapHeader(p,
283 channelFreqMhz,
284 info->device->GetPhy(phyId)->GetPrimary20Index(),
285 txVector,
286 aMpdu,
287 staId);
288 p->AddHeader(header);
289 file->Write(Simulator::Now(), p);
290 return;
291 }
292 default:
293 NS_ABORT_MSG("PcapSniffTxEvent(): Unexpected data link type " << info->pcapDlt);
294 }
295}
296
297void
298WifiPhyHelper::PcapSniffRxEvent(const std::shared_ptr<PcapFilesInfo>& info,
299 uint8_t phyId,
300 Ptr<const Packet> packet,
301 uint16_t channelFreqMhz,
302 WifiTxVector txVector,
303 MpduInfo aMpdu,
304 SignalNoiseDbm signalNoise,
305 uint16_t staId)
306{
307 auto file = GetOrCreatePcapFile(info, phyId);
308 if (!file)
309 {
310 return;
311 }
312 switch (info->pcapDlt)
313 {
315 file->Write(Simulator::Now(), packet);
316 return;
318 NS_FATAL_ERROR("PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented");
319 return;
320 }
322 Ptr<Packet> p = packet->Copy();
323 const auto header = GetRadiotapHeader(p,
324 channelFreqMhz,
325 info->device->GetPhy(phyId)->GetPrimary20Index(),
326 txVector,
327 aMpdu,
328 staId,
329 signalNoise);
330 p->AddHeader(header);
331 file->Write(Simulator::Now(), p);
332 return;
333 }
334 default:
335 NS_ABORT_MSG("PcapSniffRxEvent(): Unexpected data link type " << info->pcapDlt);
336 }
337}
338
341 uint16_t channelFreqMhz,
342 uint8_t p20Index,
343 const WifiTxVector& txVector,
344 MpduInfo aMpdu,
345 uint16_t staId,
346 std::optional<SignalNoiseDbm> signalNoise)
347{
348 RadiotapHeader header;
349
350 const auto preamble = txVector.GetPreambleType();
351 const auto modClass = txVector.GetModulationClass();
352 const auto channelWidth = txVector.GetChannelWidth();
353 const auto gi = txVector.GetGuardInterval();
354
355 header.SetWifiHeader(IsEht(preamble) ? 2 : 1);
356
357 if (signalNoise)
358 {
359 header.SetAntennaSignalPower(signalNoise->signal);
360 header.SetAntennaNoisePower(signalNoise->noise);
361 }
362
363 header.SetTsft(Simulator::Now().GetMicroSeconds());
364
365 uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
366 // Our capture includes the FCS, so we set the flag to say so.
368 if (preamble == WIFI_PREAMBLE_SHORT)
369 {
371 }
372 if (gi.GetNanoSeconds() == 400)
373 {
375 }
376 header.SetFrameFlags(frameFlags);
377
378 uint8_t mcs = 0;
379 uint8_t nss = 1;
380 uint64_t rate = 0;
381 if (modClass < WIFI_MOD_CLASS_HT)
382 {
383 rate = txVector.GetMode(staId).GetDataRate(channelWidth, gi, 1) * nss / 500000;
384 header.SetRate(static_cast<uint8_t>(rate));
385 }
386 else
387 {
388 mcs = txVector.GetMode(staId).GetMcsValue();
389 nss = txVector.GetNss(staId);
390 }
391
392 RadiotapHeader::ChannelFields channelFields{.frequency = channelFreqMhz};
393 switch (rate)
394 {
395 case 2: // 1Mbps
396 case 4: // 2Mbps
397 case 10: // 5Mbps
398 case 22: // 11Mbps
399 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_CCK;
400 break;
401 default:
402 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
403 break;
404 }
405 if (channelFreqMhz < 2500)
406 {
407 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
408 }
409 else
410 {
411 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
412 }
413 header.SetChannelFields(channelFields);
414
415 if (modClass == WIFI_MOD_CLASS_HT)
416 {
417 RadiotapHeader::McsFields mcsFields{.mcs = mcs};
418
423
424 if (channelWidth == MHz_u{40})
425 {
427 }
428
429 if (gi.GetNanoSeconds() == 400)
430 {
432 }
433
434 const auto ness = txVector.GetNess();
435 if (ness & 0x01) // bit 1
436 {
437 mcsFields.flags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
438 }
439 if (ness & 0x02) // bit 2
440 {
441 mcsFields.flags |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
442 }
443
444 if (txVector.IsStbc())
445 {
447 }
448
449 header.SetMcsFields(mcsFields);
450 }
451
452 if (txVector.IsAggregation())
453 {
454 RadiotapHeader::AmpduStatusFields ampduStatusFields{.referenceNumber = aMpdu.mpduRefNumber};
456 /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
458 uint32_t extractedLength;
459 packet->RemoveHeader(hdr);
460 extractedLength = hdr.GetLength();
461 packet = packet->CreateFragment(0, static_cast<uint32_t>(extractedLength));
462 if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof() && hdr.GetLength() > 0))
463 {
464 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST;
465 }
466 header.SetAmpduStatus(ampduStatusFields);
467 }
468
469 if (modClass == WIFI_MOD_CLASS_VHT)
470 {
471 RadiotapHeader::VhtFields vhtFields{};
472
474 if (txVector.IsStbc())
475 {
476 vhtFields.flags |= RadiotapHeader::VHT_FLAGS_STBC;
477 }
478
480 if (gi.GetNanoSeconds() == 400)
481 {
483 }
484
485 vhtFields.known |=
487 // TODO: bandwidths can be provided with sideband info
488 if (channelWidth == MHz_u{40})
489 {
490 vhtFields.bandwidth = 1;
491 }
492 else if (channelWidth == MHz_u{80})
493 {
494 vhtFields.bandwidth = 4;
495 }
496 else if (channelWidth == MHz_u{160})
497 {
498 vhtFields.bandwidth = 11;
499 }
500
501 // only SU PPDUs are currently supported
502 vhtFields.mcsNss.at(0) |= (nss & 0x0f) | ((mcs << 4) & 0xf0);
503
504 header.SetVhtFields(vhtFields);
505 }
506
507 if (modClass == WIFI_MOD_CLASS_HE)
508 {
509 RadiotapHeader::HeFields heFields{};
513 if (preamble == WIFI_PREAMBLE_HE_ER_SU)
514 {
516 }
517 else if (preamble == WIFI_PREAMBLE_HE_MU)
518 {
519 heFields.data1 |=
521 }
522 else if (preamble == WIFI_PREAMBLE_HE_TB)
523 {
524 heFields.data1 |= RadiotapHeader::HE_DATA1_FORMAT_TRIG;
525 }
526
527 heFields.data2 = RadiotapHeader::HE_DATA2_GI_KNOWN;
528 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
529 {
530 NS_ASSERT(WifiRu::IsHe(txVector.GetHeMuUserInfo(staId).ru));
531 auto heRu = std::get<HeRu::RuSpec>(txVector.GetHeMuUserInfo(staId).ru);
532 heFields.data2 |=
534 // HeRu indices start at 1 whereas RadioTap starts at 0
535 GetRadiotapField(RadiotapHeader::HE_DATA2_RU_OFFSET, heRu.GetIndex() - 1) |
536 GetRadiotapField(RadiotapHeader::HE_DATA2_PRISEC_80_SEC, !heRu.GetPrimary80MHz());
537 }
538
539 heFields.data3 =
540 GetRadiotapField(RadiotapHeader::HE_DATA3_BSS_COLOR, txVector.GetBssColor()) |
541 GetRadiotapField(RadiotapHeader::HE_DATA3_DATA_MCS, mcs);
542
543 heFields.data4 = (preamble == WIFI_PREAMBLE_HE_MU)
544 ? GetRadiotapField(RadiotapHeader::HE_DATA4_MU_STA_ID, staId)
545 : 0;
546
547 heFields.data5 = 0;
548 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
549 {
550 const auto ruType = WifiRu::GetRuType(txVector.GetHeMuUserInfo(staId).ru);
551 switch (ruType)
552 {
555 break;
558 break;
561 break;
564 break;
567 break;
570 break;
573 break;
574 default:
575 NS_ABORT_MSG("Unexpected RU type");
576 }
577 }
578 else if (channelWidth == MHz_u{40})
579 {
581 }
582 else if (channelWidth == MHz_u{80})
583 {
585 }
586 else if (channelWidth == MHz_u{160})
587 {
589 }
590 if (gi.GetNanoSeconds() == 1600)
591 {
592 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_1_6;
593 }
594 else if (gi.GetNanoSeconds() == 3200)
595 {
596 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_3_2;
597 }
598
599 header.SetHeFields(heFields);
600 }
601
602 if (preamble == WIFI_PREAMBLE_HE_MU)
603 {
604 RadiotapHeader::HeMuFields heMuFields{};
605 // TODO: fill in fields
606 header.SetHeMuFields(heMuFields);
607 RadiotapHeader::HeMuOtherUserFields heMuOtherUserFields{};
608 // TODO: fill in fields
609 header.SetHeMuOtherUserFields(heMuOtherUserFields);
610 }
611
612 if (IsEht(preamble))
613 {
614 RadiotapHeader::UsigFields usigFields{};
618 switch (static_cast<uint16_t>(channelWidth))
619 {
620 case 20:
621 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
623 break;
624 case 40:
625 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
627 break;
628 case 80:
629 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
631 break;
632 case 160:
633 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
635 break;
636 case 320:
637 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
638 channelization320MHzMap.at(channelFreqMhz));
639 break;
640 default:
641 NS_ABORT_MSG("Unexpected channel width");
642 break;
643 }
644 usigFields.common |=
645 GetRadiotapField(RadiotapHeader::USIG_COMMON_BSS_COLOR, txVector.GetBssColor());
646 if (preamble == WIFI_PREAMBLE_EHT_MU)
647 {
651 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_MU_B0_B1_PPDU_TYPE,
652 txVector.GetEhtPpduType()) |
654 txVector.GetSigBMode().GetMcsValue());
655 std::optional<bool> isLow80MHz;
656 if (txVector.IsDlMu() && channelWidth > MHz_u{80})
657 {
658 isLow80MHz = true;
659 // TODO: fix once EHT RUs are used
660 }
661 const auto puncturedChannelInfo =
663 txVector.GetEhtPpduType(),
664 isLow80MHz);
665 usigFields.value |= GetRadiotapField(RadiotapHeader::USIG2_MU_B3_B7_PUNCTURED_INFO,
666 puncturedChannelInfo);
667 }
668 else
669 {
671 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_TB_B0_B1_PPDU_TYPE,
672 txVector.GetEhtPpduType());
673 }
674 header.SetUsigFields(usigFields);
675 }
676
677 if (preamble == WIFI_PREAMBLE_EHT_MU)
678 {
679 RadiotapHeader::EhtFields ehtFields{};
682 switch (gi.GetNanoSeconds())
683 {
684 case 800:
685 ehtFields.data.at(0) =
687 break;
688 case 1600:
689 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
691 break;
692 case 3200:
693 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
695 break;
696 default:
697 NS_ABORT_MSG("Unexpected guard interval");
698 break;
699 }
701 const auto ruType = (txVector.GetEhtPpduType() == 1)
702 ? WifiRu::GetRuType(channelWidth)
703 : WifiRu::GetRuType(txVector.GetRu(staId));
704 switch (ruType)
705 {
707 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
709 break;
711 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
713 break;
715 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
717 break;
719 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
721 break;
723 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
725 break;
727 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
729 break;
731 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
733 break;
735 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
737 break;
738 default:
739 NS_ABORT_MSG("Unexpected RU type");
740 break;
741 }
742 const auto ruIndex =
743 (txVector.GetEhtPpduType() == 1) ? 1 : WifiRu::GetIndex(txVector.GetRu(staId));
744 const auto& ruAllocation = txVector.GetRuAllocation(p20Index);
745 ehtFields.data.at(1) |=
746 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_INDEX, ruIndex) |
747 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_ALLOC_CC_1_1_1, ruAllocation.at(0));
748 if (channelWidth >= MHz_u{40})
749 {
750 ehtFields.data.at(2) =
752 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_1, ruAllocation.at(1));
753 }
754 if (channelWidth >= MHz_u{80})
755 {
756 ehtFields.data.at(2) |=
759 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_1_1_2, ruAllocation.at(2)) |
760 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_2, ruAllocation.at(3));
761 }
762 if (channelWidth >= MHz_u{160})
763 {
764 ehtFields.data.at(3) =
768 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_1, ruAllocation.at(4)) |
769 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_2_2_1, ruAllocation.at(5)) |
770 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_2, ruAllocation.at(6));
771 ehtFields.data.at(4) =
773 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_2, ruAllocation.at(7));
774 ehtFields.known |= RadiotapHeader::EHT_KNOWN_PRIMARY_80;
775 const auto isLowP80 = p20Index < (channelWidth / MHz_u{40});
776 ehtFields.data.at(1) |=
780 }
781 if (channelWidth >= MHz_u{320})
782 {
783 ehtFields.data.at(4) |=
786 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_1_2_3, ruAllocation.at(8)) |
787 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_3, ruAllocation.at(9));
788 ehtFields.data.at(5) =
792 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_1_2_4, ruAllocation.at(10)) |
793 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_2_2_4, ruAllocation.at(11)) |
794 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_1_2_5, ruAllocation.at(12));
795 ehtFields.data.at(6) =
799 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_2_2_5, ruAllocation.at(13)) |
800 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_1_2_6, ruAllocation.at(14)) |
801 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_2_2_6, ruAllocation.at(15));
802 }
807 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_STA_ID, staId) |
808 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_MCS, mcs) |
809 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_NSS_O, nss);
810 ehtFields.userInfo.push_back(userInfo);
811 header.SetEhtFields(ehtFields);
812 }
813
814 return header;
815}
816
817void
819{
820 switch (dlt)
821 {
822 case DLT_IEEE802_11:
824 return;
825 case DLT_PRISM_HEADER:
827 return;
830 return;
831 default:
832 NS_ABORT_MSG("WifiPhyHelper::SetPcapFormat(): Unexpected format");
833 }
834}
835
838{
839 return m_pcapDlt;
840}
841
842void
847
850{
851 return m_pcapType;
852}
853
854void
857 bool promiscuous,
858 bool explicitFilename)
859{
860 NS_LOG_FUNCTION(this << prefix << nd << promiscuous << explicitFilename);
861
862 // All of the Pcap enable functions vector through here including the ones
863 // that are wandering through all of devices on perhaps all of the nodes in
864 // the system. We can only deal with devices of type WifiNetDevice.
865 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
866 if (!device)
867 {
868 NS_LOG_INFO("WifiHelper::EnablePcapInternal(): Device "
869 << &device << " not of type ns3::WifiNetDevice");
870 return;
871 }
872
873 NS_ABORT_MSG_IF(device->GetPhys().empty(),
874 "WifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
875
876 PcapHelper pcapHelper;
877 std::string filename;
878 if (explicitFilename)
879 {
880 filename = prefix;
881 }
882 else
883 {
884 filename = pcapHelper.GetFilenameFromDevice(prefix, device);
885 }
886
887 auto info = std::make_shared<PcapFilesInfo>(filename, m_pcapDlt, m_pcapType, device);
888 for (auto& phy : device->GetPhys())
889 {
890 phy->TraceConnectWithoutContext(
891 "MonitorSnifferTx",
892 MakeBoundCallback(&WifiPhyHelper::PcapSniffTxEvent, info, phy->GetPhyId()));
893 phy->TraceConnectWithoutContext(
894 "MonitorSnifferRx",
895 MakeBoundCallback(&WifiPhyHelper::PcapSniffRxEvent, info, phy->GetPhyId()));
896 }
897}
898
899void
901 std::string prefix,
903 bool explicitFilename)
904{
905 // All of the ASCII enable functions vector through here including the ones
906 // that are wandering through all of devices on perhaps all of the nodes in
907 // the system. We can only deal with devices of type WifiNetDevice.
908 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
909 if (!device)
910 {
911 NS_LOG_INFO("WifiHelper::EnableAsciiInternal(): Device "
912 << device << " not of type ns3::WifiNetDevice");
913 return;
914 }
915
916 // Our trace sinks are going to use packet printing, so we have to make sure
917 // that is turned on.
919
920 uint32_t nodeid = nd->GetNode()->GetId();
921 uint32_t deviceid = nd->GetIfIndex();
922 std::ostringstream oss;
923
924 // If we are not provided an OutputStreamWrapper, we are expected to create
925 // one using the usual trace filename conventions and write our traces
926 // without a context since there will be one file per context and therefore
927 // the context would be redundant.
928 if (!stream)
929 {
930 // Set up an output stream object to deal with private ofstream copy
931 // constructor and lifetime issues. Let the helper decide the actual
932 // name of the file given the prefix.
933 AsciiTraceHelper asciiTraceHelper;
934
935 std::string filename;
936 if (explicitFilename)
937 {
938 filename = prefix;
939 }
940 else
941 {
942 filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device);
943 }
944
945 // find the last point in the filename
946 auto pos = filename.find_last_of('.');
947 // if not found, set pos to filename size
948 pos = (pos == std::string::npos) ? filename.size() : pos;
949
950 for (uint8_t linkId = 0; linkId < device->GetNPhys(); linkId++)
951 {
952 std::string tmp = filename;
953 if (device->GetNPhys() > 1)
954 {
955 // insert LinkId only for multi-link devices
956 tmp.insert(pos, "-" + std::to_string(linkId));
957 }
958 auto theStream = asciiTraceHelper.CreateFileStream(tmp);
959 // We could go poking through the PHY and the state looking for the
960 // correct trace source, but we can let Config deal with that with
961 // some search cost. Since this is presumably happening at topology
962 // creation time, it doesn't seem much of a price to pay.
963 oss.str("");
964 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
965 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/RxOk";
967 oss.str(),
969
970 oss.str("");
971 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
972 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/Tx";
974 oss.str(),
976 }
977
978 return;
979 }
980
981 // If we are provided an OutputStreamWrapper, we are expected to use it, and
982 // to provide a context. We are free to come up with our own context if we
983 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
984 // compatibility and simplicity, we just use Config::Connect and let it deal
985 // with coming up with a context.
986 oss.str("");
987 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
988 << "/$ns3::WifiNetDevice/Phy/State/RxOk";
990
991 oss.str("");
992 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
993 << "/$ns3::WifiNetDevice/Phy/State/Tx";
995}
996
1000
1005{
1006 SetRemoteStationManager("ns3::IdealWifiManager");
1007 m_htConfig.SetTypeId("ns3::HtConfiguration");
1008 m_vhtConfig.SetTypeId("ns3::VhtConfiguration");
1009 m_heConfig.SetTypeId("ns3::HeConfiguration");
1010 m_ehtConfig.SetTypeId("ns3::EhtConfiguration");
1011}
1012
1013namespace
1014{
1015/// Map strings to WifiStandard enum values
1016const std::unordered_map<std::string, WifiStandard> WIFI_STANDARDS_NAME_MAP{
1017 // clang-format off
1018 {"802.11a", WIFI_STANDARD_80211a},
1019 {"11a", WIFI_STANDARD_80211a},
1020
1021 {"802.11b", WIFI_STANDARD_80211b},
1022 {"11b", WIFI_STANDARD_80211b},
1023
1024 {"802.11g", WIFI_STANDARD_80211g},
1025 {"11g", WIFI_STANDARD_80211g},
1026
1027 {"802.11p", WIFI_STANDARD_80211p},
1028 {"11p", WIFI_STANDARD_80211p},
1029
1030 {"802.11n", WIFI_STANDARD_80211n},
1031 {"11n", WIFI_STANDARD_80211n},
1032 {"HT", WIFI_STANDARD_80211n},
1033
1034 {"802.11ac", WIFI_STANDARD_80211ac},
1035 {"11ac", WIFI_STANDARD_80211ac},
1036 {"VHT", WIFI_STANDARD_80211ac},
1037
1038 {"802.11ad", WIFI_STANDARD_80211ad},
1039 {"11ad", WIFI_STANDARD_80211ad},
1040
1041 {"802.11ax", WIFI_STANDARD_80211ax},
1042 {"11ax", WIFI_STANDARD_80211ax},
1043 {"HE", WIFI_STANDARD_80211ax},
1044
1045 {"802.11be", WIFI_STANDARD_80211be},
1046 {"11be", WIFI_STANDARD_80211be},
1047 {"EHT", WIFI_STANDARD_80211be},
1048 // clang-format on
1049};
1050} // namespace
1051
1052void
1054{
1055 m_standard = standard;
1056}
1057
1058void
1059WifiHelper::SetStandard(const std::string& standard)
1060{
1061 NS_ABORT_MSG_IF(!WIFI_STANDARDS_NAME_MAP.contains(standard),
1062 "Specified Wi-Fi standard " << standard << " is currently not supported");
1063 SetStandard(WIFI_STANDARDS_NAME_MAP.at(standard));
1064}
1065
1066void
1071
1072void
1077
1080 const WifiMacHelper& macHelper,
1082 NodeContainer::Iterator last) const
1083{
1084 NetDeviceContainer devices;
1085 for (auto i = first; i != last; ++i)
1086 {
1087 Ptr<Node> node = *i;
1089 node->AddDevice(device);
1090 device->SetStandard(m_standard);
1092 {
1093 NS_FATAL_ERROR("No standard specified!");
1094 return devices;
1095 }
1097 {
1098 auto htConfiguration = m_htConfig.Create<HtConfiguration>();
1099 device->SetHtConfiguration(htConfiguration);
1100 }
1102 {
1103 // Create the VHT Configuration object even if the PHY band is 2.4GHz
1104 // (WifiNetDevice::GetVhtConfiguration() checks the PHY band being used).
1105 // This approach allows us not to worry about deleting this object when
1106 // the PHY band is switched from 5GHz to 2.4GHz and creating this object
1107 // when the PHY band is switched from 2.4GHz to 5GHz.
1108 auto vhtConfiguration = m_vhtConfig.Create<VhtConfiguration>();
1109 device->SetVhtConfiguration(vhtConfiguration);
1110 }
1112 {
1113 auto heConfiguration = m_heConfig.Create<HeConfiguration>();
1114 device->SetHeConfiguration(heConfiguration);
1115 }
1117 {
1118 auto ehtConfiguration = m_ehtConfig.Create<EhtConfiguration>();
1119 device->SetEhtConfiguration(ehtConfiguration);
1120 }
1121 std::vector<Ptr<WifiRemoteStationManager>> managers;
1122 std::vector<Ptr<WifiPhy>> phys = phyHelper.Create(node, device);
1123 device->SetPhys(phys);
1124 // if only one remote station manager model was provided, replicate it for all the links
1125 auto stationManagers = m_stationManager;
1126 if (stationManagers.size() == 1 && phys.size() > 1)
1127 {
1128 stationManagers.resize(phys.size(), stationManagers[0]);
1129 }
1130 NS_ABORT_MSG_IF(stationManagers.size() != phys.size(),
1131 "Number of station manager models ("
1132 << stationManagers.size() << ") does not match the number of links ("
1133 << phys.size() << ")");
1134 for (std::size_t i = 0; i < phys.size(); i++)
1135 {
1136 phys[i]->ConfigureStandard(m_standard);
1137 managers.push_back(stationManagers[i].Create<WifiRemoteStationManager>());
1138 }
1139 device->SetRemoteStationManagers(managers);
1140 Ptr<WifiMac> mac = macHelper.Create(device, m_standard);
1141 if ((m_standard >= WIFI_STANDARD_80211ax) && (m_obssPdAlgorithm.IsTypeIdSet()))
1142 {
1143 Ptr<ObssPdAlgorithm> obssPdAlgorithm = m_obssPdAlgorithm.Create<ObssPdAlgorithm>();
1144 device->AggregateObject(obssPdAlgorithm);
1145 obssPdAlgorithm->ConnectWifiNetDevice(device);
1146 }
1147 devices.Add(device);
1148 NS_LOG_DEBUG("node=" << node << ", mob=" << node->GetObject<MobilityModel>());
1150 {
1152 BooleanValue qosSupported;
1154
1155 mac->GetAttributeFailSafe("QosSupported", qosSupported);
1156 if (qosSupported.Get())
1157 {
1159 UintegerValue(4));
1160 for (auto& ac : {AC_BE, AC_BK, AC_VI, AC_VO})
1161 {
1162 Ptr<QosTxop> qosTxop = mac->GetQosTxop(ac);
1163 wmq = qosTxop->GetWifiMacQueue();
1164 ndqi->GetTxQueue(static_cast<std::size_t>(ac))->ConnectQueueTraces(wmq);
1165 }
1166 ndqi->SetSelectQueueCallback(m_selectQueueCallback);
1167 }
1168 else
1169 {
1171
1172 wmq = mac->GetTxop()->GetWifiMacQueue();
1173 ndqi->GetTxQueue(0)->ConnectQueueTraces(wmq);
1174 }
1175 device->AggregateObject(ndqi);
1176 }
1177 }
1178 return devices;
1179}
1180
1183 const WifiMacHelper& macHelper,
1184 NodeContainer c) const
1185{
1186 return Install(phyHelper, macHelper, c.Begin(), c.End());
1187}
1188
1191{
1192 return Install(phy, mac, NodeContainer(node));
1193}
1194
1196WifiHelper::Install(const WifiPhyHelper& phy, const WifiMacHelper& mac, std::string nodeName) const
1197{
1198 Ptr<Node> node = Names::Find<Node>(nodeName);
1199 return Install(phy, mac, NodeContainer(node));
1200}
1201
1202void
1204{
1207
1208 LogComponentEnable("AarfWifiManager", logLevel);
1209 LogComponentEnable("AarfcdWifiManager", logLevel);
1210 LogComponentEnable("AdhocWifiMac", logLevel);
1211 LogComponentEnable("AdvancedApEmlsrManager", logLevel);
1212 LogComponentEnable("AdvancedEmlsrManager", logLevel);
1213 LogComponentEnable("AmrrWifiManager", logLevel);
1214 LogComponentEnable("ApEmlsrManager", logLevel);
1215 LogComponentEnable("ApWifiMac", logLevel);
1216 LogComponentEnable("AparfWifiManager", logLevel);
1217 LogComponentEnable("ArfWifiManager", logLevel);
1218 LogComponentEnable("BlockAckAgreement", logLevel);
1219 LogComponentEnable("BlockAckManager", logLevel);
1220 LogComponentEnable("CaraWifiManager", logLevel);
1221 LogComponentEnable("ChannelAccessManager", logLevel);
1222 LogComponentEnable("ConstantObssPdAlgorithm", logLevel);
1223 LogComponentEnable("ConstantRateWifiManager", logLevel);
1224 LogComponentEnable("DefaultApEmlsrManager", logLevel);
1225 LogComponentEnable("DefaultEmlsrManager", logLevel);
1226 LogComponentEnable("DsssErrorRateModel", logLevel);
1227 LogComponentEnable("DsssPhy", logLevel);
1228 LogComponentEnable("DsssPpdu", logLevel);
1229 LogComponentEnable("EhtFrameExchangeManager", logLevel);
1230 LogComponentEnable("EhtPhy", logLevel);
1231 LogComponentEnable("EhtPpdu", logLevel);
1232 LogComponentEnable("EmlsrManager", logLevel);
1233 LogComponentEnable("ErpOfdmPhy", logLevel);
1234 LogComponentEnable("ErpOfdmPpdu", logLevel);
1235 LogComponentEnable("FrameExchangeManager", logLevel);
1236 LogComponentEnable("GcrManager", logLevel);
1237 LogComponentEnable("HeConfiguration", logLevel);
1238 LogComponentEnable("HeFrameExchangeManager", logLevel);
1239 LogComponentEnable("HePhy", logLevel);
1240 LogComponentEnable("HePpdu", logLevel);
1241 LogComponentEnable("HtConfiguration", logLevel);
1242 LogComponentEnable("HtFrameExchangeManager", logLevel);
1243 LogComponentEnable("HtPhy", logLevel);
1244 LogComponentEnable("HtPpdu", logLevel);
1245 LogComponentEnable("IdealWifiManager", logLevel);
1246 LogComponentEnable("InterferenceHelper", logLevel);
1247 LogComponentEnable("MacRxMiddle", logLevel);
1248 LogComponentEnable("MacTxMiddle", logLevel);
1249 LogComponentEnable("MinstrelHtWifiManager", logLevel);
1250 LogComponentEnable("MinstrelWifiManager", logLevel);
1251 LogComponentEnable("MpduAggregator", logLevel);
1252 LogComponentEnable("MsduAggregator", logLevel);
1253 LogComponentEnable("MultiUserScheduler", logLevel);
1254 LogComponentEnable("NistErrorRateModel", logLevel);
1255 LogComponentEnable("ObssPdAlgorithm", logLevel);
1256 LogComponentEnable("OfdmPhy", logLevel);
1257 LogComponentEnable("OfdmPpdu", logLevel);
1258 LogComponentEnable("OnoeWifiManager", logLevel);
1259 LogComponentEnable("OriginatorBlockAckAgreement", logLevel);
1260 LogComponentEnable("ParfWifiManager", logLevel);
1261 LogComponentEnable("PhyEntity", logLevel);
1262 LogComponentEnable("QosFrameExchangeManager", logLevel);
1263 LogComponentEnable("QosTxop", logLevel);
1264 LogComponentEnable("RecipientBlockAckAgreement", logLevel);
1265 LogComponentEnable("RrMultiUserScheduler", logLevel);
1266 LogComponentEnable("RraaWifiManager", logLevel);
1267 LogComponentEnable("RrpaaWifiManager", logLevel);
1268 LogComponentEnable("SimpleFrameCaptureModel", logLevel);
1269 LogComponentEnable("SpectrumWifiPhy", logLevel);
1270 LogComponentEnable("StaWifiMac", logLevel);
1271 LogComponentEnable("SupportedRates", logLevel);
1272 LogComponentEnable("TableBasedErrorRateModel", logLevel);
1273 LogComponentEnable("ThompsonSamplingWifiManager", logLevel);
1274 LogComponentEnable("ThresholdPreambleDetectionModel", logLevel);
1275 LogComponentEnable("Txop", logLevel);
1276 LogComponentEnable("VhtConfiguration", logLevel);
1277 LogComponentEnable("VhtFrameExchangeManager", logLevel);
1278 LogComponentEnable("VhtPhy", logLevel);
1279 LogComponentEnable("VhtPpdu", logLevel);
1280 LogComponentEnable("WifiAckManager", logLevel);
1281 LogComponentEnable("WifiAssocManager", logLevel);
1282 LogComponentEnable("WifiDefaultAckManager", logLevel);
1283 LogComponentEnable("WifiDefaultAssocManager", logLevel);
1284 LogComponentEnable("WifiDefaultGcrManager", logLevel);
1285 LogComponentEnable("WifiDefaultProtectionManager", logLevel);
1286 LogComponentEnable("WifiMac", logLevel);
1287 LogComponentEnable("WifiMacQueue", logLevel);
1288 LogComponentEnable("WifiMpdu", logLevel);
1289 LogComponentEnable("WifiNetDevice", logLevel);
1290 LogComponentEnable("WifiPhyStateHelper", logLevel);
1291 LogComponentEnable("WifiPhyOperatingChannel", logLevel);
1292 LogComponentEnable("WifiPhy", logLevel);
1293 LogComponentEnable("WifiPpdu", logLevel);
1294 LogComponentEnable("WifiProtectionManager", logLevel);
1295 LogComponentEnable("WifiPsdu", logLevel);
1296 LogComponentEnable("WifiRadioEnergyModel", logLevel);
1297 LogComponentEnable("WifiRemoteStationManager", logLevel);
1298 LogComponentEnable("WifiSpectrumPhyInterface", logLevel);
1299 LogComponentEnable("WifiSpectrumSignalParameters", logLevel);
1300 LogComponentEnable("WifiSpectrumValueHelper", logLevel);
1301 LogComponentEnable("WifiTxCurrentModel", logLevel);
1302 LogComponentEnable("WifiTxParameters", logLevel);
1303 LogComponentEnable("WifiTxTimer", logLevel);
1304 LogComponentEnable("YansErrorRateModel", logLevel);
1305 LogComponentEnable("YansWifiChannel", logLevel);
1306 LogComponentEnable("YansWifiPhy", logLevel);
1307
1308 LogComponentEnable("Athstats", logLevel);
1309 LogComponentEnable("WifiHelper", logLevel);
1310 LogComponentEnable("SpectrumWifiHelper", logLevel);
1311 LogComponentEnable("YansWifiHelper", logLevel);
1312}
1313
1314int64_t
1316{
1317 int64_t currentStream = stream;
1318 Ptr<NetDevice> netDevice;
1319 for (auto i = c.Begin(); i != c.End(); ++i)
1320 {
1321 netDevice = (*i);
1322 if (auto wifi = DynamicCast<WifiNetDevice>(netDevice))
1323 {
1324 // Handle any random numbers in the PHY objects.
1325 for (auto& phy : wifi->GetPhys())
1326 {
1327 currentStream += phy->AssignStreams(currentStream);
1328 }
1329
1330 // Handle any random numbers in the station managers.
1331 for (auto& manager : wifi->GetRemoteStationManagers())
1332 {
1333 currentStream += manager->AssignStreams(currentStream);
1334 }
1335
1336 // Handle any random numbers in the MAC objects.
1337 auto mac = wifi->GetMac();
1338 PointerValue ptr;
1339 if (!mac->GetQosSupported())
1340 {
1341 mac->GetAttribute("Txop", ptr);
1342 auto txop = ptr.Get<Txop>();
1343 currentStream += txop->AssignStreams(currentStream);
1344 }
1345 else
1346 {
1347 mac->GetAttribute("VO_Txop", ptr);
1348 auto vo_txop = ptr.Get<QosTxop>();
1349 currentStream += vo_txop->AssignStreams(currentStream);
1350
1351 mac->GetAttribute("VI_Txop", ptr);
1352 auto vi_txop = ptr.Get<QosTxop>();
1353 currentStream += vi_txop->AssignStreams(currentStream);
1354
1355 mac->GetAttribute("BE_Txop", ptr);
1356 auto be_txop = ptr.Get<QosTxop>();
1357 currentStream += be_txop->AssignStreams(currentStream);
1358
1359 mac->GetAttribute("BK_Txop", ptr);
1360 auto bk_txop = ptr.Get<QosTxop>();
1361 currentStream += bk_txop->AssignStreams(currentStream);
1362 }
1363
1364 // if an AP, handle any beacon jitter
1365 if (auto apMac = DynamicCast<ApWifiMac>(mac); apMac)
1366 {
1367 currentStream += apMac->AssignStreams(currentStream);
1368 }
1369 // if a STA, handle any probe request jitter
1370 if (auto staMac = DynamicCast<StaWifiMac>(mac); staMac)
1371 {
1372 currentStream += staMac->AssignStreams(currentStream);
1373 }
1374 }
1375 }
1376 return (currentStream - stream);
1377}
1378
1379} // namespace ns3
Headers for A-MPDU subframes.
uint16_t GetLength() const
Return the length field.
bool GetEof() const
Return the EOF field.
Manage ASCII trace files for device models.
std::string GetFilenameFromDevice(std::string prefix, Ptr< NetDevice > device, bool useObjectNames=true)
Let the ascii trace helper figure out a reasonable filename to use for an ascii trace file associated...
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
Hold a value for an Attribute.
Definition attribute.h:59
AttributeValue implementation for Boolean.
Definition boolean.h:26
bool Get() const
Definition boolean.cc:44
EHT configuration.
static uint8_t GetPuncturedInfo(const std::vector< bool > &inactiveSubchannels, uint8_t ehtPpduType, std::optional< bool > isLow80MHz)
Get the Punctured Channel Information field in the U-SIG.
Definition eht-ppdu.cc:301
HE configuration.
HT configuration.
Keep track of the current position and velocity of an object.
static Ptr< T > Find(std::string path)
Given a name path string, look to see if there's an object in the system with that associated to it.
Definition names.h:443
holds a vector of ns3::NetDevice pointers
Iterator Begin() const
Get an iterator which refers to the first NetDevice in the container.
Iterator End() const
Get an iterator which indicates past-the-last NetDevice in the container.
keep track of a set of node pointers.
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
Iterator End() const
Get an iterator which indicates past-the-last Node in the container.
Iterator Begin() const
Get an iterator which refers to the first Node in the container.
OBSS PD algorithm interface.
static void EnablePrinting()
Enable printing packets metadata.
Definition packet.cc:585
Manage pcap files for device models.
std::string GetFilenameFromDevice(std::string prefix, Ptr< NetDevice > device, bool useObjectNames=true)
Let the pcap helper figure out a reasonable filename to use for a pcap file associated with a device.
Ptr< PcapFileWrapper > CreateFile(std::string filename, std::ios::openmode filemode, DataLinkType dataLinkType, uint32_t snapLen=std::numeric_limits< uint32_t >::max(), int32_t tzCorrection=0)
Create and initialize a pcap file.
DataLinkType
This enumeration holds the data link types that will be written to the pcap file.
AttributeValue implementation for Pointer.
Definition pointer.h:37
Ptr< T > Get() const
Definition pointer.h:223
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
Handles the packet queue and stores DCF/EDCA access parameters (one Txop per AC).
Definition qos-txop.h:52
Radiotap header implementation.
void SetAmpduStatus(const AmpduStatusFields &ampduStatusFields)
Set the subfields of the A-MPDU status field.
@ CHANNEL_FLAG_OFDM
OFDM channel.
@ CHANNEL_FLAG_CCK
CCK channel.
@ CHANNEL_FLAG_SPECTRUM_5GHZ
5 GHz spectrum channel
@ CHANNEL_FLAG_SPECTRUM_2GHZ
2 GHz spectrum channel
void SetHeMuOtherUserFields(const HeMuOtherUserFields &heMuOtherUserFields)
Set the subfields of the HE-MU-other-user field.
void SetHeFields(const HeFields &heFields)
Set the subfields of the HE field.
void SetMcsFields(const McsFields &mcsFields)
Set the subfields of the MCS field.
void SetRate(uint8_t rate)
Set the transmit/receive channel frequency in units of megahertz.
void SetAntennaSignalPower(double signal)
Set the RF signal power at the antenna as a decibel difference from an arbitrary, fixed reference.
@ VHT_FLAGS_STBC
Set if all spatial streams of all users have space-time block coding.
@ VHT_FLAGS_GUARD_INTERVAL
Short guard interval.
void SetTsft(uint64_t tsft)
Set the Time Synchronization Function Timer (TSFT) value.
void SetUsigFields(const UsigFields &usigFields)
Set the subfields of the U-SIG field.
@ HE_DATA2_PRISEC_80_SEC
pri/sec 80 MHz
@ HE_DATA5_DATA_BW_RU_ALLOC_26T
26-tone RU allocation
@ HE_DATA1_FORMAT_TRIG
HE TRIG PPDU format.
@ HE_DATA5_DATA_BW_RU_ALLOC_484T
484-tone RU allocation
@ HE_DATA1_FORMAT_MU
HE MU PPDU format.
@ HE_DATA1_BSS_COLOR_KNOWN
BSS Color known.
@ HE_DATA5_DATA_BW_RU_ALLOC_40MHZ
40 MHz data Bandwidth
@ HE_DATA5_DATA_BW_RU_ALLOC_2x996T
2x996-tone RU allocation
@ HE_DATA5_DATA_BW_RU_ALLOC_242T
242-tone RU allocation
@ HE_DATA5_DATA_BW_RU_ALLOC_52T
52-tone RU allocation
@ HE_DATA2_RU_OFFSET
RU allocation offset.
@ HE_DATA1_FORMAT_EXT_SU
HE EXT SU PPDU format.
@ HE_DATA1_DATA_MCS_KNOWN
data MCS known
@ HE_DATA5_DATA_BW_RU_ALLOC_160MHZ
160 MHz data Bandwidth
@ HE_DATA5_DATA_BW_RU_ALLOC_106T
106-tone RU allocation
@ HE_DATA2_RU_OFFSET_KNOWN
RU allocation offset known.
@ HE_DATA1_SPTL_REUSE2_KNOWN
Spatial Reuse 2 known (HE TRIG PPDU format), STA-ID known (HE MU PPDU format)
@ HE_DATA5_DATA_BW_RU_ALLOC_996T
996-tone RU allocation
@ HE_DATA1_BW_RU_ALLOC_KNOWN
data BW/RU allocation known
@ HE_DATA5_DATA_BW_RU_ALLOC_80MHZ
80 MHz data Bandwidth
@ MCS_KNOWN_FEC_TYPE
FEC type.
@ MCS_KNOWN_GUARD_INTERVAL
Guard interval.
@ MCS_KNOWN_BANDWIDTH
Bandwidth.
@ MCS_KNOWN_NESS_BIT_1
Ness data - bit 1 (MSB) of Number of extension spatial streams.
@ MCS_KNOWN_HT_FORMAT
HT format.
@ MCS_KNOWN_NESS
Ness known (Number of extension spatial streams)
@ MCS_KNOWN_INDEX
MCS index known.
@ MCS_KNOWN_STBC
STBC known.
@ FRAME_FLAG_SHORT_PREAMBLE
Frame sent/received with short preamble.
@ FRAME_FLAG_SHORT_GUARD
Frame used short guard interval (HT)
@ FRAME_FLAG_FCS_INCLUDED
Frame includes FCS.
@ FRAME_FLAG_NONE
No flags set.
void SetVhtFields(const VhtFields &vhtFields)
Set the subfields of the VHT field.
@ MCS_FLAGS_NESS_BIT_0
Ness - bit 0 (LSB) of Number of extension spatial streams.
@ MCS_FLAGS_STBC_STREAMS
STBC enabled.
@ MCS_FLAGS_GUARD_INTERVAL
Short guard interval.
void SetAntennaNoisePower(double noise)
Set the RF noise power at the antenna as a decibel difference from an arbitrary, fixed reference.
@ A_MPDU_STATUS_LAST_KNOWN
Last subframe is known (should be set for all subframes in an A-MPDU)
@ A_MPDU_STATUS_LAST
This frame is the last subframe.
void SetEhtFields(const EhtFields &ehtFields)
Set the subfields of the EHT-SIG field.
@ VHT_KNOWN_BANDWIDTH
Bandwidth known.
@ VHT_KNOWN_STBC
Space-time block coding (1 if all spatial streams of all users have STBC, 0 otherwise).
@ VHT_KNOWN_GUARD_INTERVAL
Guard interval.
@ VHT_KNOWN_BEAMFORMED
Beamformed known/applicable (this flag should be set to zero for MU PPDUs).
void SetWifiHeader(std::size_t numPresentWords)
Set the ieee80211_radiotap_header.
void SetHeMuFields(const HeMuFields &heMuFields)
Set the subfields of the HE-MU field.
void SetChannelFields(const ChannelFields &channelFields)
Set the subfields of the Channel field.
void SetFrameFlags(uint8_t flags)
Set the frame flags of the transmitted or received frame.
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:394
Handles the packet queue and stores DCF/EDCA access parameters (one Txop per AC).
Definition txop.h:56
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition txop.cc:704
Hold an unsigned integer type.
Definition uinteger.h:34
VHT configuration.
virtual ~WifiHelper()
void SetRemoteStationManager(std::string type, Args &&... args)
Helper function used to set the station manager.
ObjectFactory m_htConfig
HT configuration.
ObjectFactory m_obssPdAlgorithm
OBSS_PD algorithm.
ObjectFactory m_ehtConfig
EHT configuration.
ObjectFactory m_vhtConfig
VHT configuration.
static void EnableLogComponents(LogLevel logLevel=LOG_LEVEL_ALL)
Helper to enable all WifiNetDevice log components with one statement.
void SetSelectQueueCallback(SelectQueueCallback f)
std::vector< ObjectFactory > m_stationManager
station manager
WifiStandard m_standard
wifi standard
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
virtual void SetStandard(WifiStandard standard)
ObjectFactory m_heConfig
HE configuration.
virtual NetDeviceContainer Install(const WifiPhyHelper &phy, const WifiMacHelper &mac, NodeContainer::Iterator first, NodeContainer::Iterator last) const
void DisableFlowControl()
Disable flow control only if you know what you are doing.
SelectQueueCallback m_selectQueueCallback
select queue callback
bool m_enableFlowControl
whether to enable flow control
WifiHelper()
Create a Wifi helper in an empty state: all its parameters must be set before calling ns3::WifiHelper...
std::function< std::size_t(Ptr< QueueItem >)> SelectQueueCallback
Callback invoked to determine the MAC queue selected for a given packet.
create MAC layers for a ns3::WifiNetDevice.
virtual Ptr< WifiMac > Create(Ptr< WifiNetDevice > device, WifiStandard standard) const
Implements the IEEE 802.11 MAC trailer.
represent a single transmission mode
Definition wifi-mode.h:38
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
Hold together all Wifi-related objects.
create PHY objects
Definition wifi-helper.h:40
void SetPcapCaptureType(PcapCaptureType type)
Set the PCAP capture type to be used.
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
void EnableAsciiInternal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< NetDevice > nd, bool explicitFilename) override
Enable ASCII trace output on the indicated net device.
WifiPhyHelper(uint8_t nLinks=1)
Constructor.
static void PcapSniffTxEvent(const std::shared_ptr< PcapFilesInfo > &info, uint8_t phyId, Ptr< const Packet > packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, uint16_t staId=SU_STA_ID)
void Set(std::string name, const AttributeValue &v)
~WifiPhyHelper() override
void DisablePreambleDetectionModel()
Disable the preamble detection model on all links.
void EnablePcapInternal(std::string prefix, Ptr< NetDevice > nd, bool promiscuous, bool explicitFilename) override
Enable pcap output the indicated net device.
PcapHelper::DataLinkType m_pcapDlt
PCAP data link type.
std::vector< ObjectFactory > m_frameCaptureModel
frame capture model
std::vector< ObjectFactory > m_preambleDetectionModel
preamble detection model
PcapHelper::DataLinkType GetPcapDataLinkType() const
Get the data link type of PCAP traces to be used.
PcapCaptureType m_pcapType
PCAP capture type.
PcapCaptureType GetPcapCaptureType() const
Get the PCAP capture type to be used.
std::vector< ObjectFactory > m_phys
PHY objects.
static void PcapSniffRxEvent(const std::shared_ptr< PcapFilesInfo > &info, uint8_t phyId, Ptr< const Packet > packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise, uint16_t staId=SU_STA_ID)
void SetPreambleDetectionModel(std::string type, Args &&... args)
Helper function used to set the preamble detection model.
static RadiotapHeader GetRadiotapHeader(Ptr< Packet > packet, uint16_t channelFreqMhz, uint8_t p20Index, const WifiTxVector &txVector, MpduInfo aMpdu, uint16_t staId, std::optional< SignalNoiseDbm > signalNoise=std::nullopt)
Get the Radiotap header for a received packet.
static Ptr< PcapFileWrapper > GetOrCreatePcapFile(const std::shared_ptr< PcapFilesInfo > &info, uint8_t phyId)
Get the PCAP file to write to from a list of PCAP files indexed by PHY ID.
SupportedPcapDataLinkTypes
An enumeration of the pcap data link types (DLTs) which this helper supports.
@ DLT_IEEE802_11
IEEE 802.11 Wireless LAN headers on packets.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
@ DLT_PRISM_HEADER
Include Prism monitor mode information.
std::vector< ObjectFactory > m_errorRateModel
error rate model
virtual std::vector< Ptr< WifiPhy > > Create(Ptr< Node > node, Ptr< WifiNetDevice > device) const =0
PcapCaptureType
An enumeration of the PCAP capture types.
@ PCAP_PER_PHY
Single capture file per PHY.
@ PCAP_PER_DEVICE
Single capture file per device.
@ PCAP_PER_LINK
Single capture file per link.
static bool IsHe(RuSpec ru)
Get whether a given RU variant is a HE RU.
Definition wifi-ru.cc:248
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
Definition wifi-ru.cc:45
static std::size_t GetIndex(RuSpec ru)
Get the index of a given RU.
Definition wifi-ru.cc:51
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint8_t GetBssColor() const
Get the BSS color.
const RuAllocation & GetRuAllocation(uint8_t p20Index) const
Get RU_ALLOCATION field.
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
bool IsStbc() const
Check if STBC is used or not.
WifiPreamble GetPreambleType() const
HeMuUserInfo GetHeMuUserInfo(uint16_t staId) const
Get the HE MU user-specific transmission information for the given STA-ID.
uint8_t GetEhtPpduType() const
Get the EHT_PPDU_TYPE parameter.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
MHz_u GetChannelWidth() const
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
Time GetGuardInterval() const
uint8_t GetNess() const
WifiRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
WifiMode GetSigBMode() const
Get MCS used for SIG-B.
const std::vector< bool > & GetInactiveSubchannels() const
Get the 20 MHz subchannels that are punctured.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:970
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:946
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition callback.h:745
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:439
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
uint8_t SelectQueueByDSField(Ptr< QueueItem > item)
Determine the TX queue for a given packet.
Definition qos-utils.cc:227
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211ad
@ WIFI_STANDARD_80211p
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_UNSPECIFIED
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
@ WIFI_PREAMBLE_HE_ER_SU
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_SHORT
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ AC_BE
Best Effort.
Definition qos-utils.h:65
@ AC_VO
Voice.
Definition qos-utils.h:71
@ AC_VI
Video.
Definition qos-utils.h:69
@ AC_BK
Background.
Definition qos-utils.h:67
@ LAST_MPDU_IN_AGGREGATE
The MPDU is the last aggregate in an A-MPDU with multiple MPDUs.
Definition wifi-types.h:60
Definition first.py:1
const std::map< MHz_u, RadiotapHeader::UsigCommonBw > channelization320MHzMap
320 MHz channelization map
uint32_t GetRadiotapField(uint32_t mask, uint32_t val)
Helper function to place the value to set in the correct bit(s) of a radiotap subfield.
const std::unordered_map< std::string, WifiStandard > WIFI_STANDARDS_NAME_MAP
Map strings to WifiStandard enum values.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition log.cc:284
bool IsEht(WifiPreamble preamble)
Return true if a preamble corresponds to an EHT transmission.
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:585
static void AsciiPhyReceiveSinkWithoutContext(Ptr< OutputStreamWrapper > stream, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
ASCII trace PHY receive sink without context.
LogLevel
Logging severity classes and levels.
Definition log.h:83
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition log.h:108
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
Definition log.h:109
static void AsciiPhyReceiveSinkWithContext(Ptr< OutputStreamWrapper > stream, std::string context, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
ASCII trace PHY receive sink with context.
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition log.cc:302
static void AsciiPhyTransmitSinkWithContext(Ptr< OutputStreamWrapper > stream, std::string context, Ptr< const Packet > p, WifiMode mode, WifiPreamble preamble, uint8_t txLevel)
ASCII trace PHY transmit sink with context.
static void AsciiPhyTransmitSinkWithoutContext(Ptr< OutputStreamWrapper > stream, Ptr< const Packet > p, WifiMode mode, WifiPreamble preamble, uint8_t txLevel)
ASCII trace PHY transmit sink without context.
WifiRu::RuSpec ru
RU specification.
MpduInfo structure.
Definition wifi-types.h:72
MpduType type
type of MPDU
Definition wifi-types.h:73
uint32_t mpduRefNumber
MPDU ref number.
Definition wifi-types.h:74
structure that contains the subfields of the A-MPDU status field.
structure that contains the subfields of the Channel field.
structure that contains the subfields of the EHT field.
structure that contains the subfields of the HE field.
structure that contains the subfields of the HE-MU field.
structure that contains the subfields of the HE-MU-other-user field.
structure that contains the subfields of the MCS field.
structure that contains the subfields of the U-SIG field.
structure that contains the subfields of the VHT field.
uint16_t known
known flags field
SignalNoiseDbm structure.
Definition wifi-types.h:65