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 * 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"
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
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("WifiDefaultProtectionManager");
39
40NS_OBJECT_ENSURE_REGISTERED(WifiDefaultProtectionManager);
41
42TypeId
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 .AddAttribute("SingleRtsPerTxop",
56 "If enabled, a protection mechanism (RTS or MU-RTS) is normally used no "
57 "more than once in a TXOP, regardless of the destination of the data "
58 "frame (unless required for specific purposes, such as transmitting an "
59 "Initial Control Frame to an EMLSR client).",
60 BooleanValue(false),
63 return tid;
64}
65
67{
68 NS_LOG_FUNCTION(this);
69}
70
72{
74}
75
76std::unique_ptr<WifiProtection>
78{
79 NS_LOG_FUNCTION(this << *mpdu << &txParams);
80
81 // Call a separate method that handles MU-RTS/CTS protection in case of DL MU PPDU containing
82 // more than one PSDU or in case the MPDU being added is addressed to an EMLSR client or in
83 // case the protection method is already MU-RTS/CTS.
84 const auto& psduInfoMap = txParams.GetPsduInfoMap();
85 auto dlMuPpdu = txParams.m_txVector.IsDlMu() && psduInfoMap.size() > 1;
86 const auto& hdr = mpdu->GetHeader();
87 auto isEmlsrDestination = GetWifiRemoteStationManager()->GetEmlsrEnabled(hdr.GetAddr1());
88
89 if (dlMuPpdu || isEmlsrDestination ||
90 (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS))
91 {
92 return TryAddMpduToMuPpdu(mpdu, txParams);
93 }
94
95 // No protection for TB PPDUs (the soliciting Trigger Frame can be protected by an MU-RTS)
96 if (txParams.m_txVector.IsUlMu())
97 {
98 if (txParams.m_protection)
99 {
100 NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
101 return nullptr;
102 }
103 return std::make_unique<WifiNoProtection>();
104 }
105
106 // if this is a Trigger Frame, call a separate method
107 if (hdr.IsTrigger())
108 {
109 return TryUlMuTransmission(mpdu, txParams);
110 }
111
112 // if the current protection method (if any) is already RTS/CTS or CTS-to-Self,
113 // it will not change by adding an MPDU
114 if (txParams.m_protection && (txParams.m_protection->method == WifiProtection::RTS_CTS ||
115 txParams.m_protection->method == WifiProtection::CTS_TO_SELF))
116 {
117 return nullptr;
118 }
119
120 // if a protection method is set, it must be NONE
121 NS_ASSERT(!txParams.m_protection || txParams.m_protection->method == WifiProtection::NONE);
122
123 std::unique_ptr<WifiProtection> protection;
124 protection = GetPsduProtection(hdr, txParams);
125
126 // return the newly computed method if none was set or it is not NONE
127 if (!txParams.m_protection || protection->method != WifiProtection::NONE)
128 {
129 return protection;
130 }
131 // the protection method has not changed
132 return nullptr;
133}
134
135std::unique_ptr<WifiProtection>
137 const WifiTxParameters& txParams)
138{
139 NS_LOG_FUNCTION(this << *msdu << &txParams);
140
141 // if the current protection method is already RTS/CTS, CTS-to-Self or MU-RTS/CTS,
142 // it will not change by aggregating an MSDU
143 NS_ASSERT(txParams.m_protection);
144 if (txParams.m_protection->method == WifiProtection::RTS_CTS ||
145 txParams.m_protection->method == WifiProtection::CTS_TO_SELF ||
146 txParams.m_protection->method == WifiProtection::MU_RTS_CTS)
147 {
148 return nullptr;
149 }
150
151 NS_ASSERT(txParams.m_protection->method == WifiProtection::NONE);
152
153 // No protection for TB PPDUs and DL MU PPDUs containing more than one PSDU
154 if (txParams.m_txVector.IsUlMu() ||
155 (txParams.m_txVector.IsDlMu() && txParams.GetPsduInfoMap().size() > 1))
156 {
157 return nullptr;
158 }
159
160 std::unique_ptr<WifiProtection> protection;
161 protection = GetPsduProtection(msdu->GetHeader(), txParams);
162
163 // the protection method may still be none
164 if (protection->method == WifiProtection::NONE)
165 {
166 return nullptr;
167 }
168
169 // the protection method has changed
170 return protection;
171}
172
173std::unique_ptr<WifiProtection>
175 const WifiTxParameters& txParams) const
176{
177 NS_LOG_FUNCTION(this << hdr << &txParams);
178
179 // a non-initial fragment does not need to be protected, unless it is being retransmitted
180 if (hdr.GetFragmentNumber() > 0 && !hdr.IsRetry())
181 {
182 return std::make_unique<WifiNoProtection>();
183 }
184
185 // no need to use protection if destination already received an RTS in this TXOP or
186 // SingleRtsPerTxop is true and a protection mechanism has been already used in this TXOP
187 if (const auto& protectedStas = m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas();
188 protectedStas.contains(hdr.GetAddr1()) || (m_singleRtsPerTxop && !protectedStas.empty()))
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, txParams))
208 {
209 auto protection = std::make_unique<WifiRtsCtsProtection>();
210 protection->rtsTxVector =
211 GetWifiRemoteStationManager()->GetRtsTxVector(hdr.GetAddr1(),
212 txParams.m_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(txParams.m_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
231std::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() && psduInfoMap.size() > 1;
240 auto isEmlsrDestination = GetWifiRemoteStationManager()->GetEmlsrEnabled(receiver);
241 NS_ASSERT(
242 dlMuPpdu || isEmlsrDestination ||
243 (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS));
244
245 const auto& protectedStas = m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas();
246 const auto isProtected = protectedStas.contains(receiver);
247 bool needMuRts =
248 (txParams.m_protection && txParams.m_protection->method == WifiProtection::MU_RTS_CTS) ||
249 (dlMuPpdu && m_sendMuRts && !isProtected &&
250 (!m_singleRtsPerTxop || protectedStas.empty())) ||
251 (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.LastAddedIsFirstMpdu(receiver))
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 // Add a User Info field for the new receiver
286 // The UL HE-MCS, UL FEC Coding Type, UL DCM, SS Allocation and UL Target RSSI fields
287 // in the User Info field are reserved (Sec. 9.3.1.22.5 of 802.11ax)
288 AddUserInfoToMuRts(protection->muRts, txWidth, receiver);
289 }
290 else
291 {
292 // we have to create a new WifiMuRtsCtsProtection object
293 protection = new WifiMuRtsCtsProtection;
294
295 // initialize the MU-RTS Trigger Frame
296 // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
297 // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
298 // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
299 // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
301 protection->muRts.SetUlBandwidth(txWidth);
302
303 // Add a User Info field for each of the receivers already in the TX params
304 for (const auto& [address, info] : txParams.GetPsduInfoMap())
305 {
306 AddUserInfoToMuRts(protection->muRts, txWidth, address);
307 }
308
309 // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
310 protection->muRtsTxVector =
311 GetWifiRemoteStationManager()->GetRtsTxVector(receiver, txWidth);
312 // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
313 // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
314 // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
315 protection->muRtsTxVector.SetChannelWidth(txWidth);
316 // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
317 const auto modulation = protection->muRtsTxVector.GetModulationClass();
318 if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
319 {
321 }
322 }
323
324 // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or
325 // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s.
326 // (Sec. 35.3.17 of 802.11be D3.0)
327 if (isEmlsrDestination && !isProtected)
328 {
329 GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector);
330 }
331
332 return std::unique_ptr<WifiMuRtsCtsProtection>(protection);
333 }
334
335 // an MPDU addressed to the same receiver has been already added
336 NS_ASSERT(protection != nullptr);
337
338 // no change is needed
339 return nullptr;
340}
341
342std::unique_ptr<WifiProtection>
344 const WifiTxParameters& txParams)
345{
346 NS_LOG_FUNCTION(this << *mpdu << &txParams);
347 NS_ASSERT(mpdu->GetHeader().IsTrigger());
348
349 CtrlTriggerHeader trigger;
350 mpdu->GetPacket()->PeekHeader(trigger);
351 NS_ASSERT(trigger.GetNUserInfoFields() > 0);
352 auto txWidth = trigger.GetUlBandwidth();
353
354 auto protection = std::make_unique<WifiMuRtsCtsProtection>();
355 // initialize the MU-RTS Trigger Frame
356 // The UL Length, GI And HE-LTF Type, MU-MIMO HE-LTF Mode, Number Of HE-LTF Symbols,
357 // UL STBC, LDPC Extra Symbol Segment, AP TX Power, Pre-FEC Padding Factor,
358 // PE Disambiguity, UL Spatial Reuse, Doppler and UL HE-SIG-A2 Reserved subfields in
359 // the Common Info field are reserved. (Sec. 9.3.1.22.5 of 802.11ax)
360 protection->muRts.SetType(TriggerFrameType::MU_RTS_TRIGGER);
361 protection->muRts.SetUlBandwidth(txWidth);
362
363 NS_ABORT_MSG_IF(m_mac->GetTypeOfStation() != AP, "HE APs only can send DL MU PPDUs");
364 const auto& staList = StaticCast<ApWifiMac>(m_mac)->GetStaList(m_linkId);
365
366 const auto& protectedStas = m_mac->GetFrameExchangeManager(m_linkId)->GetProtectedStas();
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 const auto isProtected = protectedStas.contains(staIt->second);
379 allProtected = allProtected && isProtected;
380
381 isUnprotectedEmlsrDst =
382 isUnprotectedEmlsrDst ||
383 (!isProtected && GetWifiRemoteStationManager()->GetEmlsrEnabled(staIt->second));
384 }
385
386 bool needMuRts =
387 (m_sendMuRts && !allProtected && (!m_singleRtsPerTxop || protectedStas.empty())) ||
388 isUnprotectedEmlsrDst;
389
390 if (!needMuRts)
391 {
392 // No protection needed
393 return std::make_unique<WifiNoProtection>();
394 }
395
396 // compute the TXVECTOR to use to send the MU-RTS Trigger Frame
397 protection->muRtsTxVector =
398 GetWifiRemoteStationManager()->GetRtsTxVector(mpdu->GetHeader().GetAddr1(), txWidth);
399 // The transmitter of an MU-RTS Trigger frame shall not request a non-AP STA to send
400 // a CTS frame response in a 20 MHz channel that is not occupied by the PPDU that
401 // contains the MU-RTS Trigger frame. (Sec. 26.2.6.2 of 802.11ax)
402 protection->muRtsTxVector.SetChannelWidth(txWidth);
403 // OFDM is needed to transmit the PPDU over a bandwidth that is a multiple of 20 MHz
404 const auto modulation = protection->muRtsTxVector.GetModulationClass();
405 if (modulation == WIFI_MOD_CLASS_DSSS || modulation == WIFI_MOD_CLASS_HR_DSSS)
406 {
407 protection->muRtsTxVector.SetMode(ErpOfdmPhy::GetErpOfdmRate6Mbps());
408 }
409 // The initial Control frame of frame exchanges shall be sent in the non-HT PPDU or
410 // non-HT duplicate PPDU format using a rate of 6 Mb/s, 12 Mb/s, or 24 Mb/s.
411 // (Sec. 35.3.17 of 802.11be D3.0)
412 if (isUnprotectedEmlsrDst)
413 {
414 GetWifiRemoteStationManager()->AdjustTxVectorForIcf(protection->muRtsTxVector);
415 }
416
417 return protection;
418}
419
420} // namespace ns3
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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:932
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.
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.
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:878
TypeOfStation GetTypeOfStation() const
Return the type of station.
Definition: wifi-mac.cc:436
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:988
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,...
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(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
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
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
@ AP
Definition: wifi-mac.h:69
@ 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.
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.
CtrlTriggerHeader muRts
MU-RTS.
WifiTxVector muRtsTxVector
MU-RTS TXVECTOR.