A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-default-protection-manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "ap-wifi-mac.h"
12#include "sta-wifi-mac.h"
13#include "wifi-mpdu.h"
14#include "wifi-tx-parameters.h"
15
16#include "ns3/boolean.h"
17#include "ns3/eht-frame-exchange-manager.h"
18#include "ns3/emlsr-manager.h"
19#include "ns3/erp-ofdm-phy.h"
20#include "ns3/log.h"
21
22#include <type_traits>
23
24namespace ns3
25{
26
27NS_LOG_COMPONENT_DEFINE("WifiDefaultProtectionManager");
28
29NS_OBJECT_ENSURE_REGISTERED(WifiDefaultProtectionManager);
30
31TypeId
33{
34 static TypeId tid =
35 TypeId("ns3::WifiDefaultProtectionManager")
37 .SetGroupName("Wifi")
38 .AddConstructor<WifiDefaultProtectionManager>()
39 .AddAttribute("EnableMuRts",
40 "If enabled, always protect a DL/UL MU frame exchange with MU-RTS/CTS.",
41 BooleanValue(false),
44 .AddAttribute("SingleRtsPerTxop",
45 "If enabled, a protection mechanism (RTS or MU-RTS) is normally used no "
46 "more than once in a TXOP, regardless of the destination of the data "
47 "frame (unless required for specific purposes, such as transmitting an "
48 "Initial Control Frame to an EMLSR client).",
49 BooleanValue(false),
52 .AddAttribute("SkipMuRtsBeforeBsrp",
53 "If enabled, MU-RTS is not used to protect the transmission of a BSRP "
54 "Trigger Frame.",
55 BooleanValue(true),
58 return tid;
59}
60
65
70
71std::unique_ptr<WifiProtection>
73{
74 NS_LOG_FUNCTION(this << *mpdu << &txParams);
75
76 // Call a separate method that handles MU-RTS/CTS protection in case of DL MU PPDU containing
77 // more than one PSDU or in case the MPDU being added is addressed to an EMLSR client or in
78 // case the protection method is already MU-RTS/CTS.
79 const auto& psduInfoMap = txParams.GetPsduInfoMap();
80 auto dlMuPpdu = txParams.m_txVector.IsDlMu() && psduInfoMap.size() > 1;
81 const auto& hdr = mpdu->GetHeader();
82 auto isEmlsrDestination = GetWifiRemoteStationManager()->GetEmlsrEnabled(hdr.GetAddr1());
83
84 if (dlMuPpdu || isEmlsrDestination ||
85 (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS))
86 {
87 return TryAddMpduToMuPpdu(mpdu, txParams);
88 }
89
90 // No protection for TB PPDUs (the soliciting Trigger Frame can be protected by an MU-RTS)
91 if (txParams.m_txVector.IsUlMu())
92 {
93 if (txParams.m_protection)
94 {
95 NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
96 return nullptr;
97 }
98 return std::make_unique<WifiNoProtection>();
99 }
100
101 // if this is a Trigger Frame, call a separate method
102 if (hdr.IsTrigger())
103 {
104 return TryUlMuTransmission(mpdu, txParams);
105 }
106
107 // if the current protection method (if any) is already RTS/CTS or CTS-to-Self,
108 // it will not change by adding an MPDU
109 if (txParams.m_protection && (txParams.m_protection->method == WifiProtection::RTS_CTS ||
110 txParams.m_protection->method == WifiProtection::CTS_TO_SELF))
111 {
112 return nullptr;
113 }
114
115 // if a protection method is set, it must be NONE
116 NS_ASSERT(!txParams.m_protection || txParams.m_protection->method == WifiProtection::NONE);
117
118 std::unique_ptr<WifiProtection> protection;
119 protection = GetPsduProtection(hdr, txParams);
120
121 // return the newly computed method if none was set or it is not NONE
122 if (!txParams.m_protection || protection->method != WifiProtection::NONE)
123 {
124 return protection;
125 }
126 // the protection method has not changed
127 return nullptr;
128}
129
130std::unique_ptr<WifiProtection>
132 const WifiTxParameters& txParams)
133{
134 NS_LOG_FUNCTION(this << *msdu << &txParams);
135
136 // if the current protection method is already RTS/CTS, CTS-to-Self or MU-RTS/CTS,
137 // it will not change by aggregating an MSDU
138 NS_ASSERT(txParams.m_protection);
139 if (txParams.m_protection->method == WifiProtection::RTS_CTS ||
140 txParams.m_protection->method == WifiProtection::CTS_TO_SELF ||
141 txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
142 {
143 return nullptr;
144 }
145
146 NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
147
148 // No protection for TB PPDUs and DL MU PPDUs containing more than one PSDU
149 if (txParams.m_txVector.IsUlMu() ||
150 (txParams.m_txVector.IsDlMu() && txParams.GetPsduInfoMap().size() > 1))
151 {
152 return nullptr;
153 }
154
155 std::unique_ptr<WifiProtection> protection;
156 protection = GetPsduProtection(msdu->GetHeader(), txParams);
157
158 // the protection method may still be none
159 if (protection->method == WifiProtection::NONE)
160 {
161 return nullptr;
162 }
163
164 // the protection method has changed
165 return protection;
166}
167
168std::unique_ptr<WifiProtection>
170 const WifiTxParameters& txParams) const
171{
172 NS_LOG_FUNCTION(this << hdr << &txParams);
173
174 // a non-initial fragment does not need to be protected, unless it is being retransmitted
175 if (hdr.GetFragmentNumber() > 0 && !hdr.IsRetry())
176 {
177 return std::make_unique<WifiNoProtection>();
178 }
179
180 // no need to use protection if destination already received an RTS in this TXOP or
181 // SingleRtsPerTxop is true and a protection mechanism has been already used in this TXOP
182 if (const auto& protectedStas = m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas();
183 protectedStas.contains(hdr.GetAddr1()) || (m_singleRtsPerTxop && !protectedStas.empty()))
184 {
185 return std::make_unique<WifiNoProtection>();
186 }
187
188 // when an EMLSR client starts an UL TXOP on a link while the MediumSyncDelay timer is running
189 // or on a link on which the main PHY is not operating, it needs to send an RTS frame
190 bool emlsrNeedRts = false;
191
192 if (auto staMac = DynamicCast<StaWifiMac>(m_mac))
193 {
194 auto emlsrManager = staMac->GetEmlsrManager();
195
196 emlsrNeedRts = emlsrManager && staMac->IsEmlsrLink(m_linkId) &&
197 (emlsrManager->GetElapsedMediumSyncDelayTimer(m_linkId) ||
198 m_mac->GetLinkForPhy(emlsrManager->GetMainPhyId()) != m_linkId);
199 }
200
201 // check if RTS/CTS is needed
202 if (emlsrNeedRts || GetWifiRemoteStationManager()->NeedRts(hdr, txParams))
203 {
204 auto protection = std::make_unique<WifiRtsCtsProtection>();
205 protection->rtsTxVector =
206 GetWifiRemoteStationManager()->GetRtsTxVector(hdr.GetAddr1(),
207 txParams.m_txVector.GetChannelWidth());
208 protection->ctsTxVector =
209 GetWifiRemoteStationManager()->GetCtsTxVector(hdr.GetAddr1(),
210 protection->rtsTxVector.GetMode());
211 return protection;
212 }
213
214 // check if CTS-to-Self is needed
215 if (GetWifiRemoteStationManager()->NeedCtsToSelf(txParams.m_txVector, hdr))
216 {
217 auto protection = std::make_unique<WifiCtsToSelfProtection>();
218 protection->ctsTxVector = GetWifiRemoteStationManager()->GetCtsToSelfTxVector();
219 return protection;
220 }
221
222 return std::make_unique<WifiNoProtection>();
223}
224
225std::unique_ptr<WifiProtection>
227 const WifiTxParameters& txParams)
228{
229 NS_LOG_FUNCTION(this << *mpdu << &txParams);
230
231 auto receiver = mpdu->GetHeader().GetAddr1();
232 const auto& psduInfoMap = txParams.GetPsduInfoMap();
233 auto dlMuPpdu = txParams.m_txVector.IsDlMu() && psduInfoMap.size() > 1;
234 auto isEmlsrDestination = GetWifiRemoteStationManager()->GetEmlsrEnabled(receiver);
235 NS_ASSERT(
236 dlMuPpdu || isEmlsrDestination ||
237 (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS));
238
239 const auto& protectedStas = m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas();
240 const auto isProtected = protectedStas.contains(receiver);
241 bool needMuRts =
242 (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS) ||
243 (dlMuPpdu && m_sendMuRts && !isProtected &&
244 (!m_singleRtsPerTxop || protectedStas.empty())) ||
245 (isEmlsrDestination && !isProtected);
246
247 if (!needMuRts)
248 {
249 // No protection needed
250 if (txParams.m_protection && txParams.m_protection->method == WifiProtection::NONE)
251 {
252 return nullptr;
253 }
254 return std::make_unique<WifiNoProtection>();
255 }
256
257 WifiMuRtsCtsProtection* protection = nullptr;
258 if (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
259 {
260 protection = static_cast<WifiMuRtsCtsProtection*>(txParams.m_protection.get());
261 }
262
263 if (txParams.LastAddedIsFirstMpdu(receiver))
264 {
265 // we get here if this is the first MPDU for this receiver.
266 NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
267 auto modClass = txParams.m_txVector.GetModulationClass();
268 auto txWidth = modClass == WIFI_MOD_CLASS_DSSS || modClass == WIFI_MOD_CLASS_HR_DSSS
269 ? MHz_u{20}
270 : txParams.m_txVector.GetChannelWidth();
271
272 if (protection != nullptr)
273 {
274 // txParams.m_protection points to an existing WifiMuRtsCtsProtection object.
275 // We have to return a copy of this object including the needed changes
276 protection = new WifiMuRtsCtsProtection(*protection);
277
278 // Add a User Info field for the new receiver
279 // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
280 // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
281 AddUserInfoToMuRts(protection->muRts, txWidth, receiver);
282 }
283 else
284 {
285 // we have to create a new WifiMuRtsCtsProtection object
286 protection = new WifiMuRtsCtsProtection;
287
288 // initialize the MU-RTS Trigger Frame
289 // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
290 // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
291 // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
292 // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
294 /* 35.2.2.1 MU-RTS Trigger frame transmission (IEEE P802.11be/D7.0):
295 * If a non-AP EHT STA is addressed in an MU-RTS Trigger frame from an EHT AP and any of
296 * the following conditions is met, the User Info field addressed to an EHT STA in the
297 * MU-RTS Trigger frame shall be an EHT variant User Info field:
298 * - The bandwidth of the EHT MU PPDU or non-HT duplicate PPDU carrying the MU-RTS
299 * Trigger frame is 320 MHz.
300 * - The EHT MU PPDU or non-HT duplicate PPDU carrying the MU-RTS Trigger frame is
301 * punctured. Otherwise, the EHT AP may decide whether the User Info field in the MU-RTS
302 * Trigger frame is an HE variant User Info field or an EHT variant User Info field.
303 */
304 const auto& inactiveSubchannels = txParams.m_txVector.GetInactiveSubchannels();
305 const auto isPunctured =
306 std::find(inactiveSubchannels.cbegin(), inactiveSubchannels.cend(), true) !=
307 inactiveSubchannels.cend();
308 const auto muRtsVariant = ((txWidth == MHz_u{320}) || isPunctured)
311 protection->muRts.SetVariant(muRtsVariant);
312 protection->muRts.SetUlBandwidth(txWidth);
313
314 // Add a User Info field for each of the receivers already in the TX params
315 for (const auto& [address, info] : txParams.GetPsduInfoMap())
316 {
317 AddUserInfoToMuRts(protection->muRts, txWidth, address);
318 }
319
320 // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
321 protection->muRtsTxVector =
322 GetWifiRemoteStationManager()->GetRtsTxVector(receiver, txWidth);
323 // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
324 // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
325 // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
326 protection->muRtsTxVector.SetChannelWidth(txWidth);
327 // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
328 const auto modulation = protection->muRtsTxVector.GetModulationClass();
329 if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
330 {
332 }
333 }
334
335 if (isEmlsrDestination && !isProtected)
336 {
337 // This MU-RTS is an ICF for some EMLSR client
338 auto ehtFem =
339 StaticCast<EhtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
340 ehtFem->SetIcfPaddingAndTxVector(protection->muRts, protection->muRtsTxVector);
341 }
342
343 return std::unique_ptr<WifiMuRtsCtsProtection>(protection);
344 }
345
346 // an MPDU addressed to the same receiver has been already added
347 NS_ASSERT(protection != nullptr);
348
349 // no change is needed
350 return nullptr;
351}
352
353std::unique_ptr<WifiProtection>
355 const WifiTxParameters& txParams)
356{
357 NS_LOG_FUNCTION(this << *mpdu << &txParams);
358 NS_ASSERT(mpdu->GetHeader().IsTrigger());
359
360 CtrlTriggerHeader trigger;
361 mpdu->GetPacket()->PeekHeader(trigger);
362 NS_ASSERT(trigger.GetNUserInfoFields() > 0);
363 auto txWidth = trigger.GetUlBandwidth();
364
365 auto protection = std::make_unique<WifiMuRtsCtsProtection>();
366 // initialize the MU-RTS Trigger Frame
367 // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
368 // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
369 // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
370 // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
371 protection->muRts.SetType(TriggerFrameType::MU_RTS_TRIGGER);
372 protection->muRts.SetVariant(trigger.GetVariant());
373 protection->muRts.SetUlBandwidth(txWidth);
374
375 NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
376 const auto& staList = StaticCast<ApWifiMac>(m_mac)->GetStaList(m_linkId);
377
378 const auto& protectedStas = m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas();
379 bool allProtected = true;
380 bool isUnprotectedEmlsrDst = false;
381
382 for (const auto& userInfo : trigger)
383 {
384 // Add a User Info field to the MU-RTS for this solicited station
385 // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
386 // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
387 auto staIt = staList.find(userInfo.GetAid12());
388 NS_ASSERT(staIt != staList.cend());
389 AddUserInfoToMuRts(protection->muRts, txWidth, staIt->second);
390 const auto isProtected = protectedStas.contains(staIt->second);
391 allProtected = allProtected && isProtected;
392
393 isUnprotectedEmlsrDst =
394 isUnprotectedEmlsrDst ||
395 (!isProtected && GetWifiRemoteStationManager()->GetEmlsrEnabled(staIt->second));
396 }
397
398 bool needMuRts =
399 (m_sendMuRts && !allProtected && (!m_singleRtsPerTxop || protectedStas.empty())) ||
400 isUnprotectedEmlsrDst;
401
402 // if we are sending a BSRP TF and SkipMuRtsBeforeBsrpTf is true, do not use MU-RTS (even in
403 // case of unprotected EMLSR, because the BSRP TF is an ICF)
404 needMuRts = needMuRts && (!m_skipMuRtsBeforeBsrp || !trigger.IsBsrp());
405
406 if (!needMuRts)
407 {
408 // No protection needed
409 return std::make_unique<WifiNoProtection>();
410 }
411
412 // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
413 protection->muRtsTxVector =
414 GetWifiRemoteStationManager()->GetRtsTxVector(mpdu->GetHeader().GetAddr1(), txWidth);
415 // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
416 // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
417 // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
418 protection->muRtsTxVector.SetChannelWidth(txWidth);
419 // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
420 const auto modulation = protection->muRtsTxVector.GetModulationClass();
421 if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
422 {
423 protection->muRtsTxVector.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps());
424 }
425 if (isUnprotectedEmlsrDst)
426 {
427 // This MU-RTS is an ICF for some EMLSR client
428 auto ehtFem = StaticCast<EhtFrameExchangeManager>(m_mac->GetFrameExchangeManager(m_linkId));
429 ehtFem->SetIcfPaddingAndTxVector(protection->muRts, protection->muRtsTxVector);
430 }
431
432 return protection;
433}
434
435} // namespace ns3
AttributeValue implementation for Boolean.
Definition boolean.h:26
Headers for Trigger frames.
bool IsBsrp() const
Check if this is a Buffer Status Report Poll Trigger frame.
std::size_t GetNUserInfoFields() const
Get the number of User Info fields in this Trigger Frame.
void SetType(TriggerFrameType type)
Set the Trigger frame type.
MHz_u GetUlBandwidth() const
Get the bandwidth of the solicited HE/EHT TB PPDU.
TriggerFrameVariant GetVariant() const
Get the Common Info field variant.
void SetVariant(TriggerFrameVariant variant)
Set the Common Info field variant.
void SetUlBandwidth(MHz_u bw)
Set the bandwidth of the solicited HE/EHT TB PPDU.
static WifiMode GetErpOfdmRate6Mbps()
Return a WifiMode for ERP-OFDM at 6 Mbps.
Smart pointer class similar to boost::intrusive_ptr.
a unique identifier for an interface.
Definition type-id.h:49
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
WifiDefaultProtectionManager is the default protection manager, which selects the protection method f...
std::unique_ptr< WifiProtection > TryAddMpdu(Ptr< const WifiMpdu > mpdu, const WifiTxParameters &txParams) override
Determine the protection method to use if the given MPDU is added to the current frame.
bool m_sendMuRts
true for sending an MU-RTS to protect DL MU PPDUs
bool m_skipMuRtsBeforeBsrp
whether to skip MU-RTS before BSRP TF
std::unique_ptr< WifiProtection > TryAggregateMsdu(Ptr< const WifiMpdu > msdu, const WifiTxParameters &txParams) override
Determine the protection method to use if the given MSDU is aggregated to the current frame.
bool m_singleRtsPerTxop
true for using protection only once in a TXOP
virtual std::unique_ptr< WifiProtection > TryUlMuTransmission(Ptr< const WifiMpdu > mpdu, const WifiTxParameters &txParams)
Calculate the protection method for the UL MU transmission solicited by the given Trigger Frame.
virtual std::unique_ptr< WifiProtection > GetPsduProtection(const WifiMacHeader &hdr, const WifiTxParameters &txParams) const
Select the protection method for a single PSDU.
virtual std::unique_ptr< WifiProtection > TryAddMpduToMuPpdu(Ptr< const WifiMpdu > mpdu, const WifiTxParameters &txParams)
Calculate the protection method to use if the given MPDU is added to the current DL MU PPDU (represen...
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
bool IsRetry() const
Return if the Retry bit is set.
uint8_t GetFragmentNumber() const
Return the fragment number of the header.
WifiProtectionManager is an abstract base class.
Ptr< WifiMac > m_mac
MAC which is using this Protection Manager.
void AddUserInfoToMuRts(CtrlTriggerHeader &muRts, MHz_u txWidth, const Mac48Address &receiver) const
Add a User Info field to the given MU-RTS Trigger Frame to solicit a CTS from the station with the gi...
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
uint8_t m_linkId
ID of the link this Protection Manager is operating on.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
const PsduInfoMap & GetPsduInfoMap() const
Get a const reference to the map containing information about PSDUs.
std::unique_ptr< WifiProtection > m_protection
protection method
bool LastAddedIsFirstMpdu(Mac48Address receiver) const
Check if the last added MPDU is the first MPDU for the given receiver.
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void SetChannelWidth(MHz_u channelWidth)
Sets the selected channelWidth.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
MHz_u GetChannelWidth() const
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
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
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
@ AP
Definition wifi-mac.h:60
@ WIFI_MOD_CLASS_HR_DSSS
HR/DSSS (Clause 16)
@ WIFI_MOD_CLASS_DSSS
DSSS (Clause 15)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:587
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.
CtrlTriggerHeader muRts
MU-RTS.
WifiTxVector muRtsTxVector
MU-RTS TXVECTOR.