A Discrete-Event Network Simulator
API
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 "wifi-mpdu.h"
24 #include "wifi-tx-parameters.h"
25 
26 #include "ns3/boolean.h"
27 #include "ns3/erp-ofdm-phy.h"
28 #include "ns3/log.h"
29 
30 #include <type_traits>
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("WifiDefaultProtectionManager");
36 
37 NS_OBJECT_ENSURE_REGISTERED(WifiDefaultProtectionManager);
38 
39 TypeId
41 {
42  static TypeId tid =
43  TypeId("ns3::WifiDefaultProtectionManager")
45  .SetGroupName("Wifi")
46  .AddConstructor<WifiDefaultProtectionManager>()
47  .AddAttribute("EnableMuRts",
48  "If enabled, always protect a DL/UL MU frame exchange with MU-RTS/CTS.",
49  BooleanValue(false),
52  return tid;
53 }
54 
56 {
57  NS_LOG_FUNCTION(this);
58 }
59 
61 {
63 }
64 
65 std::unique_ptr<WifiProtection>
67 {
68  NS_LOG_FUNCTION(this << *mpdu << &txParams);
69 
70  // For a DL MU PPDU containing more than one PSDU, call a separate method.
71  // A DL MU PPDU contains more than one PSDU if either the TX params' PSDU info map
72  // contains more than one entry or it contains one entry but the MPDU being added is
73  // addressed to a different receiver (hence generating a new entry if the MPDU is added)
74  if (const auto& psduInfoMap = txParams.GetPsduInfoMap();
75  txParams.m_txVector.IsDlMu() &&
76  (psduInfoMap.size() > 1 ||
77  (psduInfoMap.size() == 1 && psduInfoMap.begin()->first != mpdu->GetHeader().GetAddr1())))
78  {
79  return TryAddMpduToMuPpdu(mpdu, txParams);
80  }
81 
82  // No protection for TB PPDUs (the soliciting Trigger Frame can be protected by an MU-RTS)
83  if (txParams.m_txVector.IsUlMu())
84  {
85  if (txParams.m_protection)
86  {
87  NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
88  return nullptr;
89  }
90  return std::unique_ptr<WifiProtection>(new WifiNoProtection);
91  }
92 
93  // if this is a Trigger Frame, call a separate method
94  if (mpdu->GetHeader().IsTrigger())
95  {
96  return TryUlMuTransmission(mpdu, txParams);
97  }
98 
99  // if the current protection method (if any) is already RTS/CTS or CTS-to-Self,
100  // it will not change by adding an MPDU
101  if (txParams.m_protection && (txParams.m_protection->method == WifiProtection::RTS_CTS ||
102  txParams.m_protection->method == WifiProtection::CTS_TO_SELF))
103  {
104  return nullptr;
105  }
106 
107  // if a protection method is set, it must be NONE
108  NS_ASSERT(!txParams.m_protection || txParams.m_protection->method == WifiProtection::NONE);
109 
110  std::unique_ptr<WifiProtection> protection;
111  protection =
112  GetPsduProtection(mpdu->GetHeader(), txParams.GetSizeIfAddMpdu(mpdu), txParams.m_txVector);
113 
114  // return the newly computed method if none was set or it is not NONE
115  if (!txParams.m_protection || protection->method != WifiProtection::NONE)
116  {
117  return protection;
118  }
119  // the protection method has not changed
120  return nullptr;
121 }
122 
123 std::unique_ptr<WifiProtection>
125  const WifiTxParameters& txParams)
126 {
127  NS_LOG_FUNCTION(this << *msdu << &txParams);
128 
129  // if the current protection method is already RTS/CTS, CTS-to-Self or MU-RTS/CTS,
130  // it will not change by aggregating an MSDU
131  NS_ASSERT(txParams.m_protection);
132  if (txParams.m_protection->method == WifiProtection::RTS_CTS ||
133  txParams.m_protection->method == WifiProtection::CTS_TO_SELF ||
134  txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
135  {
136  return nullptr;
137  }
138 
139  NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
140 
141  // No protection for TB PPDUs and DL MU PPDUs containing more than one PSDU
142  if (txParams.m_txVector.IsUlMu() ||
143  (txParams.m_txVector.IsDlMu() && txParams.GetPsduInfoMap().size() > 1))
144  {
145  return nullptr;
146  }
147 
148  std::unique_ptr<WifiProtection> protection;
149  protection = GetPsduProtection(msdu->GetHeader(),
150  txParams.GetSizeIfAggregateMsdu(msdu).second,
151  txParams.m_txVector);
152 
153  // the protection method may still be none
154  if (protection->method == WifiProtection::NONE)
155  {
156  return nullptr;
157  }
158 
159  // the protection method has changed
160  return protection;
161 }
162 
163 std::unique_ptr<WifiProtection>
165  uint32_t size,
166  const WifiTxVector& txVector) const
167 {
168  NS_LOG_FUNCTION(this << hdr << size << txVector);
169 
170  // a non-initial fragment does not need to be protected, unless it is being retransmitted
171  if (hdr.GetFragmentNumber() > 0 && !hdr.IsRetry())
172  {
173  return std::unique_ptr<WifiProtection>(new WifiNoProtection());
174  }
175 
176  // check if RTS/CTS is needed
177  if (GetWifiRemoteStationManager()->NeedRts(hdr, size))
178  {
179  WifiRtsCtsProtection* protection = new WifiRtsCtsProtection;
181  protection->ctsTxVector =
183  protection->rtsTxVector.GetMode());
184  return std::unique_ptr<WifiProtection>(protection);
185  }
186 
187  // check if CTS-to-Self is needed
188  if (GetWifiRemoteStationManager()->GetUseNonErpProtection() &&
189  GetWifiRemoteStationManager()->NeedCtsToSelf(txVector))
190  {
193  return std::unique_ptr<WifiProtection>(protection);
194  }
195 
196  return std::unique_ptr<WifiProtection>(new WifiNoProtection());
197 }
198 
199 std::unique_ptr<WifiProtection>
201  const WifiTxParameters& txParams)
202 {
203  NS_LOG_FUNCTION(this << *mpdu << &txParams);
204  NS_ASSERT(txParams.m_txVector.IsDlMu());
205 
206  if (!m_sendMuRts)
207  {
208  // No protection because sending MU-RTS is disabled
209  if (txParams.m_protection && txParams.m_protection->method == WifiProtection::NONE)
210  {
211  return nullptr;
212  }
213  return std::unique_ptr<WifiProtection>(new WifiNoProtection());
214  }
215 
216  WifiMuRtsCtsProtection* protection = nullptr;
217  if (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
218  {
219  protection = static_cast<WifiMuRtsCtsProtection*>(txParams.m_protection.get());
220  }
221 
222  auto receiver = mpdu->GetHeader().GetAddr1();
223 
224  if (txParams.GetPsduInfo(receiver) == nullptr)
225  {
226  // we get here if this is the first MPDU for this receiver.
227  NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
228  auto apMac = StaticCast<ApWifiMac>(m_mac);
229  auto txWidth = txParams.m_txVector.GetChannelWidth();
230 
231  if (protection != nullptr)
232  {
233  // txParams.m_protection points to an existing WifiMuRtsCtsProtection object.
234  // We have to return a copy of this object including the needed changes
235  protection = new WifiMuRtsCtsProtection(*protection);
236  }
237  else
238  {
239  // we have to create a new WifiMuRtsCtsProtection object
240  protection = new WifiMuRtsCtsProtection;
241 
242  // initialize the MU-RTS Trigger Frame
243  // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
244  // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
245  // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
246  // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
248  protection->muRts.SetUlBandwidth(txWidth);
249 
250  NS_ASSERT_MSG(txParams.GetPsduInfoMap().size() == 1,
251  "There should be one PSDU in the DL MU PPDU when creating a new "
252  "WifiMuRtsCtsProtection object");
253 
254  // this is the first MPDU for the second receiver added to the DL MU PPDU.
255  // Add a User Info field for the first receiver
256  AddUserInfoToMuRts(protection->muRts,
257  txWidth,
258  txParams.GetPsduInfoMap().cbegin()->first);
259 
260  // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
261  protection->muRtsTxVector = GetWifiRemoteStationManager()->GetRtsTxVector(receiver);
262  // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
263  // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
264  // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
265  protection->muRtsTxVector.SetChannelWidth(txWidth);
266  }
267 
268  // Add a User Info field for the new receiver
269  // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
270  // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
271  AddUserInfoToMuRts(protection->muRts, txWidth, receiver);
272 
273  return std::unique_ptr<WifiMuRtsCtsProtection>(protection);
274  }
275 
276  // an MPDU addressed to the same receiver has been already added
277  NS_ASSERT(protection != nullptr);
278 
279  // no change is needed
280  return nullptr;
281 }
282 
283 std::unique_ptr<WifiProtection>
285  const WifiTxParameters& txParams)
286 {
287  NS_LOG_FUNCTION(this << *mpdu << &txParams);
288  NS_ASSERT(mpdu->GetHeader().IsTrigger());
289 
290  if (!m_sendMuRts)
291  {
292  // No protection because sending MU-RTS is disabled
293  return std::unique_ptr<WifiProtection>(new WifiNoProtection());
294  }
295 
296  CtrlTriggerHeader trigger;
297  mpdu->GetPacket()->PeekHeader(trigger);
298  NS_ASSERT(trigger.GetNUserInfoFields() > 0);
299  auto txWidth = trigger.GetUlBandwidth();
300 
302  // initialize the MU-RTS Trigger Frame
303  // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
304  // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
305  // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
306  // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
308  protection->muRts.SetUlBandwidth(txWidth);
309 
310  NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
311  const auto& staList = StaticCast<ApWifiMac>(m_mac)->GetStaList(m_linkId);
312  std::remove_reference_t<decltype(staList)>::const_iterator staIt;
313 
314  for (const auto& userInfo : trigger)
315  {
316  // Add a User Info field to the MU-RTS for this solicited station
317  // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
318  // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
319  staIt = staList.find(userInfo.GetAid12());
320  NS_ASSERT(staIt != staList.cend());
321  AddUserInfoToMuRts(protection->muRts, txWidth, staIt->second);
322  }
323 
324  // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
325  protection->muRtsTxVector =
326  GetWifiRemoteStationManager()->GetRtsTxVector(mpdu->GetHeader().GetAddr1());
327  // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
328  // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
329  // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
330  protection->muRtsTxVector.SetChannelWidth(txWidth);
331  // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
332  const auto modulation = protection->muRtsTxVector.GetModulationClass();
333  if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
334  {
336  }
337 
338  return std::unique_ptr<WifiMuRtsCtsProtection>(protection);
339 }
340 
341 } // namespace ns3
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for Trigger frames.
Definition: ctrl-headers.h:945
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:78
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
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.
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:418
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.
WifiTxVector GetCtsToSelfTxVector()
Since CTS-to-self parameters are not dependent on the station, it is implemented in wifi remote stati...
WifiTxVector GetCtsTxVector(Mac48Address to, WifiMode rtsTxMode) const
Return a TXVECTOR for the CTS frame given the destination and the mode of the RTS used by the sender.
WifiTxVector GetRtsTxVector(Mac48Address address)
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)
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 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
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:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
#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
@ 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.
@ AP
Definition: wifi-mac.h:63
WifiCtsToSelfProtection specifies that CTS-to-self protection method is used.
WifiTxVector ctsTxVector
CTS TXVECTOR.
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.
CtrlTriggerHeader muRts
MU-RTS.
WifiTxVector muRtsTxVector
MU-RTS TXVECTOR.
WifiNoProtection specifies that no protection method is used.
WifiRtsCtsProtection specifies that RTS/CTS protection method is used.
WifiTxVector ctsTxVector
CTS TXVECTOR.
WifiTxVector rtsTxVector
RTS TXVECTOR.