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/he-configuration.h"
19#include "ns3/ht-configuration.h"
20#include "ns3/log.h"
21#include "ns3/mobility-model.h"
22#include "ns3/names.h"
23#include "ns3/net-device-queue-interface.h"
24#include "ns3/obss-pd-algorithm.h"
25#include "ns3/pointer.h"
26#include "ns3/qos-txop.h"
27#include "ns3/qos-utils.h"
28#include "ns3/radiotap-header.h"
29#include "ns3/sta-wifi-mac.h"
30#include "ns3/vht-configuration.h"
31#include "ns3/wifi-mac-queue.h"
32#include "ns3/wifi-mac-trailer.h"
33
34#include <bit>
35#include <memory>
36
37namespace
38{
39/**
40 * Helper function to place the value to set in the correct bit(s) of a radiotap subfield.
41 *
42 * \param mask the mask of the corresponding subfield
43 * \param val the value the subfield should be set to
44 * \return the value placed at the correct position based on the mask
45 */
48{
49 const auto shift = std::countr_zero(mask);
50 return (val << shift) & mask;
51}
52} // namespace
53
54namespace ns3
55{
56
57NS_LOG_COMPONENT_DEFINE("WifiHelper");
58
59/**
60 * ASCII trace PHY transmit sink with context
61 * \param stream the output stream
62 * \param context the context name
63 * \param p the packet
64 * \param mode the wifi mode
65 * \param preamble the wifi preamble
66 * \param txLevel the transmit power level
67 */
68static void
70 std::string context,
72 WifiMode mode,
73 WifiPreamble preamble,
74 uint8_t txLevel)
75{
76 NS_LOG_FUNCTION(stream << context << p << mode << preamble << txLevel);
77 auto pCopy = p->Copy();
79 pCopy->RemoveTrailer(fcs);
80 *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << context << " " << mode
81 << " " << *pCopy << " " << fcs << std::endl;
82}
83
84/**
85 * ASCII trace PHY transmit sink without context
86 * \param stream the output stream
87 * \param p the packet
88 * \param mode the wifi mode
89 * \param preamble the wifi preamble
90 * \param txLevel the transmit power level
91 */
92static void
95 WifiMode mode,
96 WifiPreamble preamble,
97 uint8_t txLevel)
98{
99 NS_LOG_FUNCTION(stream << p << mode << preamble << txLevel);
100 auto pCopy = p->Copy();
101 WifiMacTrailer fcs;
102 pCopy->RemoveTrailer(fcs);
103 *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << mode << " " << *pCopy
104 << " " << fcs << std::endl;
105}
106
107/**
108 * ASCII trace PHY receive sink with context
109 * \param stream the output stream
110 * \param context the context name
111 * \param p the packet
112 * \param snr the SNR
113 * \param mode the wifi mode
114 * \param preamble the wifi preamble
115 */
116static void
118 std::string context,
120 double snr,
121 WifiMode mode,
122 WifiPreamble preamble)
123{
124 NS_LOG_FUNCTION(stream << context << p << snr << mode << preamble);
125 auto pCopy = p->Copy();
126 WifiMacTrailer fcs;
127 pCopy->RemoveTrailer(fcs);
128 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << mode << " " << context
129 << " " << *pCopy << " " << fcs << std::endl;
130}
131
132/**
133 * ASCII trace PHY receive sink without context
134 * \param stream the output stream
135 * \param p the packet
136 * \param snr the SNR
137 * \param mode the wifi mode
138 * \param preamble the wifi preamble
139 */
140static void
143 double snr,
144 WifiMode mode,
145 WifiPreamble preamble)
146{
147 NS_LOG_FUNCTION(stream << p << snr << mode << preamble);
148 auto pCopy = p->Copy();
149 WifiMacTrailer fcs;
150 pCopy->RemoveTrailer(fcs);
151 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << mode << " " << *pCopy
152 << " " << fcs << std::endl;
153}
154
156 : m_pcapDlt{PcapHelper::DLT_IEEE802_11},
157 m_pcapType{PcapCaptureType::PCAP_PER_PHY}
158{
159 NS_ABORT_IF(nLinks == 0);
160 m_phys.resize(nLinks);
161 m_errorRateModel.resize(nLinks);
162 m_frameCaptureModel.resize(nLinks);
163 m_preambleDetectionModel.resize(nLinks);
164
165 SetPreambleDetectionModel("ns3::ThresholdPreambleDetectionModel");
166}
167
171
172void
173WifiPhyHelper::Set(std::string name, const AttributeValue& v)
174{
175 for (auto& phy : m_phys)
176 {
177 phy.Set(name, v);
178 }
179}
180
181void
182WifiPhyHelper::Set(uint8_t linkId, std::string name, const AttributeValue& v)
183{
184 m_phys.at(linkId).Set(name, v);
185}
186
187void
193
195WifiPhyHelper::GetOrCreatePcapFile(const std::shared_ptr<PcapFilesInfo>& info, uint8_t phyId)
196{
197 uint8_t fileIdx;
198 switch (info->pcapType)
199 {
201 fileIdx = 0;
202 break;
204 fileIdx = phyId;
205 break;
207 if (const auto linkId = info->device->GetMac()->GetLinkForPhy(phyId))
208 {
209 fileIdx = *linkId;
210 break;
211 }
212 return nullptr;
213 default:
214 NS_ABORT_MSG("Unexpected PCAP capture type");
215 return nullptr;
216 }
217
218 if (!info->files.contains(fileIdx))
219 {
220 // file does not exist yet, create it
221 auto tmp = info->commonFilename;
222
223 // find the last point in the filename
224 auto pos = info->commonFilename.find_last_of('.');
225 // if not found, set pos to filename size
226 pos = (pos == std::string::npos) ? info->commonFilename.size() : pos;
227
228 // insert PHY/link ID only for multi-link devices, unless a single PCAP is generated for the
229 // device
230 if ((info->device->GetNPhys() > 1) && (info->pcapType != PcapCaptureType::PCAP_PER_DEVICE))
231 {
232 tmp.insert(pos, "-" + std::to_string(fileIdx));
233 }
234
235 PcapHelper pcapHelper;
236 auto file = pcapHelper.CreateFile(tmp, std::ios::out, info->pcapDlt);
237 info->files.emplace(fileIdx, file);
238 }
239
240 return info->files.at(fileIdx);
241}
242
243void
244WifiPhyHelper::PcapSniffTxEvent(const std::shared_ptr<PcapFilesInfo>& info,
245 uint8_t phyId,
246 Ptr<const Packet> packet,
247 uint16_t channelFreqMhz,
248 WifiTxVector txVector,
249 MpduInfo aMpdu,
250 uint16_t staId)
251{
252 auto file = GetOrCreatePcapFile(info, phyId);
253 if (!file)
254 {
255 return;
256 }
257 switch (info->pcapDlt)
258 {
260 file->Write(Simulator::Now(), packet);
261 return;
263 NS_FATAL_ERROR("PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented");
264 return;
265 }
267 Ptr<Packet> p = packet->Copy();
268 RadiotapHeader header;
269 GetRadiotapHeader(header,
270 p,
271 channelFreqMhz,
272 info->device->GetPhy(phyId)->GetPrimary20Index(),
273 txVector,
274 aMpdu,
275 staId);
276 p->AddHeader(header);
277 file->Write(Simulator::Now(), p);
278 return;
279 }
280 default:
281 NS_ABORT_MSG("PcapSniffTxEvent(): Unexpected data link type " << info->pcapDlt);
282 }
283}
284
285void
286WifiPhyHelper::PcapSniffRxEvent(const std::shared_ptr<PcapFilesInfo>& info,
287 uint8_t phyId,
288 Ptr<const Packet> packet,
289 uint16_t channelFreqMhz,
290 WifiTxVector txVector,
291 MpduInfo aMpdu,
292 SignalNoiseDbm signalNoise,
293 uint16_t staId)
294{
295 auto file = GetOrCreatePcapFile(info, phyId);
296 if (!file)
297 {
298 return;
299 }
300 switch (info->pcapDlt)
301 {
303 file->Write(Simulator::Now(), packet);
304 return;
306 NS_FATAL_ERROR("PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented");
307 return;
308 }
310 Ptr<Packet> p = packet->Copy();
311 RadiotapHeader header;
312 GetRadiotapHeader(header,
313 p,
314 channelFreqMhz,
315 info->device->GetPhy(phyId)->GetPrimary20Index(),
316 txVector,
317 aMpdu,
318 staId,
319 signalNoise);
320 p->AddHeader(header);
321 file->Write(Simulator::Now(), p);
322 return;
323 }
324 default:
325 NS_ABORT_MSG("PcapSniffRxEvent(): Unexpected data link type " << info->pcapDlt);
326 }
327}
328
329void
331 Ptr<Packet> packet,
332 uint16_t channelFreqMhz,
333 uint8_t p20Index,
334 const WifiTxVector& txVector,
335 MpduInfo aMpdu,
336 uint16_t staId,
337 SignalNoiseDbm signalNoise)
338{
339 header.SetAntennaSignalPower(signalNoise.signal);
340 header.SetAntennaNoisePower(signalNoise.noise);
341 GetRadiotapHeader(header, packet, channelFreqMhz, p20Index, txVector, aMpdu, staId);
342}
343
344void
346 Ptr<Packet> packet,
347 uint16_t channelFreqMhz,
348 uint8_t p20Index,
349 const WifiTxVector& txVector,
350 MpduInfo aMpdu,
351 uint16_t staId)
352{
353 const auto preamble = txVector.GetPreambleType();
354 const auto modClass = txVector.GetModulationClass();
355 const auto channelWidth = txVector.GetChannelWidth();
356 const auto gi = txVector.GetGuardInterval();
357
358 header.SetTsft(Simulator::Now().GetMicroSeconds());
359
360 uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
361 // Our capture includes the FCS, so we set the flag to say so.
363 if (preamble == WIFI_PREAMBLE_SHORT)
364 {
366 }
367 if (gi.GetNanoSeconds() == 400)
368 {
370 }
371 header.SetFrameFlags(frameFlags);
372
373 uint8_t mcs = 0;
374 uint8_t nss = 1;
375 uint64_t rate = 0;
376 if (modClass < WIFI_MOD_CLASS_HT)
377 {
378 rate = txVector.GetMode(staId).GetDataRate(channelWidth, gi, 1) * nss / 500000;
379 header.SetRate(static_cast<uint8_t>(rate));
380 }
381 else
382 {
383 mcs = txVector.GetMode(staId).GetMcsValue();
384 nss = txVector.GetNss(staId);
385 }
386
387 RadiotapHeader::ChannelFields channelFields{.frequency = channelFreqMhz};
388 switch (rate)
389 {
390 case 2: // 1Mbps
391 case 4: // 2Mbps
392 case 10: // 5Mbps
393 case 22: // 11Mbps
394 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_CCK;
395 break;
396 default:
397 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
398 break;
399 }
400 if (channelFreqMhz < 2500)
401 {
402 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
403 }
404 else
405 {
406 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
407 }
408 header.SetChannelFields(channelFields);
409
410 if (modClass == WIFI_MOD_CLASS_HT)
411 {
412 RadiotapHeader::McsFields mcsFields{.mcs = mcs};
413
418
419 if (channelWidth == 40)
420 {
422 }
423
424 if (gi.GetNanoSeconds() == 400)
425 {
427 }
428
429 const auto ness = txVector.GetNess();
430 if (ness & 0x01) // bit 1
431 {
432 mcsFields.flags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
433 }
434 if (ness & 0x02) // bit 2
435 {
436 mcsFields.flags |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
437 }
438
439 if (txVector.IsStbc())
440 {
442 }
443
444 header.SetMcsFields(mcsFields);
445 }
446
447 if (txVector.IsAggregation())
448 {
450 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
451 /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
453 uint32_t extractedLength;
454 packet->RemoveHeader(hdr);
455 extractedLength = hdr.GetLength();
456 packet = packet->CreateFragment(0, static_cast<uint32_t>(extractedLength));
457 if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof() && hdr.GetLength() > 0))
458 {
459 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST;
460 }
461 header.SetAmpduStatus(ampduStatusFields);
462 }
463
464 if (modClass == WIFI_MOD_CLASS_VHT)
465 {
466 RadiotapHeader::VhtFields vhtFields{};
467
469 if (txVector.IsStbc())
470 {
471 vhtFields.flags |= RadiotapHeader::VHT_FLAGS_STBC;
472 }
473
475 if (gi.GetNanoSeconds() == 400)
476 {
478 }
479
480 vhtFields.known |=
482 // TODO: bandwidths can be provided with sideband info
483 if (channelWidth == 40)
484 {
485 vhtFields.bandwidth = 1;
486 }
487 else if (channelWidth == 80)
488 {
489 vhtFields.bandwidth = 4;
490 }
491 else if (channelWidth == 160)
492 {
493 vhtFields.bandwidth = 11;
494 }
495
496 // only SU PPDUs are currently supported
497 vhtFields.mcsNss.at(0) |= (nss & 0x0f) | ((mcs << 4) & 0xf0);
498
499 header.SetVhtFields(vhtFields);
500 }
501
502 if (modClass == WIFI_MOD_CLASS_HE)
503 {
504 RadiotapHeader::HeFields heFields{};
508 if (preamble == WIFI_PREAMBLE_HE_ER_SU)
509 {
511 }
512 else if (preamble == WIFI_PREAMBLE_HE_MU)
513 {
514 heFields.data1 |=
516 }
517 else if (preamble == WIFI_PREAMBLE_HE_TB)
518 {
519 heFields.data1 |= RadiotapHeader::HE_DATA1_FORMAT_TRIG;
520 }
521
522 heFields.data2 = RadiotapHeader::HE_DATA2_GI_KNOWN;
523 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
524 {
525 heFields.data2 |=
527 // HeRu indices start at 1 whereas RadioTap starts at 0
528 GetRadiotapField(RadiotapHeader::HE_DATA2_RU_OFFSET,
529 txVector.GetHeMuUserInfo(staId).ru.GetIndex() - 1) |
531 !txVector.GetHeMuUserInfo(staId).ru.GetPrimary80MHz());
532 }
533
534 heFields.data3 =
535 GetRadiotapField(RadiotapHeader::HE_DATA3_BSS_COLOR, txVector.GetBssColor()) |
536 GetRadiotapField(RadiotapHeader::HE_DATA3_DATA_MCS, mcs);
537
538 heFields.data4 = (preamble == WIFI_PREAMBLE_HE_MU)
539 ? GetRadiotapField(RadiotapHeader::HE_DATA4_MU_STA_ID, staId)
540 : 0;
541
542 heFields.data5 = 0;
543 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
544 {
545 HeRu::RuType ruType = txVector.GetHeMuUserInfo(staId).ru.GetRuType();
546 switch (ruType)
547 {
548 case HeRu::RU_26_TONE:
550 break;
551 case HeRu::RU_52_TONE:
553 break;
556 break;
559 break;
562 break;
565 break;
568 break;
569 default:
570 NS_ABORT_MSG("Unexpected RU type");
571 }
572 }
573 else if (channelWidth == 40)
574 {
576 }
577 else if (channelWidth == 80)
578 {
580 }
581 else if (channelWidth == 160)
582 {
584 }
585 if (gi.GetNanoSeconds() == 1600)
586 {
587 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_1_6;
588 }
589 else if (gi.GetNanoSeconds() == 3200)
590 {
591 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_3_2;
592 }
593
594 header.SetHeFields(heFields);
595 }
596
597 if (preamble == WIFI_PREAMBLE_HE_MU)
598 {
599 RadiotapHeader::HeMuFields heMuFields{};
600 // TODO: fill in fields
601 header.SetHeMuFields(heMuFields);
602 RadiotapHeader::HeMuOtherUserFields heMuOtherUserFields{};
603 // TODO: fill in fields
604 header.SetHeMuOtherUserFields(heMuOtherUserFields);
605 }
606
607 if (IsEht(preamble))
608 {
609 RadiotapHeader::UsigFields usigFields{};
613 switch (static_cast<uint16_t>(channelWidth))
614 {
615 case 20:
616 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
618 break;
619 case 40:
620 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
622 break;
623 case 80:
624 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
626 break;
627 case 160:
628 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
630 break;
631 default:
632 NS_ABORT_MSG("Unexpected channel width");
633 break;
634 }
635 usigFields.common |=
636 GetRadiotapField(RadiotapHeader::USIG_COMMON_BSS_COLOR, txVector.GetBssColor());
637 if (preamble == WIFI_PREAMBLE_EHT_MU)
638 {
642 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_MU_B0_B1_PPDU_TYPE,
643 txVector.GetEhtPpduType()) |
645 txVector.GetSigBMode().GetMcsValue());
646 std::optional<bool> isLow80MHz;
647 if (txVector.IsDlMu() && channelWidth > 80)
648 {
649 const auto isLowP80 = p20Index < (channelWidth / 40);
650 const auto isP80 = txVector.GetHeMuUserInfo(staId).ru.GetPrimary80MHz();
651 isLow80MHz = (isLowP80 && isP80) || (!isLowP80 && !isP80);
652 }
653 const auto puncturedChannelInfo =
655 txVector.GetEhtPpduType(),
656 isLow80MHz);
657 usigFields.value |= GetRadiotapField(RadiotapHeader::USIG2_MU_B3_B7_PUNCTURED_INFO,
658 puncturedChannelInfo);
659 }
660 else
661 {
663 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_TB_B0_B1_PPDU_TYPE,
664 txVector.GetEhtPpduType());
665 }
666 header.SetUsigFields(usigFields);
667 }
668
669 if (preamble == WIFI_PREAMBLE_EHT_MU)
670 {
671 RadiotapHeader::EhtFields ehtFields{};
674 switch (gi.GetNanoSeconds())
675 {
676 case 800:
677 ehtFields.data.at(0) =
679 break;
680 case 1600:
681 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
683 break;
684 case 3200:
685 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
687 break;
688 default:
689 NS_ABORT_MSG("Unexpected guard interval");
690 break;
691 }
693 const auto ruType = (txVector.GetEhtPpduType() == 1) ? HeRu::GetRuType(channelWidth)
694 : txVector.GetRu(staId).GetRuType();
695 switch (ruType)
696 {
697 case HeRu::RU_26_TONE:
698 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
700 break;
701 case HeRu::RU_52_TONE:
702 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
704 break;
706 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
708 break;
710 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
712 break;
714 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
716 break;
718 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
720 break;
722 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
724 break;
725 default:
726 NS_ABORT_MSG("Unexpected RU type");
727 break;
728 }
729 const auto ruIndex =
730 (txVector.GetEhtPpduType() == 1) ? 1 : txVector.GetRu(staId).GetIndex();
731 const auto& ruAllocation = txVector.GetRuAllocation(p20Index);
732 ehtFields.data.at(1) |=
733 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_INDEX, ruIndex) |
734 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_ALLOC_CC_1_1_1, ruAllocation.at(0));
735 if (channelWidth >= 40)
736 {
737 ehtFields.data.at(2) =
739 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_1, ruAllocation.at(1));
740 }
741 if (channelWidth >= 80)
742 {
743 ehtFields.data.at(2) |=
746 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_1_1_2, ruAllocation.at(2)) |
747 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_2, ruAllocation.at(3));
748 }
749 if (channelWidth >= 160)
750 {
751 ehtFields.data.at(3) =
755 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_1, ruAllocation.at(4)) |
756 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_2_2_1, ruAllocation.at(5)) |
757 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_2, ruAllocation.at(6));
758 ehtFields.data.at(4) =
760 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_2, ruAllocation.at(7));
761 ehtFields.known |= RadiotapHeader::EHT_KNOWN_PRIMARY_80;
762 const auto isLowP80 = p20Index < (channelWidth / 40);
763 ehtFields.data.at(1) |=
767 }
768 // TODO: handle 320 MHz when supported
773 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_STA_ID, staId) |
774 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_MCS, mcs) |
775 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_NSS_O, nss);
776 ehtFields.userInfo.push_back(userInfo);
777 header.SetEhtFields(ehtFields);
778 }
779}
780
781void
783{
784 switch (dlt)
785 {
786 case DLT_IEEE802_11:
788 return;
789 case DLT_PRISM_HEADER:
791 return;
794 return;
795 default:
796 NS_ABORT_MSG("WifiPhyHelper::SetPcapFormat(): Unexpected format");
797 }
798}
799
802{
803 return m_pcapDlt;
804}
805
806void
811
814{
815 return m_pcapType;
816}
817
818void
821 bool promiscuous,
822 bool explicitFilename)
823{
824 NS_LOG_FUNCTION(this << prefix << nd << promiscuous << explicitFilename);
825
826 // All of the Pcap enable functions vector through here including the ones
827 // that are wandering through all of devices on perhaps all of the nodes in
828 // the system. We can only deal with devices of type WifiNetDevice.
829 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
830 if (!device)
831 {
832 NS_LOG_INFO("WifiHelper::EnablePcapInternal(): Device "
833 << &device << " not of type ns3::WifiNetDevice");
834 return;
835 }
836
837 NS_ABORT_MSG_IF(device->GetPhys().empty(),
838 "WifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
839
840 PcapHelper pcapHelper;
841 std::string filename;
842 if (explicitFilename)
843 {
844 filename = prefix;
845 }
846 else
847 {
848 filename = pcapHelper.GetFilenameFromDevice(prefix, device);
849 }
850
851 auto info = std::make_shared<PcapFilesInfo>(filename, m_pcapDlt, m_pcapType, device);
852 for (auto& phy : device->GetPhys())
853 {
854 phy->TraceConnectWithoutContext(
855 "MonitorSnifferTx",
856 MakeBoundCallback(&WifiPhyHelper::PcapSniffTxEvent, info, phy->GetPhyId()));
857 phy->TraceConnectWithoutContext(
858 "MonitorSnifferRx",
859 MakeBoundCallback(&WifiPhyHelper::PcapSniffRxEvent, info, phy->GetPhyId()));
860 }
861}
862
863void
865 std::string prefix,
867 bool explicitFilename)
868{
869 // All of the ASCII enable functions vector through here including the ones
870 // that are wandering through all of devices on perhaps all of the nodes in
871 // the system. We can only deal with devices of type WifiNetDevice.
872 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
873 if (!device)
874 {
875 NS_LOG_INFO("WifiHelper::EnableAsciiInternal(): Device "
876 << device << " not of type ns3::WifiNetDevice");
877 return;
878 }
879
880 // Our trace sinks are going to use packet printing, so we have to make sure
881 // that is turned on.
883
884 uint32_t nodeid = nd->GetNode()->GetId();
885 uint32_t deviceid = nd->GetIfIndex();
886 std::ostringstream oss;
887
888 // If we are not provided an OutputStreamWrapper, we are expected to create
889 // one using the usual trace filename conventions and write our traces
890 // without a context since there will be one file per context and therefore
891 // the context would be redundant.
892 if (!stream)
893 {
894 // Set up an output stream object to deal with private ofstream copy
895 // constructor and lifetime issues. Let the helper decide the actual
896 // name of the file given the prefix.
897 AsciiTraceHelper asciiTraceHelper;
898
899 std::string filename;
900 if (explicitFilename)
901 {
902 filename = prefix;
903 }
904 else
905 {
906 filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device);
907 }
908
909 // find the last point in the filename
910 auto pos = filename.find_last_of('.');
911 // if not found, set pos to filename size
912 pos = (pos == std::string::npos) ? filename.size() : pos;
913
914 for (uint8_t linkId = 0; linkId < device->GetNPhys(); linkId++)
915 {
916 std::string tmp = filename;
917 if (device->GetNPhys() > 1)
918 {
919 // insert LinkId only for multi-link devices
920 tmp.insert(pos, "-" + std::to_string(linkId));
921 }
922 auto theStream = asciiTraceHelper.CreateFileStream(tmp);
923 // We could go poking through the PHY and the state looking for the
924 // correct trace source, but we can let Config deal with that with
925 // some search cost. Since this is presumably happening at topology
926 // creation time, it doesn't seem much of a price to pay.
927 oss.str("");
928 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
929 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/RxOk";
931 oss.str(),
933
934 oss.str("");
935 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
936 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/Tx";
938 oss.str(),
940 }
941
942 return;
943 }
944
945 // If we are provided an OutputStreamWrapper, we are expected to use it, and
946 // to provide a context. We are free to come up with our own context if we
947 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
948 // compatibility and simplicity, we just use Config::Connect and let it deal
949 // with coming up with a context.
950 oss.str("");
951 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
952 << "/$ns3::WifiNetDevice/Phy/State/RxOk";
954
955 oss.str("");
956 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
957 << "/$ns3::WifiNetDevice/Phy/State/Tx";
959}
960
964
966 : m_standard(WIFI_STANDARD_80211ax),
967 m_selectQueueCallback(&SelectQueueByDSField),
968 m_enableFlowControl(true)
969{
970 SetRemoteStationManager("ns3::IdealWifiManager");
971 m_htConfig.SetTypeId("ns3::HtConfiguration");
972 m_vhtConfig.SetTypeId("ns3::VhtConfiguration");
973 m_heConfig.SetTypeId("ns3::HeConfiguration");
974 m_ehtConfig.SetTypeId("ns3::EhtConfiguration");
975}
976
977namespace
978{
979/// Map strings to WifiStandard enum values
980const std::unordered_map<std::string, WifiStandard> WIFI_STANDARDS_NAME_MAP{
981 // clang-format off
982 {"802.11a", WIFI_STANDARD_80211a},
983 {"11a", WIFI_STANDARD_80211a},
984
985 {"802.11b", WIFI_STANDARD_80211b},
986 {"11b", WIFI_STANDARD_80211b},
987
988 {"802.11g", WIFI_STANDARD_80211g},
989 {"11g", WIFI_STANDARD_80211g},
990
991 {"802.11p", WIFI_STANDARD_80211p},
992 {"11p", WIFI_STANDARD_80211p},
993
994 {"802.11n", WIFI_STANDARD_80211n},
995 {"11n", WIFI_STANDARD_80211n},
996 {"HT", WIFI_STANDARD_80211n},
997
998 {"802.11ac", WIFI_STANDARD_80211ac},
999 {"11ac", WIFI_STANDARD_80211ac},
1000 {"VHT", WIFI_STANDARD_80211ac},
1001
1002 {"802.11ad", WIFI_STANDARD_80211ad},
1003 {"11ad", WIFI_STANDARD_80211ad},
1004
1005 {"802.11ax", WIFI_STANDARD_80211ax},
1006 {"11ax", WIFI_STANDARD_80211ax},
1007 {"HE", WIFI_STANDARD_80211ax},
1008
1009 {"802.11be", WIFI_STANDARD_80211be},
1010 {"11be", WIFI_STANDARD_80211be},
1011 {"EHT", WIFI_STANDARD_80211be},
1012 // clang-format on
1013};
1014} // namespace
1015
1016void
1018{
1019 m_standard = standard;
1020}
1021
1022void
1023WifiHelper::SetStandard(const std::string& standard)
1024{
1025 NS_ABORT_MSG_IF(!WIFI_STANDARDS_NAME_MAP.contains(standard),
1026 "Specified Wi-Fi standard " << standard << " is currently not supported");
1027 SetStandard(WIFI_STANDARDS_NAME_MAP.at(standard));
1028}
1029
1030void
1035
1036void
1041
1044 const WifiMacHelper& macHelper,
1046 NodeContainer::Iterator last) const
1047{
1048 NetDeviceContainer devices;
1049 for (auto i = first; i != last; ++i)
1050 {
1051 Ptr<Node> node = *i;
1053 node->AddDevice(device);
1054 device->SetStandard(m_standard);
1056 {
1057 NS_FATAL_ERROR("No standard specified!");
1058 return devices;
1059 }
1061 {
1062 auto htConfiguration = m_htConfig.Create<HtConfiguration>();
1063 device->SetHtConfiguration(htConfiguration);
1064 }
1066 {
1067 // Create the VHT Configuration object even if the PHY band is 2.4GHz
1068 // (WifiNetDevice::GetVhtConfiguration() checks the PHY band being used).
1069 // This approach allows us not to worry about deleting this object when
1070 // the PHY band is switched from 5GHz to 2.4GHz and creating this object
1071 // when the PHY band is switched from 2.4GHz to 5GHz.
1072 auto vhtConfiguration = m_vhtConfig.Create<VhtConfiguration>();
1073 device->SetVhtConfiguration(vhtConfiguration);
1074 }
1076 {
1077 auto heConfiguration = m_heConfig.Create<HeConfiguration>();
1078 device->SetHeConfiguration(heConfiguration);
1079 }
1081 {
1082 auto ehtConfiguration = m_ehtConfig.Create<EhtConfiguration>();
1083 device->SetEhtConfiguration(ehtConfiguration);
1084 }
1085 std::vector<Ptr<WifiRemoteStationManager>> managers;
1086 std::vector<Ptr<WifiPhy>> phys = phyHelper.Create(node, device);
1087 device->SetPhys(phys);
1088 // if only one remote station manager model was provided, replicate it for all the links
1089 auto stationManagers = m_stationManager;
1090 if (stationManagers.size() == 1 && phys.size() > 1)
1091 {
1092 stationManagers.resize(phys.size(), stationManagers[0]);
1093 }
1094 NS_ABORT_MSG_IF(stationManagers.size() != phys.size(),
1095 "Number of station manager models ("
1096 << stationManagers.size() << ") does not match the number of links ("
1097 << phys.size() << ")");
1098 for (std::size_t i = 0; i < phys.size(); i++)
1099 {
1100 phys[i]->ConfigureStandard(m_standard);
1101 managers.push_back(stationManagers[i].Create<WifiRemoteStationManager>());
1102 }
1103 device->SetRemoteStationManagers(managers);
1104 Ptr<WifiMac> mac = macHelper.Create(device, m_standard);
1106 {
1108 device->AggregateObject(obssPdAlgorithm);
1109 obssPdAlgorithm->ConnectWifiNetDevice(device);
1110 }
1111 devices.Add(device);
1112 NS_LOG_DEBUG("node=" << node << ", mob=" << node->GetObject<MobilityModel>());
1114 {
1116 BooleanValue qosSupported;
1118
1119 mac->GetAttributeFailSafe("QosSupported", qosSupported);
1120 if (qosSupported.Get())
1121 {
1123 UintegerValue(4));
1124 for (auto& ac : {AC_BE, AC_BK, AC_VI, AC_VO})
1125 {
1126 Ptr<QosTxop> qosTxop = mac->GetQosTxop(ac);
1127 wmq = qosTxop->GetWifiMacQueue();
1128 ndqi->GetTxQueue(static_cast<std::size_t>(ac))->ConnectQueueTraces(wmq);
1129 }
1130 ndqi->SetSelectQueueCallback(m_selectQueueCallback);
1131 }
1132 else
1133 {
1135
1136 wmq = mac->GetTxop()->GetWifiMacQueue();
1137 ndqi->GetTxQueue(0)->ConnectQueueTraces(wmq);
1138 }
1139 device->AggregateObject(ndqi);
1140 }
1141 }
1142 return devices;
1143}
1144
1147 const WifiMacHelper& macHelper,
1148 NodeContainer c) const
1149{
1150 return Install(phyHelper, macHelper, c.Begin(), c.End());
1151}
1152
1155{
1156 return Install(phy, mac, NodeContainer(node));
1157}
1158
1160WifiHelper::Install(const WifiPhyHelper& phy, const WifiMacHelper& mac, std::string nodeName) const
1161{
1162 Ptr<Node> node = Names::Find<Node>(nodeName);
1163 return Install(phy, mac, NodeContainer(node));
1164}
1165
1166void
1168{
1171
1172 LogComponentEnable("AarfWifiManager", logLevel);
1173 LogComponentEnable("AarfcdWifiManager", logLevel);
1174 LogComponentEnable("AdhocWifiMac", logLevel);
1175 LogComponentEnable("AdvancedApEmlsrManager", logLevel);
1176 LogComponentEnable("AdvancedEmlsrManager", logLevel);
1177 LogComponentEnable("AmrrWifiManager", logLevel);
1178 LogComponentEnable("ApEmlsrManager", logLevel);
1179 LogComponentEnable("ApWifiMac", logLevel);
1180 LogComponentEnable("AparfWifiManager", logLevel);
1181 LogComponentEnable("ArfWifiManager", logLevel);
1182 LogComponentEnable("BlockAckAgreement", logLevel);
1183 LogComponentEnable("BlockAckManager", logLevel);
1184 LogComponentEnable("CaraWifiManager", logLevel);
1185 LogComponentEnable("ChannelAccessManager", logLevel);
1186 LogComponentEnable("ConstantObssPdAlgorithm", logLevel);
1187 LogComponentEnable("ConstantRateWifiManager", logLevel);
1188 LogComponentEnable("DefaultApEmlsrManager", logLevel);
1189 LogComponentEnable("DefaultEmlsrManager", logLevel);
1190 LogComponentEnable("DsssErrorRateModel", logLevel);
1191 LogComponentEnable("DsssPhy", logLevel);
1192 LogComponentEnable("DsssPpdu", logLevel);
1193 LogComponentEnable("EhtFrameExchangeManager", logLevel);
1194 LogComponentEnable("EhtPhy", logLevel);
1195 LogComponentEnable("EhtPpdu", logLevel);
1196 LogComponentEnable("EmlsrManager", logLevel);
1197 LogComponentEnable("ErpOfdmPhy", logLevel);
1198 LogComponentEnable("ErpOfdmPpdu", logLevel);
1199 LogComponentEnable("FrameExchangeManager", logLevel);
1200 LogComponentEnable("HeConfiguration", logLevel);
1201 LogComponentEnable("HeFrameExchangeManager", logLevel);
1202 LogComponentEnable("HePhy", logLevel);
1203 LogComponentEnable("HePpdu", logLevel);
1204 LogComponentEnable("HtConfiguration", logLevel);
1205 LogComponentEnable("HtFrameExchangeManager", logLevel);
1206 LogComponentEnable("HtPhy", logLevel);
1207 LogComponentEnable("HtPpdu", logLevel);
1208 LogComponentEnable("IdealWifiManager", logLevel);
1209 LogComponentEnable("InterferenceHelper", logLevel);
1210 LogComponentEnable("MacRxMiddle", logLevel);
1211 LogComponentEnable("MacTxMiddle", logLevel);
1212 LogComponentEnable("MinstrelHtWifiManager", logLevel);
1213 LogComponentEnable("MinstrelWifiManager", logLevel);
1214 LogComponentEnable("MpduAggregator", logLevel);
1215 LogComponentEnable("MsduAggregator", logLevel);
1216 LogComponentEnable("MultiUserScheduler", logLevel);
1217 LogComponentEnable("NistErrorRateModel", logLevel);
1218 LogComponentEnable("ObssPdAlgorithm", logLevel);
1219 LogComponentEnable("OfdmPhy", logLevel);
1220 LogComponentEnable("OfdmPpdu", logLevel);
1221 LogComponentEnable("OnoeWifiManager", logLevel);
1222 LogComponentEnable("OriginatorBlockAckAgreement", logLevel);
1223 LogComponentEnable("ParfWifiManager", logLevel);
1224 LogComponentEnable("PhyEntity", logLevel);
1225 LogComponentEnable("QosFrameExchangeManager", logLevel);
1226 LogComponentEnable("QosTxop", logLevel);
1227 LogComponentEnable("RecipientBlockAckAgreement", logLevel);
1228 LogComponentEnable("RrMultiUserScheduler", logLevel);
1229 LogComponentEnable("RraaWifiManager", logLevel);
1230 LogComponentEnable("RrpaaWifiManager", logLevel);
1231 LogComponentEnable("SimpleFrameCaptureModel", logLevel);
1232 LogComponentEnable("SpectrumWifiPhy", logLevel);
1233 LogComponentEnable("StaWifiMac", logLevel);
1234 LogComponentEnable("SupportedRates", logLevel);
1235 LogComponentEnable("TableBasedErrorRateModel", logLevel);
1236 LogComponentEnable("ThompsonSamplingWifiManager", logLevel);
1237 LogComponentEnable("ThresholdPreambleDetectionModel", logLevel);
1238 LogComponentEnable("Txop", logLevel);
1239 LogComponentEnable("VhtConfiguration", logLevel);
1240 LogComponentEnable("VhtFrameExchangeManager", logLevel);
1241 LogComponentEnable("VhtPhy", logLevel);
1242 LogComponentEnable("VhtPpdu", logLevel);
1243 LogComponentEnable("WifiAckManager", logLevel);
1244 LogComponentEnable("WifiAssocManager", logLevel);
1245 LogComponentEnable("WifiDefaultAckManager", logLevel);
1246 LogComponentEnable("WifiDefaultAssocManager", logLevel);
1247 LogComponentEnable("WifiDefaultProtectionManager", logLevel);
1248 LogComponentEnable("WifiMac", logLevel);
1249 LogComponentEnable("WifiMacQueue", logLevel);
1250 LogComponentEnable("WifiMpdu", logLevel);
1251 LogComponentEnable("WifiNetDevice", logLevel);
1252 LogComponentEnable("WifiPhyStateHelper", logLevel);
1253 LogComponentEnable("WifiPhyOperatingChannel", logLevel);
1254 LogComponentEnable("WifiPhy", logLevel);
1255 LogComponentEnable("WifiPpdu", logLevel);
1256 LogComponentEnable("WifiProtectionManager", logLevel);
1257 LogComponentEnable("WifiPsdu", logLevel);
1258 LogComponentEnable("WifiRadioEnergyModel", logLevel);
1259 LogComponentEnable("WifiRemoteStationManager", logLevel);
1260 LogComponentEnable("WifiSpectrumPhyInterface", logLevel);
1261 LogComponentEnable("WifiSpectrumSignalParameters", logLevel);
1262 LogComponentEnable("WifiSpectrumValueHelper", logLevel);
1263 LogComponentEnable("WifiTxCurrentModel", logLevel);
1264 LogComponentEnable("WifiTxParameters", logLevel);
1265 LogComponentEnable("WifiTxTimer", logLevel);
1266 LogComponentEnable("YansErrorRateModel", logLevel);
1267 LogComponentEnable("YansWifiChannel", logLevel);
1268 LogComponentEnable("YansWifiPhy", logLevel);
1269
1270 LogComponentEnable("Athstats", logLevel);
1271 LogComponentEnable("WifiHelper", logLevel);
1272 LogComponentEnable("SpectrumWifiHelper", logLevel);
1273 LogComponentEnable("YansWifiHelper", logLevel);
1274}
1275
1276int64_t
1278{
1279 int64_t currentStream = stream;
1280 Ptr<NetDevice> netDevice;
1281 for (auto i = c.Begin(); i != c.End(); ++i)
1282 {
1283 netDevice = (*i);
1284 if (auto wifi = DynamicCast<WifiNetDevice>(netDevice))
1285 {
1286 // Handle any random numbers in the PHY objects.
1287 for (auto& phy : wifi->GetPhys())
1288 {
1289 currentStream += phy->AssignStreams(currentStream);
1290 }
1291
1292 // Handle any random numbers in the station managers.
1293 for (auto& manager : wifi->GetRemoteStationManagers())
1294 {
1295 currentStream += manager->AssignStreams(currentStream);
1296 }
1297
1298 // Handle any random numbers in the MAC objects.
1299 auto mac = wifi->GetMac();
1300 PointerValue ptr;
1301 if (!mac->GetQosSupported())
1302 {
1303 mac->GetAttribute("Txop", ptr);
1304 auto txop = ptr.Get<Txop>();
1305 currentStream += txop->AssignStreams(currentStream);
1306 }
1307 else
1308 {
1309 mac->GetAttribute("VO_Txop", ptr);
1310 auto vo_txop = ptr.Get<QosTxop>();
1311 currentStream += vo_txop->AssignStreams(currentStream);
1312
1313 mac->GetAttribute("VI_Txop", ptr);
1314 auto vi_txop = ptr.Get<QosTxop>();
1315 currentStream += vi_txop->AssignStreams(currentStream);
1316
1317 mac->GetAttribute("BE_Txop", ptr);
1318 auto be_txop = ptr.Get<QosTxop>();
1319 currentStream += be_txop->AssignStreams(currentStream);
1320
1321 mac->GetAttribute("BK_Txop", ptr);
1322 auto bk_txop = ptr.Get<QosTxop>();
1323 currentStream += bk_txop->AssignStreams(currentStream);
1324 }
1325
1326 // if an AP, handle any beacon jitter
1327 if (auto apMac = DynamicCast<ApWifiMac>(mac); apMac)
1328 {
1329 currentStream += apMac->AssignStreams(currentStream);
1330 }
1331 // if a STA, handle any probe request jitter
1332 if (auto staMac = DynamicCast<StaWifiMac>(mac); staMac)
1333 {
1334 currentStream += staMac->AssignStreams(currentStream);
1335 }
1336 }
1337 }
1338 return (currentStream - stream);
1339}
1340
1341} // 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:247
HE configuration.
std::size_t GetIndex() const
Get the RU index.
Definition he-ru.cc:454
RuType GetRuType() const
Get the RU type.
Definition he-ru.cc:447
bool GetPrimary80MHz() const
Get the primary 80 MHz flag.
Definition he-ru.cc:461
static RuType GetRuType(MHz_u bandwidth)
Get the RU corresponding to the approximate bandwidth.
Definition he-ru.cc:781
RuType
The different HE Resource Unit (RU) types.
Definition he-ru.h:32
@ RU_26_TONE
Definition he-ru.h:33
@ RU_484_TONE
Definition he-ru.h:37
@ RU_996_TONE
Definition he-ru.h:38
@ RU_106_TONE
Definition he-ru.h:35
@ RU_52_TONE
Definition he-ru.h:34
@ RU_242_TONE
Definition he-ru.h:36
@ RU_2x996_TONE
Definition he-ru.h:39
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.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
bool IsTypeIdSet() const
Check if the ObjectFactory has been configured with a TypeId.
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.
Ptr< T > Get() const
Definition pointer.h:223
Smart pointer class similar to boost::intrusive_ptr.
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 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:392
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:674
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:40
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:111
uint8_t GetMcsValue() const
Definition wifi-mode.cc:152
Hold together all Wifi-related objects.
create PHY objects
Definition wifi-helper.h:39
void SetPcapCaptureType(PcapCaptureType type)
Set the PCAP capture type to be used.
static void GetRadiotapHeader(RadiotapHeader &header, Ptr< Packet > packet, uint16_t channelFreqMhz, uint8_t p20Index, const WifiTxVector &txVector, MpduInfo aMpdu, uint16_t staId)
Get the Radiotap header for a transmitted packet.
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 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.
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.
HeRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the 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
WifiMode GetSigBMode() const
Get MCS used for SIG-B.
const std::vector< bool > & GetInactiveSubchannels() const
Get the 20 MHz subchannels that are punctured.
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:943
#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:436
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:64
@ AC_VO
Voice.
Definition qos-utils.h:70
@ AC_VI
Video.
Definition qos-utils.h:68
@ AC_BK
Background.
Definition qos-utils.h:66
@ LAST_MPDU_IN_AGGREGATE
The MPDU is the last aggregate in an A-MPDU with multiple MPDUs.
Definition wifi-types.h:53
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.
Definition first.py:1
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:291
bool IsEht(WifiPreamble preamble)
Return true if a preamble corresponds to an EHT transmission.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
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:309
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.
HeRu::RuSpec ru
RU specification.
MpduInfo structure.
Definition wifi-types.h:65
MpduType type
type of MPDU
Definition wifi-types.h:66
uint32_t mpduRefNumber
MPDU ref number.
Definition wifi-types.h:67
structure that contains the subfields of the A-MPDU status field.
uint32_t referenceNumber
A-MPDU reference number to identify all subframes belonging to the same A-MPDU.
structure that contains the subfields of the Channel field.
uint16_t frequency
Tx/Rx frequency in MHz.
structure that contains the subfields of the EHT field.
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.
uint8_t mcs
MCS index value.
structure that contains the subfields of the U-SIG field.
structure that contains the subfields of the VHT field.
uint16_t known
known flags field
SignalNoiseDbm structure.
Definition wifi-types.h:58
dBm_u noise
noise power
Definition wifi-types.h:60
dBm_u signal
signal strength
Definition wifi-types.h:59