A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Stefano Avallone <stavallo@unina.it>
18  */
19 
21 
22 #include "ap-wifi-mac.h"
23 #include "frame-exchange-manager.h"
24 #include "sta-wifi-mac.h"
25 #include "wifi-mpdu.h"
26 #include "wifi-tx-parameters.h"
27 
28 #include "ns3/boolean.h"
29 #include "ns3/emlsr-manager.h"
30 #include "ns3/erp-ofdm-phy.h"
31 #include "ns3/log.h"
32 
33 #include <type_traits>
34 
35 namespace ns3
36 {
37 
38 NS_LOG_COMPONENT_DEFINE("WifiDefaultProtectionManager");
39 
40 NS_OBJECT_ENSURE_REGISTERED(WifiDefaultProtectionManager);
41 
42 TypeId
44 {
45  static TypeId tid =
46  TypeId("ns3::WifiDefaultProtectionManager")
48  .SetGroupName("Wifi")
49  .AddConstructor<WifiDefaultProtectionManager>()
50  .AddAttribute("EnableMuRts",
51  "If enabled, always protect a DL/UL MU frame exchange with MU-RTS/CTS.",
52  BooleanValue(false),
55  return tid;
56 }
57 
59 {
60  NS_LOG_FUNCTION(this);
61 }
62 
64 {
66 }
67 
68 std::unique_ptr<WifiProtection>
70 {
71  NS_LOG_FUNCTION(this << *mpdu << &txParams);
72 
73  // Call a separate method that handles MU-RTS/CTS protection in case of DL MU PPDU containing
74  // more than one PSDU or in case the MPDU being added is addressed to an EMLSR client or in
75  // case the protection method is already MU-RTS/CTS.
76  // A DL MU PPDU contains more than one PSDU if either the TX params' PSDU info map
77  // contains more than one entry or it contains one entry but the MPDU being added is
78  // addressed to a different receiver (hence generating a new entry if the MPDU is added)
79  const auto& psduInfoMap = txParams.GetPsduInfoMap();
80  auto dlMuPpdu =
81  txParams.m_txVector.IsDlMu() &&
82  (psduInfoMap.size() > 1 ||
83  (psduInfoMap.size() == 1 && psduInfoMap.begin()->first != mpdu->GetHeader().GetAddr1()));
84  auto isEmlsrDestination =
85  GetWifiRemoteStationManager()->GetEmlsrEnabled(mpdu->GetHeader().GetAddr1());
86 
87  if (dlMuPpdu || isEmlsrDestination ||
88  (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS))
89  {
90  return TryAddMpduToMuPpdu(mpdu, txParams);
91  }
92 
93  // No protection for TB PPDUs (the soliciting Trigger Frame can be protected by an MU-RTS)
94  if (txParams.m_txVector.IsUlMu())
95  {
96  if (txParams.m_protection)
97  {
98  NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
99  return nullptr;
100  }
101  return std::make_unique<WifiNoProtection>();
102  }
103 
104  // if this is a Trigger Frame, call a separate method
105  if (mpdu->GetHeader().IsTrigger())
106  {
107  return TryUlMuTransmission(mpdu, txParams);
108  }
109 
110  // if the current protection method (if any) is already RTS/CTS or CTS-to-Self,
111  // it will not change by adding an MPDU
112  if (txParams.m_protection && (txParams.m_protection->method == WifiProtection::RTS_CTS ||
113  txParams.m_protection->method == WifiProtection::CTS_TO_SELF))
114  {
115  return nullptr;
116  }
117 
118  // if a protection method is set, it must be NONE
119  NS_ASSERT(!txParams.m_protection || txParams.m_protection->method == WifiProtection::NONE);
120 
121  std::unique_ptr<WifiProtection> protection;
122  protection =
123  GetPsduProtection(mpdu->GetHeader(), txParams.GetSizeIfAddMpdu(mpdu), txParams.m_txVector);
124 
125  // return the newly computed method if none was set or it is not NONE
126  if (!txParams.m_protection || protection->method != WifiProtection::NONE)
127  {
128  return protection;
129  }
130  // the protection method has not changed
131  return nullptr;
132 }
133 
134 std::unique_ptr<WifiProtection>
136  const WifiTxParameters& txParams)
137 {
138  NS_LOG_FUNCTION(this << *msdu << &txParams);
139 
140  // if the current protection method is already RTS/CTS, CTS-to-Self or MU-RTS/CTS,
141  // it will not change by aggregating an MSDU
142  NS_ASSERT(txParams.m_protection);
143  if (txParams.m_protection->method == WifiProtection::RTS_CTS ||
144  txParams.m_protection->method == WifiProtection::CTS_TO_SELF ||
145  txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
146  {
147  return nullptr;
148  }
149 
150  NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
151 
152  // No protection for TB PPDUs and DL MU PPDUs containing more than one PSDU
153  if (txParams.m_txVector.IsUlMu() ||
154  (txParams.m_txVector.IsDlMu() && txParams.GetPsduInfoMap().size() > 1))
155  {
156  return nullptr;
157  }
158 
159  std::unique_ptr<WifiProtection> protection;
160  protection = GetPsduProtection(msdu->GetHeader(),
161  txParams.GetSizeIfAggregateMsdu(msdu).second,
162  txParams.m_txVector);
163 
164  // the protection method may still be none
165  if (protection->method == WifiProtection::NONE)
166  {
167  return nullptr;
168  }
169 
170  // the protection method has changed
171  return protection;
172 }
173 
174 std::unique_ptr<WifiProtection>
176  uint32_t size,
177  const WifiTxVector& txVector) const
178 {
179  NS_LOG_FUNCTION(this << hdr << size << txVector);
180 
181  // a non-initial fragment does not need to be protected, unless it is being retransmitted
182  if (hdr.GetFragmentNumber() > 0 && !hdr.IsRetry())
183  {
184  return std::make_unique<WifiNoProtection>();
185  }
186 
187  // no need to use protection if destination already received an RTS in this TXOP
188  if (m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas().count(hdr.GetAddr1()) == 1)
189  {
190  return std::make_unique<WifiNoProtection>();
191  }
192 
193  // when an EMLSR client starts an UL TXOP on a link while the MediumSyncDelay timer is running
194  // or on a link on which the main PHY is not operating, it needs to send an RTS frame
195  bool emlsrNeedRts = false;
196 
197  if (auto staMac = DynamicCast<StaWifiMac>(m_mac))
198  {
199  auto emlsrManager = staMac->GetEmlsrManager();
200 
201  emlsrNeedRts = emlsrManager && staMac->IsEmlsrLink(m_linkId) &&
202  (emlsrManager->GetElapsedMediumSyncDelayTimer(m_linkId) ||
203  m_mac->GetLinkForPhy(emlsrManager->GetMainPhyId()) != m_linkId);
204  }
205 
206  // check if RTS/CTS is needed
207  if (emlsrNeedRts || GetWifiRemoteStationManager()->NeedRts(hdr, size))
208  {
209  auto protection = std::make_unique<WifiRtsCtsProtection>();
210  protection->rtsTxVector =
211  GetWifiRemoteStationManager()->GetRtsTxVector(hdr.GetAddr1(),
212  txVector.GetChannelWidth());
213  protection->ctsTxVector =
214  GetWifiRemoteStationManager()->GetCtsTxVector(hdr.GetAddr1(),
215  protection->rtsTxVector.GetMode());
216  return protection;
217  }
218 
219  // check if CTS-to-Self is needed
220  if (GetWifiRemoteStationManager()->GetUseNonErpProtection() &&
221  GetWifiRemoteStationManager()->NeedCtsToSelf(txVector))
222  {
223  auto protection = std::make_unique<WifiCtsToSelfProtection>();
224  protection->ctsTxVector = GetWifiRemoteStationManager()->GetCtsToSelfTxVector();
225  return protection;
226  }
227 
228  return std::make_unique<WifiNoProtection>();
229 }
230 
231 std::unique_ptr<WifiProtection>
233  const WifiTxParameters& txParams)
234 {
235  NS_LOG_FUNCTION(this << *mpdu << &txParams);
236 
237  auto receiver = mpdu->GetHeader().GetAddr1();
238  const auto& psduInfoMap = txParams.GetPsduInfoMap();
239  auto dlMuPpdu = txParams.m_txVector.IsDlMu() &&
240  (psduInfoMap.size() > 1 ||
241  (psduInfoMap.size() == 1 && psduInfoMap.begin()->first != receiver));
242  auto isEmlsrDestination = GetWifiRemoteStationManager()->GetEmlsrEnabled(receiver);
243  NS_ASSERT(
244  dlMuPpdu || isEmlsrDestination ||
245  (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS));
246 
247  auto isProtected =
248  m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas().count(receiver) == 1;
249  bool needMuRts =
250  (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS) ||
251  (dlMuPpdu && m_sendMuRts && !isProtected) || (isEmlsrDestination && !isProtected);
252 
253  if (!needMuRts)
254  {
255  // No protection needed
256  if (txParams.m_protection && txParams.m_protection->method == WifiProtection::NONE)
257  {
258  return nullptr;
259  }
260  return std::make_unique<WifiNoProtection>();
261  }
262 
263  WifiMuRtsCtsProtection* protection = nullptr;
264  if (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
265  {
266  protection = static_cast<WifiMuRtsCtsProtection*>(txParams.m_protection.get());
267  }
268 
269  if (txParams.GetPsduInfo(receiver) == nullptr)
270  {
271  // we get here if this is the first MPDU for this receiver.
272  NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
273  auto apMac = StaticCast<ApWifiMac>(m_mac);
274  auto modClass = txParams.m_txVector.GetModulationClass();
275  auto txWidth = modClass == WIFI_MOD_CLASS_DSSS || modClass == WIFI_MOD_CLASS_HR_DSSS
276  ? 20
277  : txParams.m_txVector.GetChannelWidth();
278 
279  if (protection != nullptr)
280  {
281  // txParams.m_protection points to an existing WifiMuRtsCtsProtection object.
282  // We have to return a copy of this object including the needed changes
283  protection = new WifiMuRtsCtsProtection(*protection);
284  }
285  else
286  {
287  // we have to create a new WifiMuRtsCtsProtection object
288  protection = new WifiMuRtsCtsProtection;
289 
290  // initialize the MU-RTS Trigger Frame
291  // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
292  // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
293  // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
294  // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
296  protection->muRts.SetUlBandwidth(txWidth);
297 
298  // Add a User Info field for each of the receivers already in the TX params
299  for (const auto& [address, info] : txParams.GetPsduInfoMap())
300  {
301  NS_ASSERT_MSG(address != receiver, "This must be the first MPDU for " << receiver);
302  AddUserInfoToMuRts(protection->muRts, txWidth, address);
303  }
304 
305  // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
306  protection->muRtsTxVector =
307  GetWifiRemoteStationManager()->GetRtsTxVector(receiver, txWidth);
308  // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
309  // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
310  // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
311  protection->muRtsTxVector.SetChannelWidth(txWidth);
312  // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
313  const auto modulation = protection->muRtsTxVector.GetModulationClass();
314  if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
315  {
317  }
318  }
319 
320  // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or
321  // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s.
322  // (Sec. 35.3.17 of 802.11be D3.0)
323  if (isEmlsrDestination && !isProtected)
324  {
325  GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector);
326  }
327 
328  // Add a User Info field for the new receiver
329  // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
330  // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
331  AddUserInfoToMuRts(protection->muRts, txWidth, receiver);
332 
333  return std::unique_ptr<WifiMuRtsCtsProtection>(protection);
334  }
335 
336  // an MPDU addressed to the same receiver has been already added
337  NS_ASSERT(protection != nullptr);
338 
339  // no change is needed
340  return nullptr;
341 }
342 
343 std::unique_ptr<WifiProtection>
345  const WifiTxParameters& txParams)
346 {
347  NS_LOG_FUNCTION(this << *mpdu << &txParams);
348  NS_ASSERT(mpdu->GetHeader().IsTrigger());
349 
350  CtrlTriggerHeader trigger;
351  mpdu->GetPacket()->PeekHeader(trigger);
352  NS_ASSERT(trigger.GetNUserInfoFields() > 0);
353  auto txWidth = trigger.GetUlBandwidth();
354 
355  auto protection = std::make_unique<WifiMuRtsCtsProtection>();
356  // initialize the MU-RTS Trigger Frame
357  // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
358  // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
359  // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
360  // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
361  protection->muRts.SetType(TriggerFrameType::MU_RTS_TRIGGER);
362  protection->muRts.SetUlBandwidth(txWidth);
363 
364  NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
365  const auto& staList = StaticCast<ApWifiMac>(m_mac)->GetStaList(m_linkId);
366 
367  bool allProtected = true;
368  bool isUnprotectedEmlsrDst = false;
369 
370  for (const auto& userInfo : trigger)
371  {
372  // Add a User Info field to the MU-RTS for this solicited station
373  // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
374  // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
375  auto staIt = staList.find(userInfo.GetAid12());
376  NS_ASSERT(staIt != staList.cend());
377  AddUserInfoToMuRts(protection->muRts, txWidth, staIt->second);
378  bool isProtected =
379  m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas().count(staIt->second) == 1;
380  allProtected = allProtected && isProtected;
381 
382  isUnprotectedEmlsrDst =
383  isUnprotectedEmlsrDst ||
384  (!isProtected && GetWifiRemoteStationManager()->GetEmlsrEnabled(staIt->second));
385  }
386 
387  bool needMuRts = (m_sendMuRts && !allProtected) || isUnprotectedEmlsrDst;
388 
389  if (!needMuRts)
390  {
391  // No protection needed
392  return std::make_unique<WifiNoProtection>();
393  }
394 
395  // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
396  protection->muRtsTxVector =
397  GetWifiRemoteStationManager()->GetRtsTxVector(mpdu->GetHeader().GetAddr1(), txWidth);
398  // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
399  // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
400  // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
401  protection->muRtsTxVector.SetChannelWidth(txWidth);
402  // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
403  const auto modulation = protection->muRtsTxVector.GetModulationClass();
404  if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
405  {
406  protection->muRtsTxVector.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps());
407  }
408  // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or
409  // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s.
410  // (Sec. 35.3.17 of 802.11be D3.0)
411  if (isUnprotectedEmlsrDst)
412  {
413  GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector);
414  }
415 
416  return protection;
417 }
418 
419 } // namespace ns3
Headers for Trigger frames.
Definition: ctrl-headers.h:942
void SetUlBandwidth(uint16_t bw)
Set the bandwidth of the solicited HE TB PPDU.
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.
uint16_t GetUlBandwidth() const
Get the bandwidth of the solicited HE TB PPDU.
static WifiMode GetErpOfdmRate6Mbps()
Return a WifiMode for ERP-OFDM at 6 Mbps.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
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
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.
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 > 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...
virtual std::unique_ptr< WifiProtection > GetPsduProtection(const WifiMacHeader &hdr, uint32_t size, const WifiTxVector &txVector) const
Select the protection method for a single PSDU.
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.
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:864
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:422
std::optional< uint8_t > GetLinkForPhy(Ptr< const WifiPhy > phy) const
Get the ID of the link (if any) on which the given PHY is operating.
Definition: wifi-mac.cc:974
WifiProtectionManager is an abstract base class.
Ptr< WifiMac > m_mac
MAC which is using this Protection Manager.
void AddUserInfoToMuRts(CtrlTriggerHeader &muRts, uint16_t 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,...
uint32_t GetSizeIfAddMpdu(Ptr< const WifiMpdu > mpdu) const
Get the size in bytes of the frame in case the given MPDU is added.
const PsduInfoMap & GetPsduInfoMap() const
Get a const reference to the map containing information about PSDUs.
std::pair< uint32_t, uint32_t > GetSizeIfAggregateMsdu(Ptr< const WifiMpdu > msdu) const
Get the size in bytes of the frame in case the given MSDU is aggregated.
std::unique_ptr< WifiProtection > m_protection
protection method
const PsduInfo * GetPsduInfo(Mac48Address receiver) const
Get a pointer to the information about the PSDU addressed to the given receiver, if present,...
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
bool IsDlMu() const
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
bool IsUlMu() const
uint16_t GetChannelWidth() const
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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:46
@ AP
Definition: wifi-mac.h:66
@ WIFI_MOD_CLASS_HR_DSSS
HR/DSSS (Clause 16)
@ WIFI_MOD_CLASS_DSSS
DSSS (Clause 15)
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.
CtrlTriggerHeader muRts
MU-RTS.
WifiTxVector muRtsTxVector
MU-RTS TXVECTOR.