25 #include "ns3/abort.h"
26 #include "ns3/ap-wifi-mac.h"
28 #include "ns3/mgt-action-headers.h"
29 #include "ns3/sta-wifi-mac.h"
30 #include "ns3/wifi-mac-queue.h"
31 #include "ns3/wifi-net-device.h"
33 #undef NS_LOG_APPEND_CONTEXT
34 #define NS_LOG_APPEND_CONTEXT std::clog << "[link=" << +m_linkId << "][mac=" << m_self << "] "
66 static TypeId tid =
TypeId(
"ns3::EhtFrameExchangeManager")
68 .AddConstructor<EhtFrameExchangeManager>()
69 .SetGroupName(
"Wifi");
105 protectionManager->SetLinkId(linkId);
109 ackManager->SetLinkId(linkId);
123 mpdu->GetHeader().GetAddr1().IsGroup() ||
130 auto& hdr = mpdu->GetHeader();
142 if (hdr.IsQosAmsdu())
144 if (hdr.IsToDs() && !hdr.IsFromDs())
147 hdr.SetAddr3(hdr.GetAddr1());
149 else if (!hdr.IsToDs() && hdr.IsFromDs())
152 hdr.SetAddr3(hdr.GetAddr2());
180 std::optional<Time> timeToCtsEnd;
187 NS_LOG_DEBUG(
"StartTransmission called while another EMLSR link is being used");
194 if (
auto elapsed = emlsrManager->GetElapsedMediumSyncDelayTimer(
m_linkId);
195 elapsed && emlsrManager->MediumSyncDelayNTxopsExceeded(
m_linkId))
197 NS_LOG_DEBUG(
"No new TXOP attempts allowed while MediumSyncDelay is running");
201 emlsrManager->GetMediumSyncDuration() - *elapsed,
223 if (!emlsrManager->GetAuxPhyTxCapable())
225 NS_LOG_DEBUG(
"Aux PHY is not capable of transmitting a PPDU");
230 if (mainPhy->IsStateRx())
233 "Main PHY is receiving a PPDU (may be, e.g., an ICF or a Beacon); do not "
234 "transmit to avoid dropping that PPDU due to the main PHY switching to this "
235 "link to take over the TXOP");
245 const auto rtsTxVector =
247 const auto rtsTxTime =
249 const auto ctsTxVector =
251 const auto ctsTxTime =
256 timeToCtsEnd = rtsTxTime +
m_phy->
GetSifs() + ctsTxTime +
259 auto switchingTime = mainPhy->GetChannelSwitchDelay();
261 if (mainPhy->IsStateSwitching())
265 switchingTime += mainPhy->GetDelayUntilIdle();
268 if (switchingTime > timeToCtsEnd)
272 NS_LOG_DEBUG(
"Main PHY will still be switching channel when RTS/CTS ends, thus it "
273 "will not be able to take over this TXOP");
301 auto sigBMode =
phy->GetSigBMode(txVector);
351 if (
auto psduMapIt = psduMap.find(aid);
353 (psduMapIt == psduMap.cend() ||
404 std::set<uint8_t> linkIds;
409 linkIds.insert(linkId);
413 auto blockLinks = [=,
this]() {
428 auto unblockLinks = [=,
this]() {
435 emlCapabilities->get().emlsrTransitionDelay);
437 endDelay.IsZero() ? unblockLinks()
479 const auto sequence =
m_txMiddle->GetNextSequenceNumberFor(&hdr);
487 auto packet = Create<Packet>();
488 packet->AddHeader(frame);
489 packet->AddHeader(actionHdr);
495 std::optional<double>
515 std::optional<Mac48Address> linkAddress;
533 uint8_t maxPaddingDelay = 0;
545 maxPaddingDelay =
std::max(maxPaddingDelay, emlCapabilities->get().emlsrPaddingDelay);
563 if (maxPaddingDelay > 0)
571 auto rate = protection->muRtsTxVector.GetMode().GetDataRate(protection->muRtsTxVector);
572 std::size_t nDbps = rate / 1e6 * 4;
573 protection->muRts.SetPaddingSize((1 << (maxPaddingDelay + 2)) * nDbps / 8);
640 if (mpdu->GetHeader().IsTrigger())
643 mpdu->GetPacket()->PeekHeader(trigger);
692 NS_LOG_DEBUG(
"Reset the counter of TXOP attempts allowed while "
693 "MediumSyncDelay is running");
708 NS_LOG_DEBUG(
"Decrement the remaining number of TXOP attempts allowed while "
709 "MediumSyncDelay is running");
738 auto edca = DynamicCast<QosTxop>(txop);
740 if (
auto txopStart = edca->GetTxopStartTime(
m_linkId);
847 NS_ASSERT(mpdu->GetHeader().GetAddr1().IsGroup() || mpdu->GetHeader().GetAddr1() ==
m_self);
849 const auto& hdr = mpdu->GetHeader();
880 it->second.PeekEventImpl()->Invoke();
885 bool icfReceived =
false;
895 mpdu->GetPacket()->PeekHeader(trigger);
897 if (hdr.GetAddr1() !=
m_self &&
914 NS_LOG_DEBUG(
"Drop ICF because another EMLSR link is being used");
951 if (*elapsed < padding.
Get())
953 NS_LOG_DEBUG(
"Drop ICF due to not enough time for the main PHY to switch link");
982 !icfReceived && !mpdu->GetHeader().IsCts() && !mpdu->GetHeader().IsMgt())
1002 NS_LOG_DEBUG(
"PHY is decoding the PHY header of PPDU, postpone TXOP end");
1042 else if (durationId <= m_phy->GetSifs())
1046 NS_LOG_DEBUG(
"Assume TXOP will end based on Duration/ID value");
1097 if (durationId <= m_phy->GetSifs())
1099 NS_LOG_DEBUG(
"Assume TXOP ended based on Duration/ID value");
EhtFrameExchangeManager handles the frame exchange sequences for EHT stations.
void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector) override
Forward a map of PSDUs down to the PHY layer.
bool UsingOtherEmlsrLink() const
void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
void NavResetTimeout() override
Reset the NAV upon expiration of the NAV reset timer.
void ForwardPsduDown(Ptr< const WifiPsdu > psdu, WifiTxVector &txVector) override
Forward a PSDU down to the PHY layer.
void TxopEnd()
Take actions when a TXOP (of which we are not the holder) ends.
void SendEmlOmn(const Mac48Address &dest, const MgtEmlOmn &frame)
Send an EML Operating Mode Notification frame to the given station.
Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const override
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
void TransmissionFailed() override
Take necessary actions upon a transmission failure.
void IntraBssNavResetTimeout() override
Reset the intra-BSS NAV upon expiration of the intra-BSS NAV reset timer.
void SendMuRts(const WifiTxParameters &txParams) override
Send an MU-RTS to begin an MU-RTS/CTS frame exchange protecting an MU PPDU.
EhtFrameExchangeManager()
void UpdateTxopEndOnRxEnd(Time durationId)
Update the TXOP end timer when a frame reception ends.
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
bool GetEmlsrSwitchToListening(Ptr< const WifiPsdu > psdu, uint16_t aid, const Mac48Address &address) const
static TypeId GetTypeId()
Get the type ID.
void DoDispose() override
Destructor implementation.
bool StartTransmission(Ptr< Txop > edca, uint16_t allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
std::unordered_map< Mac48Address, EventId, WifiAddressHash > m_transDelayTimer
MLD address-indexed map of transition delay timers.
void NotifyChannelReleased(Ptr< Txop > txop) override
Notify the given Txop that channel has been released.
EventId m_ongoingTxopEnd
event indicating the possible end of the current TXOP (of which we are not the holder)
void RxStartIndication(WifiTxVector txVector, Time psduDuration) override
void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
void UpdateTxopEndOnTxStart(Time txDuration, Time durationId)
Update the TXOP end timer when starting a frame transmission.
void UpdateTxopEndOnRxStartIndication(Time psduDuration)
Update the TXOP end timer when receiving a PHY-RXSTART.indication.
~EhtFrameExchangeManager() override
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 CtsAfterMuRtsTimeout(Ptr< WifiMpdu > muRts, const WifiTxVector &txVector) override
Called when no CTS frame is received after an MU-RTS.
void NotifySwitchingEmlsrLink(Ptr< WifiPhy > phy, uint8_t linkId, Time delay)
Notify that the given PHY will switch channel to operate on another EMLSR link after the given delay.
std::optional< double > GetMostRecentRssi(const Mac48Address &address) const override
Get the RSSI (in dBm) of the most recent packet received from the station having the given address.
void SetLinkId(uint8_t linkId) override
Set the ID of the link this Frame Exchange Manager is associated with.
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
std::set< Mac48Address > m_sentRtsTo
the STA(s) which we sent an RTS to (waiting for CTS)
uint8_t m_linkId
the ID of the link this object is associated with
Ptr< WifiMac > m_mac
the MAC layer on this station
virtual void ResetPhy()
Remove WifiPhy associated with this FrameExchangeManager.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
Ptr< MacTxMiddle > m_txMiddle
the MAC TX Middle on this station
Mac48Address m_self
the MAC address of this device
WifiTxTimer m_txTimer
the timer set upon frame transmission
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.
virtual void NotifyChannelReleased(Ptr< Txop > txop)
Notify the given Txop that channel has been released.
Ptr< WifiAckManager > GetAckManager() const
Get the Acknowledgment Manager used by this node.
Ptr< WifiProtectionManager > GetProtectionManager() const
Get the Protection Manager used by this node.
Ptr< WifiPhy > m_phy
the PHY layer on this station
Mac48Address m_bssid
BSSID address (Mac48Address)
HeFrameExchangeManager handles the frame exchange sequences for HE stations.
Ptr< ApWifiMac > m_apMac
MAC pointer (null if not an AP)
void DoDispose() override
Destructor implementation.
virtual void IntraBssNavResetTimeout()
Reset the intra-BSS NAV upon expiration of the intra-BSS NAV reset timer.
virtual void SendMuRts(const WifiTxParameters &txParams)
Send an MU-RTS to begin an MU-RTS/CTS frame exchange protecting an MU PPDU.
void RxStartIndication(WifiTxVector txVector, Time psduDuration) override
virtual std::optional< double > GetMostRecentRssi(const Mac48Address &address) const
Get the RSSI (in dBm) of the most recent packet received from the station having the given address.
virtual void CtsAfterMuRtsTimeout(Ptr< WifiMpdu > muRts, const WifiTxVector &txVector)
Called when no CTS frame is received after an MU-RTS.
void NavResetTimeout() override
Reset the NAV upon expiration of the NAV reset timer.
Ptr< StaWifiMac > m_staMac
MAC pointer (null if not a STA)
void ReceiveMpdu(Ptr< const WifiMpdu > mpdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, bool inAmpdu) override
This method handles the reception of an MPDU (possibly included in an A-MPDU)
virtual void ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVector &txVector)
Forward a map of PSDUs down to the PHY layer.
void PostProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed after receiving any frame, independently of whether the fram...
void TransmissionSucceeded() override
Take necessary actions upon a transmission success.
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.
Implement the header for Action frames of type EML Operating Mode Notification.
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Smart pointer class similar to boost::intrusive_ptr.
void TransmissionFailed() override
Take necessary actions upon a transmission failure.
std::optional< Mac48Address > m_txopHolder
MAC address of the TXOP holder.
bool StartTransmission(Ptr< Txop > edca, uint16_t allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
virtual Ptr< WifiMpdu > CreateAliasIfNeeded(Ptr< WifiMpdu > mpdu) const
Create an alias of the given MPDU for transmission by this Frame Exchange Manager.
void PreProcessFrame(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector) override
Perform actions that are possibly needed when receiving any frame, independently of whether the frame...
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static Time Now()
Return the current simulation virtual time.
uint16_t GetAssociationId() const
Return the association ID.
void NotifySwitchingEmlsrLink(Ptr< WifiPhy > phy, uint8_t linkId, Time delay)
Notify that the given PHY switched channel to operate on another EMLSR link.
Ptr< EmlsrManager > GetEmlsrManager() const
bool IsEmlsrLink(uint8_t linkId) const
bool IsAssociated() const
Return whether we are associated with an AP.
Simulation virtual time values and global simulation resolution.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
bool IsStrictlyPositive() const
Exactly equivalent to t > 0.
bool IsZero() const
Exactly equivalent to t == 0.
void StartAccessAfterEvent(uint8_t linkId, bool hadFramesToTransmit, bool checkMediumBusy)
Request channel access on the given link after the occurrence of an event that possibly requires to g...
static constexpr bool DIDNT_HAVE_FRAMES_TO_TRANSMIT
no packet available for transmission was in the queue
virtual void Queue(Ptr< Packet > packet, const WifiMacHeader &hdr)
static constexpr bool DONT_CHECK_MEDIUM_BUSY
generation of backoff is independent of the busy/idle state of the medium
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
std::optional< Mac48Address > GetMldAddress(const Mac48Address &remoteAddr) const
Ptr< WifiMacQueueScheduler > GetMacQueueScheduler() const
Get the wifi MAC queue scheduler.
uint8_t GetNLinks() const
Get the number of links (can be greater than 1 for 11be devices only).
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...
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...
Ptr< WifiNetDevice > GetDevice() const
Return the device this PHY is associated with.
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.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Ptr< WifiPhy > GetPhy() const
Time GetSlot() const
Return the slot duration for this PHY.
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
bool IsReceivingPhyHeader() const
Ptr< PhyEntity > GetPhyEntity(WifiModulationClass modulation) const
Get the supported PHY entity corresponding to the modulation class.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
Time GetDuration() const
Get the duration from the Duration/ID field, which is common to all the MPDUs.
Mac48Address GetAddr2() const
Get the Transmitter Address (TA), which is common to all the MPDUs.
Ptr< const Packet > GetPayload(std::size_t i) const
Get the payload of the i-th MPDU.
Mac48Address GetAddr1() const
Get the Receiver Address (RA), which is common to all the MPDUs.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::unique_ptr< WifiProtection > m_protection
protection method
bool IsRunning() const
Return true if the timer is running.
const std::set< Mac48Address > & GetStasExpectedToRespond() const
Time GetDelayLeft() const
Get the remaining time until the timer will expire.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#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.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WAITING_EMLSR_TRANSITION_DELAY
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
static constexpr uint8_t WAIT_FOR_RXSTART_DELAY_USEC
Additional time (exceeding 20 us) to wait for a PHY-RXSTART.indication when the PHY is decoding a PHY...
static constexpr uint8_t RX_PHY_START_DELAY_USEC
aRxPHYStartDelay value to use when waiting for a new frame in the context of EMLSR operations (Sec.
uint32_t GetRtsSize()
Return the total RTS size (including FCS trailer).
std::tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
static constexpr uint8_t MAX_PROPAGATION_DELAY_USEC
maximum propagation delay
uint32_t GetCtsSize()
Return the total CTS size (including FCS trailer).
U * PeekPointer(const Ptr< U > &p)
static Time DecodeEmlsrTransitionDelay(uint8_t value)
RxSignalInfo structure containing info on the received signal.
WifiMuRtsCtsProtection specifies that MU-RTS/CTS protection method is used.