wifi: Define ack methods for UL OFDMA transmissions
This commit is contained in:
@@ -329,6 +329,75 @@ WifiDlMuAggregateTf::Print (std::ostream &os) const
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* WifiUlMuMultiStaBa
|
||||
*/
|
||||
|
||||
WifiUlMuMultiStaBa::WifiUlMuMultiStaBa ()
|
||||
: WifiAcknowledgment (UL_MU_MULTI_STA_BA)
|
||||
{
|
||||
}
|
||||
|
||||
std::unique_ptr<WifiAcknowledgment>
|
||||
WifiUlMuMultiStaBa::Copy (void) const
|
||||
{
|
||||
return std::unique_ptr<WifiAcknowledgment> (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<WifiAcknowledgment>
|
||||
WifiAckAfterTbPpdu::Copy (void) const
|
||||
{
|
||||
return std::unique_ptr<WifiAcknowledgment> (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);
|
||||
|
||||
@@ -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<WifiAcknowledgment> 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::pair<Mac48Address, uint8_t>, 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<WifiAcknowledgment> 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.
|
||||
*
|
||||
|
||||
@@ -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<const WifiMacQueueItem> 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<WifiNoAck*> (txParams.m_acknowledgment.get ());
|
||||
acknowledgment = new WifiNoAck (*acknowledgment);
|
||||
}
|
||||
else
|
||||
{
|
||||
acknowledgment = new WifiNoAck;
|
||||
}
|
||||
acknowledgment->SetQosAckPolicy (receiver, hdr.GetQosTid (), WifiMacHeader::NO_ACK);
|
||||
return std::unique_ptr<WifiAcknowledgment> (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<WifiAcknowledgment> (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<const WifiMacQueueItem>
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<WifiAcknowledgment>
|
||||
WifiDefaultAckManager::TryUlMuTransmission (Ptr<const WifiMacQueueItem> mpdu,
|
||||
const WifiTxParameters& txParams)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << *mpdu << &txParams);
|
||||
NS_ASSERT (mpdu->GetHeader ().IsTrigger ());
|
||||
|
||||
Ptr<ApWifiMac> apMac = DynamicCast<ApWifiMac> (m_mac);
|
||||
NS_ABORT_MSG_IF (apMac == nullptr, "HE APs only can send Trigger Frames");
|
||||
|
||||
Ptr<HeFrameExchangeManager> heFem = DynamicCast<HeFrameExchangeManager> (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<WifiUlMuMultiStaBa> (acknowledgment);
|
||||
}
|
||||
else if (trigger.IsBsrp ())
|
||||
{
|
||||
return std::unique_ptr<WifiAcknowledgment> (new WifiNoAck);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} //namespace ns3
|
||||
|
||||
@@ -128,6 +128,17 @@ private:
|
||||
virtual std::unique_ptr<WifiAcknowledgment> GetAckInfoIfAggregatedMuBar (Ptr<const WifiMacQueueItem> 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<WifiAcknowledgment> TryUlMuTransmission (Ptr<const WifiMacQueueItem> 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
|
||||
|
||||
Reference in New Issue
Block a user