A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
eht-frame-exchange-manager.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022 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 "eht-phy.h"
23
24#include "ns3/abort.h"
25#include "ns3/ap-wifi-mac.h"
26#include "ns3/log.h"
27#include "ns3/wifi-mac-queue.h"
28
29#undef NS_LOG_APPEND_CONTEXT
30#define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("EhtFrameExchangeManager");
36
37NS_OBJECT_ENSURE_REGISTERED(EhtFrameExchangeManager);
38
39TypeId
41{
42 static TypeId tid = TypeId("ns3::EhtFrameExchangeManager")
44 .AddConstructor<EhtFrameExchangeManager>()
45 .SetGroupName("Wifi");
46 return tid;
47}
48
50{
51 NS_LOG_FUNCTION(this);
52}
53
55{
57}
58
59void
61{
62 m_msduAggregator->SetLinkId(linkId);
63 m_mpduAggregator->SetLinkId(linkId);
65}
66
69{
70 NS_LOG_FUNCTION(this << *mpdu);
71
72 // alias needs only be created for non-broadcast QoS data frames exchanged between two MLDs
73 if (!mpdu->GetHeader().IsQosData() || m_mac->GetNLinks() == 1 ||
74 mpdu->GetHeader().GetAddr1().IsGroup() ||
75 !GetWifiRemoteStationManager()->GetMldAddress(mpdu->GetHeader().GetAddr1()))
76 {
78 }
79
80 mpdu = mpdu->CreateAlias(m_linkId);
81 auto& hdr = mpdu->GetHeader();
82 hdr.SetAddr2(GetAddress());
83 auto address = GetWifiRemoteStationManager()->GetAffiliatedStaAddress(hdr.GetAddr1());
84 NS_ASSERT(address);
85 hdr.SetAddr1(*address);
86 /*
87 * Set Address3 according to Table 9-30 of 802.11-2020 and Section 35.3.3 of
88 * 802.11be D2.0 ["the value of the Address 3 field and the Address 4 field (if present)
89 * in the MAC header of a data frame shall be set based on Table 9-30 (Address field
90 * contents) and the settings of the To DS and From DS bits, where the BSSID is the
91 * MAC address of the AP affiliated with the AP MLD corresponding to that link"].
92 */
93 if (hdr.IsQosAmsdu())
94 {
95 if (hdr.IsToDs() && !hdr.IsFromDs())
96 {
97 // from STA to AP: BSSID is in Address1
98 hdr.SetAddr3(hdr.GetAddr1());
99 }
100 else if (!hdr.IsToDs() && hdr.IsFromDs())
101 {
102 // from AP to STA: BSSID is in Address2
103 hdr.SetAddr3(hdr.GetAddr2());
104 }
105 }
106
107 return mpdu;
108}
109
110void
112{
113 NS_LOG_FUNCTION(this << psdu << txVector);
114
115 // EHT-SIG, the equivalent of HE-SIG-B, is present in EHT SU transmissions, too
116 if (txVector.GetPreambleType() == WIFI_PREAMBLE_EHT_MU)
117 {
118 auto phy = StaticCast<EhtPhy>(m_phy->GetPhyEntity(WIFI_MOD_CLASS_EHT));
119 auto sigBMode = phy->GetSigBMode(txVector);
120 txVector.SetSigBMode(sigBMode);
121 }
122
123 if (!m_apMac)
124 {
126 return;
127 }
128
129 auto txDuration = WifiPhy::CalculateTxDuration(psdu, txVector, m_phy->GetPhyBand());
130
131 // check if the EMLSR clients shall switch back to listening operation at the end of this PPDU
132 for (auto clientIt = m_protectedStas.begin(); clientIt != m_protectedStas.end();)
133 {
134 auto aid = GetWifiRemoteStationManager()->GetAssociationId(*clientIt);
135
136 if (GetWifiRemoteStationManager()->GetEmlsrEnabled(*clientIt) &&
137 GetEmlsrSwitchToListening(psdu, aid, *clientIt))
138 {
139 EmlsrSwitchToListening(*clientIt, txDuration);
140 // this client is no longer involved in the current TXOP
141 clientIt = m_protectedStas.erase(clientIt);
142 }
143 else
144 {
145 clientIt++;
146 }
147 }
148
150}
151
152void
154{
155 NS_LOG_FUNCTION(this << psduMap << txVector);
156
157 if (!m_apMac)
158 {
160 return;
161 }
162
163 auto txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, m_phy->GetPhyBand());
164
165 // check if the EMLSR clients shall switch back to listening operation at the end of this PPDU
166 for (auto clientIt = m_protectedStas.begin(); clientIt != m_protectedStas.end();)
167 {
168 auto aid = GetWifiRemoteStationManager()->GetAssociationId(*clientIt);
169
170 if (auto psduMapIt = psduMap.find(aid);
171 GetWifiRemoteStationManager()->GetEmlsrEnabled(*clientIt) &&
172 (psduMapIt == psduMap.cend() ||
173 GetEmlsrSwitchToListening(psduMapIt->second, aid, *clientIt)))
174 {
175 EmlsrSwitchToListening(*clientIt, txDuration);
176 // this client is no longer involved in the current TXOP
177 clientIt = m_protectedStas.erase(clientIt);
178 }
179 else
180 {
181 clientIt++;
182 }
183 }
184
186}
187
188void
190{
191 NS_LOG_FUNCTION(this << address << delay.As(Time::US));
192
193 // this EMLSR client switches back to listening operation a transition delay
194 // after the given delay
195 auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address);
196 NS_ASSERT(mldAddress);
197 auto emlCapabilities = GetWifiRemoteStationManager()->GetStationEmlCapabilities(address);
198 NS_ASSERT(emlCapabilities);
199
200 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
201 {
202 if (m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
203 {
204 Simulator::Schedule(delay, [=]() {
205 if (linkId != m_linkId)
206 {
207 // the reason for blocking the other EMLSR links has changed now
209 *mldAddress,
210 {linkId});
211 }
212
213 // block DL transmissions on this link until transition delay elapses
215 *mldAddress,
216 {linkId});
217 });
218
219 // unblock all EMLSR links when the transition delay elapses
221 emlCapabilities->emlsrTransitionDelay),
222 [=]() {
223 m_mac->UnblockUnicastTxOnLinks(
224 WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY,
225 *mldAddress,
226 {linkId});
227 });
228 }
229 }
230}
231
232void
233EhtFrameExchangeManager::SendEmlOperatingModeNotification(
234 const Mac48Address& dest,
236{
237 NS_LOG_FUNCTION(this << dest << frame);
238
239 WifiMacHeader hdr;
241 hdr.SetAddr1(dest);
242 hdr.SetAddr2(m_self);
243 hdr.SetAddr3(m_bssid);
244 hdr.SetDsNotTo();
245 hdr.SetDsNotFrom();
246
247 // get the sequence number for the TWT Setup management frame
248 const auto sequence = m_txMiddle->GetNextSequenceNumberFor(&hdr);
249 hdr.SetSequenceNumber(sequence);
250
251 WifiActionHeader actionHdr;
253 action.protectedEhtAction = WifiActionHeader::PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION;
254 actionHdr.SetAction(WifiActionHeader::PROTECTED_EHT, action);
255
256 auto packet = Create<Packet>();
257 packet->AddHeader(frame);
258 packet->AddHeader(actionHdr);
259
260 // Use AC_VO to send management frame addressed to a QoS STA (Sec. 10.2.3.2 of 802.11-2020)
261 m_mac->GetQosTxop(AC_VO)->Queue(Create<WifiMpdu>(packet, hdr));
262}
263
264std::optional<double>
265EhtFrameExchangeManager::GetMostRecentRssi(const Mac48Address& address) const
266{
267 auto optRssi = HeFrameExchangeManager::GetMostRecentRssi(address);
268
269 if (optRssi)
270 {
271 return optRssi;
272 }
273
274 auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address);
275
276 if (!mldAddress)
277 {
278 // not an MLD, nothing else can be done
279 return std::nullopt;
280 }
281
282 for (uint8_t linkId = 0; linkId < m_mac->GetNLinks(); linkId++)
283 {
284 std::optional<Mac48Address> linkAddress;
285 if (linkId != m_linkId &&
286 (linkAddress = m_mac->GetWifiRemoteStationManager(linkId)->GetAffiliatedStaAddress(
287 *mldAddress)) &&
288 (optRssi = m_mac->GetWifiRemoteStationManager(linkId)->GetMostRecentRssi(*linkAddress)))
289 {
290 return optRssi;
291 }
292 }
293
294 return std::nullopt;
295}
296
297void
298EhtFrameExchangeManager::SendMuRts(const WifiTxParameters& txParams)
299{
300 NS_LOG_FUNCTION(this << &txParams);
301
302 uint8_t maxPaddingDelay = 0;
303
304 // block transmissions on the other EMLSR links of the EMLSR clients
305 for (const auto& address : m_sentRtsTo)
306 {
307 if (!GetWifiRemoteStationManager()->GetEmlsrEnabled(address))
308 {
309 continue;
310 }
311
312 auto emlCapabilities = GetWifiRemoteStationManager()->GetStationEmlCapabilities(address);
313 NS_ASSERT(emlCapabilities);
314 maxPaddingDelay = std::max(maxPaddingDelay, emlCapabilities->emlsrPaddingDelay);
315
316 auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address);
317 NS_ASSERT(mldAddress);
318
319 for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
320 {
321 if (linkId != m_linkId &&
322 m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
323 {
324 m_mac->BlockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
325 *mldAddress,
326 {linkId});
327 }
328 }
329 }
330
331 // add padding (if needed)
332 if (maxPaddingDelay > 0)
333 {
334 NS_ASSERT(txParams.m_protection &&
335 txParams.m_protection->method == WifiProtection::MU_RTS_CTS);
336 WifiMuRtsCtsProtection* protection =
337 static_cast<WifiMuRtsCtsProtection*>(txParams.m_protection.get());
338 NS_ASSERT(protection->muRts.IsMuRts());
339
340 // see formula (35-1) in Sec. 35.5.2.2.3 of 802.11be D3.0
341 auto rate = protection->muRtsTxVector.GetMode().GetDataRate(protection->muRtsTxVector);
342 std::size_t nDbps = rate / 1e6 * 4; // see Table 17-4 of 802.11-2020
343 protection->muRts.SetPaddingSize((1 << (maxPaddingDelay + 2)) * nDbps / 8);
344 }
345
346 HeFrameExchangeManager::SendMuRts(txParams);
347}
348
349bool
350EhtFrameExchangeManager::GetEmlsrSwitchToListening(Ptr<const WifiPsdu> psdu,
351 uint16_t aid,
352 const Mac48Address& address) const
353{
354 NS_LOG_FUNCTION(this << psdu << aid << address);
355
356 // Sec. 35.3.17 of 802.11be D3.0:
357 // The non-AP MLD shall be switched back to the listening operation on the EMLSR links after
358 // the EMLSR transition delay time if [...] the non-AP STA affiliated with the non-AP MLD
359 // does not detect [...] any of the following frames:
360 // - an individually addressed frame with the RA equal to the MAC address of the non-AP STA
361 // affiliated with the non-AP MLD
362 if (psdu->GetAddr1() == address)
363 {
364 return false;
365 }
366
367 // - a Trigger frame that has one of the User Info fields addressed to the non-AP STA
368 // affiliated with the non-AP MLD
369 for (const auto& mpdu : *PeekPointer(psdu))
370 {
371 if (mpdu->GetHeader().IsTrigger())
372 {
373 CtrlTriggerHeader trigger;
374 mpdu->GetPacket()->PeekHeader(trigger);
375 if (trigger.FindUserInfoWithAid(aid) != trigger.end())
376 {
377 return false;
378 }
379 }
380 }
381
382 // - a CTS-to-self frame with the RA equal to the MAC address of the AP affiliated with
383 // the AP MLD
384 if (psdu->GetHeader(0).IsCts())
385 {
386 if (m_apMac && psdu->GetAddr1() == m_self)
387 {
388 return false;
389 }
390 if (m_staMac && psdu->GetAddr1() == m_bssid)
391 {
392 return false;
393 }
394 }
395
396 // - a Multi-STA BlockAck frame that has one of the Per AID TID Info fields addressed to
397 // the non-AP STA affiliated with the non-AP MLD
398 if (psdu->GetHeader(0).IsBlockAck())
399 {
400 CtrlBAckResponseHeader blockAck;
401 psdu->GetPayload(0)->PeekHeader(blockAck);
402 if (blockAck.IsMultiSta() && !blockAck.FindPerAidTidInfoWithAid(aid).empty())
403 {
404 return false;
405 }
406 }
407
408 // - a NDP Announcement frame that has one of the STA Info fields addressed to the non-AP
409 // STA affiliated with the non-AP MLD and a sounding NDP
410 // TODO NDP Announcement frame not supported yet
411
412 return true;
413}
414
415void
416EhtFrameExchangeManager::NotifyChannelReleased(Ptr<Txop> txop)
417{
418 NS_LOG_FUNCTION(this << txop);
419
420 // the channel has been released; all EMLSR clients will switch back to listening
421 // operation after a timeout interval of aSIFSTime + aSlotTime + aRxPHYStartDelay
422 auto delay = m_phy->GetSifs() + m_phy->GetSlot() + MicroSeconds(20);
423 for (const auto& address : m_protectedStas)
424 {
425 if (GetWifiRemoteStationManager()->GetEmlsrEnabled(address))
426 {
427 EmlsrSwitchToListening(address, delay);
428 }
429 }
430
431 HeFrameExchangeManager::NotifyChannelReleased(txop);
432}
433
434} // namespace ns3
Headers for BlockAck response.
Definition: ctrl-headers.h:203
std::vector< uint32_t > FindPerAidTidInfoWithAid(uint16_t aid) const
For Multi-STA Block Acks, get the indices of the Per AID TID Info subfields carrying the given AID in...
bool IsMultiSta() const
Check if the BlockAck frame variant is Multi-STA Block Ack.
Headers for Trigger frames.
Definition: ctrl-headers.h:942
ConstIterator end() const
Get a const iterator indicating past-the-last User Info field in the list.
bool IsMuRts() const
Check if this is a MU-RTS Trigger frame.
void SetPaddingSize(std::size_t size)
Set the size in bytes of the Padding field.
ConstIterator FindUserInfoWithAid(ConstIterator start, uint16_t aid12) const
Get a const iterator pointing to the first User Info field found (starting from the one pointed to by...
void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector) override
Forward a map of PSDUs down to the PHY layer.
void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector) override
Forward a PSDU down to the PHY layer.
Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const override
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
bool GetEmlsrSwitchToListening(Ptr< const WifiPsdu > psdu, uint16_t aid, const Mac48Address &address) const
static TypeId GetTypeId()
Get the type ID.
void EmlsrSwitchToListening(const Mac48Address &address, const Time &delay)
This method is intended to be called when an AP MLD detects that an EMLSR client previously involved ...
void SetLinkId(uint8_t linkId) override
Set the ID of the link this Frame Exchange Manager is associated with.
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
std::set< Mac48Address > m_protectedStas
STAs that have replied to an RTS in this TXOP.
Mac48Address GetAddress() const
Get the MAC address.
virtual void SetLinkId(uint8_t linkId)
Set the ID of the link this Frame Exchange Manager is associated with.
Ptr< WifiPhy > m_phy
the PHY layer on this station
HeFrameExchangeManager handles the frame exchange sequences for HE stations.
Ptr< ApWifiMac > m_apMac
MAC pointer (null if not an AP)
virtual void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector)
Forward a map of PSDUs down to the PHY layer.
Ptr< MpduAggregator > m_mpduAggregator
A-MPDU aggregator.
virtual void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector)
Forward a PSDU down to the PHY layer.
Ptr< MsduAggregator > m_msduAggregator
A-MSDU aggregator.
an EUI-48 address
Definition: mac48-address.h:46
Implement the header for Action frames of type EML Operating Mode Notification.
Definition: mgt-headers.h:1113
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
virtual Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:417
@ US
microsecond
Definition: nstime.h:118
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
Definition: mgt-headers.h:539
void SetAction(CategoryValue type, ActionValue action)
Set action for this Action header.
Definition: mgt-headers.cc:601
Implements the IEEE 802.11 MAC header.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetAddr3(Mac48Address address)
Fill the Address 3 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
Definition: wifi-mac.cc:930
void UnblockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Unblock the transmission on the given links of all unicast frames addressed to the station with the g...
Definition: wifi-mac.cc:1154
void BlockUnicastTxOnLinks(WifiQueueBlockedReason reason, const Mac48Address &address, const std::set< uint8_t > &linkIds)
Block the transmission on the given links of all unicast frames addressed to the station with the giv...
Definition: wifi-mac.cc:1113
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:910
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
Definition: wifi-mode.cc:122
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1496
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:1005
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
Definition: wifi-phy.cc:713
bool GetEmlsrEnabled(const Mac48Address &address) const
uint16_t GetAssociationId(Mac48Address remoteAddress) const
Get the AID of a remote station.
std::optional< Mac48Address > GetAffiliatedStaAddress(const Mac48Address &mldAddress) const
Get the address of the remote station operating on this link and affiliated with the MLD having the g...
std::shared_ptr< CommonInfoBasicMle::EmlCapabilities > GetStationEmlCapabilities(const Mac48Address &from)
std::optional< Mac48Address > GetMldAddress(const Mac48Address &address) const
Get the address of the MLD the given station is affiliated with, if any.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::unique_ptr< WifiProtection > m_protection
protection method
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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.
WifiPreamble GetPreambleType() const
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
Declaration of ns3::EhtPhy class.
#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_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
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ AC_VO
Voice.
Definition: qos-utils.h:80
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:488
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
@ WIFI_MAC_MGT_ACTION
static Time DecodeEmlsrTransitionDelay(uint8_t value)
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.
CtrlTriggerHeader muRts
MU-RTS.
WifiTxVector muRtsTxVector
MU-RTS TXVECTOR.
typedef for union of different ActionValues
Definition: mgt-headers.h:723