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 ns3
38{
39
40namespace
41{
42/**
43 * Helper function to place the value to set in the correct bit(s) of a radiotap subfield.
44 *
45 * @param mask the mask of the corresponding subfield
46 * @param val the value the subfield should be set to
47 * @return the value placed at the correct position based on the mask
48 */
51{
52 const auto shift = std::countr_zero(mask);
53 return (val << shift) & mask;
54}
55
56/// 320 MHz channelization map
65} // namespace
66
67NS_LOG_COMPONENT_DEFINE("WifiHelper");
68
69/**
70 * ASCII trace PHY transmit sink with context
71 * @param stream the output stream
72 * @param context the context name
73 * @param p the packet
74 * @param mode the wifi mode
75 * @param preamble the wifi preamble
76 * @param txLevel the transmit power level
77 */
78static void
80 std::string context,
82 WifiMode mode,
83 WifiPreamble preamble,
84 uint8_t txLevel)
85{
86 NS_LOG_FUNCTION(stream << context << p << mode << preamble << txLevel);
87 auto pCopy = p->Copy();
89 pCopy->RemoveTrailer(fcs);
90 *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << context << " " << mode
91 << " " << *pCopy << " " << fcs << std::endl;
92}
93
94/**
95 * ASCII trace PHY transmit sink without context
96 * @param stream the output stream
97 * @param p the packet
98 * @param mode the wifi mode
99 * @param preamble the wifi preamble
100 * @param txLevel the transmit power level
101 */
102static void
105 WifiMode mode,
106 WifiPreamble preamble,
107 uint8_t txLevel)
108{
109 NS_LOG_FUNCTION(stream << p << mode << preamble << txLevel);
110 auto pCopy = p->Copy();
111 WifiMacTrailer fcs;
112 pCopy->RemoveTrailer(fcs);
113 *stream->GetStream() << "t " << Simulator::Now().GetSeconds() << " " << mode << " " << *pCopy
114 << " " << fcs << std::endl;
115}
116
117/**
118 * ASCII trace PHY receive sink with context
119 * @param stream the output stream
120 * @param context the context name
121 * @param p the packet
122 * @param snr the SNR
123 * @param mode the wifi mode
124 * @param preamble the wifi preamble
125 */
126static void
128 std::string context,
130 double snr,
131 WifiMode mode,
132 WifiPreamble preamble)
133{
134 NS_LOG_FUNCTION(stream << context << p << snr << mode << preamble);
135 auto pCopy = p->Copy();
136 WifiMacTrailer fcs;
137 pCopy->RemoveTrailer(fcs);
138 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << mode << " " << context
139 << " " << *pCopy << " " << fcs << std::endl;
140}
141
142/**
143 * ASCII trace PHY receive sink without context
144 * @param stream the output stream
145 * @param p the packet
146 * @param snr the SNR
147 * @param mode the wifi mode
148 * @param preamble the wifi preamble
149 */
150static void
153 double snr,
154 WifiMode mode,
155 WifiPreamble preamble)
156{
157 NS_LOG_FUNCTION(stream << p << snr << mode << preamble);
158 auto pCopy = p->Copy();
159 WifiMacTrailer fcs;
160 pCopy->RemoveTrailer(fcs);
161 *stream->GetStream() << "r " << Simulator::Now().GetSeconds() << " " << mode << " " << *pCopy
162 << " " << fcs << std::endl;
163}
164
166 : m_pcapDlt{PcapHelper::DLT_IEEE802_11},
167 m_pcapType{PcapCaptureType::PCAP_PER_PHY}
168{
169 NS_ABORT_IF(nLinks == 0);
170 m_phys.resize(nLinks);
171 m_errorRateModel.resize(nLinks);
172 m_frameCaptureModel.resize(nLinks);
173 m_preambleDetectionModel.resize(nLinks);
174
175 SetPreambleDetectionModel("ns3::ThresholdPreambleDetectionModel");
176}
177
181
182void
183WifiPhyHelper::Set(std::string name, const AttributeValue& v)
184{
185 for (auto& phy : m_phys)
186 {
187 phy.Set(name, v);
188 }
189}
190
191void
192WifiPhyHelper::Set(uint8_t linkId, std::string name, const AttributeValue& v)
193{
194 m_phys.at(linkId).Set(name, v);
195}
196
197void
203
205WifiPhyHelper::GetOrCreatePcapFile(const std::shared_ptr<PcapFilesInfo>& info, uint8_t phyId)
206{
207 uint8_t fileIdx;
208 switch (info->pcapType)
209 {
211 fileIdx = 0;
212 break;
214 fileIdx = phyId;
215 break;
217 if (const auto linkId = info->device->GetMac()->GetLinkForPhy(phyId))
218 {
219 fileIdx = *linkId;
220 break;
221 }
222 return nullptr;
223 default:
224 NS_ABORT_MSG("Unexpected PCAP capture type");
225 return nullptr;
226 }
227
228 if (!info->files.contains(fileIdx))
229 {
230 // file does not exist yet, create it
231 auto tmp = info->commonFilename;
232
233 // find the last point in the filename
234 auto pos = info->commonFilename.find_last_of('.');
235 // if not found, set pos to filename size
236 pos = (pos == std::string::npos) ? info->commonFilename.size() : pos;
237
238 // insert PHY/link ID only for multi-link devices, unless a single PCAP is generated for the
239 // device
240 if ((info->device->GetNPhys() > 1) && (info->pcapType != PcapCaptureType::PCAP_PER_DEVICE))
241 {
242 tmp.insert(pos, "-" + std::to_string(fileIdx));
243 }
244
245 PcapHelper pcapHelper;
246 auto file = pcapHelper.CreateFile(tmp, std::ios::out, info->pcapDlt);
247 info->files.emplace(fileIdx, file);
248 }
249
250 return info->files.at(fileIdx);
251}
252
253void
254WifiPhyHelper::PcapSniffTxEvent(const std::shared_ptr<PcapFilesInfo>& info,
255 uint8_t phyId,
256 Ptr<const Packet> packet,
257 uint16_t channelFreqMhz,
258 WifiTxVector txVector,
259 MpduInfo aMpdu,
260 uint16_t staId)
261{
262 auto file = GetOrCreatePcapFile(info, phyId);
263 if (!file)
264 {
265 return;
266 }
267 switch (info->pcapDlt)
268 {
270 file->Write(Simulator::Now(), packet);
271 return;
273 NS_FATAL_ERROR("PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented");
274 return;
275 }
277 Ptr<Packet> p = packet->Copy();
278 RadiotapHeader header;
279 GetRadiotapHeader(header,
280 p,
281 channelFreqMhz,
282 info->device->GetPhy(phyId)->GetPrimary20Index(),
283 txVector,
284 aMpdu,
285 staId);
286 p->AddHeader(header);
287 file->Write(Simulator::Now(), p);
288 return;
289 }
290 default:
291 NS_ABORT_MSG("PcapSniffTxEvent(): Unexpected data link type " << info->pcapDlt);
292 }
293}
294
295void
296WifiPhyHelper::PcapSniffRxEvent(const std::shared_ptr<PcapFilesInfo>& info,
297 uint8_t phyId,
298 Ptr<const Packet> packet,
299 uint16_t channelFreqMhz,
300 WifiTxVector txVector,
301 MpduInfo aMpdu,
302 SignalNoiseDbm signalNoise,
303 uint16_t staId)
304{
305 auto file = GetOrCreatePcapFile(info, phyId);
306 if (!file)
307 {
308 return;
309 }
310 switch (info->pcapDlt)
311 {
313 file->Write(Simulator::Now(), packet);
314 return;
316 NS_FATAL_ERROR("PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented");
317 return;
318 }
320 Ptr<Packet> p = packet->Copy();
321 RadiotapHeader header;
322 GetRadiotapHeader(header,
323 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
339void
341 Ptr<Packet> packet,
342 uint16_t channelFreqMhz,
343 uint8_t p20Index,
344 const WifiTxVector& txVector,
345 MpduInfo aMpdu,
346 uint16_t staId,
347 SignalNoiseDbm signalNoise)
348{
349 header.SetAntennaSignalPower(signalNoise.signal);
350 header.SetAntennaNoisePower(signalNoise.noise);
351 GetRadiotapHeader(header, packet, channelFreqMhz, p20Index, txVector, aMpdu, staId);
352}
353
354void
356 Ptr<Packet> packet,
357 uint16_t channelFreqMhz,
358 uint8_t p20Index,
359 const WifiTxVector& txVector,
360 MpduInfo aMpdu,
361 uint16_t staId)
362{
363 const auto preamble = txVector.GetPreambleType();
364 const auto modClass = txVector.GetModulationClass();
365 const auto channelWidth = txVector.GetChannelWidth();
366 const auto gi = txVector.GetGuardInterval();
367
368 header.SetTsft(Simulator::Now().GetMicroSeconds());
369
370 uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
371 // Our capture includes the FCS, so we set the flag to say so.
373 if (preamble == WIFI_PREAMBLE_SHORT)
374 {
376 }
377 if (gi.GetNanoSeconds() == 400)
378 {
380 }
381 header.SetFrameFlags(frameFlags);
382
383 uint8_t mcs = 0;
384 uint8_t nss = 1;
385 uint64_t rate = 0;
386 if (modClass < WIFI_MOD_CLASS_HT)
387 {
388 rate = txVector.GetMode(staId).GetDataRate(channelWidth, gi, 1) * nss / 500000;
389 header.SetRate(static_cast<uint8_t>(rate));
390 }
391 else
392 {
393 mcs = txVector.GetMode(staId).GetMcsValue();
394 nss = txVector.GetNss(staId);
395 }
396
397 RadiotapHeader::ChannelFields channelFields{.frequency = channelFreqMhz};
398 switch (rate)
399 {
400 case 2: // 1Mbps
401 case 4: // 2Mbps
402 case 10: // 5Mbps
403 case 22: // 11Mbps
404 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_CCK;
405 break;
406 default:
407 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
408 break;
409 }
410 if (channelFreqMhz < 2500)
411 {
412 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
413 }
414 else
415 {
416 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
417 }
418 header.SetChannelFields(channelFields);
419
420 if (modClass == WIFI_MOD_CLASS_HT)
421 {
422 RadiotapHeader::McsFields mcsFields{.mcs = mcs};
423
428
429 if (channelWidth == MHz_u{40})
430 {
432 }
433
434 if (gi.GetNanoSeconds() == 400)
435 {
437 }
438
439 const auto ness = txVector.GetNess();
440 if (ness & 0x01) // bit 1
441 {
442 mcsFields.flags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
443 }
444 if (ness & 0x02) // bit 2
445 {
446 mcsFields.flags |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
447 }
448
449 if (txVector.IsStbc())
450 {
452 }
453
454 header.SetMcsFields(mcsFields);
455 }
456
457 if (txVector.IsAggregation())
458 {
460 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
461 /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
463 uint32_t extractedLength;
464 packet->RemoveHeader(hdr);
465 extractedLength = hdr.GetLength();
466 packet = packet->CreateFragment(0, static_cast<uint32_t>(extractedLength));
467 if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof() && hdr.GetLength() > 0))
468 {
469 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST;
470 }
471 header.SetAmpduStatus(ampduStatusFields);
472 }
473
474 if (modClass == WIFI_MOD_CLASS_VHT)
475 {
476 RadiotapHeader::VhtFields vhtFields{};
477
479 if (txVector.IsStbc())
480 {
481 vhtFields.flags |= RadiotapHeader::VHT_FLAGS_STBC;
482 }
483
485 if (gi.GetNanoSeconds() == 400)
486 {
488 }
489
490 vhtFields.known |=
492 // TODO: bandwidths can be provided with sideband info
493 if (channelWidth == MHz_u{40})
494 {
495 vhtFields.bandwidth = 1;
496 }
497 else if (channelWidth == MHz_u{80})
498 {
499 vhtFields.bandwidth = 4;
500 }
501 else if (channelWidth == MHz_u{160})
502 {
503 vhtFields.bandwidth = 11;
504 }
505
506 // only SU PPDUs are currently supported
507 vhtFields.mcsNss.at(0) |= (nss & 0x0f) | ((mcs << 4) & 0xf0);
508
509 header.SetVhtFields(vhtFields);
510 }
511
512 if (modClass == WIFI_MOD_CLASS_HE)
513 {
514 RadiotapHeader::HeFields heFields{};
518 if (preamble == WIFI_PREAMBLE_HE_ER_SU)
519 {
521 }
522 else if (preamble == WIFI_PREAMBLE_HE_MU)
523 {
524 heFields.data1 |=
526 }
527 else if (preamble == WIFI_PREAMBLE_HE_TB)
528 {
529 heFields.data1 |= RadiotapHeader::HE_DATA1_FORMAT_TRIG;
530 }
531
532 heFields.data2 = RadiotapHeader::HE_DATA2_GI_KNOWN;
533 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
534 {
535 NS_ASSERT(WifiRu::IsHe(txVector.GetHeMuUserInfo(staId).ru));
536 auto heRu = std::get<HeRu::RuSpec>(txVector.GetHeMuUserInfo(staId).ru);
537 heFields.data2 |=
539 // HeRu indices start at 1 whereas RadioTap starts at 0
540 GetRadiotapField(RadiotapHeader::HE_DATA2_RU_OFFSET, heRu.GetIndex() - 1) |
541 GetRadiotapField(RadiotapHeader::HE_DATA2_PRISEC_80_SEC, !heRu.GetPrimary80MHz());
542 }
543
544 heFields.data3 =
545 GetRadiotapField(RadiotapHeader::HE_DATA3_BSS_COLOR, txVector.GetBssColor()) |
546 GetRadiotapField(RadiotapHeader::HE_DATA3_DATA_MCS, mcs);
547
548 heFields.data4 = (preamble == WIFI_PREAMBLE_HE_MU)
549 ? GetRadiotapField(RadiotapHeader::HE_DATA4_MU_STA_ID, staId)
550 : 0;
551
552 heFields.data5 = 0;
553 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
554 {
555 const auto ruType = WifiRu::GetRuType(txVector.GetHeMuUserInfo(staId).ru);
556 switch (ruType)
557 {
560 break;
563 break;
566 break;
569 break;
572 break;
575 break;
578 break;
579 default:
580 NS_ABORT_MSG("Unexpected RU type");
581 }
582 }
583 else if (channelWidth == MHz_u{40})
584 {
586 }
587 else if (channelWidth == MHz_u{80})
588 {
590 }
591 else if (channelWidth == MHz_u{160})
592 {
594 }
595 if (gi.GetNanoSeconds() == 1600)
596 {
597 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_1_6;
598 }
599 else if (gi.GetNanoSeconds() == 3200)
600 {
601 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_3_2;
602 }
603
604 header.SetHeFields(heFields);
605 }
606
607 if (preamble == WIFI_PREAMBLE_HE_MU)
608 {
609 RadiotapHeader::HeMuFields heMuFields{};
610 // TODO: fill in fields
611 header.SetHeMuFields(heMuFields);
612 RadiotapHeader::HeMuOtherUserFields heMuOtherUserFields{};
613 // TODO: fill in fields
614 header.SetHeMuOtherUserFields(heMuOtherUserFields);
615 }
616
617 if (IsEht(preamble))
618 {
619 RadiotapHeader::UsigFields usigFields{};
623 switch (static_cast<uint16_t>(channelWidth))
624 {
625 case 20:
626 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
628 break;
629 case 40:
630 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
632 break;
633 case 80:
634 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
636 break;
637 case 160:
638 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
640 break;
641 case 320:
642 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
643 channelization320MHzMap.at(channelFreqMhz));
644 break;
645 default:
646 NS_ABORT_MSG("Unexpected channel width");
647 break;
648 }
649 usigFields.common |=
650 GetRadiotapField(RadiotapHeader::USIG_COMMON_BSS_COLOR, txVector.GetBssColor());
651 if (preamble == WIFI_PREAMBLE_EHT_MU)
652 {
656 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_MU_B0_B1_PPDU_TYPE,
657 txVector.GetEhtPpduType()) |
659 txVector.GetSigBMode().GetMcsValue());
660 std::optional<bool> isLow80MHz;
661 if (txVector.IsDlMu() && channelWidth > MHz_u{80})
662 {
663 isLow80MHz = true;
664 // TODO: fix once EHT RUs are used
665 }
666 const auto puncturedChannelInfo =
668 txVector.GetEhtPpduType(),
669 isLow80MHz);
670 usigFields.value |= GetRadiotapField(RadiotapHeader::USIG2_MU_B3_B7_PUNCTURED_INFO,
671 puncturedChannelInfo);
672 }
673 else
674 {
676 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_TB_B0_B1_PPDU_TYPE,
677 txVector.GetEhtPpduType());
678 }
679 header.SetUsigFields(usigFields);
680 }
681
682 if (preamble == WIFI_PREAMBLE_EHT_MU)
683 {
684 RadiotapHeader::EhtFields ehtFields{};
687 switch (gi.GetNanoSeconds())
688 {
689 case 800:
690 ehtFields.data.at(0) =
692 break;
693 case 1600:
694 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
696 break;
697 case 3200:
698 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
700 break;
701 default:
702 NS_ABORT_MSG("Unexpected guard interval");
703 break;
704 }
706 const auto ruType = (txVector.GetEhtPpduType() == 1)
707 ? WifiRu::GetRuType(channelWidth)
708 : WifiRu::GetRuType(txVector.GetRu(staId));
709 switch (ruType)
710 {
712 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
714 break;
716 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
718 break;
720 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
722 break;
724 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
726 break;
728 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
730 break;
732 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
734 break;
736 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
738 break;
740 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
742 break;
743 default:
744 NS_ABORT_MSG("Unexpected RU type");
745 break;
746 }
747 const auto ruIndex =
748 (txVector.GetEhtPpduType() == 1) ? 1 : WifiRu::GetIndex(txVector.GetRu(staId));
749 const auto& ruAllocation = txVector.GetRuAllocation(p20Index);
750 ehtFields.data.at(1) |=
751 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_INDEX, ruIndex) |
752 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_ALLOC_CC_1_1_1, ruAllocation.at(0));
753 if (channelWidth >= MHz_u{40})
754 {
755 ehtFields.data.at(2) =
757 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_1, ruAllocation.at(1));
758 }
759 if (channelWidth >= MHz_u{80})
760 {
761 ehtFields.data.at(2) |=
764 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_1_1_2, ruAllocation.at(2)) |
765 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_2, ruAllocation.at(3));
766 }
767 if (channelWidth >= MHz_u{160})
768 {
769 ehtFields.data.at(3) =
773 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_1, ruAllocation.at(4)) |
774 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_2_2_1, ruAllocation.at(5)) |
775 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_2, ruAllocation.at(6));
776 ehtFields.data.at(4) =
778 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_2, ruAllocation.at(7));
779 ehtFields.known |= RadiotapHeader::EHT_KNOWN_PRIMARY_80;
780 const auto isLowP80 = p20Index < (channelWidth / MHz_u{40});
781 ehtFields.data.at(1) |=
785 }
786 if (channelWidth >= MHz_u{320})
787 {
788 ehtFields.data.at(4) |=
791 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_1_2_3, ruAllocation.at(8)) |
792 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_3, ruAllocation.at(9));
793 ehtFields.data.at(5) =
797 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_1_2_4, ruAllocation.at(10)) |
798 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_2_2_4, ruAllocation.at(11)) |
799 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_1_2_5, ruAllocation.at(12));
800 ehtFields.data.at(6) =
804 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_2_2_5, ruAllocation.at(13)) |
805 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_1_2_6, ruAllocation.at(14)) |
806 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_2_2_6, ruAllocation.at(15));
807 }
812 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_STA_ID, staId) |
813 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_MCS, mcs) |
814 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_NSS_O, nss);
815 ehtFields.userInfo.push_back(userInfo);
816 header.SetEhtFields(ehtFields);
817 }
818}
819
820void
822{
823 switch (dlt)
824 {
825 case DLT_IEEE802_11:
827 return;
828 case DLT_PRISM_HEADER:
830 return;
833 return;
834 default:
835 NS_ABORT_MSG("WifiPhyHelper::SetPcapFormat(): Unexpected format");
836 }
837}
838
841{
842 return m_pcapDlt;
843}
844
845void
850
853{
854 return m_pcapType;
855}
856
857void
860 bool promiscuous,
861 bool explicitFilename)
862{
863 NS_LOG_FUNCTION(this << prefix << nd << promiscuous << explicitFilename);
864
865 // All of the Pcap enable functions vector through here including the ones
866 // that are wandering through all of devices on perhaps all of the nodes in
867 // the system. We can only deal with devices of type WifiNetDevice.
868 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
869 if (!device)
870 {
871 NS_LOG_INFO("WifiHelper::EnablePcapInternal(): Device "
872 << &device << " not of type ns3::WifiNetDevice");
873 return;
874 }
875
876 NS_ABORT_MSG_IF(device->GetPhys().empty(),
877 "WifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
878
879 PcapHelper pcapHelper;
880 std::string filename;
881 if (explicitFilename)
882 {
883 filename = prefix;
884 }
885 else
886 {
887 filename = pcapHelper.GetFilenameFromDevice(prefix, device);
888 }
889
890 auto info = std::make_shared<PcapFilesInfo>(filename, m_pcapDlt, m_pcapType, device);
891 for (auto& phy : device->GetPhys())
892 {
893 phy->TraceConnectWithoutContext(
894 "MonitorSnifferTx",
895 MakeBoundCallback(&WifiPhyHelper::PcapSniffTxEvent, info, phy->GetPhyId()));
896 phy->TraceConnectWithoutContext(
897 "MonitorSnifferRx",
898 MakeBoundCallback(&WifiPhyHelper::PcapSniffRxEvent, info, phy->GetPhyId()));
899 }
900}
901
902void
904 std::string prefix,
906 bool explicitFilename)
907{
908 // All of the ASCII enable functions vector through here including the ones
909 // that are wandering through all of devices on perhaps all of the nodes in
910 // the system. We can only deal with devices of type WifiNetDevice.
911 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
912 if (!device)
913 {
914 NS_LOG_INFO("WifiHelper::EnableAsciiInternal(): Device "
915 << device << " not of type ns3::WifiNetDevice");
916 return;
917 }
918
919 // Our trace sinks are going to use packet printing, so we have to make sure
920 // that is turned on.
922
923 uint32_t nodeid = nd->GetNode()->GetId();
924 uint32_t deviceid = nd->GetIfIndex();
925 std::ostringstream oss;
926
927 // If we are not provided an OutputStreamWrapper, we are expected to create
928 // one using the usual trace filename conventions and write our traces
929 // without a context since there will be one file per context and therefore
930 // the context would be redundant.
931 if (!stream)
932 {
933 // Set up an output stream object to deal with private ofstream copy
934 // constructor and lifetime issues. Let the helper decide the actual
935 // name of the file given the prefix.
936 AsciiTraceHelper asciiTraceHelper;
937
938 std::string filename;
939 if (explicitFilename)
940 {
941 filename = prefix;
942 }
943 else
944 {
945 filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device);
946 }
947
948 // find the last point in the filename
949 auto pos = filename.find_last_of('.');
950 // if not found, set pos to filename size
951 pos = (pos == std::string::npos) ? filename.size() : pos;
952
953 for (uint8_t linkId = 0; linkId < device->GetNPhys(); linkId++)
954 {
955 std::string tmp = filename;
956 if (device->GetNPhys() > 1)
957 {
958 // insert LinkId only for multi-link devices
959 tmp.insert(pos, "-" + std::to_string(linkId));
960 }
961 auto theStream = asciiTraceHelper.CreateFileStream(tmp);
962 // We could go poking through the PHY and the state looking for the
963 // correct trace source, but we can let Config deal with that with
964 // some search cost. Since this is presumably happening at topology
965 // creation time, it doesn't seem much of a price to pay.
966 oss.str("");
967 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
968 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/RxOk";
970 oss.str(),
972
973 oss.str("");
974 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
975 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/Tx";
977 oss.str(),
979 }
980
981 return;
982 }
983
984 // If we are provided an OutputStreamWrapper, we are expected to use it, and
985 // to provide a context. We are free to come up with our own context if we
986 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
987 // compatibility and simplicity, we just use Config::Connect and let it deal
988 // with coming up with a context.
989 oss.str("");
990 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
991 << "/$ns3::WifiNetDevice/Phy/State/RxOk";
993
994 oss.str("");
995 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
996 << "/$ns3::WifiNetDevice/Phy/State/Tx";
998}
999
1003
1005 : m_standard(WIFI_STANDARD_80211ax),
1006 m_selectQueueCallback(&SelectQueueByDSField),
1007 m_enableFlowControl(true)
1008{
1009 SetRemoteStationManager("ns3::IdealWifiManager");
1010 m_htConfig.SetTypeId("ns3::HtConfiguration");
1011 m_vhtConfig.SetTypeId("ns3::VhtConfiguration");
1012 m_heConfig.SetTypeId("ns3::HeConfiguration");
1013 m_ehtConfig.SetTypeId("ns3::EhtConfiguration");
1014}
1015
1016namespace
1017{
1018/// Map strings to WifiStandard enum values
1019const std::unordered_map<std::string, WifiStandard> WIFI_STANDARDS_NAME_MAP{
1020 // clang-format off
1021 {"802.11a", WIFI_STANDARD_80211a},
1022 {"11a", WIFI_STANDARD_80211a},
1023
1024 {"802.11b", WIFI_STANDARD_80211b},
1025 {"11b", WIFI_STANDARD_80211b},
1026
1027 {"802.11g", WIFI_STANDARD_80211g},
1028 {"11g", WIFI_STANDARD_80211g},
1029
1030 {"802.11p", WIFI_STANDARD_80211p},
1031 {"11p", WIFI_STANDARD_80211p},
1032
1033 {"802.11n", WIFI_STANDARD_80211n},
1034 {"11n", WIFI_STANDARD_80211n},
1035 {"HT", WIFI_STANDARD_80211n},
1036
1037 {"802.11ac", WIFI_STANDARD_80211ac},
1038 {"11ac", WIFI_STANDARD_80211ac},
1039 {"VHT", WIFI_STANDARD_80211ac},
1040
1041 {"802.11ad", WIFI_STANDARD_80211ad},
1042 {"11ad", WIFI_STANDARD_80211ad},
1043
1044 {"802.11ax", WIFI_STANDARD_80211ax},
1045 {"11ax", WIFI_STANDARD_80211ax},
1046 {"HE", WIFI_STANDARD_80211ax},
1047
1048 {"802.11be", WIFI_STANDARD_80211be},
1049 {"11be", WIFI_STANDARD_80211be},
1050 {"EHT", WIFI_STANDARD_80211be},
1051 // clang-format on
1052};
1053} // namespace
1054
1055void
1057{
1058 m_standard = standard;
1059}
1060
1061void
1062WifiHelper::SetStandard(const std::string& standard)
1063{
1064 NS_ABORT_MSG_IF(!WIFI_STANDARDS_NAME_MAP.contains(standard),
1065 "Specified Wi-Fi standard " << standard << " is currently not supported");
1066 SetStandard(WIFI_STANDARDS_NAME_MAP.at(standard));
1067}
1068
1069void
1074
1075void
1080
1083 const WifiMacHelper& macHelper,
1085 NodeContainer::Iterator last) const
1086{
1087 NetDeviceContainer devices;
1088 for (auto i = first; i != last; ++i)
1089 {
1090 Ptr<Node> node = *i;
1092 node->AddDevice(device);
1093 device->SetStandard(m_standard);
1095 {
1096 NS_FATAL_ERROR("No standard specified!");
1097 return devices;
1098 }
1100 {
1101 auto htConfiguration = m_htConfig.Create<HtConfiguration>();
1102 device->SetHtConfiguration(htConfiguration);
1103 }
1105 {
1106 // Create the VHT Configuration object even if the PHY band is 2.4GHz
1107 // (WifiNetDevice::GetVhtConfiguration() checks the PHY band being used).
1108 // This approach allows us not to worry about deleting this object when
1109 // the PHY band is switched from 5GHz to 2.4GHz and creating this object
1110 // when the PHY band is switched from 2.4GHz to 5GHz.
1111 auto vhtConfiguration = m_vhtConfig.Create<VhtConfiguration>();
1112 device->SetVhtConfiguration(vhtConfiguration);
1113 }
1115 {
1116 auto heConfiguration = m_heConfig.Create<HeConfiguration>();
1117 device->SetHeConfiguration(heConfiguration);
1118 }
1120 {
1121 auto ehtConfiguration = m_ehtConfig.Create<EhtConfiguration>();
1122 device->SetEhtConfiguration(ehtConfiguration);
1123 }
1124 std::vector<Ptr<WifiRemoteStationManager>> managers;
1125 std::vector<Ptr<WifiPhy>> phys = phyHelper.Create(node, device);
1126 device->SetPhys(phys);
1127 // if only one remote station manager model was provided, replicate it for all the links
1128 auto stationManagers = m_stationManager;
1129 if (stationManagers.size() == 1 && phys.size() > 1)
1130 {
1131 stationManagers.resize(phys.size(), stationManagers[0]);
1132 }
1133 NS_ABORT_MSG_IF(stationManagers.size() != phys.size(),
1134 "Number of station manager models ("
1135 << stationManagers.size() << ") does not match the number of links ("
1136 << phys.size() << ")");
1137 for (std::size_t i = 0; i < phys.size(); i++)
1138 {
1139 phys[i]->ConfigureStandard(m_standard);
1140 managers.push_back(stationManagers[i].Create<WifiRemoteStationManager>());
1141 }
1142 device->SetRemoteStationManagers(managers);
1143 Ptr<WifiMac> mac = macHelper.Create(device, m_standard);
1145 {
1147 device->AggregateObject(obssPdAlgorithm);
1148 obssPdAlgorithm->ConnectWifiNetDevice(device);
1149 }
1150 devices.Add(device);
1151 NS_LOG_DEBUG("node=" << node << ", mob=" << node->GetObject<MobilityModel>());
1153 {
1155 BooleanValue qosSupported;
1157
1158 mac->GetAttributeFailSafe("QosSupported", qosSupported);
1159 if (qosSupported.Get())
1160 {
1162 UintegerValue(4));
1163 for (auto& ac : {AC_BE, AC_BK, AC_VI, AC_VO})
1164 {
1165 Ptr<QosTxop> qosTxop = mac->GetQosTxop(ac);
1166 wmq = qosTxop->GetWifiMacQueue();
1167 ndqi->GetTxQueue(static_cast<std::size_t>(ac))->ConnectQueueTraces(wmq);
1168 }
1169 ndqi->SetSelectQueueCallback(m_selectQueueCallback);
1170 }
1171 else
1172 {
1174
1175 wmq = mac->GetTxop()->GetWifiMacQueue();
1176 ndqi->GetTxQueue(0)->ConnectQueueTraces(wmq);
1177 }
1178 device->AggregateObject(ndqi);
1179 }
1180 }
1181 return devices;
1182}
1183
1186 const WifiMacHelper& macHelper,
1187 NodeContainer c) const
1188{
1189 return Install(phyHelper, macHelper, c.Begin(), c.End());
1190}
1191
1194{
1195 return Install(phy, mac, NodeContainer(node));
1196}
1197
1199WifiHelper::Install(const WifiPhyHelper& phy, const WifiMacHelper& mac, std::string nodeName) const
1200{
1201 Ptr<Node> node = Names::Find<Node>(nodeName);
1202 return Install(phy, mac, NodeContainer(node));
1203}
1204
1205void
1207{
1210
1211 LogComponentEnable("AarfWifiManager", logLevel);
1212 LogComponentEnable("AarfcdWifiManager", logLevel);
1213 LogComponentEnable("AdhocWifiMac", logLevel);
1214 LogComponentEnable("AdvancedApEmlsrManager", logLevel);
1215 LogComponentEnable("AdvancedEmlsrManager", logLevel);
1216 LogComponentEnable("AmrrWifiManager", logLevel);
1217 LogComponentEnable("ApEmlsrManager", logLevel);
1218 LogComponentEnable("ApWifiMac", logLevel);
1219 LogComponentEnable("AparfWifiManager", logLevel);
1220 LogComponentEnable("ArfWifiManager", logLevel);
1221 LogComponentEnable("BlockAckAgreement", logLevel);
1222 LogComponentEnable("BlockAckManager", logLevel);
1223 LogComponentEnable("CaraWifiManager", logLevel);
1224 LogComponentEnable("ChannelAccessManager", logLevel);
1225 LogComponentEnable("ConstantObssPdAlgorithm", logLevel);
1226 LogComponentEnable("ConstantRateWifiManager", logLevel);
1227 LogComponentEnable("DefaultApEmlsrManager", logLevel);
1228 LogComponentEnable("DefaultEmlsrManager", logLevel);
1229 LogComponentEnable("DsssErrorRateModel", logLevel);
1230 LogComponentEnable("DsssPhy", logLevel);
1231 LogComponentEnable("DsssPpdu", logLevel);
1232 LogComponentEnable("EhtFrameExchangeManager", logLevel);
1233 LogComponentEnable("EhtPhy", logLevel);
1234 LogComponentEnable("EhtPpdu", logLevel);
1235 LogComponentEnable("EmlsrManager", logLevel);
1236 LogComponentEnable("ErpOfdmPhy", logLevel);
1237 LogComponentEnable("ErpOfdmPpdu", logLevel);
1238 LogComponentEnable("FrameExchangeManager", logLevel);
1239 LogComponentEnable("GcrManager", logLevel);
1240 LogComponentEnable("HeConfiguration", logLevel);
1241 LogComponentEnable("HeFrameExchangeManager", logLevel);
1242 LogComponentEnable("HePhy", logLevel);
1243 LogComponentEnable("HePpdu", logLevel);
1244 LogComponentEnable("HtConfiguration", logLevel);
1245 LogComponentEnable("HtFrameExchangeManager", logLevel);
1246 LogComponentEnable("HtPhy", logLevel);
1247 LogComponentEnable("HtPpdu", logLevel);
1248 LogComponentEnable("IdealWifiManager", logLevel);
1249 LogComponentEnable("InterferenceHelper", logLevel);
1250 LogComponentEnable("MacRxMiddle", logLevel);
1251 LogComponentEnable("MacTxMiddle", logLevel);
1252 LogComponentEnable("MinstrelHtWifiManager", logLevel);
1253 LogComponentEnable("MinstrelWifiManager", logLevel);
1254 LogComponentEnable("MpduAggregator", logLevel);
1255 LogComponentEnable("MsduAggregator", logLevel);
1256 LogComponentEnable("MultiUserScheduler", logLevel);
1257 LogComponentEnable("NistErrorRateModel", logLevel);
1258 LogComponentEnable("ObssPdAlgorithm", logLevel);
1259 LogComponentEnable("OfdmPhy", logLevel);
1260 LogComponentEnable("OfdmPpdu", logLevel);
1261 LogComponentEnable("OnoeWifiManager", logLevel);
1262 LogComponentEnable("OriginatorBlockAckAgreement", logLevel);
1263 LogComponentEnable("ParfWifiManager", logLevel);
1264 LogComponentEnable("PhyEntity", logLevel);
1265 LogComponentEnable("QosFrameExchangeManager", logLevel);
1266 LogComponentEnable("QosTxop", logLevel);
1267 LogComponentEnable("RecipientBlockAckAgreement", logLevel);
1268 LogComponentEnable("RrMultiUserScheduler", logLevel);
1269 LogComponentEnable("RraaWifiManager", logLevel);
1270 LogComponentEnable("RrpaaWifiManager", logLevel);
1271 LogComponentEnable("SimpleFrameCaptureModel", logLevel);
1272 LogComponentEnable("SpectrumWifiPhy", logLevel);
1273 LogComponentEnable("StaWifiMac", logLevel);
1274 LogComponentEnable("SupportedRates", logLevel);
1275 LogComponentEnable("TableBasedErrorRateModel", logLevel);
1276 LogComponentEnable("ThompsonSamplingWifiManager", logLevel);
1277 LogComponentEnable("ThresholdPreambleDetectionModel", logLevel);
1278 LogComponentEnable("Txop", logLevel);
1279 LogComponentEnable("VhtConfiguration", logLevel);
1280 LogComponentEnable("VhtFrameExchangeManager", logLevel);
1281 LogComponentEnable("VhtPhy", logLevel);
1282 LogComponentEnable("VhtPpdu", logLevel);
1283 LogComponentEnable("WifiAckManager", logLevel);
1284 LogComponentEnable("WifiAssocManager", logLevel);
1285 LogComponentEnable("WifiDefaultAckManager", logLevel);
1286 LogComponentEnable("WifiDefaultAssocManager", logLevel);
1287 LogComponentEnable("WifiDefaultGcrManager", logLevel);
1288 LogComponentEnable("WifiDefaultProtectionManager", logLevel);
1289 LogComponentEnable("WifiMac", logLevel);
1290 LogComponentEnable("WifiMacQueue", logLevel);
1291 LogComponentEnable("WifiMpdu", logLevel);
1292 LogComponentEnable("WifiNetDevice", logLevel);
1293 LogComponentEnable("WifiPhyStateHelper", logLevel);
1294 LogComponentEnable("WifiPhyOperatingChannel", logLevel);
1295 LogComponentEnable("WifiPhy", logLevel);
1296 LogComponentEnable("WifiPpdu", logLevel);
1297 LogComponentEnable("WifiProtectionManager", logLevel);
1298 LogComponentEnable("WifiPsdu", logLevel);
1299 LogComponentEnable("WifiRadioEnergyModel", logLevel);
1300 LogComponentEnable("WifiRemoteStationManager", logLevel);
1301 LogComponentEnable("WifiSpectrumPhyInterface", logLevel);
1302 LogComponentEnable("WifiSpectrumSignalParameters", logLevel);
1303 LogComponentEnable("WifiSpectrumValueHelper", logLevel);
1304 LogComponentEnable("WifiTxCurrentModel", logLevel);
1305 LogComponentEnable("WifiTxParameters", logLevel);
1306 LogComponentEnable("WifiTxTimer", logLevel);
1307 LogComponentEnable("YansErrorRateModel", logLevel);
1308 LogComponentEnable("YansWifiChannel", logLevel);
1309 LogComponentEnable("YansWifiPhy", logLevel);
1310
1311 LogComponentEnable("Athstats", logLevel);
1312 LogComponentEnable("WifiHelper", logLevel);
1313 LogComponentEnable("SpectrumWifiHelper", logLevel);
1314 LogComponentEnable("YansWifiHelper", logLevel);
1315}
1316
1317int64_t
1319{
1320 int64_t currentStream = stream;
1321 Ptr<NetDevice> netDevice;
1322 for (auto i = c.Begin(); i != c.End(); ++i)
1323 {
1324 netDevice = (*i);
1325 if (auto wifi = DynamicCast<WifiNetDevice>(netDevice))
1326 {
1327 // Handle any random numbers in the PHY objects.
1328 for (auto& phy : wifi->GetPhys())
1329 {
1330 currentStream += phy->AssignStreams(currentStream);
1331 }
1332
1333 // Handle any random numbers in the station managers.
1334 for (auto& manager : wifi->GetRemoteStationManagers())
1335 {
1336 currentStream += manager->AssignStreams(currentStream);
1337 }
1338
1339 // Handle any random numbers in the MAC objects.
1340 auto mac = wifi->GetMac();
1341 PointerValue ptr;
1342 if (!mac->GetQosSupported())
1343 {
1344 mac->GetAttribute("Txop", ptr);
1345 auto txop = ptr.Get<Txop>();
1346 currentStream += txop->AssignStreams(currentStream);
1347 }
1348 else
1349 {
1350 mac->GetAttribute("VO_Txop", ptr);
1351 auto vo_txop = ptr.Get<QosTxop>();
1352 currentStream += vo_txop->AssignStreams(currentStream);
1353
1354 mac->GetAttribute("VI_Txop", ptr);
1355 auto vi_txop = ptr.Get<QosTxop>();
1356 currentStream += vi_txop->AssignStreams(currentStream);
1357
1358 mac->GetAttribute("BE_Txop", ptr);
1359 auto be_txop = ptr.Get<QosTxop>();
1360 currentStream += be_txop->AssignStreams(currentStream);
1361
1362 mac->GetAttribute("BK_Txop", ptr);
1363 auto bk_txop = ptr.Get<QosTxop>();
1364 currentStream += bk_txop->AssignStreams(currentStream);
1365 }
1366
1367 // if an AP, handle any beacon jitter
1368 if (auto apMac = DynamicCast<ApWifiMac>(mac); apMac)
1369 {
1370 currentStream += apMac->AssignStreams(currentStream);
1371 }
1372 // if a STA, handle any probe request jitter
1373 if (auto staMac = DynamicCast<StaWifiMac>(mac); staMac)
1374 {
1375 currentStream += staMac->AssignStreams(currentStream);
1376 }
1377 }
1378 }
1379 return (currentStream - stream);
1380}
1381
1382} // 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.
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: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: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.
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: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: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: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.
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.
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:65
dBm_u noise
noise power
Definition wifi-types.h:67
dBm_u signal
signal strength
Definition wifi-types.h:66