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 const auto header = GetRadiotapHeader(p,
279 channelFreqMhz,
280 info->device->GetPhy(phyId)->GetPrimary20Index(),
281 txVector,
282 aMpdu,
283 staId);
284 p->AddHeader(header);
285 file->Write(Simulator::Now(), p);
286 return;
287 }
288 default:
289 NS_ABORT_MSG("PcapSniffTxEvent(): Unexpected data link type " << info->pcapDlt);
290 }
291}
292
293void
294WifiPhyHelper::PcapSniffRxEvent(const std::shared_ptr<PcapFilesInfo>& info,
295 uint8_t phyId,
296 Ptr<const Packet> packet,
297 uint16_t channelFreqMhz,
298 WifiTxVector txVector,
299 MpduInfo aMpdu,
300 SignalNoiseDbm signalNoise,
301 uint16_t staId)
302{
303 auto file = GetOrCreatePcapFile(info, phyId);
304 if (!file)
305 {
306 return;
307 }
308 switch (info->pcapDlt)
309 {
311 file->Write(Simulator::Now(), packet);
312 return;
314 NS_FATAL_ERROR("PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented");
315 return;
316 }
318 Ptr<Packet> p = packet->Copy();
319 const auto header = GetRadiotapHeader(p,
320 channelFreqMhz,
321 info->device->GetPhy(phyId)->GetPrimary20Index(),
322 txVector,
323 aMpdu,
324 staId,
325 signalNoise);
326 p->AddHeader(header);
327 file->Write(Simulator::Now(), p);
328 return;
329 }
330 default:
331 NS_ABORT_MSG("PcapSniffRxEvent(): Unexpected data link type " << info->pcapDlt);
332 }
333}
334
337 uint16_t channelFreqMhz,
338 uint8_t p20Index,
339 const WifiTxVector& txVector,
340 MpduInfo aMpdu,
341 uint16_t staId,
342 std::optional<SignalNoiseDbm> signalNoise)
343{
344 RadiotapHeader header;
345
346 const auto preamble = txVector.GetPreambleType();
347 const auto modClass = txVector.GetModulationClass();
348 const auto channelWidth = txVector.GetChannelWidth();
349 const auto gi = txVector.GetGuardInterval();
350
351 header.SetWifiHeader(IsEht(preamble) ? 2 : 1);
352
353 if (signalNoise)
354 {
355 header.SetAntennaSignalPower(signalNoise->signal);
356 header.SetAntennaNoisePower(signalNoise->noise);
357 }
358
360
361 uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
362 // Our capture includes the FCS, so we set the flag to say so.
364 if (preamble == WIFI_PREAMBLE_SHORT)
365 {
367 }
368 if (gi.GetNanoSeconds() == 400)
369 {
371 }
372 header.SetFrameFlags(frameFlags);
373
374 uint8_t mcs = 0;
375 uint8_t nss = 1;
376 uint64_t rate = 0;
377 if (modClass < WIFI_MOD_CLASS_HT)
378 {
379 rate = txVector.GetMode(staId).GetDataRate(channelWidth, gi, 1) * nss / 500000;
380 header.SetRate(static_cast<uint8_t>(rate));
381 }
382 else
383 {
384 mcs = txVector.GetMode(staId).GetMcsValue();
385 nss = txVector.GetNss(staId);
386 }
387
388 RadiotapHeader::ChannelFields channelFields{.frequency = channelFreqMhz};
389 switch (rate)
390 {
391 case 2: // 1Mbps
392 case 4: // 2Mbps
393 case 10: // 5Mbps
394 case 22: // 11Mbps
395 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_CCK;
396 break;
397 default:
398 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_OFDM;
399 break;
400 }
401 if (channelFreqMhz < 2500)
402 {
403 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ;
404 }
405 else
406 {
407 channelFields.flags |= RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ;
408 }
409 header.SetChannelFields(channelFields);
410
411 if (modClass == WIFI_MOD_CLASS_HT)
412 {
413 RadiotapHeader::McsFields mcsFields{.mcs = mcs};
414
419
420 if (channelWidth == MHz_u{40})
421 {
423 }
424
425 if (gi.GetNanoSeconds() == 400)
426 {
428 }
429
430 const auto ness = txVector.GetNess();
431 if (ness & 0x01) // bit 1
432 {
433 mcsFields.flags |= RadiotapHeader::MCS_FLAGS_NESS_BIT_0;
434 }
435 if (ness & 0x02) // bit 2
436 {
437 mcsFields.flags |= RadiotapHeader::MCS_KNOWN_NESS_BIT_1;
438 }
439
440 if (txVector.IsStbc())
441 {
443 }
444
445 header.SetMcsFields(mcsFields);
446 }
447
448 if (txVector.IsAggregation())
449 {
451 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST_KNOWN;
452 /* For PCAP file, MPDU Delimiter and Padding should be removed by the MAC Driver */
454 uint32_t extractedLength;
455 packet->RemoveHeader(hdr);
456 extractedLength = hdr.GetLength();
457 packet = packet->CreateFragment(0, static_cast<uint32_t>(extractedLength));
458 if (aMpdu.type == LAST_MPDU_IN_AGGREGATE || (hdr.GetEof() && hdr.GetLength() > 0))
459 {
460 ampduStatusFields.flags |= RadiotapHeader::A_MPDU_STATUS_LAST;
461 }
462 header.SetAmpduStatus(ampduStatusFields);
463 }
464
465 if (modClass == WIFI_MOD_CLASS_VHT)
466 {
467 RadiotapHeader::VhtFields vhtFields{};
468
470 if (txVector.IsStbc())
471 {
472 vhtFields.flags |= RadiotapHeader::VHT_FLAGS_STBC;
473 }
474
476 if (gi.GetNanoSeconds() == 400)
477 {
479 }
480
481 vhtFields.known |=
483 // TODO: bandwidths can be provided with sideband info
484 if (channelWidth == MHz_u{40})
485 {
486 vhtFields.bandwidth = 1;
487 }
488 else if (channelWidth == MHz_u{80})
489 {
490 vhtFields.bandwidth = 4;
491 }
492 else if (channelWidth == MHz_u{160})
493 {
494 vhtFields.bandwidth = 11;
495 }
496
497 // only SU PPDUs are currently supported
498 vhtFields.mcsNss.at(0) |= (nss & 0x0f) | ((mcs << 4) & 0xf0);
499
500 header.SetVhtFields(vhtFields);
501 }
502
503 if (modClass == WIFI_MOD_CLASS_HE)
504 {
505 RadiotapHeader::HeFields heFields{};
509 if (preamble == WIFI_PREAMBLE_HE_ER_SU)
510 {
512 }
513 else if (preamble == WIFI_PREAMBLE_HE_MU)
514 {
515 heFields.data1 |=
517 }
518 else if (preamble == WIFI_PREAMBLE_HE_TB)
519 {
520 heFields.data1 |= RadiotapHeader::HE_DATA1_FORMAT_TRIG;
521 }
522
523 heFields.data2 = RadiotapHeader::HE_DATA2_GI_KNOWN;
524 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
525 {
526 NS_ASSERT(WifiRu::IsHe(txVector.GetHeMuUserInfo(staId).ru));
527 auto heRu = std::get<HeRu::RuSpec>(txVector.GetHeMuUserInfo(staId).ru);
528 heFields.data2 |=
530 // HeRu indices start at 1 whereas RadioTap starts at 0
531 GetRadiotapField(RadiotapHeader::HE_DATA2_RU_OFFSET, heRu.GetIndex() - 1) |
532 GetRadiotapField(RadiotapHeader::HE_DATA2_PRISEC_80_SEC, !heRu.GetPrimary80MHz());
533 }
534
535 heFields.data3 =
536 GetRadiotapField(RadiotapHeader::HE_DATA3_BSS_COLOR, txVector.GetBssColor()) |
537 GetRadiotapField(RadiotapHeader::HE_DATA3_DATA_MCS, mcs);
538
539 heFields.data4 = (preamble == WIFI_PREAMBLE_HE_MU)
540 ? GetRadiotapField(RadiotapHeader::HE_DATA4_MU_STA_ID, staId)
541 : 0;
542
543 heFields.data5 = 0;
544 if (preamble == WIFI_PREAMBLE_HE_MU || preamble == WIFI_PREAMBLE_HE_TB)
545 {
546 const auto ruType = WifiRu::GetRuType(txVector.GetHeMuUserInfo(staId).ru);
547 switch (ruType)
548 {
551 break;
554 break;
557 break;
560 break;
563 break;
566 break;
569 break;
570 default:
571 NS_ABORT_MSG("Unexpected RU type");
572 }
573 }
574 else if (channelWidth == MHz_u{40})
575 {
577 }
578 else if (channelWidth == MHz_u{80})
579 {
581 }
582 else if (channelWidth == MHz_u{160})
583 {
585 }
586 if (gi.GetNanoSeconds() == 1600)
587 {
588 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_1_6;
589 }
590 else if (gi.GetNanoSeconds() == 3200)
591 {
592 heFields.data5 |= RadiotapHeader::HE_DATA5_GI_3_2;
593 }
594
595 header.SetHeFields(heFields);
596 }
597
598 if (preamble == WIFI_PREAMBLE_HE_MU)
599 {
600 RadiotapHeader::HeMuFields heMuFields{};
601 // TODO: fill in fields
602 header.SetHeMuFields(heMuFields);
603 RadiotapHeader::HeMuOtherUserFields heMuOtherUserFields{};
604 // TODO: fill in fields
605 header.SetHeMuOtherUserFields(heMuOtherUserFields);
606 }
607
608 if (IsEht(preamble))
609 {
610 RadiotapHeader::UsigFields usigFields{};
614 switch (static_cast<uint16_t>(channelWidth))
615 {
616 case 20:
617 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
619 break;
620 case 40:
621 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
623 break;
624 case 80:
625 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
627 break;
628 case 160:
629 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
631 break;
632 case 320:
633 usigFields.common |= GetRadiotapField(RadiotapHeader::USIG_COMMON_BW,
634 channelization320MHzMap.at(channelFreqMhz));
635 break;
636 default:
637 NS_ABORT_MSG("Unexpected channel width");
638 break;
639 }
640 usigFields.common |=
641 GetRadiotapField(RadiotapHeader::USIG_COMMON_BSS_COLOR, txVector.GetBssColor());
642 if (preamble == WIFI_PREAMBLE_EHT_MU)
643 {
647 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_MU_B0_B1_PPDU_TYPE,
648 txVector.GetEhtPpduType()) |
650 txVector.GetSigBMode().GetMcsValue());
651 std::optional<bool> isLow80MHz;
652 if (txVector.IsDlMu() && channelWidth > MHz_u{80})
653 {
654 isLow80MHz = true;
655 // TODO: fix once EHT RUs are used
656 }
657 const auto puncturedChannelInfo =
659 txVector.GetEhtPpduType(),
660 isLow80MHz);
661 usigFields.value |= GetRadiotapField(RadiotapHeader::USIG2_MU_B3_B7_PUNCTURED_INFO,
662 puncturedChannelInfo);
663 }
664 else
665 {
667 usigFields.value = GetRadiotapField(RadiotapHeader::USIG2_TB_B0_B1_PPDU_TYPE,
668 txVector.GetEhtPpduType());
669 }
670 header.SetUsigFields(usigFields);
671 }
672
673 if (preamble == WIFI_PREAMBLE_EHT_MU)
674 {
675 RadiotapHeader::EhtFields ehtFields{};
678 switch (gi.GetNanoSeconds())
679 {
680 case 800:
681 ehtFields.data.at(0) =
683 break;
684 case 1600:
685 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
687 break;
688 case 3200:
689 ehtFields.data.at(0) = GetRadiotapField(RadiotapHeader::EHT_DATA0_GI,
691 break;
692 default:
693 NS_ABORT_MSG("Unexpected guard interval");
694 break;
695 }
697 const auto ruType = (txVector.GetEhtPpduType() == 1)
698 ? WifiRu::GetRuType(channelWidth)
699 : WifiRu::GetRuType(txVector.GetRu(staId));
700 switch (ruType)
701 {
703 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
705 break;
707 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
709 break;
711 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
713 break;
715 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
717 break;
719 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
721 break;
723 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
725 break;
727 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
729 break;
731 ehtFields.data.at(1) |= GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_SIZE,
733 break;
734 default:
735 NS_ABORT_MSG("Unexpected RU type");
736 break;
737 }
738 const auto ruIndex =
739 (txVector.GetEhtPpduType() == 1) ? 1 : WifiRu::GetIndex(txVector.GetRu(staId));
740 const auto& ruAllocation = txVector.GetRuAllocation(p20Index);
741 ehtFields.data.at(1) |=
742 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_MRU_INDEX, ruIndex) |
743 GetRadiotapField(RadiotapHeader::EHT_DATA1_RU_ALLOC_CC_1_1_1, ruAllocation.at(0));
744 if (channelWidth >= MHz_u{40})
745 {
746 ehtFields.data.at(2) =
748 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_1, ruAllocation.at(1));
749 }
750 if (channelWidth >= MHz_u{80})
751 {
752 ehtFields.data.at(2) |=
755 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_1_1_2, ruAllocation.at(2)) |
756 GetRadiotapField(RadiotapHeader::EHT_DATA2_RU_ALLOC_CC_2_1_2, ruAllocation.at(3));
757 }
758 if (channelWidth >= MHz_u{160})
759 {
760 ehtFields.data.at(3) =
764 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_1, ruAllocation.at(4)) |
765 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_2_2_1, ruAllocation.at(5)) |
766 GetRadiotapField(RadiotapHeader::EHT_DATA3_RU_ALLOC_CC_1_2_2, ruAllocation.at(6));
767 ehtFields.data.at(4) =
769 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_2, ruAllocation.at(7));
770 ehtFields.known |= RadiotapHeader::EHT_KNOWN_PRIMARY_80;
771 const auto isLowP80 = p20Index < (channelWidth / MHz_u{40});
772 ehtFields.data.at(1) |=
776 }
777 if (channelWidth >= MHz_u{320})
778 {
779 ehtFields.data.at(4) |=
782 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_1_2_3, ruAllocation.at(8)) |
783 GetRadiotapField(RadiotapHeader::EHT_DATA4_RU_ALLOC_CC_2_2_3, ruAllocation.at(9));
784 ehtFields.data.at(5) =
788 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_1_2_4, ruAllocation.at(10)) |
789 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_2_2_4, ruAllocation.at(11)) |
790 GetRadiotapField(RadiotapHeader::EHT_DATA5_RU_ALLOC_CC_1_2_5, ruAllocation.at(12));
791 ehtFields.data.at(6) =
795 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_2_2_5, ruAllocation.at(13)) |
796 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_1_2_6, ruAllocation.at(14)) |
797 GetRadiotapField(RadiotapHeader::EHT_DATA6_RU_ALLOC_CC_2_2_6, ruAllocation.at(15));
798 }
803 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_STA_ID, staId) |
804 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_MCS, mcs) |
805 GetRadiotapField(RadiotapHeader::EHT_USER_INFO_NSS_O, nss);
806 ehtFields.userInfo.push_back(userInfo);
807 header.SetEhtFields(ehtFields);
808 }
809
810 return header;
811}
812
813void
815{
816 switch (dlt)
817 {
818 case DLT_IEEE802_11:
820 return;
821 case DLT_PRISM_HEADER:
823 return;
826 return;
827 default:
828 NS_ABORT_MSG("WifiPhyHelper::SetPcapFormat(): Unexpected format");
829 }
830}
831
834{
835 return m_pcapDlt;
836}
837
838void
843
846{
847 return m_pcapType;
848}
849
850void
853 bool promiscuous,
854 bool explicitFilename)
855{
856 NS_LOG_FUNCTION(this << prefix << nd << promiscuous << explicitFilename);
857
858 // All of the Pcap enable functions vector through here including the ones
859 // that are wandering through all of devices on perhaps all of the nodes in
860 // the system. We can only deal with devices of type WifiNetDevice.
861 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
862 if (!device)
863 {
864 NS_LOG_INFO("WifiHelper::EnablePcapInternal(): Device "
865 << &device << " not of type ns3::WifiNetDevice");
866 return;
867 }
868
869 NS_ABORT_MSG_IF(device->GetPhys().empty(),
870 "WifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
871
872 PcapHelper pcapHelper;
873 std::string filename;
874 if (explicitFilename)
875 {
876 filename = prefix;
877 }
878 else
879 {
880 filename = pcapHelper.GetFilenameFromDevice(prefix, device);
881 }
882
883 auto info = std::make_shared<PcapFilesInfo>(filename, m_pcapDlt, m_pcapType, device);
884 for (auto& phy : device->GetPhys())
885 {
886 phy->TraceConnectWithoutContext(
887 "MonitorSnifferTx",
888 MakeBoundCallback(&WifiPhyHelper::PcapSniffTxEvent, info, phy->GetPhyId()));
889 phy->TraceConnectWithoutContext(
890 "MonitorSnifferRx",
891 MakeBoundCallback(&WifiPhyHelper::PcapSniffRxEvent, info, phy->GetPhyId()));
892 }
893}
894
895void
897 std::string prefix,
899 bool explicitFilename)
900{
901 // All of the ASCII enable functions vector through here including the ones
902 // that are wandering through all of devices on perhaps all of the nodes in
903 // the system. We can only deal with devices of type WifiNetDevice.
904 Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice>();
905 if (!device)
906 {
907 NS_LOG_INFO("WifiHelper::EnableAsciiInternal(): Device "
908 << device << " not of type ns3::WifiNetDevice");
909 return;
910 }
911
912 // Our trace sinks are going to use packet printing, so we have to make sure
913 // that is turned on.
915
916 uint32_t nodeid = nd->GetNode()->GetId();
917 uint32_t deviceid = nd->GetIfIndex();
918 std::ostringstream oss;
919
920 // If we are not provided an OutputStreamWrapper, we are expected to create
921 // one using the usual trace filename conventions and write our traces
922 // without a context since there will be one file per context and therefore
923 // the context would be redundant.
924 if (!stream)
925 {
926 // Set up an output stream object to deal with private ofstream copy
927 // constructor and lifetime issues. Let the helper decide the actual
928 // name of the file given the prefix.
929 AsciiTraceHelper asciiTraceHelper;
930
931 std::string filename;
932 if (explicitFilename)
933 {
934 filename = prefix;
935 }
936 else
937 {
938 filename = asciiTraceHelper.GetFilenameFromDevice(prefix, device);
939 }
940
941 // find the last point in the filename
942 auto pos = filename.find_last_of('.');
943 // if not found, set pos to filename size
944 pos = (pos == std::string::npos) ? filename.size() : pos;
945
946 for (uint8_t linkId = 0; linkId < device->GetNPhys(); linkId++)
947 {
948 std::string tmp = filename;
949 if (device->GetNPhys() > 1)
950 {
951 // insert LinkId only for multi-link devices
952 tmp.insert(pos, "-" + std::to_string(linkId));
953 }
954 auto theStream = asciiTraceHelper.CreateFileStream(tmp);
955 // We could go poking through the PHY and the state looking for the
956 // correct trace source, but we can let Config deal with that with
957 // some search cost. Since this is presumably happening at topology
958 // creation time, it doesn't seem much of a price to pay.
959 oss.str("");
960 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
961 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/RxOk";
963 oss.str(),
965
966 oss.str("");
967 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
968 << "/$ns3::WifiNetDevice/Phys/" << +linkId << "/State/Tx";
970 oss.str(),
972 }
973
974 return;
975 }
976
977 // If we are provided an OutputStreamWrapper, we are expected to use it, and
978 // to provide a context. We are free to come up with our own context if we
979 // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
980 // compatibility and simplicity, we just use Config::Connect and let it deal
981 // with coming up with a context.
982 oss.str("");
983 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
984 << "/$ns3::WifiNetDevice/Phy/State/RxOk";
986
987 oss.str("");
988 oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid
989 << "/$ns3::WifiNetDevice/Phy/State/Tx";
991}
992
996
998 : m_standard(WIFI_STANDARD_80211ax),
999 m_selectQueueCallback(&SelectQueueByDSField),
1000 m_enableFlowControl(true)
1001{
1002 SetRemoteStationManager("ns3::IdealWifiManager");
1003 m_htConfig.SetTypeId("ns3::HtConfiguration");
1004 m_vhtConfig.SetTypeId("ns3::VhtConfiguration");
1005 m_heConfig.SetTypeId("ns3::HeConfiguration");
1006 m_ehtConfig.SetTypeId("ns3::EhtConfiguration");
1007}
1008
1009namespace
1010{
1011/// Map strings to WifiStandard enum values
1012const std::unordered_map<std::string, WifiStandard> WIFI_STANDARDS_NAME_MAP{
1013 // clang-format off
1014 {"802.11a", WIFI_STANDARD_80211a},
1015 {"11a", WIFI_STANDARD_80211a},
1016
1017 {"802.11b", WIFI_STANDARD_80211b},
1018 {"11b", WIFI_STANDARD_80211b},
1019
1020 {"802.11g", WIFI_STANDARD_80211g},
1021 {"11g", WIFI_STANDARD_80211g},
1022
1023 {"802.11p", WIFI_STANDARD_80211p},
1024 {"11p", WIFI_STANDARD_80211p},
1025
1026 {"802.11n", WIFI_STANDARD_80211n},
1027 {"11n", WIFI_STANDARD_80211n},
1028 {"HT", WIFI_STANDARD_80211n},
1029
1030 {"802.11ac", WIFI_STANDARD_80211ac},
1031 {"11ac", WIFI_STANDARD_80211ac},
1032 {"VHT", WIFI_STANDARD_80211ac},
1033
1034 {"802.11ad", WIFI_STANDARD_80211ad},
1035 {"11ad", WIFI_STANDARD_80211ad},
1036
1037 {"802.11ax", WIFI_STANDARD_80211ax},
1038 {"11ax", WIFI_STANDARD_80211ax},
1039 {"HE", WIFI_STANDARD_80211ax},
1040
1041 {"802.11be", WIFI_STANDARD_80211be},
1042 {"11be", WIFI_STANDARD_80211be},
1043 {"EHT", WIFI_STANDARD_80211be},
1044 // clang-format on
1045};
1046} // namespace
1047
1048void
1050{
1051 m_standard = standard;
1052}
1053
1054void
1055WifiHelper::SetStandard(const std::string& standard)
1056{
1057 NS_ABORT_MSG_IF(!WIFI_STANDARDS_NAME_MAP.contains(standard),
1058 "Specified Wi-Fi standard " << standard << " is currently not supported");
1059 SetStandard(WIFI_STANDARDS_NAME_MAP.at(standard));
1060}
1061
1062void
1067
1068void
1073
1076 const WifiMacHelper& macHelper,
1078 NodeContainer::Iterator last) const
1079{
1080 NetDeviceContainer devices;
1081 for (auto i = first; i != last; ++i)
1082 {
1083 Ptr<Node> node = *i;
1085 node->AddDevice(device);
1086 device->SetStandard(m_standard);
1088 {
1089 NS_FATAL_ERROR("No standard specified!");
1090 return devices;
1091 }
1093 {
1094 auto htConfiguration = m_htConfig.Create<HtConfiguration>();
1095 device->SetHtConfiguration(htConfiguration);
1096 }
1098 {
1099 // Create the VHT Configuration object even if the PHY band is 2.4GHz
1100 // (WifiNetDevice::GetVhtConfiguration() checks the PHY band being used).
1101 // This approach allows us not to worry about deleting this object when
1102 // the PHY band is switched from 5GHz to 2.4GHz and creating this object
1103 // when the PHY band is switched from 2.4GHz to 5GHz.
1104 auto vhtConfiguration = m_vhtConfig.Create<VhtConfiguration>();
1105 device->SetVhtConfiguration(vhtConfiguration);
1106 }
1108 {
1109 auto heConfiguration = m_heConfig.Create<HeConfiguration>();
1110 device->SetHeConfiguration(heConfiguration);
1111 }
1113 {
1114 auto ehtConfiguration = m_ehtConfig.Create<EhtConfiguration>();
1115 device->SetEhtConfiguration(ehtConfiguration);
1116 }
1117 std::vector<Ptr<WifiRemoteStationManager>> managers;
1118 std::vector<Ptr<WifiPhy>> phys = phyHelper.Create(node, device);
1119 device->SetPhys(phys);
1120 // if only one remote station manager model was provided, replicate it for all the links
1121 auto stationManagers = m_stationManager;
1122 if (stationManagers.size() == 1 && phys.size() > 1)
1123 {
1124 stationManagers.resize(phys.size(), stationManagers[0]);
1125 }
1126 NS_ABORT_MSG_IF(stationManagers.size() != phys.size(),
1127 "Number of station manager models ("
1128 << stationManagers.size() << ") does not match the number of links ("
1129 << phys.size() << ")");
1130 for (std::size_t i = 0; i < phys.size(); i++)
1131 {
1132 phys[i]->ConfigureStandard(m_standard);
1133 managers.push_back(stationManagers[i].Create<WifiRemoteStationManager>());
1134 }
1135 device->SetRemoteStationManagers(managers);
1136 Ptr<WifiMac> mac = macHelper.Create(device, m_standard);
1138 {
1140 device->AggregateObject(obssPdAlgorithm);
1141 obssPdAlgorithm->ConnectWifiNetDevice(device);
1142 }
1143 devices.Add(device);
1144 NS_LOG_DEBUG("node=" << node << ", mob=" << node->GetObject<MobilityModel>());
1146 {
1148 BooleanValue qosSupported;
1150
1151 mac->GetAttributeFailSafe("QosSupported", qosSupported);
1152 if (qosSupported.Get())
1153 {
1155 UintegerValue(4));
1156 for (auto& ac : {AC_BE, AC_BK, AC_VI, AC_VO})
1157 {
1158 Ptr<QosTxop> qosTxop = mac->GetQosTxop(ac);
1159 wmq = qosTxop->GetWifiMacQueue();
1160 ndqi->GetTxQueue(static_cast<std::size_t>(ac))->ConnectQueueTraces(wmq);
1161 }
1162 ndqi->SetSelectQueueCallback(m_selectQueueCallback);
1163 }
1164 else
1165 {
1167
1168 wmq = mac->GetTxop()->GetWifiMacQueue();
1169 ndqi->GetTxQueue(0)->ConnectQueueTraces(wmq);
1170 }
1171 device->AggregateObject(ndqi);
1172 }
1173 }
1174 return devices;
1175}
1176
1179 const WifiMacHelper& macHelper,
1180 NodeContainer c) const
1181{
1182 return Install(phyHelper, macHelper, c.Begin(), c.End());
1183}
1184
1187{
1188 return Install(phy, mac, NodeContainer(node));
1189}
1190
1192WifiHelper::Install(const WifiPhyHelper& phy, const WifiMacHelper& mac, std::string nodeName) const
1193{
1194 Ptr<Node> node = Names::Find<Node>(nodeName);
1195 return Install(phy, mac, NodeContainer(node));
1196}
1197
1198void
1200{
1203
1204 LogComponentEnable("AarfWifiManager", logLevel);
1205 LogComponentEnable("AarfcdWifiManager", logLevel);
1206 LogComponentEnable("AdhocWifiMac", logLevel);
1207 LogComponentEnable("AdvancedApEmlsrManager", logLevel);
1208 LogComponentEnable("AdvancedEmlsrManager", logLevel);
1209 LogComponentEnable("AmrrWifiManager", logLevel);
1210 LogComponentEnable("ApEmlsrManager", logLevel);
1211 LogComponentEnable("ApWifiMac", logLevel);
1212 LogComponentEnable("AparfWifiManager", logLevel);
1213 LogComponentEnable("ArfWifiManager", logLevel);
1214 LogComponentEnable("BlockAckAgreement", logLevel);
1215 LogComponentEnable("BlockAckManager", logLevel);
1216 LogComponentEnable("CaraWifiManager", logLevel);
1217 LogComponentEnable("ChannelAccessManager", logLevel);
1218 LogComponentEnable("ConstantObssPdAlgorithm", logLevel);
1219 LogComponentEnable("ConstantRateWifiManager", logLevel);
1220 LogComponentEnable("DefaultApEmlsrManager", logLevel);
1221 LogComponentEnable("DefaultEmlsrManager", logLevel);
1222 LogComponentEnable("DsssErrorRateModel", logLevel);
1223 LogComponentEnable("DsssPhy", logLevel);
1224 LogComponentEnable("DsssPpdu", logLevel);
1225 LogComponentEnable("EhtFrameExchangeManager", logLevel);
1226 LogComponentEnable("EhtPhy", logLevel);
1227 LogComponentEnable("EhtPpdu", logLevel);
1228 LogComponentEnable("EmlsrManager", logLevel);
1229 LogComponentEnable("ErpOfdmPhy", logLevel);
1230 LogComponentEnable("ErpOfdmPpdu", logLevel);
1231 LogComponentEnable("FrameExchangeManager", logLevel);
1232 LogComponentEnable("GcrManager", logLevel);
1233 LogComponentEnable("HeConfiguration", logLevel);
1234 LogComponentEnable("HeFrameExchangeManager", logLevel);
1235 LogComponentEnable("HePhy", logLevel);
1236 LogComponentEnable("HePpdu", logLevel);
1237 LogComponentEnable("HtConfiguration", logLevel);
1238 LogComponentEnable("HtFrameExchangeManager", logLevel);
1239 LogComponentEnable("HtPhy", logLevel);
1240 LogComponentEnable("HtPpdu", logLevel);
1241 LogComponentEnable("IdealWifiManager", logLevel);
1242 LogComponentEnable("InterferenceHelper", logLevel);
1243 LogComponentEnable("MacRxMiddle", logLevel);
1244 LogComponentEnable("MacTxMiddle", logLevel);
1245 LogComponentEnable("MinstrelHtWifiManager", logLevel);
1246 LogComponentEnable("MinstrelWifiManager", logLevel);
1247 LogComponentEnable("MpduAggregator", logLevel);
1248 LogComponentEnable("MsduAggregator", logLevel);
1249 LogComponentEnable("MultiUserScheduler", logLevel);
1250 LogComponentEnable("NistErrorRateModel", logLevel);
1251 LogComponentEnable("ObssPdAlgorithm", logLevel);
1252 LogComponentEnable("OfdmPhy", logLevel);
1253 LogComponentEnable("OfdmPpdu", logLevel);
1254 LogComponentEnable("OnoeWifiManager", logLevel);
1255 LogComponentEnable("OriginatorBlockAckAgreement", logLevel);
1256 LogComponentEnable("ParfWifiManager", logLevel);
1257 LogComponentEnable("PhyEntity", logLevel);
1258 LogComponentEnable("QosFrameExchangeManager", logLevel);
1259 LogComponentEnable("QosTxop", logLevel);
1260 LogComponentEnable("RecipientBlockAckAgreement", logLevel);
1261 LogComponentEnable("RrMultiUserScheduler", logLevel);
1262 LogComponentEnable("RraaWifiManager", logLevel);
1263 LogComponentEnable("RrpaaWifiManager", logLevel);
1264 LogComponentEnable("SimpleFrameCaptureModel", logLevel);
1265 LogComponentEnable("SpectrumWifiPhy", logLevel);
1266 LogComponentEnable("StaWifiMac", logLevel);
1267 LogComponentEnable("SupportedRates", logLevel);
1268 LogComponentEnable("TableBasedErrorRateModel", logLevel);
1269 LogComponentEnable("ThompsonSamplingWifiManager", logLevel);
1270 LogComponentEnable("ThresholdPreambleDetectionModel", logLevel);
1271 LogComponentEnable("Txop", logLevel);
1272 LogComponentEnable("VhtConfiguration", logLevel);
1273 LogComponentEnable("VhtFrameExchangeManager", logLevel);
1274 LogComponentEnable("VhtPhy", logLevel);
1275 LogComponentEnable("VhtPpdu", logLevel);
1276 LogComponentEnable("WifiAckManager", logLevel);
1277 LogComponentEnable("WifiAssocManager", logLevel);
1278 LogComponentEnable("WifiDefaultAckManager", logLevel);
1279 LogComponentEnable("WifiDefaultAssocManager", logLevel);
1280 LogComponentEnable("WifiDefaultGcrManager", logLevel);
1281 LogComponentEnable("WifiDefaultProtectionManager", logLevel);
1282 LogComponentEnable("WifiMac", logLevel);
1283 LogComponentEnable("WifiMacQueue", logLevel);
1284 LogComponentEnable("WifiMpdu", logLevel);
1285 LogComponentEnable("WifiNetDevice", logLevel);
1286 LogComponentEnable("WifiPhyStateHelper", logLevel);
1287 LogComponentEnable("WifiPhyOperatingChannel", logLevel);
1288 LogComponentEnable("WifiPhy", logLevel);
1289 LogComponentEnable("WifiPpdu", logLevel);
1290 LogComponentEnable("WifiProtectionManager", logLevel);
1291 LogComponentEnable("WifiPsdu", logLevel);
1292 LogComponentEnable("WifiRadioEnergyModel", logLevel);
1293 LogComponentEnable("WifiRemoteStationManager", logLevel);
1294 LogComponentEnable("WifiSpectrumPhyInterface", logLevel);
1295 LogComponentEnable("WifiSpectrumSignalParameters", logLevel);
1296 LogComponentEnable("WifiSpectrumValueHelper", logLevel);
1297 LogComponentEnable("WifiTxCurrentModel", logLevel);
1298 LogComponentEnable("WifiTxParameters", logLevel);
1299 LogComponentEnable("WifiTxTimer", logLevel);
1300 LogComponentEnable("YansErrorRateModel", logLevel);
1301 LogComponentEnable("YansWifiChannel", logLevel);
1302 LogComponentEnable("YansWifiPhy", logLevel);
1303
1304 LogComponentEnable("Athstats", logLevel);
1305 LogComponentEnable("WifiHelper", logLevel);
1306 LogComponentEnable("SpectrumWifiHelper", logLevel);
1307 LogComponentEnable("YansWifiHelper", logLevel);
1308}
1309
1310int64_t
1312{
1313 int64_t currentStream = stream;
1314 Ptr<NetDevice> netDevice;
1315 for (auto i = c.Begin(); i != c.End(); ++i)
1316 {
1317 netDevice = (*i);
1318 if (auto wifi = DynamicCast<WifiNetDevice>(netDevice))
1319 {
1320 // Handle any random numbers in the PHY objects.
1321 for (auto& phy : wifi->GetPhys())
1322 {
1323 currentStream += phy->AssignStreams(currentStream);
1324 }
1325
1326 // Handle any random numbers in the station managers.
1327 for (auto& manager : wifi->GetRemoteStationManagers())
1328 {
1329 currentStream += manager->AssignStreams(currentStream);
1330 }
1331
1332 // Handle any random numbers in the MAC objects.
1333 auto mac = wifi->GetMac();
1334 PointerValue ptr;
1335 if (!mac->GetQosSupported())
1336 {
1337 mac->GetAttribute("Txop", ptr);
1338 auto txop = ptr.Get<Txop>();
1339 currentStream += txop->AssignStreams(currentStream);
1340 }
1341 else
1342 {
1343 mac->GetAttribute("VO_Txop", ptr);
1344 auto vo_txop = ptr.Get<QosTxop>();
1345 currentStream += vo_txop->AssignStreams(currentStream);
1346
1347 mac->GetAttribute("VI_Txop", ptr);
1348 auto vi_txop = ptr.Get<QosTxop>();
1349 currentStream += vi_txop->AssignStreams(currentStream);
1350
1351 mac->GetAttribute("BE_Txop", ptr);
1352 auto be_txop = ptr.Get<QosTxop>();
1353 currentStream += be_txop->AssignStreams(currentStream);
1354
1355 mac->GetAttribute("BK_Txop", ptr);
1356 auto bk_txop = ptr.Get<QosTxop>();
1357 currentStream += bk_txop->AssignStreams(currentStream);
1358 }
1359
1360 // if an AP, handle any beacon jitter
1361 if (auto apMac = DynamicCast<ApWifiMac>(mac); apMac)
1362 {
1363 currentStream += apMac->AssignStreams(currentStream);
1364 }
1365 // if a STA, handle any probe request jitter
1366 if (auto staMac = DynamicCast<StaWifiMac>(mac); staMac)
1367 {
1368 currentStream += staMac->AssignStreams(currentStream);
1369 }
1370 }
1371 }
1372 return (currentStream - stream);
1373}
1374
1375} // 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 SetWifiHeader(std::size_t numPresentWords)
Set the ieee80211_radiotap_header.
void SetHeMuFields(const HeMuFields &heMuFields)
Set the subfields of the HE-MU field.
void SetChannelFields(const ChannelFields &channelFields)
Set the subfields of the Channel field.
void SetFrameFlags(uint8_t flags)
Set the frame flags of the transmitted or received frame.
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:394
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:404
Handles the packet queue and stores DCF/EDCA access parameters (one Txop per AC).
Definition txop.h:56
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition txop.cc:704
Hold an unsigned integer type.
Definition uinteger.h:34
VHT configuration.
virtual ~WifiHelper()
void SetRemoteStationManager(std::string type, Args &&... args)
Helper function used to set the station manager.
ObjectFactory m_htConfig
HT configuration.
ObjectFactory m_obssPdAlgorithm
OBSS_PD algorithm.
ObjectFactory m_ehtConfig
EHT configuration.
ObjectFactory m_vhtConfig
VHT configuration.
static void EnableLogComponents(LogLevel logLevel=LOG_LEVEL_ALL)
Helper to enable all WifiNetDevice log components with one statement.
void SetSelectQueueCallback(SelectQueueCallback f)
std::vector< ObjectFactory > m_stationManager
station manager
WifiStandard m_standard
wifi standard
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
virtual void SetStandard(WifiStandard standard)
ObjectFactory m_heConfig
HE configuration.
virtual NetDeviceContainer Install(const WifiPhyHelper &phy, const WifiMacHelper &mac, NodeContainer::Iterator first, NodeContainer::Iterator last) const
void DisableFlowControl()
Disable flow control only if you know what you are doing.
SelectQueueCallback m_selectQueueCallback
select queue callback
bool m_enableFlowControl
whether to enable flow control
WifiHelper()
Create a Wifi helper in an empty state: all its parameters must be set before calling ns3::WifiHelper...
std::function< std::size_t(Ptr< QueueItem >)> SelectQueueCallback
Callback invoked to determine the MAC queue selected for a given packet.
create MAC layers for a ns3::WifiNetDevice.
virtual Ptr< WifiMac > Create(Ptr< WifiNetDevice > device, WifiStandard standard) const
Implements the IEEE 802.11 MAC trailer.
represent a single transmission mode
Definition wifi-mode.h:38
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
uint8_t GetMcsValue() const
Definition wifi-mode.cc:151
Hold together all Wifi-related objects.
create PHY objects
Definition wifi-helper.h:40
void SetPcapCaptureType(PcapCaptureType type)
Set the PCAP capture type to be used.
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
void EnableAsciiInternal(Ptr< OutputStreamWrapper > stream, std::string prefix, Ptr< NetDevice > nd, bool explicitFilename) override
Enable ASCII trace output on the indicated net device.
WifiPhyHelper(uint8_t nLinks=1)
Constructor.
static void PcapSniffTxEvent(const std::shared_ptr< PcapFilesInfo > &info, uint8_t phyId, Ptr< const Packet > packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, uint16_t staId=SU_STA_ID)
void Set(std::string name, const AttributeValue &v)
~WifiPhyHelper() override
void DisablePreambleDetectionModel()
Disable the preamble detection model on all links.
void EnablePcapInternal(std::string prefix, Ptr< NetDevice > nd, bool promiscuous, bool explicitFilename) override
Enable pcap output the indicated net device.
PcapHelper::DataLinkType m_pcapDlt
PCAP data link type.
std::vector< ObjectFactory > m_frameCaptureModel
frame capture model
std::vector< ObjectFactory > m_preambleDetectionModel
preamble detection model
PcapHelper::DataLinkType GetPcapDataLinkType() const
Get the data link type of PCAP traces to be used.
PcapCaptureType m_pcapType
PCAP capture type.
PcapCaptureType GetPcapCaptureType() const
Get the PCAP capture type to be used.
std::vector< ObjectFactory > m_phys
PHY objects.
static void PcapSniffRxEvent(const std::shared_ptr< PcapFilesInfo > &info, uint8_t phyId, Ptr< const Packet > packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise, uint16_t staId=SU_STA_ID)
void SetPreambleDetectionModel(std::string type, Args &&... args)
Helper function used to set the preamble detection model.
static RadiotapHeader GetRadiotapHeader(Ptr< Packet > packet, uint16_t channelFreqMhz, uint8_t p20Index, const WifiTxVector &txVector, MpduInfo aMpdu, uint16_t staId, std::optional< SignalNoiseDbm > signalNoise=std::nullopt)
Get the Radiotap header for a received packet.
static Ptr< PcapFileWrapper > GetOrCreatePcapFile(const std::shared_ptr< PcapFilesInfo > &info, uint8_t phyId)
Get the PCAP file to write to from a list of PCAP files indexed by PHY ID.
SupportedPcapDataLinkTypes
An enumeration of the pcap data link types (DLTs) which this helper supports.
@ DLT_IEEE802_11
IEEE 802.11 Wireless LAN headers on packets.
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
@ DLT_PRISM_HEADER
Include Prism monitor mode information.
std::vector< ObjectFactory > m_errorRateModel
error rate model
virtual std::vector< Ptr< WifiPhy > > Create(Ptr< Node > node, Ptr< WifiNetDevice > device) const =0
PcapCaptureType
An enumeration of the PCAP capture types.
@ PCAP_PER_PHY
Single capture file per PHY.
@ PCAP_PER_DEVICE
Single capture file per device.
@ PCAP_PER_LINK
Single capture file per link.
static bool IsHe(RuSpec ru)
Get whether a given RU variant is a HE RU.
Definition wifi-ru.cc:248
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
Definition wifi-ru.cc:45
static std::size_t GetIndex(RuSpec ru)
Get the index of a given RU.
Definition wifi-ru.cc:51
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
uint8_t GetBssColor() const
Get the BSS color.
const RuAllocation & GetRuAllocation(uint8_t p20Index) const
Get RU_ALLOCATION field.
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
bool IsStbc() const
Check if STBC is used or not.
WifiPreamble GetPreambleType() const
HeMuUserInfo GetHeMuUserInfo(uint16_t staId) const
Get the HE MU user-specific transmission information for the given STA-ID.
uint8_t GetEhtPpduType() const
Get the EHT_PPDU_TYPE parameter.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
MHz_u GetChannelWidth() const
bool IsAggregation() const
Checks whether the PSDU contains A-MPDU.
Time GetGuardInterval() const
uint8_t GetNess() const
WifiRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
WifiMode GetSigBMode() const
Get MCS used for SIG-B.
const std::vector< bool > & GetInactiveSubchannels() const
Get the 20 MHz subchannels that are punctured.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:970
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:946
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
auto MakeBoundCallback(R(*fnPtr)(Args...), BArgs &&... bargs)
Make Callbacks with varying number of bound arguments.
Definition callback.h:745
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:439
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
uint8_t SelectQueueByDSField(Ptr< QueueItem > item)
Determine the TX queue for a given packet.
Definition qos-utils.cc:227
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211ad
@ WIFI_STANDARD_80211p
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211g
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_UNSPECIFIED
@ WIFI_STANDARD_80211ac
@ WIFI_STANDARD_80211b
@ WIFI_PREAMBLE_HE_ER_SU
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PREAMBLE_SHORT
@ WIFI_MOD_CLASS_HT
HT (Clause 19)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ AC_BE
Best Effort.
Definition qos-utils.h: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:284
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:585
static void AsciiPhyReceiveSinkWithoutContext(Ptr< OutputStreamWrapper > stream, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
ASCII trace PHY receive sink without context.
LogLevel
Logging severity classes and levels.
Definition log.h:83
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition log.h:108
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
Definition log.h:109
static void AsciiPhyReceiveSinkWithContext(Ptr< OutputStreamWrapper > stream, std::string context, Ptr< const Packet > p, double snr, WifiMode mode, WifiPreamble preamble)
ASCII trace PHY receive sink with context.
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition log.cc:302
static void AsciiPhyTransmitSinkWithContext(Ptr< OutputStreamWrapper > stream, std::string context, Ptr< const Packet > p, WifiMode mode, WifiPreamble preamble, uint8_t txLevel)
ASCII trace PHY transmit sink with context.
static void AsciiPhyTransmitSinkWithoutContext(Ptr< OutputStreamWrapper > stream, Ptr< const Packet > p, WifiMode mode, WifiPreamble preamble, uint8_t txLevel)
ASCII trace PHY transmit sink without context.
WifiRu::RuSpec ru
RU specification.
MpduInfo structure.
Definition wifi-types.h:72
MpduType type
type of MPDU
Definition wifi-types.h:73
uint32_t mpduRefNumber
MPDU ref number.
Definition wifi-types.h:74
structure that contains the subfields of the A-MPDU status field.
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