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 return tid;
56}
57
59{
60 NS_LOG_FUNCTION(this);
61}
62
64{
66}
67
68std::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
134std::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
174std::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
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() &&
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
343std::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
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.
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
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:66
@ 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.