diff --git a/src/wifi/model/frame-exchange-manager.cc b/src/wifi/model/frame-exchange-manager.cc index 480b41c38..6fe096c21 100644 --- a/src/wifi/model/frame-exchange-manager.cc +++ b/src/wifi/model/frame-exchange-manager.cc @@ -20,6 +20,7 @@ #include "frame-exchange-manager.h" #include "snr-tag.h" +#include "sta-wifi-mac.h" #include "wifi-mac-queue.h" #include "wifi-mac-trailer.h" #include "wifi-utils.h" @@ -498,7 +499,39 @@ FrameExchangeManager::ForwardMpduDown(Ptr mpdu, WifiTxVector& txVector { NS_LOG_FUNCTION(this << *mpdu << txVector); - m_phy->Send(Create(mpdu, false), txVector); + auto psdu = Create(mpdu, false); + FinalizeMacHeader(psdu); + m_phy->Send(psdu, txVector); +} + +void +FrameExchangeManager::FinalizeMacHeader(Ptr psdu) +{ + NS_LOG_FUNCTION(this << psdu); + + if (m_mac->GetTypeOfStation() != STA) + { + return; + } + + auto pmMode = StaticCast(m_mac)->GetPmMode(m_linkId); + + for (const auto& mpdu : *PeekPointer(psdu)) + { + switch (pmMode) + { + case WIFI_PM_ACTIVE: + case WIFI_PM_SWITCHING_TO_ACTIVE: + mpdu->GetHeader().SetNoPowerManagement(); + break; + case WIFI_PM_POWERSAVE: + case WIFI_PM_SWITCHING_TO_PS: + mpdu->GetHeader().SetPowerManagement(); + break; + default: + NS_ABORT_MSG("Unknown PM mode: " << +pmMode); + } + } } void diff --git a/src/wifi/model/frame-exchange-manager.h b/src/wifi/model/frame-exchange-manager.h index 2fd2b77f1..eed89318c 100644 --- a/src/wifi/model/frame-exchange-manager.h +++ b/src/wifi/model/frame-exchange-manager.h @@ -455,6 +455,14 @@ class FrameExchangeManager : public Object DroppedMpdu m_droppedMpduCallback; //!< the dropped MPDU callback AckedMpdu m_ackedMpduCallback; //!< the acknowledged MPDU callback + /** + * Finalize the MAC header of the MPDUs in the given PSDU before transmission. Tasks + * performed by this method include setting the Power Management flag in the MAC header. + * + * \param psdu the given PSDU + */ + virtual void FinalizeMacHeader(Ptr psdu); + /** * Forward an MPDU down to the PHY layer. * diff --git a/src/wifi/model/he/he-frame-exchange-manager.cc b/src/wifi/model/he/he-frame-exchange-manager.cc index 4946098d2..5e234e800 100644 --- a/src/wifi/model/he/he-frame-exchange-manager.cc +++ b/src/wifi/model/he/he-frame-exchange-manager.cc @@ -873,9 +873,10 @@ HeFrameExchangeManager::ForwardPsduMapDown(WifiConstPsduMap psduMap, WifiTxVecto NS_LOG_DEBUG("Transmitting: [STAID=" << psdu.first << ", " << *psdu.second << "]"); } NS_LOG_DEBUG("TXVECTOR: " << txVector); - for (const auto& psdu : psduMap) + for (const auto& [staId, psdu] : psduMap) { - NotifyTxToEdca(psdu.second); + FinalizeMacHeader(psdu); + NotifyTxToEdca(psdu); } if (psduMap.size() > 1 || psduMap.begin()->second->IsAggregate() || psduMap.begin()->second->IsSingle()) diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.cc b/src/wifi/model/ht/ht-frame-exchange-manager.cc index b85606bec..3d6affe25 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.cc +++ b/src/wifi/model/ht/ht-frame-exchange-manager.cc @@ -26,6 +26,7 @@ #include "ns3/mgt-headers.h" #include "ns3/recipient-block-ack-agreement.h" #include "ns3/snr-tag.h" +#include "ns3/sta-wifi-mac.h" #include "ns3/wifi-mac-queue.h" #include "ns3/wifi-utils.h" @@ -1077,6 +1078,23 @@ HtFrameExchangeManager::NotifyTxToEdca(Ptr psdu) const { NS_LOG_FUNCTION(this << psdu); + for (const auto& mpdu : *PeekPointer(psdu)) + { + auto& hdr = mpdu->GetHeader(); + + if (hdr.IsQosData() && hdr.HasData()) + { + auto tid = hdr.GetQosTid(); + m_mac->GetQosTxop(tid)->CompleteMpduTx(mpdu); + } + } +} + +void +HtFrameExchangeManager::FinalizeMacHeader(Ptr psdu) +{ + NS_LOG_FUNCTION(this << psdu); + // use an array to avoid computing the queue size for every MPDU in the PSDU std::array, 8> queueSizeForTid; @@ -1087,7 +1105,7 @@ HtFrameExchangeManager::NotifyTxToEdca(Ptr psdu) const if (hdr.IsQosData()) { uint8_t tid = hdr.GetQosTid(); - Ptr edca = m_mac->GetQosTxop(tid); + auto edca = m_mac->GetQosTxop(tid); if (m_mac->GetTypeOfStation() == STA && (m_setQosQueueSize || hdr.IsQosEosp())) { @@ -1100,13 +1118,10 @@ HtFrameExchangeManager::NotifyTxToEdca(Ptr psdu) const hdr.SetQosEosp(); hdr.SetQosQueueSize(queueSizeForTid[tid].value()); } - - if (hdr.HasData()) - { - edca->CompleteMpduTx(mpdu); - } } } + + QosFrameExchangeManager::FinalizeMacHeader(psdu); } void @@ -1126,6 +1141,7 @@ HtFrameExchangeManager::ForwardPsduDown(Ptr psdu, WifiTxVector& NS_LOG_FUNCTION(this << psdu << txVector); NS_LOG_DEBUG("Transmitting a PSDU: " << *psdu << " TXVECTOR: " << txVector); + FinalizeMacHeader(psdu); NotifyTxToEdca(psdu); if (psdu->IsAggregate()) diff --git a/src/wifi/model/ht/ht-frame-exchange-manager.h b/src/wifi/model/ht/ht-frame-exchange-manager.h index 72d72ba2d..1c982c658 100644 --- a/src/wifi/model/ht/ht-frame-exchange-manager.h +++ b/src/wifi/model/ht/ht-frame-exchange-manager.h @@ -197,6 +197,7 @@ class HtFrameExchangeManager : public QosFrameExchangeManager void RetransmitMpduAfterMissedAck(Ptr mpdu) const override; void ReleaseSequenceNumbers(Ptr psdu) const override; void ForwardMpduDown(Ptr mpdu, WifiTxVector& txVector) override; + void FinalizeMacHeader(Ptr psdu) override; void CtsTimeout(Ptr rts, const WifiTxVector& txVector) override; void TransmissionSucceeded() override;