diff --git a/src/wifi/model/wifi-acknowledgment.cc b/src/wifi/model/wifi-acknowledgment.cc index 2d0e33999..44ee4fdac 100644 --- a/src/wifi/model/wifi-acknowledgment.cc +++ b/src/wifi/model/wifi-acknowledgment.cc @@ -329,6 +329,75 @@ WifiDlMuAggregateTf::Print (std::ostream &os) const } +/* + * WifiUlMuMultiStaBa + */ + +WifiUlMuMultiStaBa::WifiUlMuMultiStaBa () + : WifiAcknowledgment (UL_MU_MULTI_STA_BA) +{ +} + +std::unique_ptr +WifiUlMuMultiStaBa::Copy (void) const +{ + return std::unique_ptr (new WifiUlMuMultiStaBa (*this)); +} + +bool +WifiUlMuMultiStaBa::CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, + WifiMacHeader::QosAckPolicy ackPolicy) const +{ + // a Basic Trigger Frame has no QoS ack policy + return true; +} + +void +WifiUlMuMultiStaBa::Print (std::ostream &os) const +{ + os << "UL_MU_MULTI_STA_BA ["; + for (const auto& sta : stationsReceivingMultiStaBa) + { + os << "(" << sta.first.first << "," << +sta.first.second << ") "; + } + os << "]"; +} + + +/* + * WifiAckAfterTbPpdu + */ + +WifiAckAfterTbPpdu::WifiAckAfterTbPpdu () + : WifiAcknowledgment (ACK_AFTER_TB_PPDU) +{ +} + +std::unique_ptr +WifiAckAfterTbPpdu::Copy (void) const +{ + return std::unique_ptr (new WifiAckAfterTbPpdu (*this)); +} + +bool +WifiAckAfterTbPpdu::CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, + WifiMacHeader::QosAckPolicy ackPolicy) const +{ + if (ackPolicy == WifiMacHeader::NORMAL_ACK) + { + return true; + } + + return false; +} + +void +WifiAckAfterTbPpdu::Print (std::ostream &os) const +{ + os << "ACK_AFTER_TB_PPDU"; +} + + std::ostream & operator << (std::ostream &os, const WifiAcknowledgment* acknowledgment) { acknowledgment->Print (os); diff --git a/src/wifi/model/wifi-acknowledgment.h b/src/wifi/model/wifi-acknowledgment.h index 8f11a6785..d1dc77192 100644 --- a/src/wifi/model/wifi-acknowledgment.h +++ b/src/wifi/model/wifi-acknowledgment.h @@ -55,7 +55,9 @@ struct WifiAcknowledgment BAR_BLOCK_ACK, DL_MU_BAR_BA_SEQUENCE, DL_MU_TF_MU_BAR, - DL_MU_AGGREGATE_TF + DL_MU_AGGREGATE_TF, + UL_MU_MULTI_STA_BA, + ACK_AFTER_TB_PPDU }; /** @@ -301,6 +303,49 @@ struct WifiDlMuAggregateTf : public WifiAcknowledgment }; +/** + * \ingroup wifi + * + * WifiUlMuMultiStaBa specifies that a Basic Trigger Frame is being sent to + * solicit TB PPDUs that will be acknowledged through a multi-STA BlockAck frame. + */ +struct WifiUlMuMultiStaBa : public WifiAcknowledgment +{ + WifiUlMuMultiStaBa (); + + // Overridden from WifiAcknowledgment + virtual std::unique_ptr Copy (void) const override; + bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override; + void Print (std::ostream &os) const override; + + ///< Map (originator, tid) pairs to the their index in baType + std::map, std::size_t> stationsReceivingMultiStaBa; + BlockAckType baType; //!< BlockAck type + WifiTxVector tbPpduTxVector; //!< TXVECTOR for a TB PPDU + WifiTxVector multiStaBaTxVector; //!< TXVECTOR for the Multi-STA BlockAck +}; + + +/** + * \ingroup wifi + * + * WifiAckAfterTbPpdu is used when a station prepares a TB PPDU to send in + * response to a Basic Trigger Frame. The acknowledgment time must be + * zero because the time taken by the actual acknowledgment is not included + * in the duration indicated by the Trigger Frame. The QoS ack policy instead + * must be Normal Ack/Implicit Block Ack Request. + */ +struct WifiAckAfterTbPpdu : public WifiAcknowledgment +{ + WifiAckAfterTbPpdu (); + + // Overridden from WifiAcknowledgment + virtual std::unique_ptr Copy (void) const override; + bool CheckQosAckPolicy (Mac48Address receiver, uint8_t tid, WifiMacHeader::QosAckPolicy ackPolicy) const override; + void Print (std::ostream &os) const override; +}; + + /** * \brief Stream insertion operator. * diff --git a/src/wifi/model/wifi-default-ack-manager.cc b/src/wifi/model/wifi-default-ack-manager.cc index 0019b6b83..db0377193 100644 --- a/src/wifi/model/wifi-default-ack-manager.cc +++ b/src/wifi/model/wifi-default-ack-manager.cc @@ -28,6 +28,7 @@ #include "ap-wifi-mac.h" #include "ctrl-headers.h" #include "ns3/he-phy.h" +#include "ns3/he-frame-exchange-manager.h" namespace ns3 { @@ -188,6 +189,48 @@ WifiDefaultAckManager::TryAddMpdu (Ptr mpdu, const WifiMacHeader& hdr = mpdu->GetHeader (); Mac48Address receiver = hdr.GetAddr1 (); + // Acknowledgment for TB PPDUs + if (txParams.m_txVector.IsUlMu ()) + { + if (hdr.IsQosData () && !hdr.HasData ()) + { + // QoS Null frame + WifiNoAck* acknowledgment = nullptr; + + if (txParams.m_acknowledgment) + { + NS_ASSERT (txParams.m_acknowledgment->method == WifiAcknowledgment::NONE); + acknowledgment = static_cast (txParams.m_acknowledgment.get ()); + acknowledgment = new WifiNoAck (*acknowledgment); + } + else + { + acknowledgment = new WifiNoAck; + } + acknowledgment->SetQosAckPolicy (receiver, hdr.GetQosTid (), WifiMacHeader::NO_ACK); + return std::unique_ptr (acknowledgment); + } + + if (txParams.m_acknowledgment) + { + NS_ASSERT (txParams.m_acknowledgment->method == WifiAcknowledgment::ACK_AFTER_TB_PPDU); + return nullptr; + } + + WifiAckAfterTbPpdu* acknowledgment = new WifiAckAfterTbPpdu; + if (hdr.IsQosData ()) + { + acknowledgment->SetQosAckPolicy (receiver, hdr.GetQosTid (), WifiMacHeader::NORMAL_ACK); + } + return std::unique_ptr (acknowledgment); + } + + // if this is a Trigger Frame, call a separate method + if (hdr.IsTrigger ()) + { + return TryUlMuTransmission (mpdu, txParams); + } + // if the current protection method (if any) is already BLOCK_ACK or BAR_BLOCK_ACK, // it will not change by adding an MPDU if (txParams.m_acknowledgment @@ -591,4 +634,70 @@ WifiDefaultAckManager::GetAckInfoIfAggregatedMuBar (Ptr return nullptr; } +std::unique_ptr +WifiDefaultAckManager::TryUlMuTransmission (Ptr mpdu, + const WifiTxParameters& txParams) +{ + NS_LOG_FUNCTION (this << *mpdu << &txParams); + NS_ASSERT (mpdu->GetHeader ().IsTrigger ()); + + Ptr apMac = DynamicCast (m_mac); + NS_ABORT_MSG_IF (apMac == nullptr, "HE APs only can send Trigger Frames"); + + Ptr heFem = DynamicCast (m_mac->GetFrameExchangeManager ()); + NS_ABORT_MSG_IF (heFem == nullptr, "HE APs only can send Trigger Frames"); + + CtrlTriggerHeader trigger; + mpdu->GetPacket ()->PeekHeader (trigger); + + if (trigger.IsBasic ()) + { + // the only supported ack method for now is through a multi-STA BlockAck frame + WifiUlMuMultiStaBa* acknowledgment = new WifiUlMuMultiStaBa; + acknowledgment->baType.m_variant = BlockAckType::MULTI_STA; + + for (const auto& userInfo : trigger) + { + uint16_t aid12 = userInfo.GetAid12 (); + + if (aid12 == 2046) + { + NS_LOG_INFO ("Unallocated RU"); + continue; + } + NS_ABORT_MSG_IF (aid12 == 0 || aid12 > 2007, "Allocation of RA-RUs is not supported"); + + NS_ASSERT (apMac->GetStaList ().find (aid12) != apMac->GetStaList ().end ()); + Mac48Address staAddress = apMac->GetStaList ().find (aid12)->second; + + // find a TID for which a BA agreement exists with the given originator + uint8_t tid = 0; + while (tid < 8 && !heFem->GetBaAgreementEstablished (staAddress, tid)) + { + tid++; + } + NS_ASSERT_MSG (tid < 8, "No Block Ack agreement established with originator " << staAddress); + + std::size_t index = acknowledgment->baType.m_bitmapLen.size (); + acknowledgment->stationsReceivingMultiStaBa.emplace (std::make_pair (staAddress, tid), index); + + // we assume the Block Acknowledgment context is used for the multi-STA BlockAck frame + // (since it requires the longest TX time due to the presence of a bitmap) + acknowledgment->baType.m_bitmapLen.push_back (heFem->GetBlockAckType (staAddress, tid).m_bitmapLen.at (0)); + } + + uint16_t staId = trigger.begin ()->GetAid12 (); + acknowledgment->tbPpduTxVector = trigger.GetHeTbTxVector (staId); + acknowledgment->multiStaBaTxVector = m_mac->GetWifiRemoteStationManager ()->GetBlockAckTxVector (apMac->GetStaList ().find (staId)->second, + acknowledgment->tbPpduTxVector); + return std::unique_ptr (acknowledgment); + } + else if (trigger.IsBsrp ()) + { + return std::unique_ptr (new WifiNoAck); + } + + return nullptr; +} + } //namespace ns3 diff --git a/src/wifi/model/wifi-default-ack-manager.h b/src/wifi/model/wifi-default-ack-manager.h index 774f2b758..fd37920fa 100644 --- a/src/wifi/model/wifi-default-ack-manager.h +++ b/src/wifi/model/wifi-default-ack-manager.h @@ -128,6 +128,17 @@ private: virtual std::unique_ptr GetAckInfoIfAggregatedMuBar (Ptr mpdu, const WifiTxParameters& txParams); + /** + * Calculate the acknowledgment method for the TB PPDUs solicited by the given + * Trigger Frame. + * + * \param mpdu the given Trigger Frame + * \param txParams the current TX parameters (just the TXVECTOR needs to be set) + * \return the acknowledgment method for the TB PPDUs solicited by the given Trigger Frame + */ + virtual std::unique_ptr TryUlMuTransmission (Ptr mpdu, + const WifiTxParameters& txParams); + bool m_useExplicitBar; //!< true for sending BARs, false for using Implicit BAR policy double m_baThreshold; //!< Threshold to determine when a BlockAck must be requested WifiAcknowledgment::Method m_dlMuAckType; //!< Type of the ack sequence for DL MU PPDUs